Best way to share out many points on a few features?

105 views Asked by At

I have 5000+ LatLng points, and for each of them I would like to find out which feature (region) they belong to. The features come from a kmz layer by Philippe Ivaldi, converted to GeoJSON.

Currently, I am doing this with turfjs in a double for loop. As expected, the calculation freezes the browser for ten minutes, which ain't very convenient.

Here's my code :

function countCeaByLayer(geoJsonLayer){
    jQuery.getJSON('http://localhost/server/retrieveData.php', function(data){
            var turfPoints = [];
            for(var i = 0; i < data.length; i++){
                turfPoints.push(turf.point([data[i].longitudeWGS84, data[i].latitudeWGS84]));
            }

            var features = geoJsonLayer.toGeoJSON().features;
            for(var i = 0; i < features.length; i++){
                var turfPointsNew = [];
                for(var j = 0; j < turfPoints.length; j++){

                    var isInside = turf.inside(turfPoints[j], features[i]);
                    if(!isInside) turfPointsNew.push(turfPoints[j]);
                }
                turfPoints = turfPointsNew;
            }

            console.log("done");
    });
}

What can I do to avoid freezing the browser?

  • Make it async?
  • Do the calculation with node and turfjs on a server?
  • Or deploy leafletjs on a server with node and leaflet-headless?

...or should I just deal with it?

Thanks!

2

There are 2 answers

2
Stranded Kid On BEST ANSWER

To optimize your code, you should do something like this.

Loop over the points.

For each point, when you iterate over polygons to know if the point is inside one of them, first get the polygon Bounds and see if the point is within the bounds. If not, you can skip going further and go to the next polygons.

If it's within the bounds, go for a plain check if it is inside the polygon itself.

If it's the case, break the loop iterating over polygons and switch to the next point.

For example, it could be:

points.forEach(function(point) {
    polygons.some(function(polygon) {
       if (polygon.getBounds().contains(point)) { // or other method if you are not playing with Leaflet features
           if (turf.isInside(polygon, point) { // for example, not sure this method actually exists but you get the concept
              // point is within the polygon, do tuff
              return true; // break the some loop
           }
       }
    });
});

I've myself developped something that exactly does the same thing also based on turf, I run it on the client side (and my loops are made with .some, not classical for loop, so it could even go further in terms of performance) and I never experienced freeze.

From my point of view, 5000 points is peanut for browser to handle, but if your polygons are really complex (dozen of hundreds of thousands of vertices), this can slow down the process of course.

Br, Vincent

0
Tom Solacroup On

If Stranded Kid's answer is overkill for you,

geoJsonLayer.eachLayer(function(layer){
    var within = turf.within(turf.featureCollection(turfPoints),turf.featureCollection([layer.toGeoJSON()]));
    console.dir(within);
});

And make sure your coordinates are floats and not strings, because that's what caused the slowdown for me.