Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend the serialization of SQL/MM (curved) geometries to WKT #1412

Merged
merged 2 commits into from
Oct 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
//$HeadURL$
/*----------------------------------------------------------------------------
This file is part of deegree, http://deegree.org/
Copyright (C) 2001-2009 by:
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -103,9 +107,7 @@
*
* @author <a href="mailto:thomas@lat-lon.de">Steffen Thomas</a>
* @author <a href="mailto:schneider@lat-lon.de">Markus Schneider</a>
* @author last edited by: $Author$
*
* @version $Revision$, $Date$
* @author <a href="mailto:reichhelm@grit.de">Stephan Reichhelm</a>
*/
public class WKTWriter {

Expand All @@ -123,9 +125,6 @@ public class WKTWriter {
* The flag is used to specify which geometric operations the database is capable of
*
* @author <a href="mailto:thomas@lat-lon.de">Steffen Thomas</a>
* @author last edited by: $Author$
*
* @version $Revision$, $Date$
*/
public enum WKTFlag {
/** Export can use ENVELOPE */
Expand Down Expand Up @@ -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 {

Expand Down Expand Up @@ -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. <br/>
* It writes just the POLYGON-coordinates.
Expand Down Expand Up @@ -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<Curve> l = geometry.subList( 0, geometry.size() );
Expand Down Expand Up @@ -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 );

Expand All @@ -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 );
Expand Down Expand Up @@ -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 );
// }
Expand Down Expand Up @@ -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 );
// }
Expand All @@ -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 );
// }
Expand Down Expand Up @@ -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 {

Expand Down Expand Up @@ -1096,7 +1161,31 @@ public void writeMultiSolid( MultiSolid geometry, Writer writer ) {
*/
public void writeMultiSurface( MultiSurface<Surface> 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 );
}
Expand All @@ -1121,7 +1210,11 @@ public void writeMultiSurface( MultiSurface<Surface> geometry, Writer writer )
public void writeMultiCurve( MultiCurve<Curve> 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 );
}
Expand Down Expand Up @@ -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
* <code>null</code>
*/
@SuppressWarnings("unchecked")
public static String write( Geometry geom ) {
if ( geom == null ) {
return "";
Expand Down Expand Up @@ -1353,11 +1447,15 @@ public static void write( Geometry geom, Writer writer )
throw new NullPointerException( "The writer may not be null." );
}
Set<WKTFlag> flags = new HashSet<WKTFlag>();
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 );
Expand Down Expand Up @@ -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<CurveSegment> segments = geometry.getCurveSegments();
if ( segments.size() > 1 )
return true;

for ( CurveSegment seg : segments ) {
if ( seg.getSegmentType() != CurveSegmentType.LINE_STRING_SEGMENT ) {
return true;
}
}
}
return true;
}
}
Loading