查找长度和面积

字数统计: 2.3k
阅读时长: 约 6 分钟
当前版本: 4.29

了解如何计算几何的长度和面积。

geometryEngine 提供了计算线长度和面积的功能。几何定义的坐标系 (或空间参考)影响测量结果。如果几何的空间参考是 Web Mercator (3857) 或 WGS84 (4326),则应使用大地测量学方式计算,考虑地球的曲率。如果空间参考与 Web Mercator (3857) 或 WGS84 (4326) 不同,是平面坐标系,则应使用基于欧氏距离。

在本教程中,我们使用 Sketch 微件在视图上绘制图形,并使用 geometryEngine 来计算测地线和平面长度及面积,以查看两个测量值之间的差异。

注: 了解有关使用 Measurement 微件执行测量的更多信息,请访问参考手册

步骤

创建新 Pen

  1. 开始之前,先完成显示地图教程

设置 HTML

  1. 创建 measurements div 用于显示计算结果,为其添加一些 CSS 样式来设置字体大小和边距。

    html
            #viewDiv {
                padding: 0;
                margin: 0;
                height: 100%;
                width: 100%;
            }
    
            #measurements {
                padding: 4px 8px;
                font-size: 16px;
                bottom: 15px;
                left: 50%;
                margin-right: -50%;
                transform: translate(-50%,-50%);
            }
    
        </style>
    
        <link rel="stylesheet" href="https://js.geoscene.cn/4.29/geoscene/themes/light/main.css">
        <script src="https://js.geoscene.cn/4.29/"></script>
        <script>
            require([
                "geoscene/config",
                "geoscene/Map",
                "geoscene/views/MapView"
                ], (
                    geosceneConfig,
                    Map,
                    MapView,
                ) => {
    
                    const map = new Map({
                        basemap: "tianditu-vector", // Basemap layer service
                    });
    
                    const view = new MapView({
                        container: "viewDiv",
                        map: map,
    
                    });
        </script>
    </head>
    <body>
        <div id="viewDiv">
    
        <div id="measurements" class="geoscene-widget">

添加模块

  1. require 语句中,添加模块。

    GeoScene Maps SDK for JavaScript 提供了 AMD 模块ES 模块,本教程中我们是以 AMD 为例。指定 "geoscene/Map" 来加载 Map 模块。加载模块后,它们将作为参数 (例如,Map) 传递给回调函数,以便在应用程序中使用。保持模块引用和回调参数的顺序相同是很重要的。有关不同类型模块的更多信息,请访问工具指南主题。

    html
        <link rel="stylesheet" href="https://js.geoscene.cn/4.29/geoscene/themes/light/main.css">
        <script src="https://js.geoscene.cn/4.29/"></script>
        <script>
            require([
                "geoscene/config",
                "geoscene/Map",
                "geoscene/views/MapView",
    
                "geoscene/widgets/ScaleBar",
                "geoscene/widgets/Sketch",
                "geoscene/Graphic",
                "geoscene/layers/GraphicsLayer",
                "geoscene/geometry/geometryEngine",
    
            ], (
                geosceneConfig,
                Map,
                MapView,
    
                ScaleBar,
                Sketch,
                Graphic,
                GraphicsLayer,
                geometryEngine,
    
            ) => {
    
                const map = new Map({
                    basemap: "tianditu-vector", // Basemap layer service
                });
    
                const view = new MapView({
                    container: "viewDiv",
                    map: map,

重定位并添加比例尺

ScaleBar 微件将在地图上显示比例尺。您可以选择公制或非公制值。例如,如果指定 metric,则会根据比例显示公里或米。

  1. 更改 viewcenterzoom 级别。

    js
        const view = new MapView({
            container: "viewDiv",
            map: map,
    
            center: [-10, 30],
            zoom: 3,
    
        });
  2. 创建 scalebar 并将 view 参数设置为 view。将 unit 指定为 metric

    js
            center: [-10, 30],
            zoom: 3,
    
        });
    
        const scalebar = new ScaleBar({
            view: view,
            unit: "metric"
        });
  3. scalebar 添加至 viewbottom-right

    js
            center: [-10, 30],
            zoom: 3,
    
        });
    
        const scalebar = new ScaleBar({
            view: view,
            unit: "metric"
        });
    
        view.ui.add(scalebar, "bottom-right");
  4. 运行应用程序以验证 centerzoom 级别中的更改。scalebar 应显示在视图的底部。

添加草绘微件

Sketch 微件提供的 UI 允许您在 MapView 中创建和更新图形。

  1. 创建 graphicsLayer ,将 GraphicsLayer 添加到 map

    js
        const scalebar = new ScaleBar({
            view: view,
            unit: "metric"
        });
    
        view.ui.add(scalebar, "bottom-right");
    
        const graphicsLayer = new GraphicsLayer();
        map.add(graphicsLayer);
  2. 创建 sketch 微件, layer 参数设置为 graphicsLayer。这样使用微件绘制的任何几何都将添加到 graphicsLayer 中。设置一些属性控制要素的显示,availableCreateTools 设置为仅显示 polylinepolygonrectangle ,禁用在 visibleElementsselectionTools 的默认值。

    js
        const scalebar = new ScaleBar({
            view: view,
            unit: "metric"
        });
    
        view.ui.add(scalebar, "bottom-right");
    
        const graphicsLayer = new GraphicsLayer();
        map.add(graphicsLayer);
    
        const sketch = new Sketch({
            layer: graphicsLayer,
            view: view,
            availableCreateTools: ["polyline", "polygon", "rectangle"],
            creationMode: "update",
            updateOnGraphicClick: true,
            visibleElements: {
                createTools: {
                    point: false,
                    circle: false
                },
                selectionTools:{
                    "lasso-selection": false,
                    "rectangle-selection":false,
                },
                settingsMenu: false,
                undoRedoMenu: false
            }
        });
  3. sketch 微件添加到 viewtop-right 处。

    js
        const sketch = new Sketch({
            layer: graphicsLayer,
            view: view,
            availableCreateTools: ["polyline", "polygon", "rectangle"],
            creationMode: "update",
            updateOnGraphicClick: true,
            visibleElements: {
                createTools: {
                    point: false,
                    circle: false
                },
                selectionTools:{
                    "lasso-selection": false,
                    "rectangle-selection":false,
                },
                settingsMenu: false,
                undoRedoMenu: false
            }
        });
    
        view.ui.add(sketch, "top-right");
  4. measurements 元素添加到 view 中以在绘制几何时显示测量值。

    js
        view.ui.add(sketch, "top-right");
    
        const measurements = document.getElementById("measurements");
        view.ui.add(measurements, "manual");
  5. 运行应用程序以验证微件是否显示在视图中,以及您是否能够绘制几何。

计算长度和面积

geometryEngine 提供了计算几何的平面长度/面积或测地线长度/面积的功能。由于此应用程序中的几何使用的是 Web Mercator 投影,因此最佳做法是使用测地线测量。但是,我们要展示测地线计算和平面计算之间的差异,需要在绘制几何时同时测量这两者。

  1. 定义 getArea 函数,参数为 polygon。调用 geodesicArea() 方法和 planarArea() 方法来计算多边形的面积,以 square-kilometers 为单位。

    js
        const measurements = document.getElementById("measurements");
        view.ui.add(measurements, "manual");
    
        function getArea(polygon) {
        const geodesicArea = geometryEngine.geodesicArea(polygon, "square-kilometers");
        const planarArea = geometryEngine.planarArea(polygon, "square-kilometers");
    
    }
  2. 将计算结果追加到 measurementsinnerHTML 中。

    js
        function getArea(polygon) {
            const geodesicArea = geometryEngine.geodesicArea(polygon, "square-kilometers");
            const planarArea = geometryEngine.planarArea(polygon, "square-kilometers");
    
            measurements.innerHTML =
            "<b>Geodesic area</b>: " + geodesicArea.toFixed(2) + " km\xB2" + "| <b>Planar area</b>: " + planarArea.toFixed(2) + " km\xB2";
    
        }
  3. 定义 getLength 函数,参数为 line。调用 geodesicLengthplanarLength 方法来计算 line 的长度,以千米为单位。

    js
            measurements.innerHTML =
            "<b>Geodesic area</b>: " + geodesicArea.toFixed(2) + " km\xB2" + "| <b>Planar area</b>: " + planarArea.toFixed(2) + " km\xB2";
    
        }
    
        function getLength(line) {
            const geodesicLength = geometryEngine.geodesicLength(line, "kilometers");
            const planarLength = geometryEngine.planarLength(line, "kilometers");
    
        }
  4. 将测地线长度计算的结果追加到 measurementsinnerHTML 中。

    js
        function getLength(line) {
            const geodesicLength = geometryEngine.geodesicLength(line, "kilometers");
            const planarLength = geometryEngine.planarLength(line, "kilometers");
    
            measurements.innerHTML =
            "<b>Geodesic length</b>: " + geodesicLength.toFixed(2) + " km" + "| <b>Planar length</b>: " + planarLength.toFixed(2) + " km";
    
        }
  5. 增加判断 switch 语句,几何为 polygon 时,调用 getArea 函数;几何为 polyline 时,调用 getLength 函数。

    js
        function getLength(line) {
            const geodesicLength = geometryEngine.geodesicLength(line, "kilometers");
            const planarLength = geometryEngine.planarLength(line, "kilometers");
    
            measurements.innerHTML =
            "<b>Geodesic length</b>: " + geodesicLength.toFixed(2) + " km" + "| <b>Planar length</b>: " + planarLength.toFixed(2) + " km";
    
        }
    
        function switchType(geom) {
            switch (geom.type) {
                case "polygon":
                    getArea(geom);
                    break;
                case "polyline":
                    getLength(geom);
                    break;
                default:
                    console.log("No value found");
            }
        }

创建默认图形以测量

要向用户展示与应用程序交互的方式,请创建一个默认多边形,并在应用程序启动时显示其区域。

  1. 创建 polygon。将 type 设置为 polygon,并将 spatialReference 属性中的 wkid 设置为 3857 (Web Mercator)。创建 simplePolygonSymbol 来设置图形样式。

    js
        const measurements = document.getElementById("measurements");
        view.ui.add(measurements, "manual");
    
        const polygon = {
            type: "polygon",
            spatialReference: {
                wkid: 3857,
            },
            rings: [
                [
                    [-4508069.082189632, 3599936.936171892],
                    [-4508069.082189632, 5478453.343307884],
                    [-2629552.6750536393, 5478453.343307884],
                    [-2629552.6750536393, 3599936.936171892],
                    [-4508069.082189632, 3599936.936171892],
                ],
            ],
        };
    
        const simplePolygonSymbol = {
            type: "simple-fill",
            outline: {
                color: [200, 0, 0],
                width: 2,
            },
        };
  2. 创建 Graphic 类实例。将 geometrysymbol 属性设置为 polygonsimplePolygonSymbol。将图形添加到 graphicsLayer

    js
        const measurements = document.getElementById("measurements");
        view.ui.add(measurements, "manual");
    
        const polygon = {
            type: "polygon",
            spatialReference: {
             wkid: 3857,
            },
            rings: [
                [
                    [-4508069.082189632, 3599936.936171892],
                    [-4508069.082189632, 5478453.343307884],
                    [-2629552.6750536393, 5478453.343307884],
                    [-2629552.6750536393, 3599936.936171892],
                    [-4508069.082189632, 3599936.936171892],
                ],
            ],
        };
    
        const simplePolygonSymbol = {
            type: "simple-fill",
            outline: {
                color: [200, 0, 0],
                width: 2,
            },
        };
    
        const polygonGraphic = new Graphic({
            geometry: polygon,
            symbol: simplePolygonSymbol
        });
    
        graphicsLayer.add(polygonGraphic);
  3. when 加载 view 时,调用 polygonGraphic 上的 update 方法,并基于 polygonGraphicgeometry 调用 getArea 函数。

    js
        graphicsLayer.add(polygonGraphic);
    
        view.when(() => {
            sketch.update(polygonGraphic);
            getArea(polygonGraphic.geometry);
        });

添加事件监听器

Sketch 微件的设置允许编辑视图中的几何。创建事件监听器,监听几何的更新状态,动态测量其面积或长度。

  1. 创建一个事件监听器,用于在创建、调整大小或移动图形时监听 update on 的更改。使用事件中第一个图形的 geometry 设置 geometry 元素。

    js
        view.when(() => {
            sketch.update(polygonGraphic);
            getArea(polygonGraphic.geometry);
        });
    
        sketch.on("update", (e) => {
            const geometry = e.graphics[0].geometry;
    
        });
  2. 根据 sketch 事件的 statestartcomplete,还是处于更改状态而创建条件语句。对于每个状态 (complete 除外),调用 switchType 语句,其中 geometry 为其参数。当事件 complete 后,从 graphicsLayer 中移除图形并清除 innerHTML

    js
        sketch.on("update", (e) => {
            const geometry = e.graphics[0].geometry;
    
            if (e.state === "start") {
                switchType(geometry);
            }
    
            if (e.state === "complete") {
                graphicsLayer.remove(graphicsLayer.graphics.getItemAt(0));
                measurements.innerHTML = null;
            }
    
            if (
                e.toolEventInfo &&
                (e.toolEventInfo.type === "scale-stop"||
                e.toolEventInfo.type === "reshape-stop"||
                e.toolEventInfo.type === "move-stop")
                ) 
            {
                switchType(geometry);
            }
    
        });

运行应用程序

CodePen 中,运行代码以显示地图。

运行应用程序时,您将看到一个面及其计算出的测地线面积和平面面积。您可以使用草绘微件绘制其他几何并显示其测量值。如果移动几何,测地线测量值将更改,但平面测量值不会更改。

下一步是什么?

要了解如何使用其他API 功能,请参阅以下教程: