Проверьте координаты / места внутри полигонов в открытых слоях - PullRequest
0 голосов
/ 10 июня 2019

У меня есть код, по которому я проверяю места или координаты внутри в многоугольниках или нет. Проблема в том, что у него может быть 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;
    }

Можно ли проверить все места внутри полигонов в открытых слоях за одну проверку вместо зацикливания для каждого?

Ответы [ 2 ]

0 голосов
/ 13 июня 2019

Вы можете использовать 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);

Но если вы хотите только сейчас, если есть несколько точек внутри или снаружи многоугольника, но не зная, какую из них вы можете сыграть со степенью многоугольника

0 голосов
/ 10 июня 2019
    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');
    }
...