Support geometry field in CSV
authorMathieu Baudier <mbaudier@argeo.org>
Mon, 11 Sep 2023 12:17:24 +0000 (14:17 +0200)
committerMathieu Baudier <mbaudier@argeo.org>
Mon, 11 Sep 2023 12:17:24 +0000 (14:17 +0200)
org.argeo.app.geo/src/org/argeo/app/geo/GeoShapeUtils.java [new file with mode: 0644]
org.argeo.app.servlet.odk/src/org/argeo/app/servlet/odk/OdkManifestServlet.java

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
new file mode 100644 (file)
index 0000000..1db099b
--- /dev/null
@@ -0,0 +1,51 @@
+package org.argeo.app.geo;
+
+import org.locationtech.jts.geom.Coordinate;
+import org.locationtech.jts.geom.Geometry;
+import org.locationtech.jts.geom.LineString;
+import org.locationtech.jts.geom.Point;
+import org.locationtech.jts.geom.Polygon;
+
+/** Utilities around ODK's GeoShape format */
+public class GeoShapeUtils {
+
+       /** Converts a {@link Geometry} with WGS84 coordinates to a GeoShape. */
+       public static String geometryToGeoShape(Geometry geometry) {
+               if (geometry instanceof Point point) {
+                       Coordinate coordinate = point.getCoordinate();
+                       StringBuilder sb = new StringBuilder();
+                       appendToGeoShape(sb, coordinate.getX(), coordinate.getY(), coordinate.getZ());
+                       return sb.toString();
+               } else if (geometry instanceof Polygon || geometry instanceof LineString) {
+                       StringBuilder sb = new StringBuilder();
+                       for (Coordinate coordinate : geometry.getCoordinates()) {
+                               appendToGeoShape(sb, coordinate.getX(), coordinate.getY(), coordinate.getZ());
+                               sb.append(';');
+                       }
+                       return sb.toString();
+               } else {
+                       throw new IllegalArgumentException("Unsupported geometry " + geometry.getClass());
+               }
+       }
+
+       public static String geoPointToGeoShape(double lon, double lat, double alt) {
+               StringBuilder sb = new StringBuilder();
+               appendToGeoShape(sb, lon, lat, alt);
+               return sb.toString();
+       }
+
+       private static void appendToGeoShape(StringBuilder sb, double lon, double lat, double alt) {
+               sb.append(lat).append(' ');
+               sb.append(lon).append(' ');
+               if (alt != Double.NaN)
+                       sb.append(alt).append(' ');
+               else
+                       sb.append("0 ");
+               sb.append('0');
+       }
+
+       /** singleton */
+       private GeoShapeUtils() {
+       }
+
+}
index 6e145c2b951fb0f87013e3887b29258a181973e9..6cc71d6f97716188ff36d3b55f1d8cee706e9b7c 100644 (file)
@@ -30,6 +30,9 @@ import javax.servlet.http.HttpServletResponse;
 
 import org.apache.commons.io.output.NullOutputStream;
 import org.argeo.app.api.EntityMimeType;
+import org.argeo.app.api.EntityType;
+import org.argeo.app.api.WGS84PosName;
+import org.argeo.app.geo.GeoShapeUtils;
 import org.argeo.app.odk.OrxManifestName;
 import org.argeo.cms.auth.RemoteAuthUtils;
 import org.argeo.cms.servlet.ServletHttpRequest;
@@ -142,6 +145,7 @@ public class OdkManifestServlet extends HttpServlet {
                        }
                        // TODO make it more configurable
                        columnNames.add("display");
+                       columnNames.add("geometry");
 
                        if (EntityMimeType.XML.equals(mimeType)) {
                        } else if (EntityMimeType.CSV.equals(mimeType)) {
@@ -158,6 +162,16 @@ public class OdkManifestServlet extends HttpServlet {
                                                }
                                                // display
                                                lst.add(row.getValue("name").getString() + " (" + row.getValue("label").getString() + ")");
+                                               Node field = row.getNode("geopoint");
+                                               if (field != null && field.isNodeType(EntityType.geopoint.get())) {
+                                                       double lat = field.getProperty(WGS84PosName.lat.get()).getDouble();
+                                                       double lon = field.getProperty(WGS84PosName.lng.get()).getDouble();
+                                                       double alt = field.hasProperty(WGS84PosName.alt.get())
+                                                                       ? field.getProperty(WGS84PosName.alt.get()).getDouble()
+                                                                       : Double.NaN;
+                                                       String geoshape = GeoShapeUtils.geoPointToGeoShape(lon, lat, alt);
+                                                       lst.add(geoshape);
+                                               }
                                                csvWriter.writeLine(lst);
                                        }
                                } else {