Method 1: Trying to select the points within a buffer of 1 mile (circle drawn by user input).
The geometry is saved in buffergeometries variable and the points layer is queried based on the geometry. But all the points in the points layer is selected. Trying to select only the points inside the buffer, any help is appreciated.
Tried other methods such as converting the graphic to feature layer, with the data source created. Query the object id and use contain, intersect but nothing worked.
Thanks in advance. This is done in Expereince Builder developer edition 1.9.
/** @jsx jsx */
// jimu / react
import {
AllWidgetProps,
DataSourceComponent,
FeatureLayerDataSource,
jsx,
React,
QueryResult,
styled,
} from 'jimu-core';
import { JimuMapViewComponent, JimuMapView } from 'jimu-arcgis';
import { Button, TextInput } from 'jimu-ui';
import geometryEngine from 'esri/geometry/geometryEngine';
import Point from 'esri/geometry/Point';
import Circle from 'esri/geometry/Circle';
import Geometry from 'esri/geometry/Geometry';
import Graphic from 'esri/Graphic';
import GraphicsLayer from 'esri/layers/GraphicsLayer';
import MapView from 'esri/views/MapView';
import FeatureLayer from "esri/layers/FeatureLayer";
// custom components
import TRSFormRow from './components/TRSFormRow';
// resources
import { IMConfig } from '../config';
import defaultMessages from './translations/default';
// types
interface State {
selectedBufferRows: Array<string[]>;
}
export default class Widget extends React.PureComponent<
AllWidgetProps<IMConfig>,
State
> {
private mapView: MapView;
private pointsLayer: GraphicsLayer;
private graphicsLayer: GraphicsLayer;
private gwsiSiteDataSource: FeatureLayerDataSource;
private bufferHighlightSymbol = {
type: 'simple-fill',
color: [255, 255, 0, 0.25],
outline: {
style: 'dash-dot',
color: [0, 0, 255],
width: 2,
},
};
public state: State = {
selectedBufferRows: [[]],
};
// store map view when available
onActiveViewChange = (jimuMapView: JimuMapView) => {
if (jimuMapView?.view) {
this.mapView = jimuMapView.view;
// create a graphics layer to show highlighted buffers
this.graphicsLayer = new GraphicsLayer({title: "Buffer Layer"});
this.pointsLayer = this.mapView.map.layers.items[0];
this.mapView.map.add(this.graphicsLayer, 0);
}
};
// store data source when available
onDataSourceCreated = (dataSource: FeatureLayerDataSource, name: string) => {
this[name] = dataSource;
};
// handle Buffer form element change
onBufferRowChange = (id: number, value: string[]) => {
const newSelectedBufferRows = [...this.state.selectedBufferRows];
newSelectedBufferRows[id] = value;
this.setState({ selectedBufferRows: newSelectedBufferRows });
};
clearSearchResults = () => {
this.graphicsLayer?.removeAll();
// clear gwsi selection
this.gwsiSiteDataSource?.selectRecordsByIds([], []);
};
onClear = async () => {
// reset selectons
this.clearSearchResults();
// short-circuit if no values selected
const selectedValues = this.state.selectedBufferRows.flat();
if (selectedValues.length < 1) {
return;
}
const selectedRows = this.state.selectedBufferRows;
selectedRows.forEach((selectedRow, index) => {
selectedRows[index] = [];
});
}
onSearch = async () => {
// reset selectons
this.clearSearchResults();
// short-circuit if no data sources
if (!this.gwsiSiteDataSource) {
return;
}
// short-circuit if no values selected
const selectedValues = this.state.selectedBufferRows.flat();
if (selectedValues.length < 1 || selectedValues[0].length < 3) {
alert('No ids selected');
return;
}
const selectedValue = selectedValues[0];
const selectedValuesSplit = selectedValue.split('_');
const searchId = selectedValuesSplit[0];
const bufferDistance = selectedValuesSplit[1];
const distanceUnits = selectedValuesSplit[2];
const where = `SITE_ID = '${searchId}' OR LOCAL_ID = '${searchId}'`
// query for siteId/localId geometries from gwsisites featue layer gave one result
const gwsiSitePointQueryResult: QueryResult = await this.gwsiSiteDataSource.query({
where,
returnGeometry: true,
});
let pointGeometry: Point;
const gwsiPointGeometries = gwsiSitePointQueryResult.records.map((record) =>
{ pointGeometry = record.getGeometry(); return pointGeometry;}
);
let selectedBufferGeometry;
const bufferGeometries = gwsiPointGeometries.map(
(point) => {
selectedBufferGeometry = geometryEngine.buffer(point, 1, "miles");
return selectedBufferGeometry;
});
/*(point) => new Circle({
center: point,
geodesic: false,
z: null,
//numberOfPoints: 100,
radius: 1,
radiusUnit: "miles"
}));*/
// select/display buffer features
const bufferGraphics = bufferGeometries.map(
(bufferGeometry) =>
new Graphic({
geometry: bufferGeometry,
symbol: this.bufferHighlightSymbol,
})
);
this.graphicsLayer?.addMany(bufferGraphics);
// zoom to buffers
const extent = geometryEngine.union(bufferGeometries).extent;
this.mapView?.goTo(extent);
debugger
// query for gwsi site ids
const gwsiSiteQueryResult: QueryResult[] = await Promise.all(
bufferGeometries.map((geometry) =>
this.gwsiSiteDataSource.query({
geometry
//spatialRel: "contains"
})
)
);
//uses datasource query to query for points in req distance from given point
/*const gwsiSiteQueryResult: QueryResult[] = await Promise.all(
gwsiPointGeometries.map((point) =>
this.gwsiSiteDataSource.query({
geometry: point,
distance: 1,
units: "miles",
//spatialRel: "contains"
}),
),
);*/
const gwsiSiteRecords = gwsiSiteQueryResult
.map((result) => result.records).flat();
const gwsiSiteIds = gwsiSiteRecords.map((record) => record.getId());
//try 2: using buffer and feature layer
/*const bufferFeaturesForFL = bufferGraphics.map(
(bufferGraphic) =>{
return {
graphic: bufferGraphic,
attributes: {
ObjectID: 1
}
};
}
);*/
/*const bufferLayer = new FeatureLayer({
source: bufferFeaturesForFL, // autocast as a Collection of new Graphic()
objectIdField: "ObjectID",
fields:[{
name:"OBJECTID",
type:"oid"
}]
});*/
/*const bufferFLGeometries = bufferLayer.graphics.map(function(graphic){
return graphic.geometry
});*/
/*let query = bufferLayer.createQuery();
query.geometry = pointGeometry; // the point location of the pointer
query.distance = 1;
query.units = "miles";
query.spatialRelationship = "intersects"; // this is the default
query.returnGeometry = true;
this.graphicsLayer.queryFeatures(query)
.then(function(response){
// returns a feature set with features containing the
// POPULATION attribute and each feature's geometry
});*/
/*2 const gwsiSiteQueryResult: QueryResult[] = await Promise.all(
bufferGeometries.map((geometry) =>
this.gwsiSiteDataSource.query({
geometry: geometry,
spatialRelationship: "contains"
}),
),
);
const gwsiSiteRecords = gwsiSiteQueryResult
.map((result) => result.records)
.flat();
const gwsiSiteIds = gwsiSiteRecords
//.filter((point) => geometryEngine.contains(circle, point))
.map((record) => record.getId());
*/
// select gwsi site features
this.gwsiSiteDataSource.selectRecordsByIds(gwsiSiteIds, gwsiSiteRecords);
alert(
`onSearch: ${where} - ${bufferGeometries.length} - sections, ${gwsiSiteIds.length} gwsi sites`,
);
//debugger
//query all points-gets 2000 records
/*const gwsiSiteQueryResult: QueryResult[] = await Promise.all(
bufferGeometries.map((geometry) =>
this.gwsiSiteDataSource.query({
})
)
);*/
/*query all points and filter - error
const gwsiSiteQueryResult: QueryResult[] = await Promise.all(
this.gwsiSiteDataSource.query({})
//.records
//.filter((point) => geometryEngine.contains(circle, point)
//).flat()
);*/
/* from TRS // query for section geometries
const sectionQueryResult: QueryResult = await this.sectionDataSource.query({
where, returnGeometry: true, });
const sectionGeometries = sectionQueryResult.records.map((record) =>
record.getGeometry()
);// query for gwsi site ids
const gwsiSiteQueryResult: QueryResult[] = await Promise.all(
sectionGeometries.map((geometry) =>
this.gwsiSiteDataSource.query({
geometry,
}), ), );
const gwsiSiteRecords = gwsiSiteQueryResult
.map((result) => result.records).flat();
const gwsiSiteIds = gwsiSiteRecords.map((record) => record.getId());
// select gwsi site features
this.gwsiSiteDataSource.selectRecordsByIds(gwsiSiteIds, gwsiSiteRecords); END TRS*/
};
render() {
const CustomDiv = styled.div`
background-color: orange;
height: 0px;
width: 0px;
`;
return (
<div className="widget-BufferSelect jimu-widget m-2">
<p>
<b>
{this.props.intl.formatMessage({
id: 'widgetLabel',
defaultMessage: defaultMessages._widgetLabel,
})}
</b>
</p>
<b>LocalId or SiteId Selection</b>
<div style={{ width: 50 }}>
<form>
<div style={{ width: 200 }}>
{this.state.selectedBufferRows.map((values, id) => (
<TRSFormRow
key={id}
values={values}
onChange={(newValues: string[]) =>
this.onBufferRowChange(id, newValues)
}
/>
))}
<Button htmlType="button" onClick={() => this.onSearch()}>
Search
</Button>
<Button htmlType="reset" onClick={() => this.onClear()}>
Clear
</Button>
</div>
</form>
</div>
{/* Retrieve map view, if configured */}
{this.props.useMapWidgetIds?.length === 1 && !this.mapView && (
<JimuMapViewComponent
useMapWidgetId={this.props.useMapWidgetIds?.[0]}
onActiveViewChange={this.onActiveViewChange}
/>
)}
{/* Retrieve data sources, if configured */}
{this.props.useDataSources?.length >= 1 && !this.gwsiSiteDataSource && (
<DataSourceComponent
useDataSource={this.props.useDataSources[0]}
widgetId={this.props.id}
onDataSourceCreated={(dataSource) =>
this.onDataSourceCreated(
dataSource as FeatureLayerDataSource,
'gwsiSiteDataSource',
)
}
/>
)}
</div>
);
}
}