diff --git a/deegree-core/deegree-core-geometry/src/main/java/org/deegree/geometry/io/WKTWriter.java b/deegree-core/deegree-core-geometry/src/main/java/org/deegree/geometry/io/WKTWriter.java index 191aa35983..c94e0fcd45 100644 --- a/deegree-core/deegree-core-geometry/src/main/java/org/deegree/geometry/io/WKTWriter.java +++ b/deegree-core/deegree-core-geometry/src/main/java/org/deegree/geometry/io/WKTWriter.java @@ -1,4 +1,3 @@ -//$HeadURL$ /*---------------------------------------------------------------------------- This file is part of deegree, http://deegree.org/ Copyright (C) 2001-2009 by: @@ -47,6 +46,7 @@ import org.deegree.cs.coordinatesystems.ICRS; import org.deegree.geometry.Envelope; import org.deegree.geometry.Geometry; +import org.deegree.geometry.GeometryException; import org.deegree.geometry.GeometryFactory; import org.deegree.geometry.composite.CompositeCurve; import org.deegree.geometry.composite.CompositeGeometry; @@ -64,14 +64,17 @@ import org.deegree.geometry.points.Points; import org.deegree.geometry.precision.PrecisionModel; import org.deegree.geometry.primitive.Curve; +import org.deegree.geometry.primitive.Curve.CurveType; import org.deegree.geometry.primitive.GeometricPrimitive; import org.deegree.geometry.primitive.LineString; import org.deegree.geometry.primitive.LinearRing; import org.deegree.geometry.primitive.Point; import org.deegree.geometry.primitive.Polygon; import org.deegree.geometry.primitive.Ring; +import org.deegree.geometry.primitive.Ring.RingType; import org.deegree.geometry.primitive.Solid; import org.deegree.geometry.primitive.Surface; +import org.deegree.geometry.primitive.Surface.SurfaceType; import org.deegree.geometry.primitive.Tin; import org.deegree.geometry.primitive.patches.GriddedSurfacePatch; import org.deegree.geometry.primitive.patches.PolygonPatch; @@ -89,6 +92,7 @@ import org.deegree.geometry.primitive.segments.Clothoid; import org.deegree.geometry.primitive.segments.CubicSpline; import org.deegree.geometry.primitive.segments.CurveSegment; +import org.deegree.geometry.primitive.segments.CurveSegment.CurveSegmentType; import org.deegree.geometry.primitive.segments.Geodesic; import org.deegree.geometry.primitive.segments.GeodesicString; import org.deegree.geometry.primitive.segments.LineStringSegment; @@ -103,9 +107,7 @@ * * @author Steffen Thomas * @author Markus Schneider - * @author last edited by: $Author$ - * - * @version $Revision$, $Date$ + * @author Stephan Reichhelm */ public class WKTWriter { @@ -123,9 +125,6 @@ public class WKTWriter { * The flag is used to specify which geometric operations the database is capable of * * @author Steffen Thomas - * @author last edited by: $Author$ - * - * @version $Revision$, $Date$ */ public enum WKTFlag { /** Export can use ENVELOPE */ @@ -210,6 +209,7 @@ public void setLinearizedControlPoints( int linearizedControlPoints ) { * that is used * @throws IOException */ + @SuppressWarnings("unchecked") public void writeGeometry( Geometry geometry, Writer writer ) throws IOException { @@ -465,14 +465,41 @@ private void writePolygonPatch( String id, ICRS crs, PrecisionModel pm, PolygonP */ public void writePolygon( Polygon geometry, Writer writer ) throws IOException { - - writer.append( "POLYGON " ); + if ( flags.contains( WKTFlag.USE_SQL_MM ) ) { + if ( isCompoundPolyogn( geometry ) ) { + writeCurvePolygon( geometry, writer ); + return; + } else { + writer.append( "POLYGON " ); + } + } else { + writer.append( "POLYGON " ); + } if ( flags.contains( WKTFlag.USE_DKT ) ) { appendObjectProps( writer, geometry ); } writePolygonWithoutPrefix( geometry, writer ); } + private void writeCurvePolygon( Polygon geometry, Writer writer ) + throws IOException { + writer.append( "CURVEPOLYGON " ); + writer.append( "(" ); + writeCurvePolygonWithoutPrefix( geometry, writer ); + writer.append( ')' ); + } + + private void writeCurvePolygonWithoutPrefix( Polygon geometry, Writer writer ) + throws IOException { + writeCurveGeometry( geometry.getExteriorRing(), writer ); + + for ( Ring ring : geometry.getInteriorRings() ) { + writer.append( ',' ); + writeCurveGeometry( ring, writer ); + + } + } + /** * Writes the POLYGON without the 'POLYGON()'-specific envelope.
* It writes just the POLYGON-coordinates. @@ -573,8 +600,20 @@ public void writeCompositeCurve( CompositeCurve geometry, Writer writer ) } else if ( flags.contains( WKTFlag.USE_SQL_MM ) ) { writer.append( "COMPOUNDCURVE " ); writer.append( '(' ); - // TODO implementation here; no values commited - + int counter = 0; + for ( Curve c : geometry ) { + counter++; + if ( c.getCurveType() == CurveType.LineString ) { + writer.append( '(' ); + writeLineStringWithoutPrefix( (LineString) c, writer ); + writer.append( ')' ); + } else { + writeCurve( c, writer ); + } + if ( counter != geometry.size() ) { + writer.append( ',' ); + } + } } else { List l = geometry.subList( 0, geometry.size() ); @@ -608,12 +647,16 @@ public void writeCurveGeometry( Curve geometry, Writer writer ) writeCurveSegments( geometry, writer ); writer.append( ')' ); } else if ( flags.contains( WKTFlag.USE_SQL_MM ) ) { - - // s.append( "COMPOUNDCURVE(" ); - throw new UnsupportedOperationException( "Handling curves within 'SQL-MM Part 3' is not implemented yet." ); - + int segments = geometry.getCurveSegments().size(); + if ( segments > 1 ) { + writer.write( "COMPOUNDCURVE (" ); + } + writeCurveSegments( geometry, writer ); + if ( segments > 1 ) { + writer.write( ')' ); + } } else { - CurveLinearizer cl = new CurveLinearizer( new GeometryFactory() ); + CurveLinearizer cl = linearizer != null ? linearizer : new CurveLinearizer( new GeometryFactory() ); LinearizationCriterion crit = new NumPointsCriterion( linearizedControlPoints ); Curve c = cl.linearize( geometry, crit ); @@ -635,7 +678,15 @@ private void writeCurveGeometryWithoutPrefix( Curve geometry, Writer writer ) throws IOException { if ( flags.contains( WKTFlag.USE_SQL_MM ) ) { - throw new UnsupportedOperationException( "Handling curves within 'SQL-MM Part 3' is not implemented yet." ); + int segments = geometry.getCurveSegments().size(); + if ( segments > 1 ) { + writer.write( "COMPOUNDCURVE (" ); + } + writeCurveSegments( geometry, writer ); + if ( segments > 1 ) { + writer.write( ')' ); + } + return; } CurveLinearizer cl = new CurveLinearizer( new GeometryFactory() ); LinearizationCriterion crit = new NumPointsCriterion( linearizedControlPoints ); @@ -852,7 +903,11 @@ private void writeArcStringByBulge( ArcStringByBulge curve, Writer writer ) { */ private void writeArcString( ArcString curve, Writer writer ) throws IOException { - writer.append( "ARCSTRING " ); + if ( flags.contains( WKTFlag.USE_SQL_MM ) ) { + writer.append( "CIRCULARSTRING " ); + } else { + writer.append( "ARCSTRING " ); + } // if(flags.contains( WKTFlag.USE_DKT )){ // appendObjectProps( writer, (Geometry) arcString ); // } @@ -897,7 +952,11 @@ private void writeArcByBulge( ArcByBulge curve, Writer writer ) { */ private void writeLineStringSegment( LineStringSegment curve, Writer writer ) throws IOException { - writer.append( "LINESTRINGSEGMENT " ); + if ( flags.contains( WKTFlag.USE_SQL_MM ) ) { + // write nothing + } else { + writer.append( "LINESTRINGSEGMENT " ); + } // if(flags.contains( WKTFlag.USE_DKT )){ // appendObjectProps( writer, (Geometry) createLineStringSegment ); // } @@ -922,7 +981,12 @@ private void writeLineStringSegment( LineStringSegment curve, Writer writer ) */ private void writeArc( Arc curve, Writer writer ) throws IOException { - writer.append( "ARC " ); + if ( flags.contains( WKTFlag.USE_SQL_MM ) ) { + writer.append( "CIRCULARSTRING " ); + } else { + writer.append( "ARC " ); + } + // if(flags.contains( WKTFlag.USE_DKT )){ // appendObjectProps( writer, (Geometry) createArc ); // } @@ -1046,6 +1110,7 @@ public void writeLinearRing( LinearRing geometry, Writer writer ) * @param writer * @throws IOException */ + @SuppressWarnings({ "unchecked", "rawtypes" }) public void writeMultiGeometry( MultiGeometry geometry, Writer writer ) throws IOException { @@ -1096,7 +1161,31 @@ public void writeMultiSolid( MultiSolid geometry, Writer writer ) { */ public void writeMultiSurface( MultiSurface geometry, Writer writer ) throws IOException { - writer.append( "MULTIPOLYGON " ); + if ( flags.contains( WKTFlag.USE_SQL_MM ) ) { + writer.append( "MULTISURFACE " ); + writer.write( '(' ); + int counter = 0; + for ( Surface surface : geometry ) { + counter++; + if ( surface.getSurfaceType() == SurfaceType.Polygon ) { + if ( isCompoundPolyogn( (Polygon) surface ) ) { + writeCurvePolygon( (Polygon) surface, writer ); + } else { + writer.write( '(' ); + writeCurvePolygonWithoutPrefix( (Polygon) surface, writer ); + writer.write( ')' ); + } + } else { + writeSurface( surface, writer ); + } + if ( counter < geometry.size() ) + writer.write( ',' ); + } + writer.write( ')' ); + return; + } else { + writer.append( "MULTIPOLYGON " ); + } if ( flags.contains( WKTFlag.USE_DKT ) ) { appendObjectProps( writer, geometry ); } @@ -1121,7 +1210,11 @@ public void writeMultiSurface( MultiSurface geometry, Writer writer ) public void writeMultiCurve( MultiCurve geometry, Writer writer ) throws IOException { - writer.append( "MULTILINESTRING " ); + if ( flags.contains( WKTFlag.USE_SQL_MM ) ) { + writer.append( "MULTICURVE " ); + } else { + writer.append( "MULTILINESTRING " ); + } if ( flags.contains( WKTFlag.USE_DKT ) ) { appendObjectProps( writer, geometry ); } @@ -1315,6 +1408,7 @@ public void writeEnvelope( Envelope envelope, Writer writer ) * @return a wkt String representation of the given geometry, of the emtpy string if the geometry is * null */ + @SuppressWarnings("unchecked") public static String write( Geometry geom ) { if ( geom == null ) { return ""; @@ -1353,11 +1447,15 @@ public static void write( Geometry geom, Writer writer ) throw new NullPointerException( "The writer may not be null." ); } Set flags = new HashSet(); - int dim =geom.getCoordinateDimension(); - if (dim == 3){ - flags.add( WKTWriter.WKTFlag.USE_3D ); - } - else{ + try { + int dim = geom.getCoordinateDimension(); + if ( dim == 3 ) { + flags.add( WKTWriter.WKTFlag.USE_3D ); + } else { + flags = null; + } + } catch ( GeometryException gex ) { + // ignore dimension on empty geometries flags = null; } WKTWriter wktW = new WKTWriter( flags, null ); @@ -1387,4 +1485,67 @@ private void appendObjectProps( Writer writer, Geometry geom ) writer.append( '\'' ); writer.append( ']' ); } + + /** + * Test if Polygon is made from compound rings + * + * @return true if the polygon is constructed from non-linear rings, rings which are non-linear or rings with + * contains more than one segment + */ + private boolean isCompoundPolyogn( Polygon geometry ) { + if ( isCompoundRing( geometry.getExteriorRing() ) ) { + return true; + } + for ( Ring ring : geometry.getInteriorRings() ) { + if ( isCompoundRing( ring ) ) { + return true; + } + } + return false; + } + + /** + * Test if Ring is compound (non-linear or made from more than one segment) + * + * @return true if the ring is non-linear or the ring is made from more than one segment + */ + private boolean isCompoundRing( Ring geometry ) { + if ( geometry.getRingType() == RingType.LinearRing ) { + return false; + } else { + if ( geometry.getMembers().size() > 1 ) + return true; + + for ( Curve c : geometry.getMembers() ) { + if ( isCompoundCurve( c ) ) { + return true; + } + } + } + return false; + } + + /** + * Test if Curve is compound (non-linear or made from more than one segment) + * + * @return true if the curve is non-linear or the curve is made from more than one segment + */ + private boolean isCompoundCurve( Curve geometry ) { + if ( geometry.getCurveType() == CurveType.LineString ) { + return false; + } else if ( geometry.getCurveType() == CurveType.Ring ) { + return isCompoundRing( (Ring) geometry ); + } else if ( geometry.getCurveType() == CurveType.Curve ) { + List segments = geometry.getCurveSegments(); + if ( segments.size() > 1 ) + return true; + + for ( CurveSegment seg : segments ) { + if ( seg.getSegmentType() != CurveSegmentType.LINE_STRING_SEGMENT ) { + return true; + } + } + } + return true; + } } diff --git a/deegree-core/deegree-core-geometry/src/main/java/org/deegree/geometry/linearization/CurveLinearizer.java b/deegree-core/deegree-core-geometry/src/main/java/org/deegree/geometry/linearization/CurveLinearizer.java index c7e8e28703..49b42e3c9d 100644 --- a/deegree-core/deegree-core-geometry/src/main/java/org/deegree/geometry/linearization/CurveLinearizer.java +++ b/deegree-core/deegree-core-geometry/src/main/java/org/deegree/geometry/linearization/CurveLinearizer.java @@ -230,13 +230,17 @@ public LineStringSegment linearizeArc( Arc arc, LinearizationCriterion crit ) { LineStringSegment lineSegment = null; if ( areCollinear( arc.getPoint1(), arc.getPoint2(), arc.getPoint3() ) ) { + // non-standard special case full circle defined by diameter (p0 - p1, p0 == p2) + if ( arc.getPoint1().equals( arc.getPoint3() ) ) { + return linearizeArcString( arc, crit ); + } + // if the points are already on a line we don't need to (and must not) apply any linearization algorithm Points points = null; if ( arc instanceof Circle ) { - points = new PointsList( - Arrays.asList( new Point[] { arc.getPoint1(), arc.getPoint2(), arc.getPoint1() } ) ); + points = new PointsList( Arrays.asList( arc.getPoint1(), arc.getPoint2(), arc.getPoint1() ) ); } else { - points = new PointsList( Arrays.asList( new Point[] { arc.getPoint1(), arc.getPoint3() } ) ); + points = new PointsList( Arrays.asList( arc.getPoint1(), arc.getPoint3() ) ); } lineSegment = geomFac.createLineStringSegment( points ); @@ -254,7 +258,7 @@ public LineStringSegment linearizeArc( Arc arc, LinearizationCriterion crit ) { if ( maxNumPoints > 0 && maxNumPoints < numPoints ) { numPoints = maxNumPoints; } - LOG.debug( "Using " + numPoints + " for segment linearization." ); + LOG.debug( "Using {} for segment linearization.", numPoints ); lineSegment = geomFac.createLineStringSegment( interpolate( arc.getPoint1(), arc.getPoint2(), arc.getPoint3(), numPoints, arc instanceof Circle ) ); @@ -296,7 +300,20 @@ public LineStringSegment linearizeArcString( ArcString arcString, LinearizationC a = srcpnts.get( i ); b = srcpnts.get( i + 1 ); c = srcpnts.get( i + 2 ); - if ( areCollinear( a, b, c ) ) { + if ( j == 1 && a.equals( c ) ) { + // non-standard special case full circle defined by diameter (p0 - p1, p0 == p2) + int numPoints; + if ( crit instanceof NumPointsCriterion ) { + numPoints = ( (NumPointsCriterion) crit ).getNumberOfPoints(); + } else if (crit instanceof MaxErrorCriterion) { + double error = ( (MaxErrorCriterion) crit ).getMaxError(); + numPoints = calcNumPointsForCircleByDiameter( a, b, error ); + } else { + String msg = "Handling of criterion '" + crit.getClass().getName() + "' is not implemented yet."; + throw new IllegalArgumentException( msg ); + } + pnts = interpolateCircleByDiameter( a, b, numPoints ); + } else if ( areCollinear( a, b, c ) ) { pnts = new PointsArray( a, b, c ); } else if ( crit instanceof NumPointsCriterion ) { int numPoints = ( (NumPointsCriterion) crit ).getNumberOfPoints(); @@ -308,7 +325,7 @@ public LineStringSegment linearizeArcString( ArcString arcString, LinearizationC if ( maxNumPoints > 0 && maxNumPoints < numPoints ) { numPoints = maxNumPoints; } - LOG.debug( "Using " + numPoints + " for segment linearization." ); + LOG.debug( "Using {} for segment linearization.", numPoints ); pnts = interpolate( a, b, c, numPoints, false ); } else { String msg = "Handling of criterion '" + crit.getClass().getName() + "' is not implemented yet."; @@ -568,6 +585,35 @@ private double createAngleStep( double startAngle, double endAngle, int numPoint return angleStep; } + /** + * interpolate a circle where the points p0 and p1 define the diameter + */ + private Points interpolateCircleByDiameter( Point p0, Point p1, int numPoints ){ + // shift the points down (to reduce the occurrence of floating point errors), independently on the x and y axes + double minOrd0 = findShiftOrd0( p0, p1, p1 ); + double minOrd1 = findShiftOrd1( p0, p1, p1 ); + + // if the points are already shifted, this does no harm! + Point p0Shifted = new DefaultPoint( null, p0.getCoordinateSystem(), p0.getPrecision(), + new double[] { p0.get0() - minOrd0, p0.get1() - minOrd1 } ); + Point p1Shifted = new DefaultPoint( null, p1.getCoordinateSystem(), p1.getPrecision(), + new double[] { p1.get0() - minOrd0, p1.get1() - minOrd1 } ); + + double centerX = ( p0Shifted.get0() + p1Shifted.get0() ) / 2; + double centerY = ( p0Shifted.get1() + p1Shifted.get1() ) / 2; + + double dx = p0Shifted.get0() - centerX; + double dy = p0Shifted.get1() - centerY; + + double startAngle = Math.atan2( dy, dx ); + double endAngle = startAngle; + double radius = Math.sqrt( dx * dx + dy * dy ); + + double angleStep = createAngleStep( startAngle, endAngle, numPoints, true ); + + return interpolatePoints( startAngle, angleStep, radius, numPoints, centerX, centerY, minOrd0, minOrd1, p0Shifted, p0Shifted ); + } + private Points interpolate( Point p0, Point p1, Point p2, int numPoints, boolean isCircle ) { // shift the points down (to reduce the occurrence of floating point errors), independently on the x and y axes @@ -582,7 +628,6 @@ private Points interpolate( Point p0, Point p1, Point p2, int numPoints, boolean Point p2Shifted = new DefaultPoint( null, p2.getCoordinateSystem(), p2.getPrecision(), new double[] { p2.get0() - minOrd0, p2.get1() - minOrd1 } ); - List interpolationPoints = new ArrayList( numPoints ); Point center = calcCircleCenter( p0Shifted, p1Shifted, p2Shifted ); double centerX = center.get0(); @@ -599,9 +644,19 @@ private Points interpolate( Point p0, Point p1, Point p2, int numPoints, boolean double angleStep = createAngleStep( startAngle, endAngle, numPoints, isClockwise( p0Shifted, p1Shifted, p2Shifted ) ); - ICRS crs = p0Shifted.getCoordinateSystem(); + + return interpolatePoints( startAngle, angleStep, radius, numPoints, centerX, centerY, minOrd0, minOrd1, + p0Shifted, isCircle ? p0Shifted : p2Shifted); + } + + private Points interpolatePoints( double startAngle, double angleStep, double radius, int numPoints, + double centerX, double centerY, double minOrd0, double minOrd1, + Point startPointShifted, Point endPointShifted ) { + List interpolationPoints = new ArrayList<>( numPoints ); + + ICRS crs = startPointShifted.getCoordinateSystem(); // ensure numerical stability for start point (= use original circle start point) - interpolationPoints.add( p0Shifted ); + interpolationPoints.add( startPointShifted ); // calculate intermediate (=interpolated) points on arc for ( int i = 1; i < numPoints - 1; i++ ) { @@ -611,10 +666,10 @@ private Points interpolate( Point p0, Point p1, Point p2, int numPoints, boolean interpolationPoints.add( geomFac.createPoint( null, new double[] { x, y }, crs ) ); } // ensure numerical stability for end point (= use original circle start point) - interpolationPoints.add( isCircle ? p0Shifted : p2Shifted ); + interpolationPoints.add( endPointShifted ); // shift the points back up - List realPoints = new ArrayList( interpolationPoints.size() ); + List realPoints = new ArrayList<>( interpolationPoints.size() ); for ( Point p : interpolationPoints ) { realPoints.add( new DefaultPoint( null, p.getCoordinateSystem(), p.getPrecision(), new double[] { p.get0() + minOrd0, p.get1() + minOrd1 } ) ); @@ -623,6 +678,32 @@ private Points interpolate( Point p0, Point p1, Point p2, int numPoints, boolean return new PointsList( realPoints ); } + /** + * calculate the required number of point for a circle where the points p0 and p1 define the diameter + */ + private int calcNumPointsForCircleByDiameter(Point p0, Point p1, double error) { + double minOrd0 = CurveLinearizer.findShiftOrd0( p0, p1, p1 ); + double minOrd1 = CurveLinearizer.findShiftOrd1( p0, p1, p1 ); + + // if the points are already shifted, this does no harm! + Point p0Shifted = new DefaultPoint( null, p0.getCoordinateSystem(), p0.getPrecision(), + new double[] { p0.get0() - minOrd0, p0.get1() - minOrd1 } ); + Point p1Shifted = new DefaultPoint( null, p1.getCoordinateSystem(), p1.getPrecision(), + new double[] { p1.get0() - minOrd0, p1.get1() - minOrd1 } ); + + double centerX = ( p0Shifted.get0() + p1Shifted.get0() ) / 2; + double centerY = ( p0Shifted.get1() + p1Shifted.get1() ) / 2; + + double dx = p0Shifted.get0() - centerX; + double dy = p0Shifted.get1() - centerY; + + double radius = Math.sqrt( dx * dx + dy * dy ); + + double angleStep = 2 * Math.acos( 1 - error / radius ); + int numPoints = (int) Math.ceil( 2 * Math.PI / angleStep ) + 2; + return numPoints; + } + private int calcNumPoints( Point p0, Point p1, Point p2, boolean isCircle, double error ) { // shift the points down (to reduce the occurrence of floating point errors), independently on the x and y axes diff --git a/deegree-core/deegree-core-geometry/src/main/java/org/deegree/geometry/standard/multi/DefaultMultiCurve.java b/deegree-core/deegree-core-geometry/src/main/java/org/deegree/geometry/standard/multi/DefaultMultiCurve.java index a900fb5c88..63e246b5fe 100644 --- a/deegree-core/deegree-core-geometry/src/main/java/org/deegree/geometry/standard/multi/DefaultMultiCurve.java +++ b/deegree-core/deegree-core-geometry/src/main/java/org/deegree/geometry/standard/multi/DefaultMultiCurve.java @@ -35,13 +35,13 @@ ----------------------------------------------------------------------------*/ package org.deegree.geometry.standard.multi; +import java.util.ArrayList; import java.util.List; - import org.deegree.cs.coordinatesystems.ICRS; import org.deegree.geometry.multi.MultiCurve; import org.deegree.geometry.precision.PrecisionModel; import org.deegree.geometry.primitive.Curve; - +import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.LineString; import org.locationtech.jts.geom.MultiLineString; @@ -82,11 +82,18 @@ public MultiGeometryType getMultiGeometryType() { @Override protected MultiLineString buildJTSGeometry() { - LineString[] jtsMembers = new LineString[size()]; - int i = 0; + List jtsMembers = new ArrayList<>( size() ); + for ( Curve geometry : members ) { - jtsMembers[i++] = (LineString) getAsDefaultGeometry( geometry ).getJTSGeometry(); + Geometry jtsGeom = getAsDefaultGeometry( geometry ).getJTSGeometry(); + if ( jtsGeom instanceof MultiLineString ) { + for ( int i = 0; i < jtsGeom.getNumGeometries(); i++ ) { + jtsMembers.add( (LineString) jtsGeom.getGeometryN( i ) ); + } + } else { + jtsMembers.add( (LineString) jtsGeom ); + } } - return jtsFactory.createMultiLineString( jtsMembers ); + return jtsFactory.createMultiLineString( jtsMembers.toArray( new LineString[0] ) ); } } diff --git a/deegree-core/deegree-core-geometry/src/test/java/org/deegree/geometry/io/WKTWriterSqlMMTests.java b/deegree-core/deegree-core-geometry/src/test/java/org/deegree/geometry/io/WKTWriterSqlMMTests.java new file mode 100644 index 0000000000..153c4d1743 --- /dev/null +++ b/deegree-core/deegree-core-geometry/src/test/java/org/deegree/geometry/io/WKTWriterSqlMMTests.java @@ -0,0 +1,105 @@ +/*---------------------------------------------------------------------------- + This file is part of deegree, http://deegree.org/ + Copyright (C) 2022 by: + - grit graphische Informationstechnik Beratungsgesellschaft mbH - + + This library is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at your option) + any later version. + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + details. + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Contact information: + + grit graphische Informationstechnik Beratungsgesellschaft mbH + Landwehrstr. 143, 59368 Werne + Germany + http://www.grit.de/ + + lat/lon GmbH + Aennchenstr. 19, 53177 Bonn + Germany + http://lat-lon.de/ + + Department of Geography, University of Bonn + Prof. Dr. Klaus Greve + Postfach 1147, 53001 Bonn + Germany + http://www.geographie.uni-bonn.de/deegree/ + + e-mail: info@deegree.org + ----------------------------------------------------------------------------*/ +package org.deegree.geometry.io; + +import static org.deegree.geometry.io.WKTWriter.WKTFlag.USE_SQL_MM; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; + +import java.io.IOException; +import java.io.StringWriter; +import java.util.List; +import java.util.Set; +import org.deegree.geometry.Geometry; +import org.deegree.geometry.GeometryFactory; +import org.deegree.geometry.primitive.Curve; +import org.deegree.geometry.primitive.Point; +import org.deegree.geometry.primitive.Ring; +import org.deegree.geometry.primitive.segments.ArcString; +import org.deegree.geometry.primitive.segments.LineStringSegment; +import org.junit.Test; + +public class WKTWriterSqlMMTests { + private static GeometryFactory fac = new GeometryFactory(); + + private static WKTWriter wkt = new WKTWriter( Set.of( USE_SQL_MM ), new DecimalCoordinateFormatter( 0 ) ); + + @Test + public void testPolygonFromArcString() + throws IOException { + List points = List.of( fac.createPoint( null, 0, 0, null ), // + fac.createPoint( null, 10, 0, null ), // + fac.createPoint( null, 0, 0, null ) ); + ArcString circle = fac.createArcString( fac.createPoints( points ) ); + Ring ring = fac.createRing( null, null, List.of( fac.createCurve( null, null, circle ) ) ); + Geometry geom = fac.createPolygon( null, null, ring, null ); + + StringWriter out = new StringWriter(); + wkt.writeGeometry( geom, out ); + assertThat( out.toString(), is( "CURVEPOLYGON (CIRCULARSTRING (0 0,10 0,0 0))" ) ); + } + + @Test + public void testCurveArcString() + throws IOException { + List points = List.of( fac.createPoint( null, 0, 0, null ), // + fac.createPoint( null, 10, 0, null ), // + fac.createPoint( null, 0, 0, null ) ); + ArcString circle = fac.createArcString( fac.createPoints( points ) ); + Curve curve = fac.createCurve( null, null, circle ); + + StringWriter out = new StringWriter(); + wkt.writeCurveGeometry( curve, out ); + assertThat( out.toString(), is( "CIRCULARSTRING (0 0,10 0,0 0)" ) ); + } + + @Test + public void testCompoundCurve() + throws IOException { + List points = List.of( fac.createPoint( null, 0, 0, null ), // + fac.createPoint( null, 10, 0, null ), // + fac.createPoint( null, 0, 0, null ) ); + ArcString circle = fac.createArcString( fac.createPoints( points ) ); + LineStringSegment line = fac.createLineStringSegment( fac.createPoints( points ) ); + Curve curve = fac.createCurve( null, null, circle, line ); + + StringWriter out = new StringWriter(); + wkt.writeCurveGeometry( curve, out ); + assertThat( out.toString(), is( "COMPOUNDCURVE (CIRCULARSTRING (0 0,10 0,0 0),(0 0,10 0,0 0))" ) ); + } +}