locationtech / jts

The JTS Topology Suite is a Java library for creating and manipulating vector geometry.
Other
1.98k stars 443 forks source link

GeometryCollection difference #833

Open halset opened 2 years ago

halset commented 2 years ago

Should we add support for Geometry.difference from/to a non-empty GeometryCollection? I just made a method for this in one of my projects to get around some Exceptions, but having support for more such operations for GeometryCollection would make it easier to use JTS.

dr-jts commented 2 years ago

I made an RFC for this: #761. It needs a bit more detail about the exact semantics, however. What is the behaviour that you are proposing?

halset commented 2 years ago

For difference, I am currently doing this:

This is the utility method I now use to do this. Perhaps GeometryCollection.difference could do something similar.

    public static Geometry difference(Geometry g0, Geometry g1) {

        if (g0.getClass().equals(GeometryCollection.class)) {
            // left side is geometry collection
            GeometryCollection gc = (GeometryCollection) g0;

            List<Geometry> geoms = new ArrayList<>(g0.getNumGeometries());
            for (int i = 0; i < gc.getNumGeometries(); i++) {
                Geometry g = gc.getGeometryN(i);
                g = difference(g, g1);
                if (!g.isEmpty()) {
                    geoms.add(g);
                }
            }

            if (geoms.isEmpty()) {
                return // empty;
            }

            Geometry result = UnaryUnionOp.union(geoms);

            if (result == null) {
                return // empty;
            }

            return result;
        } else if (g1.getClass().equals(GeometryCollection.class)) {
            // right side is geometry collection
            GeometryCollection gc = (GeometryCollection) g1;

            Geometry result = g0;
            for (int i = 0; i < gc.getNumGeometries(); i++) {
                Geometry g = gc.getGeometryN(i);
                result = difference(result, g);
            }
            return result;
        }

        return g0.difference(g1);
    }

Today, I also got trapped with the same issue for the union operation and worked around it in a similar way.