GeoShape to Geometry
authorMathieu Baudier <mbaudier@argeo.org>
Fri, 6 Oct 2023 05:24:47 +0000 (07:24 +0200)
committerMathieu Baudier <mbaudier@argeo.org>
Fri, 6 Oct 2023 05:24:47 +0000 (07:24 +0200)
org.argeo.app.geo/src/org/argeo/app/geo/GeoShapeUtils.java
org.argeo.app.geo/src/org/argeo/app/geo/GpxUtils.java

index 1db099bb8a4a03d56eee96e011fed968e4c8d7b1..d35492ad68d881b673b37e6a28b872f97003d440 100644 (file)
@@ -1,14 +1,63 @@
 package org.argeo.app.geo;
 
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.StringTokenizer;
+
 import org.locationtech.jts.geom.Coordinate;
 import org.locationtech.jts.geom.Geometry;
+import org.locationtech.jts.geom.GeometryFactory;
 import org.locationtech.jts.geom.LineString;
+import org.locationtech.jts.geom.MultiPoint;
 import org.locationtech.jts.geom.Point;
 import org.locationtech.jts.geom.Polygon;
 
 /** Utilities around ODK's GeoShape format */
 public class GeoShapeUtils {
 
+       @SuppressWarnings("unchecked")
+       public static <T> T geoShapeToGeometry(String geoShape, Class<T> clss) {
+               Objects.requireNonNull(geoShape);
+               GeometryFactory geometryFactory = JTS.GEOMETRY_FACTORY_WGS84;
+               List<Coordinate> coordinates = new ArrayList<>();
+               StringTokenizer stSeg = new StringTokenizer(geoShape.trim(), ";");
+               while (stSeg.hasMoreTokens()) {
+                       StringTokenizer stPt = new StringTokenizer(stSeg.nextToken().trim(), " ");
+                       String lat = stPt.nextToken();
+                       String lng = stPt.nextToken();
+                       String alt = stPt.nextToken();
+                       // String precision = stPt.nextToken();
+                       Coordinate coord;
+                       if (!alt.equals("0.0")) {
+                               coord = new Coordinate(Double.parseDouble(lat), Double.parseDouble(lng), Double.parseDouble(alt));
+                       } else {
+                               coord = new Coordinate(Double.parseDouble(lat), Double.parseDouble(lng));
+                       }
+                       coordinates.add(coord);
+               }
+               if (LineString.class.isAssignableFrom(clss)) {
+                       LineString lineString = geometryFactory
+                                       .createLineString(coordinates.toArray(new Coordinate[coordinates.size()]));
+                       return (T) lineString;
+               } else if (MultiPoint.class.isAssignableFrom(clss)) {
+                       MultiPoint multiPoint = geometryFactory
+                                       .createMultiPointFromCoords(coordinates.toArray(new Coordinate[coordinates.size()]));
+                       return (T) multiPoint;
+               } else if (Polygon.class.isAssignableFrom(clss)) {
+                       Coordinate first = coordinates.get(0);
+                       Coordinate last = coordinates.get(coordinates.size() - 1);
+                       if (!(first.getX() == last.getX() && first.getY() == last.getY())) {
+                               // close the line string
+                               coordinates.add(first);
+                       }
+                       Polygon polygon = geometryFactory.createPolygon(coordinates.toArray(new Coordinate[coordinates.size()]));
+                       return (T) polygon;
+               } else {
+                       throw new IllegalArgumentException("Unsupported format " + clss);
+               }
+       }
+
        /** Converts a {@link Geometry} with WGS84 coordinates to a GeoShape. */
        public static String geometryToGeoShape(Geometry geometry) {
                if (geometry instanceof Point point) {
index 5b07d1677fe72166ae9329327062812ddf35b37b..2a946f48ac29998bc413187d421e5dde09a445f2 100644 (file)
@@ -88,8 +88,12 @@ public class GpxUtils {
                        // multiPoint.normalize();
                        return (T) multiPoint;
                } else if (Polygon.class.isAssignableFrom(clss)) {
-                       // close the line string
-                       coordinates.add(coordinates.get(0));
+                       Coordinate first = coordinates.get(0);
+                       Coordinate last = coordinates.get(coordinates.size() - 1);
+                       if (!(first.getX() == last.getX() && first.getY() == last.getY())) {
+                               // close the line string
+                               coordinates.add(first);
+                       }
                        Polygon polygon = geometryFactory.createPolygon(coordinates.toArray(new Coordinate[coordinates.size()]));
                        return (T) polygon;
                } else if (SimpleFeature.class.isAssignableFrom(clss)) {
@@ -114,7 +118,7 @@ public class GpxUtils {
                return area;
        }
 
-       /** Write ODK GepShape as a GPX file. */
+       /** Write ODK GeoShape as a GPX file. */
        public static void writeGeoShapeAsGpx(String geoShape, OutputStream out) throws IOException {
                Objects.requireNonNull(geoShape);
                Writer writer = new OutputStreamWriter(out, StandardCharsets.UTF_8);