javageotoolsjts

How to filter SpatialIndexFeatureCollection by intersection between MultiPoint and MultiPolygon considering a min amount of points required


The data base are MultiPolygons representing for example the neighbourhoods of a city held in a SpatialIndexFeatureCollection. The incoming request data is a shapefile containing a MultiPoint object representing for example buildings. Our goal is to return all multipolygons that contain at least n points of the input data.

Without the minimum requirement we have a working solution by querying the collection with FilterFactory2.dwithin() as the filter and the mulitpoint split into a set of points as input to create a SimpleFeatureCollection. This approach only returns every found multipolygon once, though. Therefore we can't filter the result by number of occurrences. Filtering the collection for every point separately seems very inefficient.

Is there a way to work with the intersection between a multipoint and multipolygon?


Solution

  • It sounds as if you need to query the points collection for each polygon in turn and keep the ones where the returned collection is greater than N.

        int N = 3;
        FileDataStore pointsDS = new ShapefileDataStore(URLs.fileToUrl(new File("/data/natural_earth/110m_cultural/110m_populated_places.shp")));
        FileDataStore polyDS = new ShapefileDataStore(URLs.fileToUrl(new File("/data/natural_earth/110m_cultural/110m_admin_0_countries.shp")));
        SimpleFeatureCollection points = pointsDS.getFeatureSource().getFeatures();
        SimpleFeatureCollection polys = polyDS.getFeatureSource().getFeatures();
        FilterFactory2 filterFactory = CommonFactoryFinder.getFilterFactory2();
        Expression propertyName = filterFactory.property(points.getSchema()
                .getGeometryDescriptor().getName());
    
        ArrayList<SimpleFeature> results = new ArrayList<>();
        try(SimpleFeatureIterator itr = polys.features()){
            while (itr.hasNext()) {
                SimpleFeature poly = itr.next();
                Filter filter = filterFactory.within(propertyName, filterFactory.literal(poly.getDefaultGeometry()));
                SimpleFeatureCollection sub = points.subCollection(filter);
                if(sub.size()>N){
                    results.add(poly);
                }
            }
        }
        for(SimpleFeature f:results){
            System.out.println(f.getAttribute("NAME"));
        }