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 lab you will use the geometry engine to buffer, intersect and calculate distances between points.

Steps

Create a starter app

  1. Go to the JavaScript Starter App.

  2. 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.

  1. 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",
      "dojo/domReady!"
      //*** ADD ***//
    ], function(Map, MapView, Point, Graphic, geometryEngine
    ) {
    
  2. In the main function, declare a malibuPoint 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
        });
      });
    
  3. 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.

  1. In the main function, create a bufferGraphic variable and add code to listen to when the pointer moves over the View. Create a point and use the geometryEngine buffer 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
      });
    
  2. Add code to listen for the drag event and use StopPropagation 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();
      });
    
  3. 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.

  1. In the same function, add code to use the geometryEngine intersects function to determine if the malibuPoint 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
      });
    
  2. 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.

  1. In the pointer-move function, add code to create a line graphic and draw a line from the cursor to the malibuPoint.

      //*** 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);
      });
    
  2. In the pointer-move function, add code to create text graphic and use the geometryEngine distance function to calculate how far the cursor is from the malibuPoint 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)
      });
    
  3. 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");