检查openlayers中的多边形内部的坐标/位置

时间:2019-06-10 17:27:34

标签: openlayers openlayers-5

我有一些代码可以用来检查多边形内的位置或坐标。问题是它可能有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中的多边形内部,而不是为每个位置进行循环?

2 个答案:

答案 0 :(得分:0)

    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);
                }
            })
        }
    }

然后您可以从源代码中的places功能获得结果

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

答案 1 :(得分:0)

您可以使用turf.js,特别是功能pointsWithinPolygon。 从多多边形或多边形以及点列表开始,函数会返回多边形内的所有点,但是复杂度与点的数量呈线性关系。 如果我们使用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);

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