arcgis学习系列11--绘制不自己交叉的Polygon

概述

本文演示如何阻止用户使用Draw画子线交叉的线。

Draw操作使用视图事件生成一组坐标,可以从中创建不同类型的几何图形。每种几何类型都有一个对应的draw action类。实例化Draw之后,调用 draw.create()方法将返回一个draw Action的引用。

在这一篇文章中,draw.create()方法被调用,并传递polyline作为参数,我们监听PolylineDrawAction的相关事件实现自己的逻辑,即:组织用户绘制自相交叉的线。

// draw polyline button
document.getElementById("line-button").onclick = function() {
  view.graphics.removeAll();

  // creates and returns an instance of PolyLineDrawAction
  const action = draw.create("polyline");

  // focus the view to activate keyboard shortcuts for sketching
  view.focus();

  // listen polylineDrawAction events to give immediate visual feedback
  // to users as the line is being drawn on the view.
  action.on("vertex-add", updateVertices);
  action.on("vertex-remove", updateVertices);
  action.on("cursor-update", updateVertices);
  action.on("redo", updateVertices);
  action.on("undo", updateVertices);
  action.on("draw-complete", updateVertices);
};

完整代码

<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport"
          content="initial-scale=1,maximum-scale=1,user-scalable=no" />
    <!--
    ArcGIS API for JavaScript, https://js.arcgis.com
    For more information about the draw-line sample, read the original sample description at developers.arcgis.com.
    https://developers.arcgis.com/javascript/latest/sample-code/draw-line/index.html
    -->
    <title>Draw polyline - 4.11</title>

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

    <style>
        html,
        body,
        #viewDiv {
            height: 100%;
            width: 100%;
            margin: 0;
            padding: 0;
        }
    </style>

    <script>
      require([
        "esri/Map",
        "esri/views/MapView",
        "esri/views/draw/Draw",
        "esri/Graphic",
        "esri/geometry/geometryEngine"
      ], function(Map, MapView, Draw, Graphic, geometryEngine) {
        const map = new Map({
          basemap: "gray"
        });

        const view = new MapView({
          container: "viewDiv",
          map: map,
          zoom: 16,
          center: [18.06, 59.34]
        });

        // add the button for the draw tool
        view.ui.add("line-button", "top-left");

        const draw = new Draw({
          view: view
        });

        // draw polyline button
        document.getElementById("line-button").onclick = function() {
          view.graphics.removeAll();

          // creates and returns an instance of PolyLineDrawAction
          const action = draw.create("polyline");

          // focus the view to activate keyboard shortcuts for sketching
          view.focus();

          // listen polylineDrawAction events to give immediate visual feedback
          // to users as the line is being drawn on the view.
          action.on(
            [
              "vertex-add",
              "vertex-remove",
              "cursor-update",
              "redo",
              "undo",
              "draw-complete"
            ],
            updateVertices
          );
        };

        // Checks if the last vertex is making the line intersect itself.
        function updateVertices(event) {
          // create a polyline from returned vertices
          if (event.vertices.length > 1) {
            const result = createGraphic(event);

            // if the last vertex is making the line intersects itself,
            // prevent the events from firing
            if (result.selfIntersects) {
              event.preventDefault();
            }
          }
        }

        // create a new graphic presenting the polyline that is being drawn on the view
        function createGraphic(event) {
          const vertices = event.vertices;
          view.graphics.removeAll();

          // a graphic representing the polyline that is being drawn
          const graphic = new Graphic({
            geometry: {
              type: "polyline",
              paths: vertices,
              spatialReference: view.spatialReference
            },
            symbol: {
              type: "simple-line", // autocasts as new SimpleFillSymbol
              color: [4, 90, 141],
              width: 4,
              cap: "round",
              join: "round"
            }
          });

          // check if the polyline intersects itself.
          const intersectingSegment = getIntersectingSegment(graphic.geometry);

          // Add a new graphic for the intersecting segment.
          if (intersectingSegment) {
            view.graphics.addMany([graphic, intersectingSegment]);
          }
          // Just add the graphic representing the polyline if no intersection
          else {
            view.graphics.add(graphic);
          }

          // return intersectingSegment
          return {
            selfIntersects: intersectingSegment
          };
        }

        // function that checks if the line intersects itself
        function isSelfIntersecting(polyline) {
          if (polyline.paths[0].length < 3) {
            return false;
          }
          const line = polyline.clone();

          //get the last segment from the polyline that is being drawn
          const lastSegment = getLastSegment(polyline);
          line.removePoint(0, line.paths[0].length - 1);

          // returns true if the line intersects itself, false otherwise
          return geometryEngine.crosses(lastSegment, line);
        }

        // Checks if the line intersects itself. If yes, change the last
        // segment's symbol giving a visual feedback to the user.
        function getIntersectingSegment(polyline) {
          if (isSelfIntersecting(polyline)) {
            return new Graphic({
              geometry: getLastSegment(polyline),
              symbol: {
                type: "simple-line", // autocasts as new SimpleLineSymbol
                style: "short-dot",
                width: 3.5,
                color: "yellow"
              }
            });
          }
          return null;
        }

        // Get the last segment of the polyline that is being drawn
        function getLastSegment(polyline) {
          const line = polyline.clone();
          const lastXYPoint = line.removePoint(0, line.paths[0].length - 1);
          const existingLineFinalPoint = line.getPoint(
            0,
            line.paths[0].length - 1
          );

          return {
            type: "polyline",
            spatialReference: view.spatialReference,
            hasZ: false,
            paths: [
              [
                [existingLineFinalPoint.x, existingLineFinalPoint.y],
                [lastXYPoint.x, lastXYPoint.y]
              ]
            ]
          };
        }
      });
    </script>
</head>

<body>
    <div id="viewDiv">
        <div id="line-button"
             class="esri-widget esri-widget--button esri-interactive"
             title="Draw polyline">
            <span class="esri-icon-polyline"></span>
        </div>
    </div>
</body>
</html>

你可能感兴趣的:(arcgis,arcgis,polygon,不交叉)