2

How can I increase speed of counting? I want to select points which is included by shape (GIS shapefile .shp). I have 5 million points and 10 shape files.

    qry="CONTAINS(the_geom, POINT (69.95781 41.667324))";
    tName="WATER";
 
public Object[] filterFeatures(String qry,String tName) throws Exception {

    String[] typeNames=dataStore.getTypeNames();
    if(typeNames.length==0)return null;
    FeatureSource source =(FeatureSource) dataStore.getFeatureSource(typeNames[0]);
    Filter filter = CQL.toFilter(qry);
    FeatureCollection features = source.getFeatures(filter);
    Object[] objArr=features.toArray();
    return objArr;
 }
2
  • how many polygons are there in the shapefiles?
    – Ian Turton
    Commented Jun 15, 2021 at 12:04
  • 183 polygons grouped into 5 shape files.
    – user187101
    Commented Jun 18, 2021 at 7:40

2 Answers 2

2

The easiest way to answer this sort of question is to do some experimenting, so I tried out some quick and dirty tests using the Natural Earth populated places and admin countries - 7322 points and 177 polygons, and 3 test methods:

One that loops across the points doing a contains query (like you do):

public static HashMap<String, Integer> pointLoop(SimpleFeatureCollection points, SimpleFeatureCollection polys,
      Expression propertyName) {
    long start = System.currentTimeMillis();
    HashMap<String, Integer> results = new HashMap<>();
    try (SimpleFeatureIterator itr = points.features()) {
      while (itr.hasNext()) {
        SimpleFeature point = itr.next();
        Filter filter = filterFactory.contains(propertyName, filterFactory.literal(point.getDefaultGeometry()));
        SimpleFeatureCollection sub = polys.subCollection(filter);
        try (SimpleFeatureIterator fs = sub.features()) {
          while (fs.hasNext()) {
            SimpleFeature ff = fs.next();
            String name = (String) ff.getAttribute("NAME");
            if (results.containsKey(name)) {
              int count = results.get(name);
              results.put(name, count + 1);
            } else {
              results.put(name, 1);
            }
          }
        }
      }
    }
    long end = System.currentTimeMillis();
    System.out.println("PointLoop Time = " + (end - start) + "ms");
    return results;
  }

One that loops over the polygons and counts the points:

  public static HashMap<String, Integer> polygonLoop(SimpleFeatureCollection points, SimpleFeatureCollection polys,
      Expression propertyName) {
    long start = System.currentTimeMillis();
    HashMap<String, Integer> results = new HashMap<>();
    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);
        results.put((String) poly.getAttribute("NAME"), sub.size());

      }
    }
    long end = System.currentTimeMillis();
    System.out.println("Polygon Loop Time = " + (end - start) + "ms");
    return results;
  }

and finally one that uses a SpatialIndexFeatureCollection on the points to improve the speed of the point in polygon query:

  public static HashMap<String, Integer> polygonLoopIndex(SimpleFeatureCollection points, SimpleFeatureCollection polys,
      Expression propertyName) throws IOException {
    long start = System.currentTimeMillis();
    HashMap<String, Integer> results = new HashMap<>();
    SpatialIndexFeatureCollection index = new SpatialIndexFeatureCollection(points);
    try (SimpleFeatureIterator itr = polys.features()) {
      while (itr.hasNext()) {
        SimpleFeature poly = itr.next();
        Filter filter = filterFactory.within(propertyName, filterFactory.literal(poly.getDefaultGeometry()));
        SimpleFeatureCollection sub = index.subCollection(filter);
        results.put((String) poly.getAttribute("NAME"), sub.size());

      }
    }
    long end = System.currentTimeMillis();
    System.out.println("Indexed Polygon Loop Time = " + (end - start) + "ms");
    return results;
  }

I got the following results:

Point Loop Time = 3566ms
Polygon Loop Time = 151ms
Indexed Polygon Loop Time = 186ms

so the polygon by polygon loop wins. But I then turned up the size of the points collection and this is the result:

500,000 points
177 polygons
Point Loop Time = 146.029s
Polygon Loop Time = 12.517s
Indexed Polygon Loop Time = 2.801s

So beyond a certain point building the index pays off and it is worth the effort.

14
  • It is very good solution! But I use geotools 2.6 version. I cant get newer version of geotools. Which geotools version are you u sing?
    – user187101
    Commented Jun 21, 2021 at 5:56
  • I am using 26.x master version - to use a version 20 versions old is probably a mistake
    – Ian Turton
    Commented Jun 21, 2021 at 7:28
  • Sorry can you tell me what is the value of propertyName?
    – user187101
    Commented Jun 22, 2021 at 11:09
  • What ever your geometry is
    – Ian Turton
    Commented Jun 22, 2021 at 11:31
  • polygonLoopIndex(getPOINTS(),getPolygons("8"), CQL.toExpression("???")); What do I have to write instead of question mark?
    – user187101
    Commented Jun 22, 2021 at 11:35
-1
CQL.toExpression("the_geom,location.*") is correct!
1
  • Not worked Sorry
    – user187101
    Commented Jun 22, 2021 at 12:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.