查找空间关系

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

了解如何确定几何之间的空间关系。

空间关系 (*spatial relation*) 指一个几何与另一个几何的拓扑关联关系。这种关联关系通过要素内部、边界和外部确定。

在本教程中,我们演示如何使用 geometryEngine 来确定两个几何之间的空间关系。要确定空间关系是否存在,可以尝试 intersectsdisjointwithin 等操作。如果操作成功,则存在对应空间关系。

步骤

创建新 Pen

  1. 在此之前,先了解显示地图教程

添加模块

  1. 通过 require 引入GraphicGraphicsLayerSketchgeometryEngine 模块。

    更多信息

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

    js
    require([
        "geoscene/config",
        "geoscene/Map",
        "geoscene/views/MapView",
    
        "geoscene/Graphic",
        "geoscene/layers/GraphicsLayer",
        "geoscene/widgets/Sketch",
        "geoscene/geometry/geometryEngine"
    ], (geosceneConfig, Map, MapView, Graphic, GraphicsLayer, Sketch, geometryEngine) => {

添加 HTML 元素

添加 <div> 元素,显示各种空间关系情况。

  1. 使用 HTML 创建 div 元素以显示要评估的每种空间关系。

    html
        <div id="viewDiv"></div>
    
        <div id="relationshipResults" class="geoscene-widget">
            <div><b>Spatial relationships</b></div>
            <div id="Contains"></div>
            <div id="Crosses"></div>
            <div id="Disjoint"></div>
            <div id="Equals"></div>
            <div id="Intersects"></div>
            <div id="Overlaps"></div>
            <div id="Touches"></div>
            <div id="Within"></div>
        </div>
  2. relationshipResults 添加至视图 UI 的右下角。

    js
        const view = new MapView({
            map: map,
            center: [118.80500, 34.02700], //经度,纬度
            zoom: 12,
            container: "viewDiv"
        });
    
        const relationshipDiv = document.getElementById("relationshipResults");
        view.ui.add(relationshipDiv, "bottom-right");
  3. relationshipResults <div> 设置CSS样式 。

    js
        .viewDiv {
            padding: 0;
            margin: 0;
            height: 100%;
            width: 100%;
        }
    
        .relationshipResults {
            width: 175px;
            padding: 10px;
        }

创建图形

执行空间关系需要两个几何图形。我们创建一个折线和一个面图形来演示空间关系。

注 :了解更多关于图形添加到地图的信息,请访问添加点、线和面教程。

  1. 创建一个 GraphicsLayer 类,添加到 map 中。

    js
        const view = new MapView({
            map: map,
            center: [118.80500, 34.02700], //经度,纬度
            zoom: 12,
            container: "viewDiv"
        });
    
        const relationshipDiv = document.getElementById("relationshipResults");
        view.ui.add(relationshipDiv, "bottom-right");
    
        const graphicsLayer = new GraphicsLayer();
        map.add(graphicsLayer);
  2. 定义一个折线图形,添加至 graphicsLayer

    js
        const view = new MapView({
            map: map,
            center: [118.80500, 34.02700], //经度,纬度
            zoom: 12,
            container: "viewDiv"
        });
    
        const relationshipDiv = document.getElementById("relationshipResults");
        view.ui.add(relationshipDiv, "bottom-right");
    
        const graphicsLayer = new GraphicsLayer();
        map.add(graphicsLayer);
    
        const polyline = {
            type: "polyline",
            paths: [
                [13227000.704542402, 4032506.197638312],
                [13223540.698857695, 4034443.92109266],
                [13222135.94452635, 4032506.197638312],
                [13221470.479577951, 4033494.9524006792],
                [13221470.404932415, 4033494.9524006792]
            ],
            spatialReference: {
                wkid: 102100
            }
        };
        const simpleLineSymbol = {
            type: "simple-line",
            width: 2
        };
        const polylineGraphic = new Graphic({
            geometry: polyline,
            symbol: simpleLineSymbol
        });
        graphicsLayer.add(polylineGraphic);
  3. 创建面图形并将其添加至 graphicsLayer

    js
        const view = new MapView({
            map: map,
            center: [118.80500, 34.02700], //经度,纬度
            zoom: 12,
            container: "viewDiv"
        });
    
        const relationshipDiv = document.getElementById("relationshipResults");
        view.ui.add(relationshipDiv, "bottom-right");
    
        const graphicsLayer = new GraphicsLayer();
        map.add(graphicsLayer);
    
        const polyline = {
            type: "polyline",
                paths: [
                    [13227000.704542402, 4032506.197638312],
                    [13223540.698857695, 4034443.92109266],
                    [13222135.94452635, 4032506.197638312],
                    [13221470.479577951, 4033494.9524006792],
                    [13221470.404932415, 4033494.9524006792]
                ],
            spatialReference: {
                wkid: 102100
            }
        };
        const simpleLineSymbol = {
            type: "simple-line",
            width: 2
        };
        const polylineGraphic = new Graphic({
            geometry: polyline,
            symbol: simpleLineSymbol
        });
        graphicsLayer.add(polylineGraphic);
    
        // Create a polygon geometry
        const polygon = {
            type: "polygon",
            rings: [
                [13228098.704542402, 4035365.9427463487],
                [13226362.225451587, 4035365.9427463487],
                [13226362.225451587, 4032059.2948176656],
                [13228098.704542402, 4032059.2948176656],
                [13228098.704542402, 4035365.9427463487]
            ],
            spatialReference: {
                wkid: 102100
            }
        };
        const simpleFillSymbol = {
            type: "simple-fill"
        };
        const polygonGraphic = new Graphic({
            geometry: polygon,
            symbol: simpleFillSymbol
        });
    
        graphicsLayer.add(polygonGraphic);
  4. 将图形添加至 selectedGraphics 数组。

    js
        graphicsLayer.add(polygonGraphic);
    
        let selectedGraphics = [polygonGraphic, polylineGraphic];
  5. 运行代码以验证图形是否显示在视图中。

创建草绘微件

使用 SketchGraphicsLayer 类,我们进一步展示如何根据草绘图形的变化实时更新空间关系。

  1. 定义 Sketch 微件对象,设置 layer 值为之前定义的 graphicsLayer。这样可以通过草图微件移动和更新在上一步中创建的线和折线图形。在 Sketch 微件上启用 snappingOptions设置。最后,设置微件的 visibleElements ,移除不需要的工具。

    js
        let selectedGraphics = [polygonGraphic, polylineGraphic];
    
        const sketch = new Sketch({
            view: view,
            layer: graphicsLayer,
            updateOnGraphicClick: true,
            snappingOptions: {
                enabled: true,
                featureSources: [{
                    layer: graphicsLayer
                }]
            },
            visibleElements: {
                createTools: {
                    point: false
                },
                selectionTools: {
                    "lasso-selection": false,
                    "rectangle-selection": false,
                },
                settingsMenu: false,
                undoRedoMenu: false
            }
        });
  2. 将草绘微件添加到视图 UI 的右上角。

    js
        const sketch = new Sketch({
            view: view,
            layer: graphicsLayer,
            updateOnGraphicClick: true,
            snappingOptions: {
                enabled: true,
                featureSources: [{
                    layer: graphicsLayer
                }]
            },
            visibleElements: {
                createTools: {
                    point: false
                },
                selectionTools: {
                    "lasso-selection": false,
                    "rectangle-selection": false,
                },
                settingsMenu: false,
                undoRedoMenu: false
            }
        });
    
        view.ui.add(sketch, "top-right");
  3. 运行代码以验证草绘微件是否显示在视图中。

确定空间关系

空间关系是根据两个几何的内部、边界和外部确定的。使用 contains()intersects() 等方法查找草图几何之间的空间关系。

  1. 定义 showSpatialRelationship 函数,根据空间关系更新元素中的显示值。如果空间关系的 value 为 true,则以粗体显示。

    js
        view.ui.add(sketch, "top-right");
    
        function showSpatialRelationship(string, value) {
            const element = document.getElementById(string)
            if (value) {
                element.innerHTML = "<b>" + string + ": " + value + "</b>";
            } else {
                element.innerHTML = string + ": " + value;
            }
        }
  2. 定义函数 onGraphicUpdate ,处理图形变化时的操作。

    js
        view.ui.add(sketch, "top-right");
    
        function onGraphicUpdate() {
    
        }
    
        function showSpatialRelationship(string, value) {
            const element = document.getElementById(string)
            if (value) {
                element.innerHTML = "<b>" + string + ": " + value + "</b>";
            } else {
                element.innerHTML = string + ": " + value;
            }
        }
  3. 图形更新时,从 selectedGraphics 数组中提取几何,接下来分析它们的空间关系。

    js
        function onGraphicUpdate() {
    
            let geometry1 = selectedGraphics[0].geometry;
            let geometry2 = selectedGraphics[1].geometry;
    
        }
  4. 判断两个几何每种空间关系的结果,并在 relationshipResults div 块级元素中显示结果。调用 showSpatialRelationship 函数显示结果。

    js
        function onGraphicUpdate() {
    
            let geometry1 = selectedGraphics[0].geometry;
            let geometry2 = selectedGraphics[1].geometry;
    
            const contains = geometryEngine.contains(geometry1, geometry2);
            showSpatialRelationship("Contains", contains)
    
            const crosses = geometryEngine.crosses(geometry1, geometry2);
            showSpatialRelationship("Crosses", crosses)
    
            const disjoint = geometryEngine.disjoint(geometry1, geometry2);
            showSpatialRelationship("Disjoint", disjoint)
    
            const equals = geometryEngine.equals(geometry1, geometry2);
            showSpatialRelationship("Equals", equals)
    
            const intersects = geometryEngine.intersects(geometry1, geometry2);
            showSpatialRelationship("Intersects", intersects)
    
            const overlaps = geometryEngine.overlaps(geometry1, geometry2);
            showSpatialRelationship("Overlaps", overlaps)
    
            const touches = geometryEngine.touches(geometry1, geometry2);
            showSpatialRelationship("Touches", touches)
    
            const within = geometryEngine.within(geometry1, geometry2);
            showSpatialRelationship("Within", within)
    
        }

添加事件监听器

创建事件监听器,在绘制或更新新几何时触发。如果绘制新几何,则会从 selectedGraphics 数组中移除最后一个几何。调用 onGraphicUpdate 函数,确定其余几何之间的空间关系。

  1. 监听 Sketch 微件上的事件。监视 updateundoredo 事件,并调用 onGraphicUpdate 方法以确定这些事件发生时的空间关系。

    js
        view.ui.add(sketch, "top-right");
    
        sketch.on(["update", "undo", "redo"], onGraphicUpdate);
  2. 监听 Sketch 微件上的 create 事件。创建新图形时,从 selectedGraphics 数组中获取最后一个图形,并从 graphicsLayer 中移除该图形,以便在 view 中一次仅显示两个图形。调用 onGraphicUpdate 函数,确定几何之间的空间关系。

    js
        sketch.on(["update", "undo", "redo"], onGraphicUpdate);
    
        sketch.on("create", (event) => {
            if (event.state === "start") {
                const arrVal = selectedGraphics.pop();
                graphicsLayer.remove(arrVal);
            }
            if (event.state === "complete") {
                selectedGraphics.unshift(event.graphic);
    
                onGraphicUpdate();
    
            }
        })
  3. when 加载应用程序时,可调用 onGraphicUpdate 来计算空间关系。使用草绘微件的 update 方法选择折线图形,以便用户知道他们可以移动该图形。

    js
        sketch.on("create", (event) => {
            if (event.state === "start") {
                const arrVal = selectedGraphics.pop();
                graphicsLayer.remove(arrVal);
            }
            if (event.state === "complete") {
                selectedGraphics.unshift(event.graphic);
    
                onGraphicUpdate();
    
            }
            })
    
            view.when(() => {
            sketch.update(polylineGraphic).then(onGraphicUpdate)
        });

运行应用程序

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

地图加载并显示线和面图形。同时在右下角,会显示图形之间的空间关系。移动图形时空间关系会随之变化。还可以进一步使用 Sketch 微件创建新图形,探索不同几何类型之间的空间关系。

下一步是什么?

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