From ef62b6f2aa5d42ae45865eed142ab1e69f6ae43f Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Fri, 6 Oct 2023 07:24:47 +0200 Subject: [PATCH] GeoShape to Geometry --- .../src/org/argeo/app/geo/GeoShapeUtils.java | 49 +++++++++++++++++++ .../src/org/argeo/app/geo/GpxUtils.java | 10 ++-- 2 files changed, 56 insertions(+), 3 deletions(-) diff --git a/org.argeo.app.geo/src/org/argeo/app/geo/GeoShapeUtils.java b/org.argeo.app.geo/src/org/argeo/app/geo/GeoShapeUtils.java index 1db099b..d35492a 100644 --- a/org.argeo.app.geo/src/org/argeo/app/geo/GeoShapeUtils.java +++ b/org.argeo.app.geo/src/org/argeo/app/geo/GeoShapeUtils.java @@ -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 geoShapeToGeometry(String geoShape, Class clss) { + Objects.requireNonNull(geoShape); + GeometryFactory geometryFactory = JTS.GEOMETRY_FACTORY_WGS84; + List 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) { diff --git a/org.argeo.app.geo/src/org/argeo/app/geo/GpxUtils.java b/org.argeo.app.geo/src/org/argeo/app/geo/GpxUtils.java index 5b07d16..2a946f4 100644 --- a/org.argeo.app.geo/src/org/argeo/app/geo/GpxUtils.java +++ b/org.argeo.app.geo/src/org/argeo/app/geo/GpxUtils.java @@ -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); -- 2.30.2