create polygon with x,y coordinate and edit it via sketchviewmodel

2459
27
Jump to solution
02-26-2020 11:32 PM
rsharma
Occasional Contributor III

I need to display and edit polygon but problem is in updatesketchview model they are using different coordinates format like this:

0 Kudos
1 Solution

Accepted Solutions
RobertScheitlin__GISP
MVP Esteemed Contributor

Rajni,

  To update a graphic using SketchViewModel, the graphic has to be in the same SpatialReference as the map. So in this case you use WebMercatorUtils to project the polygon to webmercator before you add it to the map.

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
  <title>Intro to MapView - Create a 2D map - 4.14</title>
  <style>
    html,
    body,
    #viewDiv {
      padding: 0;
      margin: 0;
      height: 100%;
      width: 100%;
    }
  </style>

  <link rel="stylesheet" href="https://js.arcgis.com/4.14/esri/themes/light/main.css" />
  <script src="https://js.arcgis.com/4.14/"></script>

  <script>
    require(["esri/views/MapView",
      "esri/WebMap",
      "esri/Graphic",
      "esri/layers/GraphicsLayer",
      "esri/widgets/Sketch/SketchViewModel",
      "esri/geometry/Polygon",
      "esri/geometry/SpatialReference",
      "esri/geometry/support/webMercatorUtils"
    ], function (MapView, WebMap, Graphic, GraphicsLayer, SketchViewModel, Polygon, SpatialReference, webMercatorUtils) {

      let sketchViewModel,
        validSymbol,
        newDevelopmentGraphic;
      /************************************************************
       * Creates a new WebMap instance. A WebMap must reference
       * a PortalItem ID that represents a WebMap saved to
       * arcgis.com or an on-premise portal.
       *
       * To load a WebMap from an on-premise portal, set the portal
       * url with esriConfig.portalUrl.
       ************************************************************/
      var webmap = new WebMap({
        portalItem: {
          // autocasts as new PortalItem()
          id: "a8e76ad6641b46978f148cba03ab3e2d"
        }
      });

      /************************************************************
       * Set the WebMap instance to the map property in a MapView.
       ************************************************************/
      var view = new MapView({
        map: webmap,
        container: "viewDiv",
        center: [175.9258624, -37.55590445],
        zoom: 20
      });

      var graphicsLayer = new GraphicsLayer();
      webmap.add(graphicsLayer);

      setUpGraphicClickHandler();

      view.when(function () {
        // Add the boundary polygon and new lot polygon graphics
        addGraphics();

        // Create a new instance of sketchViewModel
        sketchViewModel = new SketchViewModel({
          view: view,
          layer: graphicsLayer,
          updateOnGraphicClick: false,
          defaultUpdateOptions: {
            // set the default options for the update operations
            toggleToolOnClick: false // only reshape operation will be enabled
          }
        });

        // Listen to sketchViewModel's update event to do
        // graphic reshape or move validation
        sketchViewModel.on(["update", "undo", "redo"], onGraphicUpdate);
      });

      function onGraphicUpdate(event) {
        // get the graphic as it is being updated
        const graphic = event.graphics[0];

        // check if the update event's the toolEventInfo.type is move-stop or reshape-stop
        // then it means user finished moving or reshaping the graphic, call complete method.
        // this will change update event state to complete and we will check the validity of the graphic location.
        if (
          event.toolEventInfo &&
          (event.toolEventInfo.type === "move-stop" ||
            event.toolEventInfo.type === "reshape-stop")
        ) {
          sketchViewModel.complete();
        } else if (event.state === "cancel" || event.state === "complete") {
          // graphic moving or reshaping has been completed or cancelled
          // if the graphic is in an illegal spot, call sketchviewmodel's update method again
          // giving user a chance to correct the location of the graphic
          sketchViewModel.update([graphic], {
            tool: "reshape"
          });
        }
      }

      // This function is called when a user clicks on the view.
      function setUpGraphicClickHandler() {
        view.on("click", function (event) {
          // check if the sketch's state active if it is then that means
          // the graphic is already being updated, no action required.
          if (sketchViewModel.state === "active") {
            return;
          }
          view.hitTest(event).then(function (response) {
            var results = response.results;
            // Check if the new development graphic was clicked and pass
            // the graphic to sketchViewModel.update() with reshape tool.
            //console.log(results);
            results.forEach(function (result) {
              console.log(result.mapPoint);
              if (
                result.graphic.layer === sketchViewModel.layer &&
                result.graphic.attributes &&
                result.graphic.attributes.newDevelopment
              ) {
                sketchViewModel.update([result.graphic], {
                  tool: "reshape"
                });
              }
            });
          });
        });
      }

      function addGraphics() {
        const vertices = [
          [175.9258624, -37.55590445],
          [175.9258630667, -37.55587745],
          [175.9258671333, -37.5557153],
          [175.92626316670004, -37.5557216],
          [175.92625955, -37.5558657],
          [175.9262584333, -37.5559107333],
          [175.9258624, -37.55590445]
        ];

        const polygon = createGeometry(vertices);
        validSymbol = createSymbol([0, 170, 255, 0.8], "solid", 2, [
          255,
          255,
          255
        ]);
        newDevelopmentGraphic = new Graphic({
          geometry: webMercatorUtils.geographicToWebMercator(polygon),
          symbol: validSymbol,
          attributes: {
            newDevelopment: "new store"
          }
        });
        graphicsLayer.add(newDevelopmentGraphic);
      }

      function createGeometry(vertices) {
        return new Polygon({
          rings: vertices,
          spatialReference: new SpatialReference({
            wkid: 4326
          })
        });
      }

      function createSymbol(color, style, width, outlineColor) {
        return {
          type: "simple-fill",
          style: style,
          color: color,
          outline: {
            color: outlineColor,
            width: width
          }
        };
      }
    });
  </script>
</head>

<body>
  <div id="viewDiv"></div>
</body>

</html>

View solution in original post

27 Replies
RobertScheitlin__GISP
MVP Esteemed Contributor

Rajni,

   The issue is that you are using Lat Long coordinates but when you specify the geometries spatialReference you use the view.spatialReference which is web mercator (line 4).

        function createGeometry(vertices) {
          return new Polygon({
            rings: vertices,
            spatialReference: view.spatialReference
          });
        }

You need to specify the spatialReference as {wkid:4326}

        function createGeometry(vertices) {
          return new Polygon({
            rings: vertices,
            spatialReference: new SpatialReference({wkid:4326})
          });
        }‍‍‍‍‍‍
rsharma
Occasional Contributor III

Hi Robert,

   Thanks for the reply, finally i got a reply from this community, i have already tried it, but it didn't show my polygon on my coordinates, but if i comment this line, it show uneditable polygon

// spatialReference: new SpatialReference({wkid:4326})

My task :I have to display property boundary with x,y coordinates, edit it and  then save editedable
polygon coordinates in my websites db or any other place apart from that user can also draw polygon dynamically
 Ex:hazard zone near boundary , i have to save that also
Could you pls guide me, if there is any other way that i could try.
From the below code i am able to only display my property boundary from linz db.
Now i have to make it editable and save it.

0 Kudos
rsharma
Occasional Contributor III

I tried to solve above code with updatesketchview model, but it do not help. Please help . Please help if am going in wrong direction to solve my problem

0 Kudos
RobertScheitlin__GISP
MVP Esteemed Contributor

Rajni,

   To be able to use a new class constructor (i.e. new SpatialReference) you will have to add the module to your require array.

require(["esri/views/MapView", 
        "esri/WebMap",
         "esri/Graphic",
        "esri/layers/GraphicsLayer",
        "esri/widgets/Sketch",
        "esri/geometry/SpatialReference"
       ], function(MapView, WebMap, Graphic, GraphicsLayer, Sketch, SpatialReference) {
...
rsharma
Occasional Contributor III

Ok Robert, i follow your steps, now my polygon is visible, but it is not editable, how can  i edit it ,  if i click on it. Please find below updated code

0 Kudos
RobertScheitlin__GISP
MVP Esteemed Contributor

Rajni,

  To update a graphic using SketchViewModel, the graphic has to be in the same SpatialReference as the map. So in this case you use WebMercatorUtils to project the polygon to webmercator before you add it to the map.

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
  <title>Intro to MapView - Create a 2D map - 4.14</title>
  <style>
    html,
    body,
    #viewDiv {
      padding: 0;
      margin: 0;
      height: 100%;
      width: 100%;
    }
  </style>

  <link rel="stylesheet" href="https://js.arcgis.com/4.14/esri/themes/light/main.css" />
  <script src="https://js.arcgis.com/4.14/"></script>

  <script>
    require(["esri/views/MapView",
      "esri/WebMap",
      "esri/Graphic",
      "esri/layers/GraphicsLayer",
      "esri/widgets/Sketch/SketchViewModel",
      "esri/geometry/Polygon",
      "esri/geometry/SpatialReference",
      "esri/geometry/support/webMercatorUtils"
    ], function (MapView, WebMap, Graphic, GraphicsLayer, SketchViewModel, Polygon, SpatialReference, webMercatorUtils) {

      let sketchViewModel,
        validSymbol,
        newDevelopmentGraphic;
      /************************************************************
       * Creates a new WebMap instance. A WebMap must reference
       * a PortalItem ID that represents a WebMap saved to
       * arcgis.com or an on-premise portal.
       *
       * To load a WebMap from an on-premise portal, set the portal
       * url with esriConfig.portalUrl.
       ************************************************************/
      var webmap = new WebMap({
        portalItem: {
          // autocasts as new PortalItem()
          id: "a8e76ad6641b46978f148cba03ab3e2d"
        }
      });

      /************************************************************
       * Set the WebMap instance to the map property in a MapView.
       ************************************************************/
      var view = new MapView({
        map: webmap,
        container: "viewDiv",
        center: [175.9258624, -37.55590445],
        zoom: 20
      });

      var graphicsLayer = new GraphicsLayer();
      webmap.add(graphicsLayer);

      setUpGraphicClickHandler();

      view.when(function () {
        // Add the boundary polygon and new lot polygon graphics
        addGraphics();

        // Create a new instance of sketchViewModel
        sketchViewModel = new SketchViewModel({
          view: view,
          layer: graphicsLayer,
          updateOnGraphicClick: false,
          defaultUpdateOptions: {
            // set the default options for the update operations
            toggleToolOnClick: false // only reshape operation will be enabled
          }
        });

        // Listen to sketchViewModel's update event to do
        // graphic reshape or move validation
        sketchViewModel.on(["update", "undo", "redo"], onGraphicUpdate);
      });

      function onGraphicUpdate(event) {
        // get the graphic as it is being updated
        const graphic = event.graphics[0];

        // check if the update event's the toolEventInfo.type is move-stop or reshape-stop
        // then it means user finished moving or reshaping the graphic, call complete method.
        // this will change update event state to complete and we will check the validity of the graphic location.
        if (
          event.toolEventInfo &&
          (event.toolEventInfo.type === "move-stop" ||
            event.toolEventInfo.type === "reshape-stop")
        ) {
          sketchViewModel.complete();
        } else if (event.state === "cancel" || event.state === "complete") {
          // graphic moving or reshaping has been completed or cancelled
          // if the graphic is in an illegal spot, call sketchviewmodel's update method again
          // giving user a chance to correct the location of the graphic
          sketchViewModel.update([graphic], {
            tool: "reshape"
          });
        }
      }

      // This function is called when a user clicks on the view.
      function setUpGraphicClickHandler() {
        view.on("click", function (event) {
          // check if the sketch's state active if it is then that means
          // the graphic is already being updated, no action required.
          if (sketchViewModel.state === "active") {
            return;
          }
          view.hitTest(event).then(function (response) {
            var results = response.results;
            // Check if the new development graphic was clicked and pass
            // the graphic to sketchViewModel.update() with reshape tool.
            //console.log(results);
            results.forEach(function (result) {
              console.log(result.mapPoint);
              if (
                result.graphic.layer === sketchViewModel.layer &&
                result.graphic.attributes &&
                result.graphic.attributes.newDevelopment
              ) {
                sketchViewModel.update([result.graphic], {
                  tool: "reshape"
                });
              }
            });
          });
        });
      }

      function addGraphics() {
        const vertices = [
          [175.9258624, -37.55590445],
          [175.9258630667, -37.55587745],
          [175.9258671333, -37.5557153],
          [175.92626316670004, -37.5557216],
          [175.92625955, -37.5558657],
          [175.9262584333, -37.5559107333],
          [175.9258624, -37.55590445]
        ];

        const polygon = createGeometry(vertices);
        validSymbol = createSymbol([0, 170, 255, 0.8], "solid", 2, [
          255,
          255,
          255
        ]);
        newDevelopmentGraphic = new Graphic({
          geometry: webMercatorUtils.geographicToWebMercator(polygon),
          symbol: validSymbol,
          attributes: {
            newDevelopment: "new store"
          }
        });
        graphicsLayer.add(newDevelopmentGraphic);
      }

      function createGeometry(vertices) {
        return new Polygon({
          rings: vertices,
          spatialReference: new SpatialReference({
            wkid: 4326
          })
        });
      }

      function createSymbol(color, style, width, outlineColor) {
        return {
          type: "simple-fill",
          style: style,
          color: color,
          outline: {
            color: outlineColor,
            width: width
          }
        };
      }
    });
  </script>
</head>

<body>
  <div id="viewDiv"></div>
</body>

</html>
rsharma
Occasional Contributor III

Thanks Robert for being so patient and helpful to me, you are a life saver. As i was stuck in the task from the last  1 week, Besides this can you please tell me about any event or function like on mouse click up to get coordinates of polygon  ring vertices , when we edit it (to save it in my db), So that next time when i login to my app it gave me same editable polygon.

Any example will be helpful.

Thanks in advance.

0 Kudos
RobertScheitlin__GISP
MVP Esteemed Contributor

Rajni,

   Think carefully of you exact workflow (that would not interfere with standard editing of the polygon). I am not sure how a click event would work for what you want.

0 Kudos
rsharma
Occasional Contributor III

Robert , i just want updated vertices when the user reshape the polygon which i draw it for him through sketchviewmodel. is there any function to get updated vertices when polygon reshapes

0 Kudos