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) {
// 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)) {
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);