Search code examples
c#shapefilenettopologysuitegeopositioning

Quickly filtering geopositions in or out of a multipolygon with C#


I am using NetTopologySuite with C# to filter points inside the precise boundaries of a country with a pretty simple way:

var path = "fr.shp"; // "big" country and boundaries need to be precise in my case

var reader = new ShapeDataReader(path);
var mbr = reader.ShapefileBounds;
var result = reader.ReadByMBRFilter(mbr);

var polygons = new List<Geometry>();

using (var coll = result.GetEnumerator())
{
    while (coll.MoveNext())
    {
        var item = coll.Current;

        if (item == null)
        {
            continue;
        }

        polygons.Add(item.Geometry);
    }
}

var polygon = new GeometryCombiner(polygons).Combine();

var points = new List<Point>();
List<Point> pointsToFilterWithBorders; // loaded from DB, not visible here but we have 1,350,000 points to filter

Parallel.ForEach(pointsToFilterWithBorders, point =>
{
    if (polygon.Contains(point))
        points.Add(point);
});

It's working fine (filtering works great!) but it's pretty slow... like one day to do the filtering for only 1,350,000 points!

Any idea on how to improve that?

I tried to use Parallel.ForEach but still very long and I tried to find something like a "batch" compare in NetTopologySuite but couldn't find a quicker solution to filter my points in this big shapefile...


Solution

  • Thanks everyone for the help! At the end, I found a solution inspired by your ideas :-)

    I can't share the code itself because it's inside a closed source code but here is the idea:

    My code was already grouping all the points by squares of 1 km² for other purposes: I just had to check if these polygons where not fully inside the boundaries. When that was not the case, I just had to do a check on all points inside these squares!

    Still a little bit long (but less than one hour for France and it's mixed with other pieces of code which were already a little bit slow) but clearly quicker!