1

I am working with GeoTools libraries to implement GIS features. Here, I have two different shapefiles and I want to generate a new separate layer containing the differences between the two shape files. This new layer should show the extra features which are there in one of the two input shp files.

The image attached shows how it is done in QGIS

It generates a new layer showing the differences between polygon2.shp and polygon1.shp.

Are there any specific methods in the GeoTools libraries which can capture the differences if we provide the two layers of shapefiles?

0

As I said in the comments this is a fairly simple algorithm once you work out what the QGIS code is doing.

  1. Loop through the first feature collection
  2. Find any geometries in the second collection that intersect with the current feature
  3. Union those together (if there are more than one) and subtract (difference) that union from the first feature
  4. Save the results.

GeoTools actually makes this a fair bit easier than QGIS as you don't need to create your own indexes etc.

public static SimpleFeatureCollection difference(SimpleFeatureCollection collA, SimpleFeatureCollection collB) {
    SimpleFeatureBuilder builder = new SimpleFeatureBuilder(collA.getSchema());
    List<SimpleFeature> ret = new ArrayList<>();
    try (SimpleFeatureIterator itr = collA.features()) {
      while (itr.hasNext()) {
        SimpleFeature f = itr.next();
        Geometry geom = (Geometry) f.getDefaultGeometry();
        Filter filter = ff.intersects(ff.property(collB.getSchema().getGeometryDescriptor().getLocalName()),
            ff.literal(geom));
        SimpleFeatureCollection sub = collB.subCollection(filter);
        if (!sub.isEmpty()) {
          // union the geometries that overlap
          Geometry result = null;
          try (SimpleFeatureIterator itr2 = sub.features()) {

            while (itr2.hasNext()) {
              SimpleFeature f2 = itr2.next();
              Geometry geom2 = (Geometry) f2.getDefaultGeometry();
              if (result == null) {
                result = geom2;
              } else {
                result = result.union(geom2);
              }
            }
          }
          if (result.isValid() && geom.isValid()) {
            // calc difference
            Geometry g = geom.difference(result);
            builder.addAll(f.getAttributes());
            String geomName = collA.getSchema().getGeometryDescriptor().getLocalName();
            builder.set(geomName, g);
            SimpleFeature fout = builder.buildFeature(null);
            ret.add(fout);
          } else {
            if (!result.isValid()) {
              System.out.println("Invalid result");
              System.out.println(result);
            }
            if (!geom.isValid()) {
              System.out.println("Invalid geom");
              System.out.println(geom);
            }
          }
        } else {// no intersection
          ret.add(f);
        }
      }
    }
    return DataUtilities.collection(ret);

  }

Here I've differenced the Natural Earth countries and the lakes layer (Ignore India, it's an invalid polygon and I can't be bothered to fix it):

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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