Add CurvePolygon geometry type interface
diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/CurvePolygon.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/CurvePolygon.java
new file mode 100644
index 0000000..a026e5e
--- /dev/null
+++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/CurvePolygon.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.sis.geometries;
+
+import java.util.List;
+import static org.opengis.annotation.Specification.ISO_19107;
+import org.opengis.annotation.UML;
+import org.opengis.geometry.coordinate.GriddedSurface;
+import org.apache.sis.geometries.privy.AbstractGeometry;
+
+
+/**
+ * A curve polygon is a surface where each ring is a closed line string, circular string, or compound curve.
+ * The first ring is the exterior boundary and, all other rings are interior boundaries.
+ *
+ * @todo is Polygon a subclass of CurvePolygon ?
+ * ISO-19107 use the name Polygon for CurvePolygon
+ * OGC Features and Geometries JSON separates them
+ * In practice most geometry library have only polygon with straight lines
+ *
+ * @author Johann Sorel (Geomatys)
+ * @see https://docs.ogc.org/DRAFTS/21-045r1.html#curve_polygon
+ */
+@UML(identifier="Polygon", specification=ISO_19107) // section 8.1.2
+public interface CurvePolygon extends Surface {
+
+ public static final String TYPE = "CURVEPOLYGON";
+
+ @Override
+ public default String getGeometryType() {
+ return TYPE;
+ }
+
+ @Override
+ public default AttributesType getAttributesType() {
+ return getExteriorRing().getAttributesType();
+ }
+
+ @UML(identifier="rings", specification=ISO_19107) // section 8.1 figure 28
+ List<Curve> getInteriorRings();
+
+ /**
+ * Returns the exterior ring of this Polygon.
+ *
+ * @see OGC Simple Feature Access 1.2.1 - 6.1.11.2
+ * @return exterior ring of this Polygon.
+ */
+ @UML(identifier="exteriorRing", specification=ISO_19107) // section 8.1 figure 28
+ Curve getExteriorRing();
+
+ /**
+ * Returns the number of interior rings in this Polygon.
+ *
+ * @see OGC Simple Feature Access 1.2.1 - 6.1.11.2
+ * @return number of interior rings in this Polygon.
+ */
+ @UML(identifier="numInteriorRing", specification=ISO_19107) // section 8.1 figure 28
+ default int getNumInteriorRing() {
+ return getInteriorRings().size();
+ }
+
+ /**
+ * Returns the Nth interior ring for this Polygon as a LineString.
+ *
+ * @see OGC Simple Feature Access 1.2.1 - 6.1.11.2
+ * @param n ring index
+ * @return interior ring for this Polygon.
+ */
+ @UML(identifier="interiorRingN", specification=ISO_19107) // section 8.1 figure 28
+ default Curve getInteriorRingN(int n) {
+ return getInteriorRings().get(n);
+ }
+
+ @UML(identifier="spanningSurface", specification=ISO_19107) // section 8.1.2.3
+ default GriddedSurface getSpanningSurface() {
+ //TODO
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ default String asText() {
+ final StringBuilder sb = new StringBuilder("POLYGON ((");
+ AbstractGeometry.toText(sb, getExteriorRing().asLine(null, null).getPoints());
+ sb.append(')');
+ for (int i = 0, n = getNumInteriorRing(); i < n; i++) {
+ if (i != 0) sb.append(',');
+ sb.append('(');
+ AbstractGeometry.toText(sb, getInteriorRingN(i).asLine(null, null).getPoints());
+ sb.append(')');
+ }
+ sb.append(')');
+ return sb.toString();
+ }
+
+}
diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/GeometryFactory.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/GeometryFactory.java
index 4585ced..628413d 100644
--- a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/GeometryFactory.java
+++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/GeometryFactory.java
@@ -130,6 +130,7 @@
case CLOTHOID : return Clothoid.class;
case COMPOUNDCURVE : return CompoundCurve.class;
case CURVE : return Curve.class;
+ case CURVEPOLYGON : return CurvePolygon.class;
case GEOMETRY : return Geometry.class;
case GEOMETRYCOLLECTION : return GeometryCollection.class;
case LINESTRING : return LineString.class;
@@ -147,7 +148,6 @@
//todo
case BREPSOLID :
case COMPOUNDSURFACE :
- case CURVEPOLYGON :
case ELLIPTICALCURVE :
case GEODESICSTRING :
case NURBSCURVE :
diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/MultiPolygon.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/MultiPolygon.java
index 8c39f09..dfadb5e 100644
--- a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/MultiPolygon.java
+++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/MultiPolygon.java
@@ -55,7 +55,7 @@
for (int i = 0, n = polygon.getNumInteriorRing(); i < n; i++) {
if (i != 0) sb.append(',');
sb.append('(');
- AbstractGeometry.toText(sb, polygon.getInteriorRingN(i).asLine(null, null).getPoints());
+ AbstractGeometry.toText(sb, polygon.getInteriorRingN(i).getPoints());
sb.append(')');
}
sb.append(')');
diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/Polygon.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/Polygon.java
index fa1f1cf..7ae7832 100644
--- a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/Polygon.java
+++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/Polygon.java
@@ -42,7 +42,6 @@
* f) The exterior of a Polygon with 1 or more holes is not connected. Each hole defines a connected component of the exterior.
*
* @author Johann Sorel (Geomatys)
- * @see https://docs.ogc.org/DRAFTS/21-045r1.html#curve_polygon
*/
@UML(identifier="Polygon", specification=ISO_19107) // section 8.1.2
public interface Polygon extends Surface {
@@ -60,7 +59,7 @@
}
@UML(identifier="rings", specification=ISO_19107) // section 8.1 figure 28
- List<Curve> getInteriorRings();
+ List<LinearRing> getInteriorRings();
/**
* Returns the exterior ring of this Polygon.
@@ -69,7 +68,7 @@
* @return exterior ring of this Polygon.
*/
@UML(identifier="exteriorRing", specification=ISO_19107) // section 8.1 figure 28
- Curve getExteriorRing();
+ LinearRing getExteriorRing();
/**
* Returns the number of interior rings in this Polygon.
@@ -90,7 +89,7 @@
* @return interior ring for this Polygon.
*/
@UML(identifier="interiorRingN", specification=ISO_19107) // section 8.1 figure 28
- default Curve getInteriorRingN(int n) {
+ default LinearRing getInteriorRingN(int n) {
return getInteriorRings().get(n);
}
@@ -108,7 +107,7 @@
for (int i = 0, n = getNumInteriorRing(); i < n; i++) {
if (i != 0) sb.append(',');
sb.append('(');
- AbstractGeometry.toText(sb, getInteriorRingN(i).asLine(null, null).getPoints());
+ AbstractGeometry.toText(sb, getInteriorRingN(i).getPoints());
sb.append(')');
}
sb.append(')');
diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/Triangle.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/Triangle.java
index fabf57e..a5345f6 100644
--- a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/Triangle.java
+++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/Triangle.java
@@ -56,7 +56,7 @@
LinearRing getExteriorRing();
@Override
- default List<Curve> getInteriorRings() {
+ default List<LinearRing> getInteriorRings() {
return Collections.emptyList();
}
diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/privy/DefaultPolygon.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/privy/DefaultPolygon.java
index 0d875e2..b16e83e 100644
--- a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/privy/DefaultPolygon.java
+++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/privy/DefaultPolygon.java
@@ -34,8 +34,8 @@
*/
public class DefaultPolygon extends AbstractGeometry implements Polygon {
- protected final Curve exterior;
- protected final List<Curve> interiors;
+ protected final LinearRing exterior;
+ protected final List<LinearRing> interiors;
public DefaultPolygon(LinearRing exterior) {
this(exterior, null);
@@ -72,12 +72,12 @@
}
@Override
- public Curve getExteriorRing() {
+ public LinearRing getExteriorRing() {
return exterior;
}
@Override
- public List<Curve> getInteriorRings() {
+ public List<LinearRing> getInteriorRings() {
return interiors;
}
diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/processor/spatialedition/Transform.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/processor/spatialedition/Transform.java
index 43bc6e2..521e92f 100644
--- a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/processor/spatialedition/Transform.java
+++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/processor/spatialedition/Transform.java
@@ -119,14 +119,14 @@
public void process(org.apache.sis.geometries.operation.spatialedition.Transform operation) throws OperationException {
final org.apache.sis.geometries.Polygon p = (org.apache.sis.geometries.Polygon) operation.geometry;
- Curve exterior = (Curve) GeometryOperations.SpatialEdition.transform(p.getExteriorRing(), operation.crs, operation.transform);
+ org.apache.sis.geometries.LinearRing exterior = (org.apache.sis.geometries.LinearRing) GeometryOperations.SpatialEdition.transform(p.getExteriorRing(), operation.crs, operation.transform);
- final List<Curve> interiors = new ArrayList<>(p.getInteriorRings());
+ final List<org.apache.sis.geometries.LinearRing> interiors = new ArrayList<>(p.getInteriorRings());
for (int i = 0, n = interiors.size(); i < n; i++) {
- interiors.set(i, (Curve) GeometryOperations.SpatialEdition.transform(interiors.get(i), operation.crs, operation.transform));
+ interiors.set(i, (org.apache.sis.geometries.LinearRing) GeometryOperations.SpatialEdition.transform(interiors.get(i), operation.crs, operation.transform));
}
- operation.result = GeometryFactory.createPolygon((org.apache.sis.geometries.LinearRing) exterior, (List) interiors);
+ operation.result = GeometryFactory.createPolygon(exterior, interiors);
}
}
diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/processor/spatialrelations2d/Contains.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/processor/spatialrelations2d/Contains.java
index e5427ba..b0cac29 100644
--- a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/processor/spatialrelations2d/Contains.java
+++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/processor/spatialrelations2d/Contains.java
@@ -110,7 +110,7 @@
{ //check exterior
- final TupleArray coords = asLineString(polygon.getExteriorRing()).getPoints().getAttributeArray(AttributesType.ATT_POSITION);
+ final TupleArray coords = polygon.getExteriorRing().getPoints().getAttributeArray(AttributesType.ATT_POSITION);
if (!contains(coords, candidate.getPosition())) {
//point is outside the exterior ring
operation.result = false;
@@ -120,7 +120,7 @@
{ //check holes
for (int i = 0, n = polygon.getNumInteriorRing(); i < n; i++) {
- final LineString hole = asLineString(polygon.getInteriorRingN(i));
+ final LineString hole = polygon.getInteriorRingN(i);
final TupleArray coords = hole.getPoints().getAttributeArray(AttributesType.ATT_POSITION);
if (contains(coords, candidate.getPosition())) {
//point is within a hole
@@ -135,11 +135,4 @@
}
}
- private static LineString asLineString(Curve curve) {
- if (curve instanceof LineString ls) {
- return ls;
- }
- throw new OperationException("Curve type not supported");
- }
-
}
diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/triangulate/EarClipping.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/triangulate/EarClipping.java
index 9170630..01a6138 100644
--- a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/triangulate/EarClipping.java
+++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/triangulate/EarClipping.java
@@ -110,12 +110,12 @@
final SimplePolygon part = new SimplePolygon();
//copy collection to avoid modifications
- part.outter = (LineString) ((Polygon)geometry).getExteriorRing();
+ part.outter = geometry.getExteriorRing();
- final int nbHole = ((Polygon)geometry).getNumInteriorRing();
+ final int nbHole = geometry.getNumInteriorRing();
for(int i=0;i<nbHole;i++){
- final LineString inner = (LineString) ((Polygon)geometry).getInteriorRingN(i);
+ final LineString inner = geometry.getInteriorRingN(i);
part.inners.add(inner);
}
@@ -157,7 +157,7 @@
//we must find the minimum x coordinate in the inner loop
final List<Tuple> loop = part.inners.get(i).getPoints().getAttributeArray(AttributesType.ATT_POSITION).stream(false).toList();
int index = 0;
- Tuple min = (Tuple) loop.get(index);
+ Tuple min = loop.get(index);
for(int k=1,p=loop.size();k<p;k++){
Tuple candidate = (Tuple) loop.get(1);
if (candidate.get(0) < min.get(0)) {
@@ -192,9 +192,9 @@
}
//remove any neighor points overlaping
- Tuple t = (Tuple) borderCoords.get(0);
+ Tuple t = borderCoords.get(0);
for(int i=1,n=borderCoords.size();i<n;i++){
- Tuple candidate = (Tuple) borderCoords.get(i);
+ Tuple candidate = borderCoords.get(i);
if(candidate.equals(t)){
borderCoords.remove(i);
i--;
@@ -210,7 +210,7 @@
nbCoords = borderCoords.size();
coordType = new int[nbCoords];
- coords = borderCoords.toArray(new Tuple[0]);
+ coords = borderCoords.toArray(Tuple[]::new);
//flip coordinates if not clockwise
if(!clockwise){