Overview
You will learn: how to perform buffer, intersect and distance calculations using the geometry engine.
The geometry engine and the ArcGIS Geometry Service can be used to perform sophisticated spatial operations with geometry such as buffering, projecting, simplification, calculating distance and area, and determining spatial relationships. The geometry engine performs all of its operations client-side and can be used to build high performance and highly interactive applications. The ArcGIS Geometry Service performs all of the same operations as the geometry engine, with the addition of being able to project geometries and perform geometric operations in different spatial references. You can use the geometryEngine class for synchronous operations and the GeometryEngineAsync class for asynchronous operations, while the ArcGIS Geometry Service only works asynchronously. To learn more about all of the possible geometric operations, please visit the documentation.
In this tutorial you will use the geometry engine to buffer, intersect and calculate distances between points.
Steps
Create a starter app
Go to the JavaScript Starter App.
In CodePen, click Fork and save the pen as
ArcGIS DevLabs: Buffer and intersect geometry
.
Create a point
In this step you will load the required modules for the application and create a point that represents the location for Malibu, California. This point will be used to for the geometric calculations in later steps.
In the
require
statement, add the Point, Graphic and geometryEngine module. The Graphic and geometryEngine module will be used later.require([ "esri/Map", "esri/views/MapView", //*** ADD ***// "esri/geometry/Point", "esri/Graphic", "esri/geometry/geometryEngine" ], function(Map, MapView, Point, Graphic, geometryEngine ) {
In the main
function
, declare amalibuPoint
variable and create it when the View is ready.//*** ADD ***// var malibuPoint; view.when(function(){ malibuPoint = new Point({ latitude: 34.03539, longitude: -118.68634, spatialReference: view.spatialReference }); });
Run the app to ensure there are no errors.
Create a buffer
In this step you will create and display a ten mile buffer graphic every time the cursor moves.
In the main
function
, create abufferGraphic
variable and add code to listen to when the pointer moves over the View. Create a point and use the geometryEnginebuffer
function to create a ten mile buffer and then add it to the map as a graphic.//*** ADD ***// var bufferGraphic; //*** ADD ***// view.on("pointer-move", function(event){ // Buffer the point var point = view.toMap(event); var buffer = geometryEngine.buffer(point, 10, "miles"); // Draw the buffer view.graphics.remove(bufferGraphic); // Remove graphic bufferGraphic = new Graphic({ geometry: buffer, symbol: { type: "simple-fill", color: "rgba(0,0,0,.15)", outline: { color: "green", width: 2 } } }); view.graphics.add(bufferGraphic); // Add graphic });
Add code to listen for the
drag
event and useStopPropagation
to prevent the map from panning as you move the mouse or your finger on the map. Clear all graphics when the pointer leaves the map.//*** ADD ***// view.on("drag", function(){ // Prevent panning event.stopPropagation(); }); //*** ADD ***// view.on("pointer-leave", function(){ view.graphics.removeAll(); });
Run the app and move your mouse on the map. You should see a buffer appear as you move.
Intersect a point with a polygon
In this step you will determine if the malibuPoint
intersects with the buffer (polygon), and if it does, you will change the border color accordingly.
In the same function, add code to use the geometryEngine
intersects
function to determine if themalibuPoint
and buffer intersect. If they do, change the symbol color of the buffer to red.view.on("pointer-move", function(event){ // Buffer the point var point = view.toMap(event); var buffer = geometryEngine.buffer(point, 10, "miles"); //*** ADD ***// var intersects = geometryEngine.intersects(malibuPoint, buffer); // Draw the buffer green or red (if it intersects) view.graphics.remove(bufferGraphic); // Add graphic bufferGraphic = new Graphic({ geometry: buffer, symbol: { type: "simple-fill", color: "rgba(0,0,0,.15)", outline: { //*** ADD ***// color: intersects ? "red" : "green", width: 2 } } }); view.graphics.add(bufferGraphic); // Remove graphic });
Run the app and move your cursor over Malibu. You should see the buffer outline turn red when they intersect.
Calculate distance
In this step you will create a line to show the "line of sight" distance between the cursor and Malibu.
In the
pointer-move
function, add code to create a line graphic and draw a line from the cursor to themalibuPoint
.//*** ADD ***// var lineGraphic; view.on("pointer-move", function(event){ ... //*** ADD ***// // Draw line between points view.graphics.remove(lineGraphic); lineGraphic = new Graphic({ geometry: { type: "polyline", paths: [ [point.longitude, point.latitude], [malibuPoint.longitude, malibuPoint.latitude] ] }, symbol: { type: "simple-line", color: "#333", width: 1 } }); view.graphics.add(lineGraphic); });
In the
pointer-move
function, add code to create text graphic and use the geometryEnginedistance
function to calculate how far the cursor is from themalibuPoint
and add the distance to the map.//*** ADD ***// var textGraphic; view.on("pointer-move", function(event){ ... //*** ADD ***// // Draw a text label to show distance var distance = geometryEngine.distance(point, malibuPoint,"miles"); view.graphics.remove(textGraphic); textGraphic = new Graphic({ geometry: point, symbol: { type: "text", text: distance.toFixed(2) + " miles", color: "black", font: { size: 12 } } }); view.graphics.add(textGraphic) });
Run the app and move your cursor around the map. You should see a line and the distance draw on the map.
Congratulations, you're done!
Your app should look something like this.
Challenge
Densify the buffer and find the nearest point
You can add or remove points to any geometry by using the densify
function. Use this function to add points every 250 meters around the buffer. Next, use the nearestVertex
function to find the closest vertex in the buffer to the malibuPoint
. Add the nearest vertex (point) as a graphic to the map after the buffer draws.
//*** ADD ***//
var nearestPointGraphic;
view.on("pointer-move", function(event){
event.stopPropagation();
// Buffer the point
var point = view.toMap(event);
var buffer = geometryEngine.buffer(point, 10, "miles");
//*** ADD ***//
buffer = geometryEngine.densify(buffer, 250, "meters");
...
//*** ADD ***//
var nearestPoint = geometryEngine.nearestVertex(buffer, malibuPoint);
view.graphics.remove(nearestPointGraphic);
nearestPointGraphic = new Graphic({
geometry: nearestPoint.coordinate,
symbol: {
type: "simple-marker",
color: "black",
size: 6,
outline: {
color: "white",
width: 1
}
}
});
view.graphics.add(nearestPointGraphic);
});
Perform geodesic calculations
Geodesic calculations take into consideration the curvature of the earth and provide highly accurate results. Try replacing the buffer
and distance
functions with the geodesicBuffer
and geodesicLength
functions and compare the results. Visit the documentation to see what other geodesic functions are available.
NOTE: Geodesic functions only work with WGS84 and Web Mercator spatial references. Use the ArcGIS Geometry Service if you need to work in a different spatial reference.
//*** Add ***//
var buffer = geometryEngine.geodesicBuffer(point, 500, "meters");
...
//*** Add ***//
var distance = geometryEngine.geodesicLength(point, malibuPoint,"miles");