X-Git-Url: https://git.argeo.org/?a=blobdiff_plain;f=org.argeo.app.geo%2Fsrc%2Forg%2Fargeo%2Fapp%2Fgeo%2FGpxUtils.java;h=5b07d1677fe72166ae9329327062812ddf35b37b;hb=b96d17f3eb275a97109cc160db1cfd3731a01d31;hp=645b08bda8d9ed13b05c4488e1c3ad326e3f660f;hpb=37c5768d88096f4eb7be02f18770b6a40be5c110;p=gpl%2Fargeo-suite.git 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 645b08b..5b07d16 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 @@ -18,9 +18,11 @@ import javax.xml.parsers.SAXParserFactory; 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.MultiPoint; import org.locationtech.jts.geom.Polygon; import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.simple.SimpleFeatureType; @@ -30,14 +32,30 @@ import org.xml.sax.helpers.DefaultHandler; /** 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 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 parseGpxTrackTo(InputStream in, Class clss) throws IOException { + GeometryFactory geometryFactory = JTS.GEOMETRY_FACTORY_WGS84; + List coordinates = new ArrayList<>(); + try { SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser saxParser = factory.newSAXParser(); @@ -49,24 +67,54 @@ public class GpxUtils { 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 (MultiPoint.class.isAssignableFrom(clss)) { + MultiPoint multiPoint = geometryFactory + .createMultiPointFromCoords(coordinates.toArray(new Coordinate[coordinates.size()])); + // multiPoint.normalize(); + return (T) multiPoint; + } 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; + } 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);