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 extends Geometry> 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))" ) );
+ }
+}