+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" immediate="true">
- <implementation class="org.argeo.app.geo.http.WfsHttpHandler"/>
- <service>
- <provide interface="com.sun.net.httpserver.HttpHandler"/>
- </service>
- <property name="context.path" type="String" value="/api/geojson/" />
- <property name="context.public" type="String" value="true" />
- <reference bind="setContentRepository" cardinality="1..1" interface="org.argeo.api.acr.spi.ProvidedRepository" name="ProvidedRepository" policy="static"/>
-</scr:component>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" immediate="true">
+ <implementation class="org.argeo.app.geo.http.WfsHttpHandler"/>
+ <service>
+ <provide interface="com.sun.net.httpserver.HttpHandler"/>
+ </service>
+ <property name="context.path" type="String" value="/api/wfs/" />
+ <reference bind="setContentRepository" cardinality="1..1" interface="org.argeo.api.acr.spi.ProvidedRepository" name="ProvidedRepository" policy="static"/>
+</scr:component>
*
Service-Component:\
-OSGI-INF/geoJsonHttpHandler.xml,\
+OSGI-INF/wfsHttpHandler.xml,\
--- /dev/null
+package org.argeo.app.geo;
+
+import org.argeo.api.cms.CmsLog;
+import org.geotools.factory.CommonFactoryFinder;
+import org.geotools.geometry.jts.JTSFactoryFinder;
+import org.geotools.styling.StyleFactory;
+import org.locationtech.jts.geom.GeometryFactory;
+import org.opengis.filter.FilterFactory2;
+
+/**
+ * Factories initialisation and workarounds for the GeoTools library. The idea
+ * is to code defensively around factory initialisation, API changes, and issues
+ * related to running in an OSGi environment. Rather see {@link GeoUtils} for
+ * functional static utilities.
+ */
+public class GeoTools {
+ private final static CmsLog log = CmsLog.getLog(GeoTools.class);
+
+ public final static GeometryFactory GEOMETRY_FACTORY;
+ public final static StyleFactory STYLE_FACTORY;
+ public final static FilterFactory2 FILTER_FACTORY;
+
+ static {
+ try {
+ GEOMETRY_FACTORY = JTSFactoryFinder.getGeometryFactory();
+ STYLE_FACTORY = CommonFactoryFinder.getStyleFactory();
+ FILTER_FACTORY = CommonFactoryFinder.getFilterFactory2();
+ } catch (RuntimeException e) {
+ log.error("Basic GeoTools initialisation failed, geographical utilities are probably not available", e);
+ throw e;
+ }
+ }
+
+}
import org.geotools.data.DataUtilities;
import org.geotools.feature.SchemaException;
import org.geotools.feature.simple.SimpleFeatureBuilder;
-import org.geotools.geometry.jts.JTSFactoryFinder;
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.Polygon;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
/** Utilities around the GPX format. */
public class GpxUtils {
+ /** GPX as a LineString in WGS84 (feature type with only the_geom). */
+ public static final SimpleFeatureType LINESTRING_FEATURE_TYPE;
+ /** GPX as a Polygon in WGS84 (feature type with only the_geom). */
+ public static final SimpleFeatureType POLYGON_FEATURE_TYPE;
- public static SimpleFeature parseGpxToPolygon(InputStream in) throws IOException {
+ static {
try {
- final SimpleFeatureType TYPE = DataUtilities.createType("Area", "the_geom:Polygon:srid=4326");
- SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(TYPE);
+ LINESTRING_FEATURE_TYPE = DataUtilities.createType("Area", "the_geom:LineString:srid=4326");
+ POLYGON_FEATURE_TYPE = DataUtilities.createType("Area", "the_geom:Polygon:srid=4326");
+ } catch (SchemaException e) {
+ throw new RuntimeException("Cannot create GPX Feature type", e);
+ }
+ }
- GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory();
- List<Coordinate> coordinates = new ArrayList<>();
+ /**
+ * Converts a GPX track to either a {@link Geometry} with WGS84 coordinates
+ * ({@link LineString} or {@link Polygon}) or a {@link SimpleFeature} (with
+ * {@link #LINESTRING_FEATURE_TYPE}).
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> T parseGpxTrackTo(InputStream in, Class<T> clss) throws IOException {
+ GeometryFactory geometryFactory = GeoTools.GEOMETRY_FACTORY;
+ List<Coordinate> coordinates = new ArrayList<>();
+ try {
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
if ("trkpt".equals(qName)) {
Double latitude = Double.parseDouble(attributes.getValue("lat"));
Double longitude = Double.parseDouble(attributes.getValue("lon"));
+ // TODO elevation in 3D context
Coordinate coordinate = new Coordinate(longitude, latitude);
coordinates.add(coordinate);
}
}
});
+ } catch (ParserConfigurationException | SAXException e) {
+ throw new RuntimeException("Cannot convert GPX", e);
+ }
+
+ if (LineString.class.isAssignableFrom(clss)) {
+ LineString lineString = geometryFactory
+ .createLineString(coordinates.toArray(new Coordinate[coordinates.size()]));
+ return (T) lineString;
+ } else if (Polygon.class.isAssignableFrom(clss)) {
// close the line string
coordinates.add(coordinates.get(0));
-
Polygon polygon = geometryFactory.createPolygon(coordinates.toArray(new Coordinate[coordinates.size()]));
- featureBuilder.add(polygon);
+ return (T) polygon;
+ }
+ // TODO MultiPoint? MultiLine? etc.
+ else if (SimpleFeature.class.isAssignableFrom(clss)) {
+ SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(LINESTRING_FEATURE_TYPE);
+ LineString lineString = geometryFactory
+ .createLineString(coordinates.toArray(new Coordinate[coordinates.size()]));
+ featureBuilder.add(lineString);
SimpleFeature area = featureBuilder.buildFeature(null);
- return area;
- } catch (ParserConfigurationException | SAXException | SchemaException e) {
- throw new RuntimeException("Cannot convert GPX", e);
+ return (T) area;
+ } else {
+ throw new IllegalArgumentException("Unsupported format " + clss);
}
}
+ /** @deprecated Use {@link #parseGpxTrackTo(InputStream, Class)} instead. */
+ @Deprecated
+ public static SimpleFeature parseGpxToPolygon(InputStream in) throws IOException {
+ SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(POLYGON_FEATURE_TYPE);
+ Polygon polygon = parseGpxTrackTo(in, Polygon.class);
+ featureBuilder.add(polygon);
+ SimpleFeature area = featureBuilder.buildFeature(null);
+ return area;
+ }
+
+ /** Write ODK GepShape 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);
import org.argeo.app.api.EntityType;
import org.argeo.app.api.WGS84PosName;
import org.argeo.app.geo.CqlUtils;
+import org.argeo.app.geo.GeoTools;
import org.argeo.app.geo.GpxUtils;
import org.argeo.cms.http.HttpHeader;
import org.argeo.cms.http.server.HttpServerUtils;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.GeometryFactory;
+import org.locationtech.jts.geom.Polygon;
import org.opengis.feature.GeometryAttribute;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
// SimpleFeatureType featureType = DataUtilities.simple(parsed);
SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(featureType);
- GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory();
DefaultFeatureCollection featureCollection = new DefaultFeatureCollection();
res.forEach((c) -> {
// boolean gpx = false;
Geometry the_geom = null;
- Geometry the_area = null;
+ Polygon the_area = null;
// if (gpx) {
Content area = c.getContent("gpx/area.gpx").orElse(null);
if (area != null) {
try (InputStream in = area.open(InputStream.class)) {
- SimpleFeature feature = GpxUtils.parseGpxToPolygon(in);
- the_area = (Geometry) feature.getDefaultGeometry();
+ the_area = GpxUtils.parseGpxTrackTo(in, Polygon.class);
} catch (IOException e) {
throw new UncheckedIOException("Cannot parse " + c, e);
}
double longitude = c.get(WGS84PosName.lng, Double.class).get();
Coordinate coordinate = new Coordinate(longitude, latitude);
- the_geom = geometryFactory.createPoint(coordinate);
+ the_geom = GeoTools.GEOMETRY_FACTORY.createPoint(coordinate);
}
// }
if (the_geom != null)
featureBuilder.set(new NameImpl(namespace, "geopoint"), the_geom);
if (the_area != null)
- featureBuilder.set(new NameImpl(namespace, "area"), the_geom);
+ featureBuilder.set(new NameImpl(namespace, "area"), the_area);
List<AttributeDescriptor> attrDescs = featureType.getAttributeDescriptors();
for (AttributeDescriptor attrDesc : attrDescs) {