diff --git a/core/src/main/java/org/polypheny/db/type/entity/spatial/GeometryTopologicalException.java b/core/src/main/java/org/polypheny/db/type/entity/spatial/GeometryTopologicalException.java
new file mode 100644
index 0000000000..4080ceefa8
--- /dev/null
+++ b/core/src/main/java/org/polypheny/db/type/entity/spatial/GeometryTopologicalException.java
@@ -0,0 +1,25 @@
+/*
+ * 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;
+
+public class GeometryTopologicalException extends Exception {
+
+ public GeometryTopologicalException( String message ) {
+ super( message );
+ }
+
+}
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 2787708916..4ecd124edf 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
@@ -33,6 +33,7 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.locationtech.jts.geom.Geometry;
+import org.locationtech.jts.geom.TopologyException;
import org.locationtech.jts.io.ParseException;
import org.locationtech.jts.io.WKTReader;
import org.polypheny.db.type.PolySerializable;
@@ -156,27 +157,31 @@ private void init( String wkt, int srid ) throws InvalidGeometryException {
protected PolyGeometryType getPolyGeometryType() {
switch ( jtsGeometry.getGeometryType() ) {
- case "Point":
+ case Geometry.TYPENAME_POINT:
return PolyGeometryType.POINT;
- case "LineString":
+ case Geometry.TYPENAME_LINESTRING:
return PolyGeometryType.LINESTRING;
- case "LinearRing":
+ case Geometry.TYPENAME_LINEARRING:
return PolyGeometryType.LINEARRING;
- case "Polygon":
+ case Geometry.TYPENAME_POLYGON:
return PolyGeometryType.POLYGON;
- case "GeometryCollection":
+ case Geometry.TYPENAME_GEOMETRYCOLLECTION:
return PolyGeometryType.GEOMETRYCOLLECTION;
- case "MultiPoint":
+ case Geometry.TYPENAME_MULTIPOINT:
return PolyGeometryType.MULTIPOINT;
- case "MultiLineString":
+ case Geometry.TYPENAME_MULTILINESTRING:
return PolyGeometryType.MULTILINESTRING;
- case "MultiPolygon":
+ case Geometry.TYPENAME_MULTIPOLYGON:
return PolyGeometryType.MULTIPOLYGON;
default:
throw new NotImplementedException( "value" );
}
}
+ /*
+ * Casting methods
+ */
+
public boolean isPoint() {
return geometryType.equals( PolyGeometryType.POINT );
@@ -247,6 +252,10 @@ public PolyGeometryCollection asGeometryCollection() {
throw cannotParse( this, PolyGeometryCollection.class );
}
+ /*
+ * Query Geometry properties
+ */
+
/**
* Tests whether this {@link PolyGeometry} is a simple geometry: does not intersect itself.
@@ -419,6 +428,318 @@ public PolyGeometry reverse() {
return PolyGeometry.of( jtsGeometry.reverse() );
}
+ /*
+ * Topological relationships
+ */
+
+ /*
+ * Binary predicates
+ */
+
+
+ /**
+ * Check that another {@link PolyGeometry} is withing the Euclidean distance.
+ *
+ * @param g another {@link PolyGeometry}
+ * @param distance metric value to compare, measured in Cartesian coordinate units
+ * @return true
if {@link PolyGeometry} is withing the given distance
+ */
+ public boolean isWithinDistance( @NotNull PolyGeometry g, double distance ) {
+ return jtsGeometry.isWithinDistance( g.getJtsGeometry(), distance );
+ }
+
+
+ /**
+ * Check that another {@link PolyGeometry} is withing the distance.
+ *
+ * @param g another {@link PolyGeometry}
+ * @param distance metric value to compare, measured in meters if spheroid, otherwise in Cartesian coordinate units
+ * @param spheroid use the spheroid physical model to calculate the distance
+ * @return true
if {@link PolyGeometry} is withing the given distance
+ */
+ public boolean isWithinDistance( @NotNull PolyGeometry g, double distance, boolean spheroid ) {
+ if ( !spheroid ) {
+ return isWithinDistance( g, distance );
+ }
+ // TODO: implement on Perfect Sphere and for WGS84
+ return false;
+ }
+
+
+ /**
+ * Check that this {@link PolyGeometry} is disjoint from another {@link PolyGeometry}:
+ * 2 {@link PolyGeometry} do not have points in common
+ *
+ * @param g another {@link PolyGeometry}
+ * @return true
if 2 {@link PolyGeometry} are disjoint
+ */
+ public boolean disjoint( @NotNull PolyGeometry g ) {
+ return jtsGeometry.disjoint( g.getJtsGeometry() );
+ }
+
+
+ /**
+ * Check that this {@link PolyGeometry} touches another {@link PolyGeometry}:
+ * 2 {@link PolyGeometry} have at least one point in common, but interiors do not intersect
+ *
+ * @param g another {@link PolyGeometry}
+ * @return true
if one {@link PolyGeometry} touches another. false
if two {@link PolyGeometry} are {@link PolyPoint}s
+ */
+ public boolean touches( @NotNull PolyGeometry g ) {
+ return jtsGeometry.touches( g.getJtsGeometry() );
+ }
+
+
+ /**
+ * Check that this {@link PolyGeometry} intersects another {@link PolyGeometry}:
+ * 2 {@link PolyGeometry} have at least one point in common
+ *
+ * @param g another {@link PolyGeometry}
+ * @return true
if {@link PolyGeometry} intersects another.
+ */
+ public boolean intersects( @NotNull PolyGeometry g ) {
+ return jtsGeometry.intersects( g.getJtsGeometry() );
+ }
+
+
+ /**
+ * Check that this {@link PolyGeometry} crosses another {@link PolyGeometry}:
+ * 2 {@link PolyGeometry} have some, but not all interior points in common
+ *
+ * @param g another {@link PolyGeometry}
+ * @return true
if {@link PolyGeometry} crosses another.
+ */
+ public boolean crosses( @NotNull PolyGeometry g ) {
+ return jtsGeometry.crosses( g.getJtsGeometry() );
+ }
+
+
+ /**
+ * Check that this {@link PolyGeometry} within another {@link PolyGeometry}:
+ * Every point of this {@link PolyGeometry} is a point of another {@link PolyGeometry}
+ * and the interiors of two {@link PolyGeometry} intersect (have at least one point in common)
+ *
+ * @param g another {@link PolyGeometry}
+ * @return true
if {@link PolyGeometry} within another.
+ */
+ public boolean within( @NotNull PolyGeometry g ) {
+ return jtsGeometry.within( g.getJtsGeometry() );
+ }
+
+
+ /**
+ * Check that this {@link PolyGeometry} contains another {@link PolyGeometry}:
+ * Every point of another {@link PolyGeometry} is a point of this {@link PolyGeometry}
+ * and the interiors of two {@link PolyGeometry} intersect (have at least one point in common)
+ *
+ * @param g another {@link PolyGeometry}
+ * @return true
if {@link PolyGeometry} contains another.
+ */
+ public boolean contains( @NotNull PolyGeometry g ) {
+ return jtsGeometry.contains( g.getJtsGeometry() );
+ }
+
+
+ /**
+ * Check that this {@link PolyGeometry} overlaps another {@link PolyGeometry}:
+ * at least one point is not shared by both {@link PolyGeometry}s, they have the same dimension
+ * and the intersection of interiors have the same dimension as {@link PolyGeometry}s have.
+ *
+ * @param g another {@link PolyGeometry}
+ * @return true
if {@link PolyGeometry} overlaps another.
+ */
+ public boolean overlaps( @NotNull PolyGeometry g ) {
+ return jtsGeometry.overlaps( g.getJtsGeometry() );
+ }
+
+
+ /**
+ * Check that this {@link PolyGeometry} covers another {@link PolyGeometry}:
+ * Every point of another {@link PolyGeometry} is a point of this {@link PolyGeometry}.
+ * More inclusive than {@link #contains(PolyGeometry)}
+ * (does not differentiate between points in interior and boundary)
+ *
+ * @param g another {@link PolyGeometry}
+ * @return true
if {@link PolyGeometry} covers another.
+ */
+ public boolean covers( @NotNull PolyGeometry g ) {
+ return jtsGeometry.covers( g.getJtsGeometry() );
+ }
+
+
+ /**
+ * Check that this {@link PolyGeometry} is covered by another {@link PolyGeometry}:
+ * Every point of this {@link PolyGeometry} is a point of another {@link PolyGeometry}.
+ * More inclusive than {@link #within(PolyGeometry)}
+ * (does not differentiate between points in interior and boundary)
+ *
+ * @param g another {@link PolyGeometry}
+ * @return true
if {@link PolyGeometry} is covered by another.
+ */
+ public boolean coveredBy( @NotNull PolyGeometry g ) {
+ return jtsGeometry.coveredBy( g.getJtsGeometry() );
+ }
+
+
+ /**
+ * Check that this {@link PolyGeometry} is spatially related to another {@link PolyGeometry}
+ * based on the given intersection DE-9IM pattern matrix.
+ * The DE-9IM pattern consists of 9 characters:
+ *
+ * PolyGeometry g1 = PolyGeometry.of( "LINESTRING (0 1, 2 2)" );
+ * PolyGeometry g2 = PolyGeometry.of( "LINESTRING (2 2, 0 1)" );
+ * g1.relate( g2, "T*F**FFF2" ); // true
+ *
+ *
+ *
+ * @param g another {@link PolyGeometry}
+ * @param intersectionPattern pattern to check the intersection matrix of two {@link PolyGeometry}
+ * @return true
if the DE-9IM intersection matrix for both {@link PolyGeometry} matches the intersectionPattern
+ * @throws GeometryTopologicalException in case intersectionPattern
contains not of 9 characters
+ */
+ public boolean relate( @NotNull PolyGeometry g, @NotNull String intersectionPattern ) throws GeometryTopologicalException {
+ if ( intersectionPattern.length() == 9 ) {
+ throw new GeometryTopologicalException( "DE-9IM pattern should contain 9 characters." );
+ }
+ return jtsGeometry.relate( g.getJtsGeometry(), intersectionPattern );
+ }
+
+ /*
+ * Yield metric values
+ */
+
+
+ /**
+ * Calculate the Euclidean distance between two {@link PolyGeometry}.
+ * The distance is measured in Cartesian coordinate units.
+ *
+ * @param g another {@link PolyGeometry}
+ * @return the distance in Cartesian coordinate units
+ */
+ public double distance( @NotNull PolyGeometry g ) {
+ return jtsGeometry.distance( g.getJtsGeometry() );
+ }
+
+
+ /**
+ * Calculate the distance between two {@link PolyGeometry}.
+ *
+ * @param g another {@link PolyGeometry}
+ * @param spheroid use the spheroid physical model to calculate the distance
+ * @return the distance in meters if spheroid, otherwise in Cartesian coordinate units
+ */
+ public double distance( @NotNull PolyGeometry g, boolean spheroid ) {
+ if ( !spheroid ) {
+ return jtsGeometry.distance( g.getJtsGeometry() );
+ }
+ // TODO: implement on Perfect Sphere and for WGS84
+ return 42;
+ }
+
+
+ /*
+ * Set operations
+ */
+
+
+ /**
+ * Compute the intersection set of both {@link PolyGeometry}s.
+ * The produced {@link PolyGeometry} is less than original or equal to the minimum dimension of both {@link PolyGeometry}
+ * {@link PolyGeometryCollection} is allowed only for homogeneous collection types.
+ *
+ * @param g another {@link PolyGeometry}
+ * @return a {@link PolyGeometry} that represent an intersection set of both {@link PolyGeometry}s
+ * @throws GeometryTopologicalException in case a non-empty heterogeneous {@link PolyGeometryCollection} as an input
+ * or a robustness error occurs
+ */
+ public PolyGeometry intersection( @NotNull PolyGeometry g ) throws GeometryTopologicalException {
+ try {
+ return PolyGeometry.of( jtsGeometry.intersection( g.getJtsGeometry() ) );
+ } catch ( TopologyException | IllegalArgumentException e ) {
+ // TopologyException: robustness error occurs
+ // IllegalArgumentException: non-empty heterogeneous GeometryCollection as an input
+ throw new GeometryTopologicalException( e.getMessage() );
+ }
+ }
+
+
+ /**
+ * Compute the union set of both {@link PolyGeometry}s.
+ * The dimension of the produced union set is equal to the maximum dimension of both {@link PolyGeometry}.
+ * The result may be a heterogeneous {@link PolyGeometryCollection}.
+ *
+ * @param g another {@link PolyGeometry}
+ * @return a {@link PolyGeometry} that represent a union set of both {@link PolyGeometry}s
+ * @throws GeometryTopologicalException in case a non-empty {@link PolyGeometryCollection} as an input
+ * or a robustness error occurs
+ */
+ public PolyGeometry union( @NotNull PolyGeometry g ) throws GeometryTopologicalException {
+ try {
+ return PolyGeometry.of( jtsGeometry.union( g.getJtsGeometry() ) );
+ } catch ( TopologyException | IllegalArgumentException e ) {
+ // TopologyException: robustness error occurs
+ // IllegalArgumentException: non-empty GeometryCollection as an input
+ throw new GeometryTopologicalException( e.getMessage() );
+ }
+ }
+
+
+ /**
+ * Compute the difference set of both {@link PolyGeometry}s.
+ * Produced difference set consists of points contained in this {@link PolyGeometry} not contained in other {@link PolyGeometry}.
+ *
+ * @param g another {@link PolyGeometry}
+ * @return a {@link PolyGeometry} that represent a difference set of both {@link PolyGeometry}s
+ * @throws GeometryTopologicalException in case a non-empty {@link PolyGeometryCollection} as an input
+ * or a robustness error occurs
+ */
+ public PolyGeometry difference( @NotNull PolyGeometry g ) throws GeometryTopologicalException {
+ try {
+ return PolyGeometry.of( jtsGeometry.difference( g.getJtsGeometry() ) );
+ } catch ( TopologyException | IllegalArgumentException e ) {
+ // TopologyException: robustness error occurs
+ // IllegalArgumentException: non-empty GeometryCollection as an input
+ throw new GeometryTopologicalException( e.getMessage() );
+ }
+ }
+
+
+ /**
+ * Compute the symmetric difference set of both {@link PolyGeometry}s.
+ * Produced symmetric difference set consists of the union
+ * of points contained in this {@link PolyGeometry} not contained in other {@link PolyGeometry}
+ * and of points contained in other {@link PolyGeometry} not contained in this {@link PolyGeometry}.
+ *
+ * @param g another {@link PolyGeometry}
+ * @return a {@link PolyGeometry} that represent a difference set of both {@link PolyGeometry}s
+ * @throws GeometryTopologicalException in case a non-empty {@link PolyGeometryCollection} as an input
+ * or a robustness error occurs
+ */
+ public PolyGeometry symDifference( @NotNull PolyGeometry g ) throws GeometryTopologicalException {
+ try {
+ return PolyGeometry.of( jtsGeometry.symDifference( g.getJtsGeometry() ) );
+ } catch ( TopologyException | IllegalArgumentException e ) {
+ // TopologyException: robustness error occurs
+ // IllegalArgumentException: non-empty GeometryCollection as an input
+ throw new GeometryTopologicalException( e.getMessage() );
+ }
+ }
+
+
+ /*
+ * PolyType methods
+ */
+
/**
* {@link #equals(Object) equals} ensures that the {@link PolyGeometry} types and coordinates are the same.
diff --git a/core/src/main/java/org/polypheny/db/type/entity/spatial/PolyGeometryCollection.java b/core/src/main/java/org/polypheny/db/type/entity/spatial/PolyGeometryCollection.java
index b24d450215..5a2f251710 100644
--- a/core/src/main/java/org/polypheny/db/type/entity/spatial/PolyGeometryCollection.java
+++ b/core/src/main/java/org/polypheny/db/type/entity/spatial/PolyGeometryCollection.java
@@ -68,25 +68,6 @@ public static PolyGeometryCollection of( Geometry geometry ) {
}
- /**
- * @return the number of {@link PolyGeometry} geometries in the {@link PolyGeometryCollection}.
- */
- public int getNumGeometries() {
- return jtsGeometryCollection.getNumGeometries();
- }
-
-
- /**
- * Get the nth {@link PolyGeometry} in the collection.
- *
- * @param n number of the {@link PolyGeometry} in the collection
- * @return the nth {@link PolyGeometry} in the collection.
- */
- public PolyGeometry getGeometryN( int n ) {
- return PolyGeometry.of( jtsGeometryCollection.getGeometryN( n ) );
- }
-
-
public boolean isMultiPoint() {
return geometryType.equals( PolyGeometryType.MULTIPOINT );
}
@@ -128,4 +109,33 @@ public PolyMultiPolygon asMultiPolygon() {
throw cannotParse( this, PolyMultiPolygon.class );
}
+
+ /**
+ * @return the number of {@link PolyGeometry} geometries in the {@link PolyGeometryCollection}.
+ */
+ public int getNumGeometries() {
+ return jtsGeometryCollection.getNumGeometries();
+ }
+
+
+ /**
+ * Get the nth {@link PolyGeometry} in the collection.
+ *
+ * @param n number of the {@link PolyGeometry} in the collection
+ * @return the nth {@link PolyGeometry} in the collection.
+ */
+ public PolyGeometry getGeometryN( int n ) {
+ return PolyGeometry.of( jtsGeometryCollection.getGeometryN( n ) );
+ }
+
+
+ /**
+ * Compute the union set of all {@link PolyGeometry} in the collection.
+ *
+ * @return the union set of all {@link PolyGeometry} in the collection.
+ */
+ public PolyGeometry union() {
+ return PolyGeometry.of( jtsGeometryCollection.union() );
+ }
+
}
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
index 39b652f419..87f84b94a6 100644
--- 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
@@ -72,6 +72,11 @@ public static PolyPolygon of( Geometry geometry ) {
}
+ public boolean isRectangle() {
+ return jtsPolygon.isRectangle();
+ }
+
+
public PolyLinearRing getExteriorRing() {
return PolyLinearRing.of( jtsPolygon.getExteriorRing() );
}