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?

  • hava a look at github.com/qgis/QGIS/blob/master/src/analysis/processing/…
    – Ian Turton
    Oct 1, 2018 at 10:19
  • Thanks for the update Ian. But the code looks really complicated. Is there a simple way to get this done.
    – Neha
    Oct 1, 2018 at 10:31
  • as far as I can see it is a simple loop through all of the polygons in A and for each one calculate the difference with any intersecting polygons in B.
    – Ian Turton
    Oct 1, 2018 at 10:33

2 Answers 2


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()),
        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);
            String geomName = collA.getSchema().getGeometryDescriptor().getLocalName();
            builder.set(geomName, g);
            SimpleFeature fout = builder.buildFeature(null);
          } else {
            if (!result.isValid()) {
              System.out.println("Invalid result");
            if (!geom.isValid()) {
              System.out.println("Invalid geom");
        } else {// no intersection
    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


This question is old now, but current versions of QGIS can detect changes between datasets using "Detect Dataset Changes"

It is in the Processing Toolbox, under "Vector general"enter image description here

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.