I see a lot of examples of queries using a circle to find features within a given distance of a center point, but I have yet to be able to find an example of a query done using a feature to find all features within a given distance.
Can someone point me in the right direction? I'm sure it's very similar to a circle but something just isn't clicking in my head.
Thank you.
Solved! Go to Solution.
Here is a mashup of the Select with Feature Layer and Geometry Service - Buffer samples. It querys the census block layer and buffers the results and uses that buffer to query census block points that intersect the buffer.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
<title>Select with feature layer</title>
<link rel="stylesheet" href="https://js.arcgis.com/3.35/dijit/themes/tundra/tundra.css">
<link rel="stylesheet" href="https://js.arcgis.com/3.35/esri/css/esri.css">
<style>
html, body, #mapDiv {
padding: 0;
margin: 0;
height: 100%;
}
#messages{
background-color: #fff;
box-shadow: 0 0 5px #888;
font-size: 1.1em;
max-width: 15em;
padding: 0.5em;
position: absolute;
right: 20px;
top: 20px;
z-index: 40;
}
</style>
<script src="https://js.arcgis.com/3.35/"></script>
<script>
var map;
require([
"esri/map", "esri/layers/FeatureLayer",
"esri/tasks/query", "esri/tasks/GeometryService",
"esri/tasks/BufferParameters",
"esri/graphic", "esri/symbols/SimpleMarkerSymbol",
"esri/symbols/SimpleLineSymbol", "esri/symbols/SimpleFillSymbol", "esri/renderers/SimpleRenderer",
"esri/config", "esri/Color", "dojo/dom", "dojo/domReady!"
], function(
Map, FeatureLayer,
Query, GeometryService, BufferParameters,
Graphic, SimpleMarkerSymbol,
SimpleLineSymbol, SimpleFillSymbol, SimpleRenderer,
esriConfig, Color, dom
) {
esriConfig.defaults.geometryService = new GeometryService("https://utility.arcgisonline.com/ArcGIS/rest/services/Geometry/GeometryServer");
map = new Map("mapDiv", {
basemap: "streets",
center: [-95.249, 38.954],
zoom: 14,
slider: false
});
// Add the census block points in on demand mode. An outfield is specified since it is used when calculating the total population falling within the one mile radius.
var featureLayer = new FeatureLayer("https://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer/0",{
outFields: ["POP2000"]
});
// census block polygon layer
var featureLayer2 = new FeatureLayer("https://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer/1",{
outFields: ["FIPS"]
});
// Selection symbol used to draw the selected census block points within the buffer polygon
var symbol = new SimpleMarkerSymbol(
SimpleMarkerSymbol.STYLE_CIRCLE,
12,
new SimpleLineSymbol(
SimpleLineSymbol.STYLE_NULL,
new Color([247, 34, 101, 0.9]),
1
),
new Color([207, 34, 171, 0.5])
);
featureLayer.setSelectionSymbol(symbol);
// Make unselected features invisible
var nullSymbol = new SimpleMarkerSymbol().setSize(0);
featureLayer.setRenderer(new SimpleRenderer(nullSymbol));
map.addLayer(featureLayer);
var blockSymb = new SimpleFillSymbol(
SimpleFillSymbol.STYLE_NULL,
new SimpleLineSymbol(
SimpleLineSymbol.STYLE_SHORTDASHDOTDOT,
new Color([105, 105, 105]),
2
), new Color([255, 255, 0, 0.25])
);
var block, buffer;
//setup the buffer parameters
var params = new BufferParameters();
params.distances = [0.5];
params.outSpatialReference = map.spatialReference;
params.unit = GeometryService["UNIT_STATUTE_MILE"];
setTimeout(function(){
var query2 = new Query();
query2.where = "FIPS = '200450004001'";
query2.returnGeometry = true;
query2.outSpatialReference = map.spatialReference;
featureLayer2.queryFeatures(query2, function(response){
map.graphics.clear();
block = response.features[0].geometry;
var graphic = new Graphic(block, blockSymb);
map.graphics.add(graphic);
params.geometries = [block];
esriConfig.defaults.geometryService.buffer(params, showBuffer);
});
}, 2000);
function showBuffer(bufferedGeometries){
var symbol = new SimpleFillSymbol(
SimpleFillSymbol.STYLE_NULL,
new SimpleLineSymbol(
SimpleLineSymbol.STYLE_SOLID,
new Color([255,0,0,0.65]), 2
),
new Color([255,0,0,0.35])
);
buffer = bufferedGeometries[0];
var graphic = new Graphic(buffer, symbol);
map.graphics.add(graphic);
var query = new Query();
query.geometry = buffer.getExtent();
featureLayer.queryFeatures(query, selectInBuffer);
}
function selectInBuffer(response){
var feature;
var features = response.features;
var inBuffer = [];
// Filter out features that are not actually in buffer, since we got all points in the buffer's bounding box
for (var i = 0; i < features.length; i++) {
feature = features[i];
if(buffer.contains(feature.geometry)){
inBuffer.push(feature.attributes[featureLayer.objectIdField]);
}
}
var query = new Query();
query.objectIds = inBuffer;
// Use an objectIds selection query (should not need to go to the server)
featureLayer.selectFeatures(query, FeatureLayer.SELECTION_NEW, function(results){
var totalPopulation = sumPopulation(results);
var r = "";
r = "<b>The total Census Block population within the Census Block buffered by .5 mi is <i>" + totalPopulation + "</i>.</b>";
dom.byId("messages").innerHTML = r;
});
}
function sumPopulation(features) {
var popTotal = 0;
for (var x = 0; x < features.length; x++) {
popTotal = popTotal + features[x].attributes["POP2000"];
}
return popTotal;
}
});
</script>
</head>
<body>
<span id="messages">Wait for FIPS = '200450004001' Query to execute...</span>
<div id="mapDiv"></div>
</body>
</html>
Here is a mashup of the Select with Feature Layer and Geometry Service - Buffer samples. It querys the census block layer and buffers the results and uses that buffer to query census block points that intersect the buffer.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
<title>Select with feature layer</title>
<link rel="stylesheet" href="https://js.arcgis.com/3.35/dijit/themes/tundra/tundra.css">
<link rel="stylesheet" href="https://js.arcgis.com/3.35/esri/css/esri.css">
<style>
html, body, #mapDiv {
padding: 0;
margin: 0;
height: 100%;
}
#messages{
background-color: #fff;
box-shadow: 0 0 5px #888;
font-size: 1.1em;
max-width: 15em;
padding: 0.5em;
position: absolute;
right: 20px;
top: 20px;
z-index: 40;
}
</style>
<script src="https://js.arcgis.com/3.35/"></script>
<script>
var map;
require([
"esri/map", "esri/layers/FeatureLayer",
"esri/tasks/query", "esri/tasks/GeometryService",
"esri/tasks/BufferParameters",
"esri/graphic", "esri/symbols/SimpleMarkerSymbol",
"esri/symbols/SimpleLineSymbol", "esri/symbols/SimpleFillSymbol", "esri/renderers/SimpleRenderer",
"esri/config", "esri/Color", "dojo/dom", "dojo/domReady!"
], function(
Map, FeatureLayer,
Query, GeometryService, BufferParameters,
Graphic, SimpleMarkerSymbol,
SimpleLineSymbol, SimpleFillSymbol, SimpleRenderer,
esriConfig, Color, dom
) {
esriConfig.defaults.geometryService = new GeometryService("https://utility.arcgisonline.com/ArcGIS/rest/services/Geometry/GeometryServer");
map = new Map("mapDiv", {
basemap: "streets",
center: [-95.249, 38.954],
zoom: 14,
slider: false
});
// Add the census block points in on demand mode. An outfield is specified since it is used when calculating the total population falling within the one mile radius.
var featureLayer = new FeatureLayer("https://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer/0",{
outFields: ["POP2000"]
});
// census block polygon layer
var featureLayer2 = new FeatureLayer("https://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer/1",{
outFields: ["FIPS"]
});
// Selection symbol used to draw the selected census block points within the buffer polygon
var symbol = new SimpleMarkerSymbol(
SimpleMarkerSymbol.STYLE_CIRCLE,
12,
new SimpleLineSymbol(
SimpleLineSymbol.STYLE_NULL,
new Color([247, 34, 101, 0.9]),
1
),
new Color([207, 34, 171, 0.5])
);
featureLayer.setSelectionSymbol(symbol);
// Make unselected features invisible
var nullSymbol = new SimpleMarkerSymbol().setSize(0);
featureLayer.setRenderer(new SimpleRenderer(nullSymbol));
map.addLayer(featureLayer);
var blockSymb = new SimpleFillSymbol(
SimpleFillSymbol.STYLE_NULL,
new SimpleLineSymbol(
SimpleLineSymbol.STYLE_SHORTDASHDOTDOT,
new Color([105, 105, 105]),
2
), new Color([255, 255, 0, 0.25])
);
var block, buffer;
//setup the buffer parameters
var params = new BufferParameters();
params.distances = [0.5];
params.outSpatialReference = map.spatialReference;
params.unit = GeometryService["UNIT_STATUTE_MILE"];
setTimeout(function(){
var query2 = new Query();
query2.where = "FIPS = '200450004001'";
query2.returnGeometry = true;
query2.outSpatialReference = map.spatialReference;
featureLayer2.queryFeatures(query2, function(response){
map.graphics.clear();
block = response.features[0].geometry;
var graphic = new Graphic(block, blockSymb);
map.graphics.add(graphic);
params.geometries = [block];
esriConfig.defaults.geometryService.buffer(params, showBuffer);
});
}, 2000);
function showBuffer(bufferedGeometries){
var symbol = new SimpleFillSymbol(
SimpleFillSymbol.STYLE_NULL,
new SimpleLineSymbol(
SimpleLineSymbol.STYLE_SOLID,
new Color([255,0,0,0.65]), 2
),
new Color([255,0,0,0.35])
);
buffer = bufferedGeometries[0];
var graphic = new Graphic(buffer, symbol);
map.graphics.add(graphic);
var query = new Query();
query.geometry = buffer.getExtent();
featureLayer.queryFeatures(query, selectInBuffer);
}
function selectInBuffer(response){
var feature;
var features = response.features;
var inBuffer = [];
// Filter out features that are not actually in buffer, since we got all points in the buffer's bounding box
for (var i = 0; i < features.length; i++) {
feature = features[i];
if(buffer.contains(feature.geometry)){
inBuffer.push(feature.attributes[featureLayer.objectIdField]);
}
}
var query = new Query();
query.objectIds = inBuffer;
// Use an objectIds selection query (should not need to go to the server)
featureLayer.selectFeatures(query, FeatureLayer.SELECTION_NEW, function(results){
var totalPopulation = sumPopulation(results);
var r = "";
r = "<b>The total Census Block population within the Census Block buffered by .5 mi is <i>" + totalPopulation + "</i>.</b>";
dom.byId("messages").innerHTML = r;
});
}
function sumPopulation(features) {
var popTotal = 0;
for (var x = 0; x < features.length; x++) {
popTotal = popTotal + features[x].attributes["POP2000"];
}
return popTotal;
}
});
</script>
</head>
<body>
<span id="messages">Wait for FIPS = '200450004001' Query to execute...</span>
<div id="mapDiv"></div>
</body>
</html>