Search code examples
castinggeometrygeotoolsjts

jts convert single polygon to multipolygon


Ho everyone I am using JTS 1.15 with geotools snapshot 21:

I wrote a method with a Polygon Collection as input parameter and the output method is a MultiPolygon Geometry. This is working fine without one exception: I have also an union flag that will be union my polygons if overlapping or touching. If now all polygons are overlapping only a single polygon will be returned. But then there will be a ClassCastException.

A single polygon can’t be casted into a MultiPolygon

Is there a simple way to cast a single polygon into MultiPolygon? I couldn't find a geometry jts uml diagram but as I found out Polygons extends the Geometry class with the interface Polygonal Multipolygon extends GeometryCollection, which extends Geometry and having also the Polygonal interface.

In the JTS Geometry Jacadoc following is mentioned: Overlay Methods

The overlay methods return the most specific class possible to represent the result. If the result is homogeneous, a Point, LineString, or Polygon will be returned if the result contains a single element; otherwise, a MultiPoint, MultiLineString, or MultiPolygon will be returned. If the result is heterogeneous a GeometryCollection will be returned.

I wrote a simple string manipulator method to change my wkt string, but is there another way to achieve the goal?

here is my method

public static MultiPolygon createSPMultiPolygon(Collection<Polygon> polygons, boolean dissolveResult) {


    // if emty collection is returned
    if (polygons.size() == 0){
        //emty collection returns emty MultiPolygon

        GeometryFactory geomFactory = new GeometryFactory();
        MultiPolygon fail = geomFactory.createMultiPolygon();

        return fail;
    }

    //it will be assumed that all polygons have the same epsg code

    int epsgCode = polygons.iterator().next().getSRID();
    prec = new PrecisionModel(1000000)
    //creates the factory object
    GeometryFactory geomFactory = new GeometryFactory(prec, epsgCode);

    MultiPolygon result = null;


    // main task

    result = (MultiPolygon) geomFactory.buildGeometry(polygons);


        //mergedOptions
        if (dissolveResult) {

            try {
                result = (MultiPolygon) result.union();
                // there will be an exception if result or merge is a single polygon that polygon cant be cast to Multipolygon
            } catch (ClassCastException e) {

                // DO SOMETHING ELSE
            }

        }

    }

I am using following maven packages:

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <geotools.version>21-SNAPSHOT</geotools.version>
</properties>
<dependencies>
<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.11</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.geotools</groupId>
  <artifactId>gt-geometry</artifactId>
  <version>${geotools.version}</version>
</dependency>
<dependency>
  <groupId>org.geotools</groupId>
  <artifactId>gt-epsg-hsql</artifactId>
  <version>${geotools.version}</version>
</dependency>
<dependency>
  <groupId>org.geotools</groupId>
  <artifactId>gt-epsg-wkt </artifactId>
  <version>${geotools.version}</version>
</dependency>

I am working with following example data and helper function:

    String touches1_wkt = "POLYGON ((7.896407750956972 49.73405361813658, 8.14886306623246 49.73405361813658, 8.14886306623246 49.73405361813658, 8.14886306623246 49.46768344296402, 7.902371262341433 49.46569560583586, 7.896407750956972 49.73405361813658))";
    String touches2_wkt = "POLYGON ((8.14886306623246 49.61478339044737, 8.39137919586718 49.616771227575526, 8.39137919586718 49.616771227575526, 8.399330544379795 49.35835240091558, 8.14886306623246 49.35835240091558, 8.14886306623246 49.46768344296402, 8.14886306623246 49.61478339044737))";


    Polygon touch1 = (Polygon) createSPGeom(touches1_wkt, 4326);
    Polygon touch2 = (Polygon) createSPGeom(touches2_wkt, 4326);

    Collection<Polygon> polyCollection = new ArrayList<>();
    polyCollection.add(touch1);
    polyCollection.add(touch2);

    MultiPolygon multi = createSPMultiPolygon(polyCollection, true);

with following helpfer method for wkt reading:

     public static Geometry createSPGeom(String wktString, Integer epsgCode){

    Geometry returnedGeom =null;
    prec = new PrecisionModel(1000000);

    GeometryFactory geomFactory = new GeometryFactory(prec, epsgCode);
    WKTReader wktReader = new WKTReader(geomFactory);

    try {
        returnedGeom = wktReader.read(wktString);
    } catch (ParseException e) {
        // if wktString is invalid, an emty point geometry is used
        returnedGeom = geomFactory.createPoint();
    }

    return returnedGeom;
}

Thanks for any help in advance


Solution

  • As GeoMesaJim say's this is a simple problem, just promote the polygon to a multipolygon.

    GeometryFactory gf = new GeometryFactory();
    MultiPolygon mPoly;
    if (p instanceOf Polygon){
      Polygon[] polys = new Polygon[1];
      polys[0] = p;
      mPoly = gf.createMultiPolygon(polys);
    } else {
       mPoly = p;
    }
    System.out.println(mPoly);