[GIS] How to create a JTS geometry with holes and islands

jts-topology-suitepolygon-creationunion

I have a JTS multipolygon geometry created by an Polygon array:

multipolygon = gf.createMultiPolygon(this.polygons.toArray(new Polygon[this.polygons.size()]));

Those polygons can describe holes or islands. It is not determined which one is a hole or an island.

Examples:

enter image description here

All polygons are sorted by their area in descending order.
The first polygon "geom" is the largest where all other polygons g1..gn have to be removed or added to.

1) My algorithm to remove or add polygons in short form:

while(geomDescIterator.hasNext())
{
  Geometry g = //iterator.get..
  if(geom.covers(g))
  {
    geom = geom.difference(g);
  }
  else
  {
    geom = geom.union(g);
  }
}

return geom;

But there will be only geometries removed from, but never added to.

2) I switched then to another try where i used a collection:

GeometryFactory gf = new GeometryFactory();

while(geomDescIterator.hasNext())
{
  Geometry g = //iterator.get..
  if(geom.covers(g))
  {
    geom = geom.difference(g);
  }
  else
  {
    geomList = new LinkedList<>();
    geomList.add(geom);
    geomList.add(g);

    geom = gf.buildGeometry(geomList);
  }
}

return geom;

By using a collection to create a new geometry it results in a MultiPolygon, but in some situations "geom" ends up as GeometryCollection instead of MultiPolygon if it holds heterogeneous geometries like MultiPolygon and Polygons.
For further purposes I need an Geometry-Object as MultiPolygon type with all holes and islands(Compare picture above).

3) Another try where I created a new MultiPolygon by adding all polygons and multipolygons
by using following method…:

private List<Polygon> createMultiPolygonFrom(Geometry gc, GeometryFactory gf)
{
    List<Polygon> subPolygons = new LinkedList<>();
    for(int i = 0; i < gc.getNumGeometries(); i++)
    {
        Geometry subGeom = gc.getGeometryN(i);

        if(subGeom instanceof Polygon)
        {
            subPolygons.add((Polygon) subGeom);
        }
        else if(subGeom instanceof MultiPolygon)
        {
            for(int j = 0; j < subGeom.getNumGeometries(); j++)
                subPolygons.addAll(createMultiPolygonFrom(subGeom.getGeometryN(j), gf));
        }
    }

    return subPolygons;
}

By using it like that in upper iteration:

List<Polygon> polygons = createMultiPolygonFrom(geom, gf);
geom = gf.createMultiPolygon(polygons.toArray(new Polygon[polygons.size()]));

After this a valid MultiPolygon is returned, but no islands appear in the results.
The result is also the same like variant 1 above.

How can I achive this for getting such a multipolygon?

Best Answer

Try using Geometry.symDifference(Geometry) to merge them all together. Symmetric Difference is like an xor, see Wikipedia's explanation. I have tested merging a collection of jts Polygon that started off as holes and islands but were supplied as distinct Polygons and the result is as desired.