diff --git a/core/src/main/java/org/polypheny/db/type/entity/spatial/PolyGeometry.java b/core/src/main/java/org/polypheny/db/type/entity/spatial/PolyGeometry.java index c962049d2e..28c6a58685 100644 --- a/core/src/main/java/org/polypheny/db/type/entity/spatial/PolyGeometry.java +++ b/core/src/main/java/org/polypheny/db/type/entity/spatial/PolyGeometry.java @@ -37,6 +37,7 @@ import org.polypheny.db.type.PolySerializable; import org.polypheny.db.type.PolyType; import org.polypheny.db.type.entity.PolyValue; +import org.polypheny.db.type.entity.spatial.PolyGeometryType.BufferCapStyle; /** * {@link PolyGeometry} is an abstraction for all spatial data types. @@ -54,11 +55,6 @@ public class PolyGeometry extends PolyValue { /** * Wrap the JTS {@link Geometry} class. - *
- * It is possible to extract useful information from the {@link Geometry}:
- * jtsGeometry.getGeometryType()
- * jtsGeometry.getSRID()
- * jtsGeometry.getCoordinate()
*/
@Getter
protected Geometry jtsGeometry;
@@ -71,14 +67,14 @@ public class PolyGeometry extends PolyValue {
/**
- * Constructor creates the {@link Geometry} from the WKT text.
+ * Constructor creates the {@link PolyGeometry} from the WKT text.
*
* The WKT may contain SRID in the text, e.g. "SRID=4326;POINT (13.4050 52.5200)"
.
* In this case SRID from the WKT would be used, otherwise the default one is selected.
*
*
* @param wkt Well Know Text representation of the geometry
- * @throws InvalidGeometryException if {@link Geometry} is invalid or provided WKT is invalid.
+ * @throws InvalidGeometryException if {@link PolyGeometry} is invalid or provided WKT is invalid.
*/
public PolyGeometry( @JsonProperty("wkt") @Deserialize("wkt") String wkt ) throws InvalidGeometryException {
this( PolyType.GEOMETRY );
@@ -95,21 +91,23 @@ public PolyGeometry( @JsonProperty("wkt") @Deserialize("wkt") String wkt ) throw
} catch ( NumberFormatException e ) {
throw new InvalidGeometryException( e.getMessage() );
}
- init(wkt, SRID);
+ init( wkt, SRID );
}
+
/**
- * Constructor creates the {@link Geometry} from the WKT text using the provided SRID.
+ * Constructor creates the {@link PolyGeometry} from the WKT text using the provided SRID.
*
* @param wkt Well Know Text representation of the geometry
* @param SRID Spatial reference system of the geometry
- * @throws InvalidGeometryException if {@link Geometry} is invalid or provided WKT is invalid.
+ * @throws InvalidGeometryException if {@link PolyGeometry} is invalid or provided WKT is invalid.
*/
public PolyGeometry( @JsonProperty("wkt") @Deserialize("wkt") String wkt, int SRID ) throws InvalidGeometryException {
this( PolyType.GEOMETRY );
init( wkt, SRID );
}
+
public PolyGeometry( Geometry geometry ) {
super( PolyType.GEOMETRY );
this.jtsGeometry = geometry;
@@ -122,27 +120,12 @@ protected PolyGeometry( PolyType type ) {
super( type );
}
- private void init( String wkt, int SRID) throws InvalidGeometryException {
- this.SRID = SRID;
- WKTReader reader = new WKTReader();
- try {
- this.jtsGeometry = reader.read( wkt );
- if ( !jtsGeometry.isValid() ) {
- throw new ParseException( "Provided geometry is not valid." );
- }
- this.jtsGeometry.setSRID( this.SRID );
- } catch ( ParseException | IllegalArgumentException e) {
- // IllegalArgumentException is thrown in case geometry conditions are not met
- throw new InvalidGeometryException( e.getMessage() );
- }
- this.geometryType = getPolyGeometryType();
- }
-
public static PolyGeometry of( String wkt ) throws InvalidGeometryException {
return new PolyGeometry( wkt );
}
+
public static PolyGeometry of( String wkt, int SRID ) throws InvalidGeometryException {
return new PolyGeometry( wkt, SRID );
}
@@ -153,6 +136,23 @@ public static PolyGeometry of( Geometry geometry ) {
}
+ private void init( String wkt, int SRID ) throws InvalidGeometryException {
+ this.SRID = SRID;
+ WKTReader reader = new WKTReader();
+ try {
+ this.jtsGeometry = reader.read( wkt );
+ if ( !jtsGeometry.isValid() ) {
+ throw new ParseException( "Provided geometry is not valid." );
+ }
+ this.jtsGeometry.setSRID( this.SRID );
+ } catch ( ParseException | IllegalArgumentException e ) {
+ // IllegalArgumentException is thrown in case geometry conditions are not met
+ throw new InvalidGeometryException( e.getMessage() );
+ }
+ this.geometryType = getPolyGeometryType();
+ }
+
+
protected PolyGeometryType getPolyGeometryType() {
switch ( jtsGeometry.getGeometryType() ) {
case "Point":
@@ -161,6 +161,8 @@ protected PolyGeometryType getPolyGeometryType() {
return PolyGeometryType.LINESTRING;
case "LinearRing":
return PolyGeometryType.LINEAR_RING;
+ case "Polygon":
+ return PolyGeometryType.POLYGON;
default:
throw new NotImplementedException( "value" );
}
@@ -180,6 +182,7 @@ public PolyPoint asPoint() {
throw cannotParse( this, PolyPoint.class );
}
+
public boolean isLineString() {
return geometryType.equals( PolyGeometryType.LINESTRING );
}
@@ -193,6 +196,7 @@ public PolyLineString asLineString() {
throw cannotParse( this, PolyLineString.class );
}
+
public boolean isLinearRing() {
return geometryType.equals( PolyGeometryType.LINEAR_RING );
}
@@ -207,8 +211,23 @@ public PolyLinearRing asLinearRing() {
}
+ public boolean isPolygon() {
+ return geometryType.equals( PolyGeometryType.POLYGON );
+ }
+
+
+ @NotNull
+ public PolyPolygon asPolygon() {
+ if ( isPolygon() ) {
+ return PolyPolygon.of( jtsGeometry );
+ }
+ throw cannotParse( this, PolyPolygon.class );
+ }
+
+
/**
* Tests whether this {@link Geometry} is simple.
+ *
* @return true
if {@link Geometry} is simple.
*/
public boolean isSimple() {
@@ -239,10 +258,16 @@ public int getDimension() {
return jtsGeometry.getDimension();
}
+ // TODO: add geometry collections (@link) to documentation
+
/**
* Linear geometries return their length.
* Areal geometries return their perimeter.
+ * The length of a {@link PolyPoint} or {link PolyMultiPoint} is 0.
+ * The length of a {@link PolyLineString} is the sum of the lengths of each line segment: distance from the start point to the end point
+ * The length of a {@link PolyPolygon} is the sum of the lengths of the exterior boundary and any interior boundaries.
+ * The length of any {link GeometryCollection} is the sum of the lengths of all {@link PolyGeometry} it contains.
*
* @return the length of this {@link Geometry}
*/
@@ -262,17 +287,108 @@ public double getArea() {
/**
- * Bound the {@link Geometry} my the minimum box that could fit this geometry.
+ * Bound the {@link PolyGeometry} my the minimum box that could fit this geometry.
*
* @return {@link PolyGeometry} with minimum bounding box
*/
- public PolyGeometry getMinimumBoundingBox() {
+ public PolyGeometry getEnvelope() {
return PolyGeometry.of( jtsGeometry.getEnvelope() );
}
/**
- * {@link #equals(Object) equals} ensures that the {@link Geometry} types and coordinates are the same.
+ * The boundary of a {@link PolyGeometry} is a set of {@link PolyGeometry}s of the next lower dimension
+ * that define the limit of this {@link PolyGeometry}.
+ *
+ * @return the closure of the combinatorial boundary of this {@link PolyGeometry}
+ */
+ public PolyGeometry getBoundary() {
+ return PolyGeometry.of( jtsGeometry.getBoundary() );
+ }
+
+
+ /**
+ * Calculate the smallest convex {@link PolyGeometry} that contains this {@link PolyGeometry}.
+ * @return the minimum area {@link PolyGeometry} containing all points in this {@link PolyGeometry}
+ */
+ public PolyGeometry convexHull() {
+ return PolyGeometry.of( jtsGeometry.convexHull() );
+ }
+
+
+ /**
+ * Computes the geometric center - centroid - of this {@link PolyGeometry}.
+ *
+ * When a geometry contains a combination of {@link PolyPoint}s, {@link PolyLineString}s, and {@link PolyPolygon}s, + * the centroid calculation is influenced solely by the {@link PolyPolygon}s within the {@link PolyGeometry}. + *
+ * Likewise, in the presence of both {@link PolyPoint}s and {@link PolyLineString}s within a {@link PolyGeometry}, + * the contribution of {@link PolyPoint}s to the centroid calculation is disregarded. + * + * @return {@link PolyPoint} that is the centroid of this {@link PolyGeometry} + */ + public PolyPoint getCentroid() { + return PolyPoint.of( jtsGeometry.getCentroid() ); + } + + + /** + * Compute a buffer area around this {@link PolyGeometry} within the given distance. + * The buffer maybe empty. + * The negative or zero-distance buffer of {@link PolyLineString}s and {@link PolyPoint}s + * is always an {@link PolyPolygon}. + * + * @param distance width of the buffer + * @return a {@link PolyPolygon} that represent buffer region around this {@link PolyGeometry} + */ + public PolyGeometry buffer( double distance ) { + return PolyPoint.of( jtsGeometry.buffer( distance ) ); + } + + + /** + * Compute a buffer area around this {@link PolyGeometry} within the given distance + * and accuracy of approximation for circular arcs. + * The buffer maybe empty. + * The negative or zero-distance buffer of {@link PolyLineString}s and {@link PolyPoint}s + * is always an {@link PolyPolygon}. + * + * @param distance width of the buffer + * @param quadrantSegments number of line segments to represent a quadrant of a circle + * @return a {@link PolyPolygon} that represent buffer region around this {@link PolyGeometry} + */ + public PolyGeometry buffer( double distance, int quadrantSegments ) { + return PolyPoint.of( jtsGeometry.buffer( distance, quadrantSegments ) ); + } + + + /** + * Compute a buffer area around this {@link PolyGeometry} within the given distance + * and accuracy of approximation for circular arcs, and use provided buffer end cap style. + * The buffer maybe empty. + * The negative or zero-distance buffer of {@link PolyLineString}s and {@link PolyPoint}s + * is an empty {@link PolyPolygon}. + * + * @param distance width of the buffer + * @param quadrantSegments number of line segments to represent a quadrant of a circle + * @param endCapStyle specifies how the buffer command terminates the end of a line. + * @return a {@link PolyPolygon} that represent buffer region around this {@link PolyGeometry} + */ + public PolyGeometry buffer( double distance, int quadrantSegments, BufferCapStyle endCapStyle ) { + return PolyPoint.of( jtsGeometry.buffer( distance, quadrantSegments, endCapStyle.code ) ); + } + + + /** + * @return new {@link PolyGeometry} with coordinates in a reverse order. + */ + public PolyGeometry reverse() { + return PolyGeometry.of( jtsGeometry.reverse() ); + } + + + /** + * {@link #equals(Object) equals} ensures that the {@link PolyGeometry} types and coordinates are the same. * And {@link #SRID} used for representation of coordinates are also identical. */ @Override @@ -321,7 +437,7 @@ public int compareTo( @NotNull PolyValue o ) { /** - * Output the {@link Geometry} in a WKT format with its SRID. So-called EWKT + * Output the {@link PolyGeometry} in a WKT format with its SRID. So-called EWKT */ @Override public String toString() { diff --git a/core/src/main/java/org/polypheny/db/type/entity/spatial/PolyGeometryType.java b/core/src/main/java/org/polypheny/db/type/entity/spatial/PolyGeometryType.java index 8d6b622991..56fdbcf773 100644 --- a/core/src/main/java/org/polypheny/db/type/entity/spatial/PolyGeometryType.java +++ b/core/src/main/java/org/polypheny/db/type/entity/spatial/PolyGeometryType.java @@ -17,11 +17,56 @@ package org.polypheny.db.type.entity.spatial; /** - * Represent Geometry types supported by Polypheny. + * Geometry types, with the names and codes assigned by OGC. */ public enum PolyGeometryType { + GEOMETRY( 0 ), + POINT( 1 ), + LINESTRING( 2 ), + // not actually a full type + LINEAR_RING( 2 ), + POLYGON(3), + MULTIPOINT( 4 ), + MULTILINESTRING( 5 ), + MULTIPOLYGON( 6 ), + GEOMCOLLECTION( 7 ), + CURVE( 13 ), + SURFACE( 14 ), + POLYHEDRALSURFACE( 15 ); - POINT, - LINESTRING, - LINEAR_RING + final int code; + + + PolyGeometryType( int code ) { + this.code = code; + } + + + /** + * How the "buffer" command terminates the end of a line. + */ + public enum BufferCapStyle { + ROUND( 1 ), FLAT( 2 ), SQUARE( 3 ); + + final int code; + + + BufferCapStyle( int code ) { + this.code = code; + } + + + static BufferCapStyle of( String value ) { + switch ( value ) { + case "round": + return ROUND; + case "flat": + return FLAT; + case "square": + return SQUARE; + default: + throw new IllegalArgumentException( "unknown endcap value: " + value ); + } + } + } } diff --git a/core/src/main/java/org/polypheny/db/type/entity/spatial/PolyLineString.java b/core/src/main/java/org/polypheny/db/type/entity/spatial/PolyLineString.java index bffbee4a19..c37b7dd44c 100644 --- a/core/src/main/java/org/polypheny/db/type/entity/spatial/PolyLineString.java +++ b/core/src/main/java/org/polypheny/db/type/entity/spatial/PolyLineString.java @@ -20,7 +20,6 @@ import io.activej.serializer.annotations.Deserialize; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.LineString; -import org.locationtech.jts.geom.Point; import org.polypheny.db.type.PolyType; /** @@ -28,6 +27,7 @@ * The line segments may intersect other segments. * If line segments do not intersect each other, the line is simple * The line may start and end at the same point. In this case, it is called closed. + *
* The {@link PolyLineString} is valid if it has * either 0 or 2 or more points. * The {@link PolyLineString} could store up to 4 dimensions. @@ -44,6 +44,7 @@ public PolyLineString( @JsonProperty("wkt") @Deserialize("wkt") String wkt ) thr this.jtsLineString = (LineString) jtsGeometry; } + public PolyLineString( @JsonProperty("wkt") @Deserialize("wkt") String wkt, int SRID ) throws InvalidGeometryException { super( wkt, SRID ); this.geometryType = PolyGeometryType.LINESTRING; @@ -128,12 +129,4 @@ public PolyPoint getEndPoint() { return PolyPoint.of( jtsLineString.getEndPoint() ); } - - /** - * @return new {@link PolyLineString} with coordinates in a reverse order. - */ - public PolyLineString reverse() { - return PolyLineString.of( jtsLineString.reverse() ); - } - } diff --git a/core/src/main/java/org/polypheny/db/type/entity/spatial/PolyLinearRing.java b/core/src/main/java/org/polypheny/db/type/entity/spatial/PolyLinearRing.java index 9b96c29437..3277655f38 100644 --- a/core/src/main/java/org/polypheny/db/type/entity/spatial/PolyLinearRing.java +++ b/core/src/main/java/org/polypheny/db/type/entity/spatial/PolyLinearRing.java @@ -19,7 +19,6 @@ import com.fasterxml.jackson.annotation.JsonProperty; import io.activej.serializer.annotations.Deserialize; import org.locationtech.jts.geom.Geometry; -import org.locationtech.jts.geom.LineString; import org.locationtech.jts.geom.LinearRing; import org.polypheny.db.type.PolyType; @@ -32,12 +31,14 @@ public class PolyLinearRing extends PolyLineString { private LinearRing jtsLinearRing; + public PolyLinearRing( @JsonProperty("wkt") @Deserialize("wkt") String wkt ) throws InvalidGeometryException { super( wkt ); this.geometryType = PolyGeometryType.LINEAR_RING; this.jtsLinearRing = (LinearRing) jtsGeometry; } + public PolyLinearRing( @JsonProperty("wkt") @Deserialize("wkt") String wkt, int SRID ) throws InvalidGeometryException { super( wkt, SRID ); this.geometryType = PolyGeometryType.LINEAR_RING; @@ -59,6 +60,7 @@ protected PolyLinearRing( PolyType type ) { this.geometryType = PolyGeometryType.LINEAR_RING; } + public static PolyLinearRing of( Geometry geometry ) { return new PolyLinearRing( geometry ); } diff --git a/core/src/main/java/org/polypheny/db/type/entity/spatial/PolyPoint.java b/core/src/main/java/org/polypheny/db/type/entity/spatial/PolyPoint.java index 67a96c5864..5b49a4a751 100644 --- a/core/src/main/java/org/polypheny/db/type/entity/spatial/PolyPoint.java +++ b/core/src/main/java/org/polypheny/db/type/entity/spatial/PolyPoint.java @@ -24,6 +24,7 @@ /** * Represent a single point in the space. + *
* The {@link PolyPoint} is valid if * X and Y coordinates are provided. * The {@link PolyPoint} could store up to 4 dimensions @@ -32,18 +33,21 @@ public class PolyPoint extends PolyGeometry { private Point jtsPoint; + public PolyPoint( @JsonProperty("wkt") @Deserialize("wkt") String wkt ) throws InvalidGeometryException { super( wkt ); this.geometryType = PolyGeometryType.POINT; this.jtsPoint = (Point) jtsGeometry; } + public PolyPoint( @JsonProperty("wkt") @Deserialize("wkt") String wkt, int SRID ) throws InvalidGeometryException { super( wkt, SRID ); this.geometryType = PolyGeometryType.POINT; this.jtsPoint = (Point) jtsGeometry; } + protected PolyPoint( Geometry geometry ) { super( PolyType.GEOMETRY ); this.geometryType = PolyGeometryType.POINT; @@ -52,35 +56,43 @@ protected PolyPoint( Geometry geometry ) { this.SRID = geometry.getSRID(); } + protected PolyPoint( PolyType type ) { super( type ); this.geometryType = PolyGeometryType.POINT; } + public static PolyPoint of( Geometry geometry ) { return new PolyPoint( geometry ); } + public double getX() { return jtsPoint.getX(); } + public double getY() { return jtsPoint.getY(); } + public boolean hasZ() { return !Double.isNaN( jtsPoint.getCoordinate().getZ() ); } + public double getZ() { return jtsPoint.getCoordinate().getZ(); } + public boolean hasM() { return !Double.isNaN( jtsPoint.getCoordinate().getM() ); } + public double getM() { return jtsPoint.getCoordinate().getM(); } diff --git a/core/src/main/java/org/polypheny/db/type/entity/spatial/PolyPolygon.java b/core/src/main/java/org/polypheny/db/type/entity/spatial/PolyPolygon.java new file mode 100644 index 0000000000..39b652f419 --- /dev/null +++ b/core/src/main/java/org/polypheny/db/type/entity/spatial/PolyPolygon.java @@ -0,0 +1,89 @@ +/* + * Copyright 2019-2023 The Polypheny Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.polypheny.db.type.entity.spatial; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.activej.serializer.annotations.Deserialize; +import org.locationtech.jts.geom.Geometry; +import org.locationtech.jts.geom.Polygon; +import org.polypheny.db.type.PolyType; + +/** + * Represent a polygon with linear edges, may contain holes. + * The outer boundary (shell) and inner boundaries (holes) are represented by {@link PolyLinearRing}. + * It means {@link PolyPolygon} is simple and closed. + * Interior holes should not split the {@link PolyPolygon} into more than one part. + *
+ * The {@link PolyPolygon} is valid if + * outer and inner boundaries are valid ({@link PolyLinearRing}) + * holes touch the shell or another hole at most one point + * Interior holes should not make the interior of the polygon disconnected + */ +public class PolyPolygon extends PolyGeometry { + + private Polygon jtsPolygon; + + + public PolyPolygon( @JsonProperty("wkt") @Deserialize("wkt") String wkt ) throws InvalidGeometryException { + super( wkt ); + this.geometryType = PolyGeometryType.POLYGON; + this.jtsPolygon = (Polygon) jtsGeometry; + } + + + public PolyPolygon( String wkt, int SRID ) throws InvalidGeometryException { + super( wkt, SRID ); + this.geometryType = PolyGeometryType.POLYGON; + this.jtsPolygon = (Polygon) jtsGeometry; + } + + + public PolyPolygon( Geometry geometry ) { + super( geometry ); + this.geometryType = PolyGeometryType.POLYGON; + this.jtsGeometry = geometry; + this.jtsPolygon = (Polygon) jtsGeometry; + this.SRID = geometry.getSRID(); + } + + + protected PolyPolygon( PolyType type ) { + super( type ); + this.geometryType = PolyGeometryType.POLYGON; + } + + + public static PolyPolygon of( Geometry geometry ) { + return new PolyPolygon( geometry ); + } + + + public PolyLinearRing getExteriorRing() { + return PolyLinearRing.of( jtsPolygon.getExteriorRing() ); + } + + + public int getNumInteriorRing() { + return jtsPolygon.getNumInteriorRing(); + } + + + public PolyLinearRing getInteriorRingN( int n ) { + return PolyLinearRing.of( jtsPolygon.getInteriorRingN( n ) ); + } + +} diff --git a/dbms/src/test/java/org/polypheny/db/type/spatial/GeometryConstants.java b/dbms/src/test/java/org/polypheny/db/type/spatial/GeometryConstants.java index d155ea6b2a..c3aace1a66 100644 --- a/dbms/src/test/java/org/polypheny/db/type/spatial/GeometryConstants.java +++ b/dbms/src/test/java/org/polypheny/db/type/spatial/GeometryConstants.java @@ -22,6 +22,7 @@ public class GeometryConstants { static final String POINT_WKT = "POINT (13.4050 52.5200 36.754)"; static final String LINESTRING_WKT = "LINESTRING(-1 -1, 2 2, 4 5, 6 7)"; static final String LINEAR_RING_WKT = "LINEARRING (0 0, 0 10, 10 10, 10 0, 0 0)"; + static final String POLYGON_WKT = "POLYGON((-1 -1, 2 2, -1 2, -1 -1))"; static final double DELTA = 1e-5; static final int NO_SRID = 0; } diff --git a/dbms/src/test/java/org/polypheny/db/type/spatial/GeometryTest.java b/dbms/src/test/java/org/polypheny/db/type/spatial/GeometryTest.java index fa41a0cf98..c5080ad9a0 100644 --- a/dbms/src/test/java/org/polypheny/db/type/spatial/GeometryTest.java +++ b/dbms/src/test/java/org/polypheny/db/type/spatial/GeometryTest.java @@ -35,6 +35,7 @@ import org.polypheny.db.type.entity.spatial.PolyLineString; import org.polypheny.db.type.entity.spatial.PolyLinearRing; import org.polypheny.db.type.entity.spatial.PolyPoint; +import org.polypheny.db.type.entity.spatial.PolyPolygon; public class GeometryTest { @@ -42,6 +43,7 @@ public class GeometryTest { private PolyGeometry point3d; private PolyGeometry lineString; private PolyGeometry linearRing; + private PolyGeometry polygon; @BeforeClass @@ -55,6 +57,7 @@ public void prepareGeometries() throws InvalidGeometryException { point3d = PolyGeometry.of( GeometryConstants.POINT_WKT ); lineString = PolyGeometry.of( GeometryConstants.LINESTRING_WKT ); linearRing = PolyGeometry.of( GeometryConstants.LINEAR_RING_WKT ); + polygon = PolyGeometry.of( GeometryConstants.POLYGON_WKT ); } @@ -125,6 +128,25 @@ public void testLinearRingValidity() { assertThrows( InvalidGeometryException.class, () -> PolyGeometry.of( "LINEARRING(0 0, 0 10, 10 10, 10 5, 5 5)" ) ); } + @Test + public void testPolygonValidity() { + assertAll( "Group assertions of valid Polygon", + () -> assertDoesNotThrow( () -> PolyGeometry.of( GeometryConstants.POLYGON_WKT ) ), + () -> { + assertEquals( PolyGeometryType.POLYGON, polygon.getGeometryType() ); + assertEquals( GeometryConstants.NO_SRID, (long) polygon.getSRID() ); + PolyPolygon poly = polygon.asPolygon(); + assertEquals( PolyPoint.of( "POINT (-0 1)" ), poly.getCentroid() ); + assertEquals( PolyLinearRing.of( "LINEARRING (-1 -1, 2 2, -1 2, -1 -1)" ), poly.getBoundary() ); + assertEquals( poly.getExteriorRing(), poly.getBoundary() ); + assertEquals( 10.2426406, poly.getLength(), GeometryConstants.DELTA ); + assertEquals( 4.5, poly.getArea(), GeometryConstants.DELTA ); + assertEquals( 4, poly.getNumPoints() ); + } ); + + assertThrows( InvalidGeometryException.class, () -> PolyGeometry.of( "POLYGON((-1 -1, 2 2, -1 1, -1 2, 2 2, -1 -1))" ) ); + } + @Test public void testPointsEquality() throws InvalidGeometryException {