检查 coordinates/places openlayers 中的多边形内部

Check coordinates/places inside polygons in openlayers

我有一些代码可以检查多边形内部的位置或坐标。问题是它可能有 10000 个或更多的地方,这会导致性能问题并且地图变慢。请在下面找到我的代码:

    places.forEach(p => {
       this.isInsidePolygons(p.latitude, p.longitude)
    })

    isInsidePolygons(latitude: number, longitude: number): boolean {
                let isInsidePolygon = false;

                var coordinate = OlHelper.transformToEPSG3857([Number(longitude), Number(latitude)]);
                var shapes = this.getShapes();
                for (let i = 0; i < shapes.length; i++) {
                    let features = shapes[i].getSource().getFeatures();
                    if (!features || features.length == 0) continue;

                    for (let j = 0; j < features.length; j++) {
                        var geometry = features[j].getGeometry();
                        isInsidePolygon = geometry.intersectsCoordinate(coordinate);
                        if (isInsidePolygon) break;
                    }
                    if (isInsidePolygon) break;
                }

                return isInsidePolygon;
            }

   getShapes(): ol.layer.Vector[] {
        var shapes = [];
        this.MapControl.getLayers().forEach((layer) => {
            if (layer instanceof ol.layer.Vector) shapes.push(layer);
        });
        return shapes;
    }

是否可以一次检查 openlayers 中的所有位置都在多边形内,而不是对每个位置进行循环?

    let features = shapes[i].getSource().getFeatures();
    if (!features || features.length == 0) continue;

    for (let j = 0; j < features.length; j++) {
        var geometry = features[j].getGeometry();
        isInsidePolygon = geometry.intersectsCoordinate(coordinate);
        if (isInsidePolygon) break;
    }

可以替换为

    isInsidePolygon = (shapes[i].getSource().getFeaturesAtCoordinate(coordinate).length > 0);

代码更少,但效率可能不会更高

要针对更多地点测试形状,您需要为您的地点创建矢量源。使用形状的范围来获取地点的候选名单,并且仅针对形状几何体

测试这些地点
    let placesFeatures = [];
    places.forEach((p) => {
        placesFeatures.push(new Feature({
            geometry: new Point(fromLonLat[p.longitude, p.latitude]))
            id: [p.latitude, p.longitude].toString,
            isInsidePolygon: false
        }))
    })
    let placesSource = new VectorSource({features: placesFeatures});

    for (let i = 0; i < shapes.length; i++) {
        let features = shapes[i].getSource().getFeatures();
        if (!features || features.length == 0) continue;

        for (let j = 0; j < features.length; j++) {
            var geometry = features[j].getGeometry();
            let extent = features[j].getGeometry().getExtent();
            let candidates = placesSource.getFeaturesInExtent(geometry.getExtent());
            if (!candidates || candidates.length == 0) continue;

            for (let k = 0; k < candidates.length; k++) {
                isInsidePolygon = geometry.intersectsCoordinate(candidates[k].getGeometry().getCoordinates());
                if (isInsidePolygon) {
                    candidates[k].set('isInsidePolygon', true);
                }
            })
        }
    }

然后您可以从源中的地点特征中获取结果

    isInsidePolygons(latitude: number, longitude: number): boolean {
        return placesSource.getFeatureById([latitude, longitude].toString()).get('isInsidePolygon');
    }

您可以使用 turf.js, specifically the function pointsWithinPolygon。 从一个 multi-polygon 或一个多边形和一个点列表开始,函数它 returns 多边形内的所有点,但复杂度与点数成线性关系。 如果我们使用 turf.js 你必须转换 GeoJSON 中的特征。

let format = new ol.format.GeoJSON();
let pointsInsidePolygon = turf.pointsWithinPolygon(
         format.writeFeatureObject(points),
         format.writeFeatureObject(polygon)
    );

然后阅读 GeoJson 功能

let features =  format.readFeatures(pointsInsidePolygon);

但是如果你现在只想在多边形内部或外部有一些点,但不知道你可以玩哪一个多边形的范围