Skip to content

Commit

Permalink
deegree#1124 (#8363) - use JTS WKTReader instead of PostGIS WKTReader
Browse files Browse the repository at this point in the history
  • Loading branch information
lgoltz committed Jun 30, 2022
1 parent 9224bf4 commit 008246d
Show file tree
Hide file tree
Showing 5 changed files with 202 additions and 119 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@

package org.deegree.geometry;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

Expand All @@ -53,10 +54,12 @@
import org.deegree.geometry.precision.PrecisionModel;
import org.deegree.geometry.primitive.Curve;
import org.deegree.geometry.primitive.GeometricPrimitive;
import org.deegree.geometry.primitive.LineString;
import org.deegree.geometry.primitive.LinearRing;
import org.deegree.geometry.primitive.OrientableCurve;
import org.deegree.geometry.primitive.OrientableSurface;
import org.deegree.geometry.primitive.Point;
import org.deegree.geometry.primitive.Polygon;
import org.deegree.geometry.primitive.PolyhedralSurface;
import org.deegree.geometry.primitive.Ring;
import org.deegree.geometry.primitive.Solid;
Expand Down Expand Up @@ -88,6 +91,7 @@
import org.deegree.geometry.primitive.segments.Knot;
import org.deegree.geometry.primitive.segments.LineStringSegment;
import org.deegree.geometry.primitive.segments.OffsetCurve;
import org.deegree.geometry.standard.AbstractDefaultGeometry;
import org.deegree.geometry.standard.composite.DefaultCompositeCurve;
import org.deegree.geometry.standard.composite.DefaultCompositeGeometry;
import org.deegree.geometry.standard.composite.DefaultCompositeSolid;
Expand All @@ -109,12 +113,20 @@
import org.deegree.geometry.standard.curvesegments.DefaultLineStringSegment;
import org.deegree.geometry.standard.curvesegments.DefaultOffsetCurve;
import org.deegree.geometry.standard.multi.DefaultMultiCurve;
import org.deegree.geometry.standard.multi.DefaultMultiGeometry;
import org.deegree.geometry.standard.multi.DefaultMultiLineString;
import org.deegree.geometry.standard.multi.DefaultMultiPoint;
import org.deegree.geometry.standard.multi.DefaultMultiPolygon;
import org.deegree.geometry.standard.multi.DefaultMultiSolid;
import org.deegree.geometry.standard.multi.DefaultMultiSurface;
import org.deegree.geometry.standard.points.JTSPoints;
import org.deegree.geometry.standard.primitive.DefaultCurve;
import org.deegree.geometry.standard.primitive.DefaultLineString;
import org.deegree.geometry.standard.primitive.DefaultLinearRing;
import org.deegree.geometry.standard.primitive.DefaultOrientableCurve;
import org.deegree.geometry.standard.primitive.DefaultOrientableSurface;
import org.deegree.geometry.standard.primitive.DefaultPoint;
import org.deegree.geometry.standard.primitive.DefaultPolygon;
import org.deegree.geometry.standard.primitive.DefaultPolyhedralSurface;
import org.deegree.geometry.standard.primitive.DefaultRing;
import org.deegree.geometry.standard.primitive.DefaultSolid;
Expand All @@ -128,6 +140,7 @@
import org.deegree.geometry.standard.surfacepatches.DefaultRectangle;
import org.deegree.geometry.standard.surfacepatches.DefaultSphere;
import org.deegree.geometry.standard.surfacepatches.DefaultTriangle;
import org.locationtech.jts.geom.CoordinateSequence;

/**
* Augments the {@link SimpleGeometryFactory} with additional methods for building complex {@link Geometry} and
Expand Down Expand Up @@ -741,4 +754,93 @@ public CompositeGeometry<GeometricPrimitive> createCompositeGeometry( String id,
public GriddedSurfacePatch createGriddedSurfacePatch( List<Points> grid ) {
return new DefaultGriddedSurfacePatch( grid );
}


/**
* Helper methods for creating {@link AbstractDefaultGeometry} from JTS geometries that have been derived from this
* geometry by JTS spatial analysis methods.
*
* @param jtsGeom
* @param crs
* @return geometry with precision model and CoordinateSystem information that are identical to the ones of this
* geometry, or null if the given geometry is an empty collection
*/
@SuppressWarnings("unchecked")
public AbstractDefaultGeometry createFromJTS( org.locationtech.jts.geom.Geometry jtsGeom, ICRS crs ) {
AbstractDefaultGeometry geom = null;
if ( jtsGeom.isEmpty() ) {
return null;
}
if ( jtsGeom instanceof org.locationtech.jts.geom.Point ) {
org.locationtech.jts.geom.Point jtsPoint = (org.locationtech.jts.geom.Point) jtsGeom;
if ( Double.isNaN( jtsPoint.getCoordinate().z ) ) {
geom = new DefaultPoint( null, crs, pm, new double[] { jtsPoint.getX(), jtsPoint.getY() } );
} else {
geom = new DefaultPoint( null, crs, pm, new double[] { jtsPoint.getX(), jtsPoint.getY(),
jtsPoint.getCoordinate().z } );
}
} else if ( jtsGeom instanceof org.locationtech.jts.geom.LinearRing ) {
org.locationtech.jts.geom.LinearRing jtsLinearRing = (org.locationtech.jts.geom.LinearRing) jtsGeom;
geom = new DefaultLinearRing( null, crs, pm, getAsPoints( jtsLinearRing.getCoordinateSequence(), crs ) );
} else if ( jtsGeom instanceof org.locationtech.jts.geom.LineString ) {
org.locationtech.jts.geom.LineString jtsLineString = (org.locationtech.jts.geom.LineString) jtsGeom;
geom = new DefaultLineString( null, crs, pm, getAsPoints( jtsLineString.getCoordinateSequence(), crs ) );
} else if ( jtsGeom instanceof org.locationtech.jts.geom.Polygon ) {
org.locationtech.jts.geom.Polygon jtsPolygon = (org.locationtech.jts.geom.Polygon) jtsGeom;
Points exteriorPoints = getAsPoints( jtsPolygon.getExteriorRing().getCoordinateSequence(), crs );
LinearRing exteriorRing = new DefaultLinearRing( null, crs, pm, exteriorPoints );
List<Ring> interiorRings = new ArrayList<Ring>( jtsPolygon.getNumInteriorRing() );
for ( int i = 0; i < jtsPolygon.getNumInteriorRing(); i++ ) {
Points interiorPoints = getAsPoints( jtsPolygon.getInteriorRingN( i ).getCoordinateSequence(), crs );
interiorRings.add( new DefaultLinearRing( null, crs, pm, interiorPoints ) );
}
geom = new DefaultPolygon( null, crs, pm, exteriorRing, interiorRings );
} else if ( jtsGeom instanceof org.locationtech.jts.geom.MultiPoint ) {
org.locationtech.jts.geom.MultiPoint jtsMultiPoint = (org.locationtech.jts.geom.MultiPoint) jtsGeom;
if ( jtsMultiPoint.getNumGeometries() > 0 ) {
List<Point> members = new ArrayList<Point>( jtsMultiPoint.getNumGeometries() );
for ( int i = 0; i < jtsMultiPoint.getNumGeometries(); i++ ) {
members.add( (Point) createFromJTS( jtsMultiPoint.getGeometryN( i ), crs ) );
}
geom = new DefaultMultiPoint( null, crs, pm, members );
}
} else if ( jtsGeom instanceof org.locationtech.jts.geom.MultiLineString ) {
org.locationtech.jts.geom.MultiLineString jtsMultiLineString = (org.locationtech.jts.geom.MultiLineString) jtsGeom;
if ( jtsMultiLineString.getNumGeometries() > 0 ) {
List<LineString> members = new ArrayList<LineString>( jtsMultiLineString.getNumGeometries() );
for ( int i = 0; i < jtsMultiLineString.getNumGeometries(); i++ ) {
Curve curve = (Curve) createFromJTS( jtsMultiLineString.getGeometryN( i ), crs );
members.add( curve.getAsLineString() );
}
geom = new DefaultMultiLineString( null, crs, pm, members );
}
} else if ( jtsGeom instanceof org.locationtech.jts.geom.MultiPolygon ) {
org.locationtech.jts.geom.MultiPolygon jtsMultiPolygon = (org.locationtech.jts.geom.MultiPolygon) jtsGeom;
if ( jtsMultiPolygon.getNumGeometries() > 0 ) {
List<Polygon> members = new ArrayList<Polygon>( jtsMultiPolygon.getNumGeometries() );
for ( int i = 0; i < jtsMultiPolygon.getNumGeometries(); i++ ) {
members.add( (Polygon) createFromJTS( jtsMultiPolygon.getGeometryN( i ), crs ) );
}
geom = new DefaultMultiPolygon( null, crs, pm, members );
}
} else if ( jtsGeom instanceof org.locationtech.jts.geom.GeometryCollection ) {
org.locationtech.jts.geom.GeometryCollection jtsGeometryCollection = (org.locationtech.jts.geom.GeometryCollection) jtsGeom;
if ( jtsGeometryCollection.getNumGeometries() > 0 ) {
List<Geometry> members = new ArrayList<Geometry>( jtsGeometryCollection.getNumGeometries() );
for ( int i = 0; i < jtsGeometryCollection.getNumGeometries(); i++ ) {
members.add( createFromJTS( jtsGeometryCollection.getGeometryN( i ), crs ) );
}
geom = new DefaultMultiGeometry( null, crs, pm, members );
}
} else {
throw new RuntimeException( "Internal error. Encountered unhandled JTS geometry type '"
+ jtsGeom.getClass().getName() + "'." );
}
return geom;
}

private Points getAsPoints( CoordinateSequence seq, ICRS crs ) {
return new JTSPoints( crs, seq );
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,15 @@
----------------------------------------------------------------------------*/
package org.deegree.geometry.io;

import java.io.IOException;
import java.io.InputStream;

import org.deegree.cs.coordinatesystems.ICRS;
import org.deegree.geometry.Geometry;
import org.deegree.geometry.standard.AbstractDefaultGeometry;
import org.deegree.geometry.standard.primitive.DefaultPoint;

import org.deegree.geometry.GeometryFactory;
import org.locationtech.jts.io.InputStreamInStream;
import org.locationtech.jts.io.ParseException;

import java.io.IOException;
import java.io.InputStream;

/**
* Reads {@link Geometry} objects encoded as Well-Known Binary (WKB).
*
Expand All @@ -58,20 +56,18 @@
*/
public class WKBReader {

// TODO remove the need for this object
private static AbstractDefaultGeometry defaultGeom = new DefaultPoint( null, null, null, new double[] { 0.0, 0.0 } );

public static Geometry read( byte[] wkb, ICRS crs )
throws ParseException {
// org.locationtech.jts.io.WKBReader() is not thread safe
return defaultGeom.createFromJTS( new org.locationtech.jts.io.WKBReader().read( wkb ), crs );
org.locationtech.jts.geom.Geometry jtsGeom = new org.locationtech.jts.io.WKBReader().read( wkb );
return new GeometryFactory().createFromJTS( jtsGeom, crs );
}

public static Geometry read( InputStream is, ICRS crs )
throws IOException, ParseException {
// org.locationtech.jts.io.WKBReader() is not thread safe
return defaultGeom.createFromJTS(
new org.locationtech.jts.io.WKBReader().read( new InputStreamInStream( is ) ),
crs );
org.locationtech.jts.geom.Geometry jtsGeom = new org.locationtech.jts.io.WKBReader().read(
new InputStreamInStream( is ) );
return new GeometryFactory().createFromJTS( jtsGeom, crs );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,20 +38,16 @@
import org.apache.commons.io.IOUtils;
import org.deegree.cs.coordinatesystems.ICRS;
import org.deegree.geometry.Geometry;
import org.deegree.geometry.GeometryFactory;
import org.locationtech.jts.io.ParseException;
import org.postgis.GeometryBuilder;
import org.postgis.binary.BinaryWriter;

import java.io.IOException;
import java.io.Reader;
import java.sql.SQLException;

/**
* Reads {@link Geometry} objects encoded as Well-Known Text (WKT).
*
* TODO re-implement without delegating to JTS TODO add support for non-SFS geometries (e.g. non-linear curves) TODO
* TODO TODO do not go about using PostGIS for parsing the WKT, generate WKB and then parse it back using JTS TODO TODO
* TODO repeat after me s/TODO/TODO TODO/g
*
* @author <a href="mailto:schneider@lat-lon.de">Markus Schneider</a>
* @author last edited by: $Author$
Expand All @@ -78,15 +74,8 @@ public Geometry read( Reader reader )

public Geometry read( String wkt )
throws ParseException {
try {
org.postgis.Geometry g = GeometryBuilder.geomFromString( wkt );
byte[] bs = new BinaryWriter().writeBinary( g );
return WKBReader.read( bs, crs );
} catch ( SQLException e ) {
e.printStackTrace();
// wrap the exception nicely as to not break 172643521 API calls
throw new ParseException( e );
}
org.locationtech.jts.geom.Geometry jtsGeom = new org.locationtech.jts.io.WKTReader().read( wkt );
return new GeometryFactory().createFromJTS( jtsGeom, crs );
}

}
Loading

0 comments on commit 008246d

Please sign in to comment.