Introduce geometry to SVG
authorMathieu Baudier <mbaudier@argeo.org>
Mon, 16 Oct 2023 07:11:33 +0000 (09:11 +0200)
committerMathieu Baudier <mbaudier@argeo.org>
Mon, 16 Oct 2023 07:11:33 +0000 (09:11 +0200)
org.argeo.app.geo/src/org/argeo/app/geo/GeoUtils.java
org.argeo.app.geo/src/org/argeo/app/geo/acr/GeoEntityUtils.java
org.argeo.app.servlet.publish/src/org/argeo/app/servlet/publish/FopServlet.java
org.argeo.app.servlet.publish/src/org/argeo/app/servlet/publish/GeoToSvgServlet.java [deleted file]

index e565866bc123cb89ce9ddc172d84b4ee0bd84f7a..47096ccc0d1f5b7b2fddb2ce27cedf9d705235b6 100644 (file)
@@ -47,7 +47,6 @@ import org.geotools.data.collection.ListFeatureCollection;
 import org.geotools.data.shapefile.ShapefileDataStore;
 import org.geotools.data.shapefile.ShapefileDataStoreFactory;
 import org.geotools.data.simple.SimpleFeatureCollection;
-import org.geotools.data.simple.SimpleFeatureIterator;
 import org.geotools.factory.CommonFactoryFinder;
 import org.geotools.geometry.jts.JTS;
 import org.geotools.referencing.CRS;
@@ -116,44 +115,45 @@ public class GeoUtils {
                }
        }
 
-       public static void exportToSvg(SimpleFeatureCollection features, Writer out, int width, int height) {
+       public static void exportToSvg(Geometry[] geometries, Writer out, int width, int height) {
                try {
                        double minY = Double.POSITIVE_INFINITY;
                        double maxY = Double.NEGATIVE_INFINITY;
                        double minX = Double.POSITIVE_INFINITY;
                        double maxX = Double.NEGATIVE_INFINITY;
                        List<String> shapes = new ArrayList<>();
-                       for (SimpleFeatureIterator it = features.features(); it.hasNext();) {
-                               SimpleFeature feature = it.next();
+                       for (Geometry geometry : geometries) {
                                StringBuffer sb = new StringBuffer();
                                sb.append("<polyline style=\"stroke-width:1;stroke:#000000;fill:none;\" points=\"");
 
-                               Polygon p = (Polygon) feature.getDefaultGeometry();
-                               Point centroid = p.getCentroid();
-                               String code = "AUTO:42001," + centroid.getX() + "," + centroid.getY();
-                               CoordinateReferenceSystem auto = CRS.decode(code);
-
-                               MathTransform transform = CRS.findMathTransform(DefaultGeographicCRS.WGS84, auto);
-
-                               Polygon projed = (Polygon) JTS.transform(p, transform);
-
-                               for (Coordinate coord : projed.getCoordinates()) {
-                                       double x = coord.x;
-                                       if (x < minX)
-                                               minX = x;
-                                       if (x > maxX)
-                                               maxX = x;
-                                       double y = -coord.y;
-                                       if (y < minY)
-                                               minY = y;
-                                       if (y > maxY)
-                                               maxY = y;
-                                       sb.append(x + "," + y + " ");
+                               if (geometry instanceof Polygon p) {
+                                       Point centroid = p.getCentroid();
+                                       String code = "AUTO:42001," + centroid.getX() + "," + centroid.getY();
+                                       CoordinateReferenceSystem auto = CRS.decode(code);
+
+                                       MathTransform transform = CRS.findMathTransform(DefaultGeographicCRS.WGS84, auto);
+
+                                       Polygon projed = (Polygon) JTS.transform(p, transform);
+
+                                       for (Coordinate coord : projed.getCoordinates()) {
+                                               double x = coord.x;
+                                               if (x < minX)
+                                                       minX = x;
+                                               if (x > maxX)
+                                                       maxX = x;
+                                               double y = -coord.y;
+                                               if (y < minY)
+                                                       minY = y;
+                                               if (y > maxY)
+                                                       maxY = y;
+                                               sb.append(x + "," + y + " ");
+                                       }
+                                       sb.append("\">");
+                                       sb.append("</polyline>\n");
+                                       shapes.add(sb.toString());
+                               } else {
+                                       throw new IllegalArgumentException("Unsuppported geometry type " + geometry.getClass().getName());
                                }
-                               sb.append("\">");
-                               sb.append("</polyline>\n");
-                               shapes.add(sb.toString());
-
                        }
                        double viewportHeight = maxY - minY;
                        double viewportWidth = maxX - minX;
index dca696285c25a4dc75c5e5c448329daf476afbfe..43f0a022e772fcaa754e369bf469a6e97baa1c2d 100644 (file)
@@ -35,7 +35,6 @@ import jakarta.json.stream.JsonGenerator;
 
 /** Utilities around entity types related to geography. */
 public class GeoEntityUtils {
-       public static final String PLACE_GEOM_JSON = "place.geom.json";
        public static final String _GEOM_JSON = ".geom.json";
 
        public static void putGeometry(Content c, QNamed name, Geometry geometry) {
index 3344d75c112af1ab7a6806c60d3082f421451b30..c81619860d248a2a5f93e9dfce99fe3fecefbf93 100644 (file)
@@ -40,15 +40,16 @@ import org.apache.xmlgraphics.io.ResourceResolver;
 import org.argeo.api.acr.Content;
 import org.argeo.api.acr.ContentRepository;
 import org.argeo.api.acr.ContentSession;
+import org.argeo.api.acr.NamespaceUtils;
 import org.argeo.app.geo.GeoUtils;
 import org.argeo.app.geo.GpxUtils;
+import org.argeo.app.geo.acr.GeoEntityUtils;
 import org.argeo.cms.acr.xml.XmlNormalizer;
 import org.argeo.cms.auth.RemoteAuthUtils;
 import org.argeo.cms.servlet.ServletHttpRequest;
 import org.argeo.cms.util.LangUtils;
-import org.geotools.api.feature.simple.SimpleFeature;
-import org.geotools.data.collection.ListFeatureCollection;
-import org.geotools.data.simple.SimpleFeatureCollection;
+import org.locationtech.jts.geom.Geometry;
+import org.locationtech.jts.geom.Polygon;
 
 import net.sf.saxon.BasicTransformerFactory;
 
@@ -81,7 +82,7 @@ public class FopServlet extends HttpServlet {
                Content content = session.get(path);
 
                // dev only
-               final boolean DEV = false;
+               final boolean DEV = true;
                if (DEV) {
                        try (InputStream in = xslUrl.openStream()) {
                                Source xslSource = new StreamSource(in);
@@ -109,21 +110,35 @@ public class FopServlet extends HttpServlet {
                                                return new StreamSource(in);
                                        }
                                        if (url.getScheme().equals("geo2svg")) {
-                                               String includePath = path + url.getPath();
-                                               String geoExt = includePath.substring(includePath.lastIndexOf('.'));
-                                               Content geoContent = session.get(includePath);
-                                               if (".gpx".equals(geoExt)) {
-                                                       try (InputStream in = geoContent.open(InputStream.class)) {
-                                                               SimpleFeature field = GpxUtils.parseGpxToPolygon(in);
-                                                               SimpleFeatureCollection features = new ListFeatureCollection(field.getType(), field);
-                                                               try (StringWriter writer = new StringWriter()) {
-                                                                       GeoUtils.exportToSvg(features, writer, 100, 100);
-                                                                       StreamSource res = new StreamSource(new StringReader(writer.toString()));
-                                                                       return res;
+                                               int lastDot = url.getPath().lastIndexOf('.');
+                                               Polygon polygon;
+                                               if (lastDot > 0) {
+                                                       String includePath = path + url.getPath();
+                                                       Content geoContent = session.get(includePath);
+                                                       String geoExt = includePath.substring(lastDot);
+                                                       if (".gpx".equals(geoExt)) {
+                                                               try (InputStream in = geoContent.open(InputStream.class)) {
+                                                                       polygon = GpxUtils.parseGpxTrackTo(in, Polygon.class);
                                                                }
+                                                       } else {
+                                                               throw new UnsupportedOperationException(geoExt + " is not supported");
                                                        }
                                                } else {
-                                                       throw new UnsupportedOperationException(geoExt + " is not supported");
+                                                       Content geoContent;
+                                                       String attrName;
+                                                       if (url.getPath().startsWith("/@")) {
+                                                               geoContent = content;
+                                                               attrName = url.getPath().substring(2);// remove /@
+                                                       } else {
+                                                               throw new IllegalArgumentException("Only direct attributes are currently supported");
+                                                       }
+                                                       polygon = GeoEntityUtils.getGeometry(geoContent, NamespaceUtils.parsePrefixedName(attrName),
+                                                                       Polygon.class);
+                                               }
+                                               try (StringWriter writer = new StringWriter()) {
+                                                       GeoUtils.exportToSvg(new Geometry[] { polygon }, writer, 100, 100);
+                                                       StreamSource res = new StreamSource(new StringReader(writer.toString()));
+                                                       return res;
                                                }
                                        }
                                }
diff --git a/org.argeo.app.servlet.publish/src/org/argeo/app/servlet/publish/GeoToSvgServlet.java b/org.argeo.app.servlet.publish/src/org/argeo/app/servlet/publish/GeoToSvgServlet.java
deleted file mode 100644 (file)
index 7ae9527..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-package org.argeo.app.servlet.publish;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URLDecoder;
-import java.nio.charset.StandardCharsets;
-import java.util.Map;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.argeo.api.acr.Content;
-import org.argeo.api.acr.ContentRepository;
-import org.argeo.api.acr.ContentSession;
-import org.argeo.app.geo.GeoUtils;
-import org.argeo.app.geo.GpxUtils;
-import org.argeo.cms.auth.RemoteAuthUtils;
-import org.argeo.cms.servlet.ServletHttpRequest;
-import org.geotools.api.feature.simple.SimpleFeature;
-import org.geotools.data.collection.ListFeatureCollection;
-import org.geotools.data.simple.SimpleFeatureCollection;
-
-/**
- * A servlet transforming an geographical data to SVG.
- */
-public class GeoToSvgServlet extends HttpServlet {
-       private static final long serialVersionUID = -6346379324580671894L;
-       private ContentRepository contentRepository;
-
-       @Override
-       protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
-               String servletPath = req.getServletPath();
-
-               servletPath = servletPath.substring(1, servletPath.lastIndexOf('.'));
-               servletPath = servletPath.substring(servletPath.indexOf('/'), servletPath.length());
-               String path = URLDecoder.decode(servletPath, StandardCharsets.UTF_8);
-               String ext = servletPath.substring(path.lastIndexOf('.'));
-
-               resp.setContentType("image/svg+xml");
-
-               ContentSession session = RemoteAuthUtils.doAs(() -> contentRepository.get(), new ServletHttpRequest(req));
-               Content content = session.get(path);
-               if (".gpx".equals(ext)) {
-                       try (InputStream in = content.open(InputStream.class)) {
-                               SimpleFeature field = GpxUtils.parseGpxToPolygon(in);
-
-                               SimpleFeatureCollection features = new ListFeatureCollection(field.getType(), field);
-                               GeoUtils.exportToSvg(features, resp.getWriter(), 100, 100);
-//                     log.debug("SVG:\n" + writer.toString() + "\n");
-                       }
-               }
-       }
-
-       public void start(Map<String, Object> properties) {
-       }
-
-       public void stop(Map<String, Object> properties) {
-
-       }
-
-       public void setContentRepository(ContentRepository contentRepository) {
-               this.contentRepository = contentRepository;
-       }
-
-}