This is an automated email from the ASF dual-hosted git repository. asf-gitbox-commits pushed a commit to branch geoapi-4.0 in repository https://gitbox.apache.org/repos/asf/sis.git
commit ac5b23c3f8dd82aed5767a3a17ebcc0a3b2b1c04 Author: jsorel <[email protected]> AuthorDate: Thu Sep 3 14:52:15 2026 +0200 feat(Geometry): implement several geometry types --- .../org/apache/sis/geometries/CompoundCurve.java | 86 ++++++++++++- .../org/apache/sis/geometries/GeometryFactory.java | 111 +++++++++++++++++ .../org/apache/sis/geometries/GeometryVisitor.java | 2 +- .../org/apache/sis/geometries/MultiSurface.java | 9 +- .../main/org/apache/sis/geometries/Orientable.java | 11 +- .../main/org/apache/sis/geometries/Polyhedron.java | 2 +- .../main/org/apache/sis/geometries/Solid.java | 36 ++++-- .../sis/geometries/conics/CircularString.java | 76 +++++++++++- .../internal/shared/AbstractGeometry.java | 30 +++++ .../internal/shared/DefaultCircularString.java | 65 ++++++++++ .../internal/shared/DefaultCompoundCurve.java | 106 ++++++++++++++++ .../internal/shared/DefaultCurvePolygon.java | 97 +++++++++++++++ .../internal/shared/DefaultGeometryCollection.java | 25 +++- .../internal/shared/DefaultMultiCurve.java | 28 +---- .../internal/shared/DefaultMultiLineString.java | 5 + .../internal/shared/DefaultMultiPolygon.java | 5 + ...ltiPolygon.java => DefaultMultiPolyhedron.java} | 17 ++- .../internal/shared/DefaultMultiSurface.java | 33 +---- .../internal/shared/DefaultPolyhedralSurface.java | 107 ++++++++++++++++ .../internal/shared/DefaultPolyhedron.java | 137 +++++++++++++++++++++ .../internal/shared/DefaultRawMultiPoint.java | 28 +---- .../internal/shared/DefaultReversedCurve.java | 132 ++++++++++++++++++++ .../internal/shared/DefaultReversedSurface.java | 107 ++++++++++++++++ ...iCurve.java => DefaultTriangulatedSurface.java} | 40 +++--- 24 files changed, 1173 insertions(+), 122 deletions(-) diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/CompoundCurve.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/CompoundCurve.java index 28cb6ffc2b..019f8b6ca3 100644 --- a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/CompoundCurve.java +++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/CompoundCurve.java @@ -16,10 +16,14 @@ */ package org.apache.sis.geometries; +import java.util.ArrayList; +import java.util.List; /** + * A curve made of several curves joined end to end, each of which may use a different + * interpolation. The end point of each component is the start point of the next one, so a compound + * curve is a single connected curve and not a collection — that is {@link MultiCurve}. * - * @todo * @author Johann Sorel (Geomatys * @see https://docs.ogc.org/DRAFTS/21-045r1.html#compound_curve */ @@ -31,4 +35,84 @@ public interface CompoundCurve extends Curve { public default String getGeometryType() { return TYPE; } + + /** + * Returns the number of curves this compound curve is made of. + * + * @return number of components, zero or more. + */ + int getNumCurves(); + + /** + * Returns the component curve at the given index. + * + * @param n index of the component to return, from 0 inclusive to {@link #getNumCurves()} exclusive. + * @return the component curve at the given index. + * @throws IndexOutOfBoundsException if the index is out of bounds. + */ + Curve getCurveN(int n); + + /** + * Returns all the component curves, in order. + * + * @return the components, in the order in which they are traversed. + */ + default List<Curve> getCurves() { + final int n = getNumCurves(); + final List<Curve> curves = new ArrayList<>(n); + for (int i = 0; i < n; i++) { + curves.add(getCurveN(i)); + } + return curves; + } + + /** + * Returns {@link CurveInterpolation#COMPOSITE_CURVE}: the interpolation of a compound curve is + * not a single one, it is whatever each component declares. + */ + @Override + default CurveInterpolation getInterpolation() { + return CurveInterpolation.COMPOSITE_CURVE; + } + + /** + * Returns the start point of the first component. + */ + @Override + default Point getStartPoint() { + return getCurveN(0).getStartPoint(); + } + + /** + * Returns the end point of the last component. + */ + @Override + default Point getEndPoint() { + return getCurveN(getNumCurves() - 1).getEndPoint(); + } + + /** + * Returns the sum of the lengths of the components. + */ + @Override + default double getLength() { + double length = 0; + for (int i = 0, n = getNumCurves(); i < n; i++) { + length += getCurveN(i).getLength(); + } + return length; + } + + /** + * Returns whether the last component ends where the first one starts. + * An empty compound curve is not closed. + */ + @Override + default boolean isClosed() { + final int n = getNumCurves(); + if (n == 0) { + return false; + } + return getStartPoint().getPosition().equals(getEndPoint().getPosition(), 0); + } } 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 73743486aa..b8748a9692 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 @@ -28,18 +28,28 @@ import org.apache.sis.geometries.math.SampleSystem; import org.apache.sis.geometries.math.NDArrays; import org.apache.sis.geometries.math.Array; import org.apache.sis.geometries.internal.shared.ArraySequence; +import org.apache.sis.geometries.internal.shared.DefaultCircularString; +import org.apache.sis.geometries.internal.shared.DefaultCompoundCurve; +import org.apache.sis.geometries.internal.shared.DefaultCurvePolygon; import org.apache.sis.geometries.internal.shared.DefaultEmpty; import org.apache.sis.geometries.internal.shared.DefaultGeometryCollection; import org.apache.sis.geometries.internal.shared.DefaultLineString; import org.apache.sis.geometries.internal.shared.DefaultLinearRing; +import org.apache.sis.geometries.internal.shared.DefaultMultiCurve; import org.apache.sis.geometries.internal.shared.DefaultMultiLineString; import org.apache.sis.geometries.internal.shared.DefaultMultiPoint; import org.apache.sis.geometries.internal.shared.DefaultMultiPolygon; +import org.apache.sis.geometries.internal.shared.DefaultMultiPolyhedron; import org.apache.sis.geometries.internal.shared.DefaultMultiSurface; import org.apache.sis.geometries.internal.shared.DefaultPoint; import org.apache.sis.geometries.internal.shared.DefaultPolygon; +import org.apache.sis.geometries.internal.shared.DefaultPolyhedralSurface; +import org.apache.sis.geometries.internal.shared.DefaultPolyhedron; import org.apache.sis.geometries.internal.shared.DefaultRawMultiPoint; +import org.apache.sis.geometries.internal.shared.DefaultReversedCurve; +import org.apache.sis.geometries.internal.shared.DefaultReversedSurface; import org.apache.sis.geometries.internal.shared.DefaultTriangle; +import org.apache.sis.geometries.internal.shared.DefaultTriangulatedSurface; import org.apache.sis.geometries.math.DataType; import org.apache.sis.geometries.spirals.Clothoid; import org.apache.sis.geometry.wrapper.Capability; @@ -115,6 +125,10 @@ public final class GeometryFactory extends org.apache.sis.geometry.wrapper.Geome return new DefaultMultiLineString(geometries); } + public static <T extends Curve> MultiCurve<T> createMultiCurve(T ... geometries) { + return new DefaultMultiCurve<>(geometries); + } + public static MultiPolygon createMultiPolygon(Polygon ... geometries) { return new DefaultMultiPolygon(geometries); } @@ -127,6 +141,103 @@ public final class GeometryFactory extends org.apache.sis.geometry.wrapper.Geome return new DefaultGeometryCollection<>(geometries); } + /* + * Variants taking an explicit coordinate reference system, used when the collection may be + * empty. An aggregate normally reports the CRS of its first element; with no element there is + * nothing to report, so the CRS has to be supplied by the caller. + */ + + public static MultiPoint createMultiPoint(CoordinateReferenceSystem crs, Point ... geometries) { + return new DefaultRawMultiPoint(crs, geometries); + } + + public static MultiLineString createMultiLineString(CoordinateReferenceSystem crs, LineString ... geometries) { + return new DefaultMultiLineString(crs, geometries); + } + + public static <T extends Curve> MultiCurve<T> createMultiCurve(CoordinateReferenceSystem crs, T ... geometries) { + return new DefaultMultiCurve<>(crs, geometries); + } + + public static MultiPolygon createMultiPolygon(CoordinateReferenceSystem crs, Polygon ... geometries) { + return new DefaultMultiPolygon(crs, geometries); + } + + public static <T extends Surface> MultiSurface<T> createMultiSurface(CoordinateReferenceSystem crs, T ... geometries) { + return new DefaultMultiSurface<>(crs, geometries); + } + + public static <T extends Geometry> GeometryCollection<T> createGeometryCollection(CoordinateReferenceSystem crs, T ... geometries) { + return new DefaultGeometryCollection<>(crs, geometries); + } + + /* + * Curves and surfaces beyond the linear ones, and solids. These are what the GML 3 constructs + * `gml:Curve`, `gml:CompositeCurve`, `gml:Ring`, `gml:ArcString`, `gml:Surface`, + * `gml:CompositeSurface`, `gml:Solid`, `gml:CompositeSolid` and the two `gml:Orientable*` + * elements map onto. + */ + + public static CompoundCurve createCompoundCurve(Curve ... curves) { + return new DefaultCompoundCurve(curves); + } + + public static CompoundCurve createCompoundCurve(CoordinateReferenceSystem crs, Curve ... curves) { + return new DefaultCompoundCurve(crs, curves); + } + + public static CircularString createCircularString(PointSequence sequence) { + return new DefaultCircularString(sequence); + } + + public static CurvePolygon createCurvePolygon(Curve exterior, List<Curve> interiors) { + return new DefaultCurvePolygon(exterior, interiors); + } + + public static <T extends Polygon> PolyhedralSurface<T> createPolyhedralSurface(T ... patches) { + return new DefaultPolyhedralSurface<>(null, patches); + } + + public static <T extends Polygon> PolyhedralSurface<T> createPolyhedralSurface(CoordinateReferenceSystem crs, T[] patches) { + return new DefaultPolyhedralSurface<>(crs, patches); + } + + public static TIN createTIN(Triangle ... patches) { + return new DefaultTriangulatedSurface(patches); + } + + public static TIN createTIN(CoordinateReferenceSystem crs, Triangle[] patches) { + return new DefaultTriangulatedSurface(crs, patches); + } + + public static Polyhedron createPolyhedron(MultiPolygon exteriorShell, List<MultiPolygon> interiorShells) { + return new DefaultPolyhedron(exteriorShell, interiorShells); + } + + public static MultiPolyhedron createMultiPolyhedron(Polyhedron ... solids) { + return new DefaultMultiPolyhedron(solids); + } + + public static MultiPolyhedron createMultiPolyhedron(CoordinateReferenceSystem crs, Polyhedron ... solids) { + return new DefaultMultiPolyhedron(crs, solids); + } + + /** + * Returns a curve traversed in the opposite direction to the given one. + * This is what a GML {@code gml:OrientableCurve} with {@code orientation="-"} describes. + */ + public static Curve createReversed(Curve base) { + return new DefaultReversedCurve(base); + } + + /** + * Returns a surface whose up-normal points the opposite way to the given one's. + * This is what a GML {@code gml:OrientableSurface} with {@code orientation="-"} describes. + */ + public static Surface createReversed(Surface base) { + return new DefaultReversedSurface(base); + } + public static PointSequence createSequence(Array positions) { return createSequence(Collections.singletonMap(AttributesType.ATT_POSITION, positions)); } diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/GeometryVisitor.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/GeometryVisitor.java index deac5dbc57..6ea87869e8 100644 --- a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/GeometryVisitor.java +++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/GeometryVisitor.java @@ -32,9 +32,9 @@ public class GeometryVisitor { else if (geometry instanceof Triangle candidate) visit(candidate); else if (geometry instanceof Polygon candidate) visit(candidate); - else if (geometry instanceof Surface candidate) visit(candidate); else if (geometry instanceof TIN candidate) visit(candidate); else if (geometry instanceof PolyhedralSurface candidate) visit(candidate); + else if (geometry instanceof Surface candidate) visit(candidate); else if (geometry instanceof MultiPolygon candidate) visit(candidate); else if (geometry instanceof MultiLineString candidate) visit(candidate); diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/MultiSurface.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/MultiSurface.java index 069f454581..01ce887dcc 100644 --- a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/MultiSurface.java +++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/MultiSurface.java @@ -36,6 +36,13 @@ package org.apache.sis.geometries; */ public interface MultiSurface<T extends Surface> extends GeometryCollection<T>{ + public static final String TYPE = "MULTISURFACE"; + + @Override + public default String getGeometryType() { + return TYPE; + } + /** * The area of this MultiSurface, as measured in the spatial reference system of this MultiSurface. * @@ -45,7 +52,7 @@ public interface MultiSurface<T extends Surface> extends GeometryCollection<T>{ default double getArea() { double area = 0.0; for (int i = 0, n = getNumGeometries(); i < n; i++) { - area += getGeometryN(n).getArea(); + area += getGeometryN(i).getArea(); } return area; } diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/Orientable.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/Orientable.java index 6f821aa5b8..feabb3c8e1 100644 --- a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/Orientable.java +++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/Orientable.java @@ -32,10 +32,17 @@ public interface Orientable extends Primitive { NEGATIVE } + /** + * Returns whether this geometry is traversed in the direction of its underlying primitive + * ({@link Sign#POSITIVE}) or in the opposite direction ({@link Sign#NEGATIVE}). + * + * <p>The default is {@link Sign#POSITIVE}, which is what a geometry defined directly by its own + * coordinates is: only a geometry that stands for the reverse of another one reports + * {@link Sign#NEGATIVE}.</p> + */ @UML(identifier="orientation", specification=ISO_19107) // section 6.4.15.2 default Sign getOrientationSign(){ - //TODO - throw new UnsupportedOperationException(); + return Sign.POSITIVE; } @UML(identifier="proxy", specification=ISO_19107) // section 6.4.15.3 diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/Polyhedron.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/Polyhedron.java index 4c6562e391..77f244f756 100644 --- a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/Polyhedron.java +++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/Polyhedron.java @@ -33,7 +33,7 @@ import java.util.List; * @author Johann Sorel (Geomatys) * @see https://docs.ogc.org/DRAFTS/21-045r1.html#polyhedron */ -public interface Polyhedron extends Geometry { +public interface Polyhedron extends Solid { public static final String TYPE = "POLYHEDRON"; diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/Solid.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/Solid.java index fd9c662293..2dddda6053 100644 --- a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/Solid.java +++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/Solid.java @@ -31,25 +31,47 @@ import org.opengis.geometry.DirectPosition; @UML(identifier="Solid", specification=ISO_19107) // section 6.4.28 public interface Solid extends Primitive { + /** + * Returns 3: a polyhedron bounds a volume. + */ + @Override + public default int getTopologicDimension() { + return 3; + } + @UML(identifier="boundary", specification=ISO_19107) // section 6.4.28.2 - Geometry getBoundary(); + default Geometry getBoundary() { + throw new UnsupportedOperationException(); + } @UML(identifier="area", specification=ISO_19107) // section 6.4.28.3 - Area getArea(); + default Area getArea() { + throw new UnsupportedOperationException(); + } @UML(identifier="volume", specification=ISO_19107) // section 6.4.28.4 - Volume getVolume(); + default Volume getVolume() { + throw new UnsupportedOperationException(); + } @UML(identifier="dataPoint", specification=ISO_19107) // section 6.4.28.5 - List<DirectPosition> getDataPoints(); + default List<DirectPosition> getDataPoints() { + throw new UnsupportedOperationException(); + } @UML(identifier="controlPoint", specification=ISO_19107) // section 6.4.28.6 - List<DirectPosition> getControlPoints(); + default List<DirectPosition> getControlPoints() { + throw new UnsupportedOperationException(); + } @UML(identifier="interpolation", specification=ISO_19107) // section 6.4.28.7 - SolidInterpolation getInterpolation(); + default SolidInterpolation getInterpolation() { + throw new UnsupportedOperationException(); + } @UML(identifier="knot", specification=ISO_19107) // section 6.4.28.8 - List<Knot> getKnots(); + default List<Knot> getKnots() { + throw new UnsupportedOperationException(); + } } diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/conics/CircularString.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/conics/CircularString.java index b7f19733d4..5f79396621 100644 --- a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/conics/CircularString.java +++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/conics/CircularString.java @@ -16,13 +16,23 @@ */ package org.apache.sis.geometries.conics; +import org.opengis.referencing.crs.CoordinateReferenceSystem; +import org.apache.sis.geometries.AttributesType; import org.apache.sis.geometries.Curve; +import org.apache.sis.geometries.CurveInterpolation; +import org.apache.sis.geometries.Point; +import org.apache.sis.geometries.PointSequence; /** - * @todo + * A curve made of circular arcs joined end to end, each arc being defined by three points: its + * start, a point somewhere along it, and its end. Consecutive arcs share a point, so a circular + * string of <var>k</var> arcs has 2·<var>k</var>+1 points — always an odd number, and at least + * three. + * * @author Johann Sorel (Geomatys) * @see https://docs.ogc.org/DRAFTS/21-045r1.html#circular_string + * @see GML ArcString */ public interface CircularString extends Curve { @@ -32,4 +42,68 @@ public interface CircularString extends Curve { public default String getGeometryType() { return TYPE; } + + /** + * Returns the control points of this circular string: for each arc, its start point, a point + * on the arc and its end point, with consecutive arcs sharing a point. + * + * @return the control points, never null. Its size is odd and at least 3, or 0 if empty. + */ + PointSequence getPoints(); + + /** + * Returns the number of arcs this circular string is made of. + */ + default int getNumArcs() { + final int size = getPoints().size(); + return (size == 0) ? 0 : (size - 1) / 2; + } + + /** + * Returns {@link CurveInterpolation#CIRCULAR}. + */ + @Override + default CurveInterpolation getInterpolation() { + return CurveInterpolation.CIRCULAR; + } + + @Override + default CoordinateReferenceSystem getCoordinateReferenceSystem() { + return getPoints().getCoordinateReferenceSystem(); + } + + @Override + default void setCoordinateReferenceSystem(CoordinateReferenceSystem cs) throws IllegalArgumentException { + getPoints().setCoordinateReferenceSystem(cs); + } + + @Override + default AttributesType getAttributesType() { + return getPoints().getAttributesType(); + } + + @Override + default boolean isEmpty() { + return getPoints().isEmpty(); + } + + @Override + default Point getStartPoint() { + return getPoints().getPoint(0); + } + + @Override + default Point getEndPoint() { + return getPoints().getPoint(getPoints().size() - 1); + } + + @Override + default boolean isClosed() { + final PointSequence points = getPoints(); + final int size = points.size(); + if (size == 0) { + return false; + } + return points.getPosition(0).equals(points.getPosition(size - 1), 0); + } } diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/AbstractGeometry.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/AbstractGeometry.java index a58e7f5b82..d765953328 100644 --- a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/AbstractGeometry.java +++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/AbstractGeometry.java @@ -23,6 +23,8 @@ import org.apache.sis.geometries.PointSequence; import org.apache.sis.geometries.math.Tuple; import org.apache.sis.geometries.math.Cursor; import org.apache.sis.geometries.math.Array; +import org.apache.sis.geometry.GeneralEnvelope; +import org.opengis.geometry.Envelope; /** @@ -78,4 +80,32 @@ public abstract class AbstractGeometry implements Geometry { toText(sb, array.getPosition(i)); } } + + /** + * Returns the union of the envelopes of the given geometries, + * or {@code null} if there is nothing to compute a union of. + */ + protected static Envelope envUnion(final Geometry... geometries) { + GeneralEnvelope union = null; + for (final Geometry geometry : geometries) { + union = add(union, geometry); + } + return union; + } + + /** + * Adds the envelope of the given geometry to the given union, creating it if needed. + * Geometries with no envelope at all (an empty one, typically) are skipped. + */ + private static GeneralEnvelope add(GeneralEnvelope union, final Geometry geometry) { + final Envelope envelope = geometry.getEnvelope(); + if (envelope != null) { + if (union == null) { + union = new GeneralEnvelope(envelope); + } else { + union.add(envelope); + } + } + return union; + } } diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultCircularString.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultCircularString.java new file mode 100644 index 0000000000..a96a1f265f --- /dev/null +++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultCircularString.java @@ -0,0 +1,65 @@ +/* + * 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.internal.shared; + +import org.apache.sis.geometries.PointSequence; +import org.apache.sis.geometries.conics.CircularString; +import org.opengis.geometry.Envelope; + +/** + * A curve made of circular arcs, each defined by three of the control points. + * + * @author Johann Sorel (Geomatys) + */ +public class DefaultCircularString extends AbstractGeometry implements CircularString { + + private final PointSequence points; + + /** + * Creates a circular string from the given control points. + * + * @param points start point, mid point and end point of each arc, consecutive arcs sharing a + * point. Its size must be odd and at least 3, or 0 for an empty circular string. + * @throws IllegalArgumentException if the number of points cannot describe a whole number of arcs. + */ + public DefaultCircularString(PointSequence points) { + final int size = points.size(); + if (size != 0 && (size < 3 || (size % 2) == 0)) { + throw new IllegalArgumentException("A circular string needs an odd number of at least 3 points " + + "(start, mid and end of each arc, consecutive arcs sharing a point), but got " + size + '.'); + } + this.points = points; + } + + @Override + public PointSequence getPoints() { + return points; + } + + @Override + public Envelope getEnvelope() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public String asText() { + final StringBuilder sb = new StringBuilder(TYPE).append(" ("); + toText(sb, points); + return sb.append(')').toString(); + } + +} diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultCompoundCurve.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultCompoundCurve.java new file mode 100644 index 0000000000..91509203e0 --- /dev/null +++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultCompoundCurve.java @@ -0,0 +1,106 @@ +/* + * 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.internal.shared; + +import org.opengis.geometry.Envelope; +import org.opengis.referencing.crs.CoordinateReferenceSystem; +import org.apache.sis.geometries.AttributesType; +import org.apache.sis.geometries.CompoundCurve; +import org.apache.sis.geometries.Curve; + + +/** + * A curve made of several curves joined end to end. + * + * @author Johann Sorel (Geomatys) + */ +public class DefaultCompoundCurve extends AbstractGeometry implements CompoundCurve { + + private final Curve[] curves; + + /** + * The coordinate reference system to report when this curve has no component. + * Ignored otherwise, in which case the first component is authoritative. May be {@code null}. + */ + private CoordinateReferenceSystem fallbackCRS; + + public DefaultCompoundCurve(Curve... curves) { + this(null, curves); + } + + /** + * Creates a compound curve which reports the given coordinate reference system + * when {@code curves} is empty. + */ + public DefaultCompoundCurve(CoordinateReferenceSystem fallbackCRS, Curve... curves) { + this.curves = curves; + this.fallbackCRS = fallbackCRS; + } + + @Override + public int getNumCurves() { + return curves.length; + } + + @Override + public Curve getCurveN(int n) { + return curves[n]; + } + + @Override + public boolean isEmpty() { + for (final Curve c : curves) { + if (!c.isEmpty()) { + return false; + } + } + return true; + } + + @Override + public CoordinateReferenceSystem getCoordinateReferenceSystem() { + return (curves.length != 0) ? curves[0].getCoordinateReferenceSystem() : fallbackCRS; + } + + @Override + public void setCoordinateReferenceSystem(CoordinateReferenceSystem crs) throws IllegalArgumentException { + this.fallbackCRS = crs; + for (final Curve c : curves) { + c.setCoordinateReferenceSystem(crs); + } + } + + @Override + public AttributesType getAttributesType() { + return (curves.length != 0) ? curves[0].getAttributesType() : AttributesType.EMPTY; + } + + @Override + public Envelope getEnvelope() { + return envUnion(curves); + } + + @Override + public String asText() { + final StringBuilder sb = new StringBuilder(TYPE).append(" ("); + for (int i = 0; i < curves.length; i++) { + if (i != 0) sb.append(", "); + sb.append(curves[i].asText()); + } + return sb.append(')').toString(); + } +} diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultCurvePolygon.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultCurvePolygon.java new file mode 100644 index 0000000000..05a9a7bb89 --- /dev/null +++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultCurvePolygon.java @@ -0,0 +1,97 @@ +/* + * 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.internal.shared; + +import java.util.List; +import java.util.Objects; +import org.opengis.geometry.Envelope; +import org.opengis.referencing.crs.CoordinateReferenceSystem; +import org.apache.sis.geometries.Curve; +import org.apache.sis.geometries.CurvePolygon; +import org.apache.sis.geometries.Geometries; + + +/** + * A planar surface whose boundary rings may use any interpolation, not only the linear one that a + * {@link org.apache.sis.geometries.Polygon} is restricted to. + * + * @author Johann Sorel (Geomatys) + */ +public class DefaultCurvePolygon extends AbstractGeometry implements CurvePolygon { + + protected final Curve exterior; + protected final List<Curve> interiors; + + public DefaultCurvePolygon(Curve exterior) { + this(exterior, null); + } + + public DefaultCurvePolygon(Curve exterior, List<Curve> interiors) { + this.exterior = Objects.requireNonNull(exterior); + this.interiors = (interiors == null) ? List.of() : List.copyOf(interiors); + for (final Curve interior : this.interiors) { + Geometries.ensureSameAttributes(exterior.getAttributesType(), interior.getAttributesType()); + } + } + + @Override + public Curve getExteriorRing() { + return exterior; + } + + @Override + public List<Curve> getInteriorRings() { + return interiors; + } + + @Override + public boolean isEmpty() { + return exterior.isEmpty(); + } + + @Override + public CoordinateReferenceSystem getCoordinateReferenceSystem() { + return exterior.getCoordinateReferenceSystem(); + } + + @Override + public void setCoordinateReferenceSystem(CoordinateReferenceSystem cs) throws IllegalArgumentException { + exterior.setCoordinateReferenceSystem(cs); + for (final Curve interior : interiors) { + interior.setCoordinateReferenceSystem(cs); + } + } + + @Override + public Envelope getEnvelope() { + return exterior.getEnvelope(); + } + + @Override + public double getArea() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public String asText() { + final StringBuilder sb = new StringBuilder(TYPE).append(" (").append(exterior.asText()); + for (final Curve interior : interiors) { + sb.append(", ").append(interior.asText()); + } + return sb.append(')').toString(); + } +} diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultGeometryCollection.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultGeometryCollection.java index e327209a35..7fd7ba5fd5 100644 --- a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultGeometryCollection.java +++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultGeometryCollection.java @@ -29,19 +29,36 @@ public class DefaultGeometryCollection<T extends Geometry> extends AbstractGeome private final T[] geometries; + /** + * The coordinate reference system to report when this collection is empty. + * Ignored when at least one geometry is present, in which case the first + * geometry is authoritative. May be {@code null}. + */ + private CoordinateReferenceSystem fallbackCRS; + public DefaultGeometryCollection(T[] geometries) { - this.geometries = geometries; + this(null, geometries); + } + + /** + * Creates a collection which reports the given coordinate reference system + * when {@code geometries} is empty. + */ + public DefaultGeometryCollection(CoordinateReferenceSystem fallbackCRS, T[] geometries) { + this.geometries = geometries; + this.fallbackCRS = fallbackCRS; } @Override public CoordinateReferenceSystem getCoordinateReferenceSystem() { - return geometries[0].getCoordinateReferenceSystem(); + return (geometries.length != 0) ? geometries[0].getCoordinateReferenceSystem() : fallbackCRS; } @Override - public void setCoordinateReferenceSystem(CoordinateReferenceSystem cs) throws IllegalArgumentException { + public void setCoordinateReferenceSystem(CoordinateReferenceSystem crs) throws IllegalArgumentException { + fallbackCRS = crs; for (T c : geometries) { - c.setCoordinateReferenceSystem(cs); + c.setCoordinateReferenceSystem(crs); } } diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultMultiCurve.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultMultiCurve.java index 1085be62aa..3da9597157 100644 --- a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultMultiCurve.java +++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultMultiCurve.java @@ -25,34 +25,14 @@ import org.apache.sis.geometries.MultiCurve; * * @author Johann Sorel (Geomatys) */ -public class DefaultMultiCurve<T extends Curve> extends AbstractGeometry implements MultiCurve<T> { - - private final T[] curves; +public class DefaultMultiCurve<T extends Curve> extends DefaultGeometryCollection<T> implements MultiCurve<T> { public DefaultMultiCurve(T[] geometries) { - this.curves = geometries; - } - - @Override - public CoordinateReferenceSystem getCoordinateReferenceSystem() { - return curves[0].getCoordinateReferenceSystem(); - } - - @Override - public void setCoordinateReferenceSystem(CoordinateReferenceSystem cs) throws IllegalArgumentException { - for (Curve c : curves) { - c.setCoordinateReferenceSystem(cs); - } - } - - @Override - public int getNumGeometries() { - return curves.length; + this(null, geometries); } - @Override - public T getGeometryN(int n) { - return curves[n]; + public DefaultMultiCurve(CoordinateReferenceSystem fallbackCRS, T[] geometries) { + super(fallbackCRS, geometries); } } diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultMultiLineString.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultMultiLineString.java index cbeaba3959..bee4876af6 100644 --- a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultMultiLineString.java +++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultMultiLineString.java @@ -16,6 +16,7 @@ */ package org.apache.sis.geometries.internal.shared; +import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.apache.sis.geometries.LineString; import org.apache.sis.geometries.MultiLineString; @@ -30,4 +31,8 @@ public class DefaultMultiLineString extends DefaultMultiCurve<LineString> implem super(geometries); } + public DefaultMultiLineString(CoordinateReferenceSystem fallbackCRS, LineString... geometries) { + super(fallbackCRS, geometries); + } + } diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultMultiPolygon.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultMultiPolygon.java index 9fc249ca7c..cff7054b0d 100644 --- a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultMultiPolygon.java +++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultMultiPolygon.java @@ -16,6 +16,7 @@ */ package org.apache.sis.geometries.internal.shared; +import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.apache.sis.geometries.MultiPolygon; import org.apache.sis.geometries.Polygon; @@ -30,4 +31,8 @@ public class DefaultMultiPolygon extends DefaultMultiSurface<Polygon> implements super(geometries); } + public DefaultMultiPolygon(CoordinateReferenceSystem fallbackCRS, Polygon[] geometries) { + super(fallbackCRS, geometries); + } + } diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultMultiPolygon.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultMultiPolyhedron.java similarity index 60% copy from incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultMultiPolygon.java copy to incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultMultiPolyhedron.java index 9fc249ca7c..fb52a4c671 100644 --- a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultMultiPolygon.java +++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultMultiPolyhedron.java @@ -16,18 +16,25 @@ */ package org.apache.sis.geometries.internal.shared; -import org.apache.sis.geometries.MultiPolygon; -import org.apache.sis.geometries.Polygon; +import org.opengis.referencing.crs.CoordinateReferenceSystem; +import org.apache.sis.geometries.MultiPolyhedron; +import org.apache.sis.geometries.Polyhedron; /** + * A collection of solids, each defined by its bounding shells. * * @author Johann Sorel (Geomatys) + * @see GML CompositeSolid, MultiSolid */ -public class DefaultMultiPolygon extends DefaultMultiSurface<Polygon> implements MultiPolygon { +public class DefaultMultiPolyhedron extends DefaultGeometryCollection<Polyhedron> implements MultiPolyhedron { - public DefaultMultiPolygon(Polygon[] geometries) { - super(geometries); + public DefaultMultiPolyhedron(Polyhedron... solids) { + this(null, solids); + } + + public DefaultMultiPolyhedron(CoordinateReferenceSystem fallbackCRS, Polyhedron... solids) { + super(fallbackCRS, solids); } } diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultMultiSurface.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultMultiSurface.java index 211d72a4d2..a9ba2b8711 100644 --- a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultMultiSurface.java +++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultMultiSurface.java @@ -25,39 +25,14 @@ import org.apache.sis.geometries.Surface; * * @author Johann Sorel (Geomatys) */ -public class DefaultMultiSurface<T extends Surface> extends AbstractGeometry implements MultiSurface<T> { - - private final T[] surfaces; +public class DefaultMultiSurface<T extends Surface> extends DefaultGeometryCollection<T> implements MultiSurface<T> { public DefaultMultiSurface(T[] geometries) { - this.surfaces = geometries; - } - - @Override - public String getGeometryType() { - return "MULTISURFACE"; - } - - @Override - public CoordinateReferenceSystem getCoordinateReferenceSystem() { - return surfaces[0].getCoordinateReferenceSystem(); - } - - @Override - public void setCoordinateReferenceSystem(CoordinateReferenceSystem cs) throws IllegalArgumentException { - for (T c : surfaces) { - c.setCoordinateReferenceSystem(cs); - } - } - - @Override - public int getNumGeometries() { - return surfaces.length; + this(null, geometries); } - @Override - public T getGeometryN(int n) { - return surfaces[n]; + public DefaultMultiSurface(CoordinateReferenceSystem fallbackCRS, T[] geometries) { + super(fallbackCRS, geometries); } } diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultPolyhedralSurface.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultPolyhedralSurface.java new file mode 100644 index 0000000000..1f458071c8 --- /dev/null +++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultPolyhedralSurface.java @@ -0,0 +1,107 @@ +/* + * 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.internal.shared; + +import org.opengis.geometry.Envelope; +import org.opengis.referencing.crs.CoordinateReferenceSystem; +import org.apache.sis.geometries.AttributesType; +import org.apache.sis.geometries.Polygon; +import org.apache.sis.geometries.PolyhedralSurface; + + +/** + * A surface made of polygonal patches which share their common boundary segments. + * + * @author Johann Sorel (Geomatys) + * @see GML Surface patches PolygonPatch CompositeSurface + */ +public class DefaultPolyhedralSurface<T extends Polygon> extends AbstractGeometry implements PolyhedralSurface<T> { + + private final T[] patches; + + /** + * The coordinate reference system to report when this surface has no patch. + * Ignored otherwise, in which case the first patch is authoritative. May be {@code null}. + */ + private final CoordinateReferenceSystem fallbackCRS; + + @SafeVarargs + public DefaultPolyhedralSurface(T... patches) { + this(null, patches); + } + + /** + * Creates a surface which reports the given coordinate reference system + * when {@code patches} is empty. + */ + public DefaultPolyhedralSurface(CoordinateReferenceSystem fallbackCRS, T[] patches) { + this.patches = patches; + this.fallbackCRS = fallbackCRS; + } + + @Override + public int getNumPatches() { + return patches.length; + } + + @Override + public T getPatchN(int n) { + return patches[n]; + } + + @Override + public boolean isEmpty() { + for (final T patch : patches) { + if (!patch.isEmpty()) { + return false; + } + } + return true; + } + + @Override + public CoordinateReferenceSystem getCoordinateReferenceSystem() { + return (patches.length != 0) ? patches[0].getCoordinateReferenceSystem() : fallbackCRS; + } + + @Override + public void setCoordinateReferenceSystem(CoordinateReferenceSystem cs) throws IllegalArgumentException { + for (final T patch : patches) { + patch.setCoordinateReferenceSystem(cs); + } + } + + @Override + public AttributesType getAttributesType() { + return (patches.length != 0) ? patches[0].getAttributesType() : AttributesType.EMPTY; + } + + @Override + public Envelope getEnvelope() { + return envUnion(patches); + } + + @Override + public String asText() { + final StringBuilder sb = new StringBuilder(PolyhedralSurface.TYPE).append(" ("); + for (int i = 0; i < patches.length; i++) { + if (i != 0) sb.append(", "); + sb.append(patches[i].asText()); + } + return sb.append(')').toString(); + } +} diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultPolyhedron.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultPolyhedron.java new file mode 100644 index 0000000000..c96b04d20d --- /dev/null +++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultPolyhedron.java @@ -0,0 +1,137 @@ +/* + * 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.internal.shared; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import javax.measure.quantity.Area; +import javax.measure.quantity.Volume; +import org.apache.sis.geometries.Geometry; +import org.apache.sis.geometries.Knot; +import org.opengis.geometry.Envelope; +import org.opengis.referencing.crs.CoordinateReferenceSystem; +import org.apache.sis.geometries.MultiPolygon; +import org.apache.sis.geometries.Polyhedron; +import org.apache.sis.geometries.SolidInterpolation; +import org.opengis.geometry.DirectPosition; + + +/** + * A solid defined by its bounding shells, each shell being a closed set of polygons. + * + * @author Johann Sorel (Geomatys) + */ +public class DefaultPolyhedron extends AbstractGeometry implements Polyhedron { + + private final MultiPolygon exterior; + private final List<MultiPolygon> interiors; + + public DefaultPolyhedron(MultiPolygon exterior) { + this(exterior, null); + } + + public DefaultPolyhedron(MultiPolygon exterior, List<MultiPolygon> interiors) { + this.exterior = Objects.requireNonNull(exterior); + this.interiors = (interiors == null) ? List.of() : List.copyOf(interiors); + } + + @Override + public MultiPolygon getExteriorShell() { + return exterior; + } + + @Override + public List<MultiPolygon> getInteriorShells() { + return interiors; + } + + @Override + public boolean isEmpty() { + return exterior.isEmpty(); + } + + @Override + public CoordinateReferenceSystem getCoordinateReferenceSystem() { + return exterior.getCoordinateReferenceSystem(); + } + + @Override + public void setCoordinateReferenceSystem(CoordinateReferenceSystem cs) throws IllegalArgumentException { + exterior.setCoordinateReferenceSystem(cs); + for (final MultiPolygon interior : interiors) { + interior.setCoordinateReferenceSystem(cs); + } + } + + /** + * Returns the envelope of the exterior shell. The interior shells are voids inside it, + * so they cannot extend it. + */ + @Override + public Envelope getEnvelope() { + return exterior.getEnvelope(); + } + + @Override + public String asText() { + final List<MultiPolygon> shells = new ArrayList<>(interiors.size() + 1); + shells.add(exterior); + shells.addAll(interiors); + final StringBuilder sb = new StringBuilder(TYPE).append(" ("); + for (int i = 0; i < shells.size(); i++) { + if (i != 0) sb.append(", "); + sb.append(shells.get(i).asText()); + } + return sb.append(')').toString(); + } + + @Override + public Geometry getBoundary() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public Area getArea() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public Volume getVolume() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public List<DirectPosition> getDataPoints() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public List<DirectPosition> getControlPoints() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public SolidInterpolation getInterpolation() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public List<Knot> getKnots() { + throw new UnsupportedOperationException("Not supported yet."); + } +} diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultRawMultiPoint.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultRawMultiPoint.java index ad9d28f720..b1ddf3cfbb 100644 --- a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultRawMultiPoint.java +++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultRawMultiPoint.java @@ -25,34 +25,14 @@ import org.apache.sis.geometries.Point; * * @author Johann Sorel (Geomatys) */ -public class DefaultRawMultiPoint extends AbstractGeometry implements MultiPoint<Point> { - - private final Point[] geometries; +public class DefaultRawMultiPoint extends DefaultGeometryCollection<Point> implements MultiPoint<Point> { public DefaultRawMultiPoint(Point[] geometries) { - this.geometries = geometries; - } - - @Override - public CoordinateReferenceSystem getCoordinateReferenceSystem() { - return geometries[0].getCoordinateReferenceSystem(); - } - - @Override - public void setCoordinateReferenceSystem(CoordinateReferenceSystem cs) throws IllegalArgumentException { - for (Point c : geometries) { - c.setCoordinateReferenceSystem(cs); - } - } - - @Override - public int getNumGeometries() { - return geometries.length; + this(null, geometries); } - @Override - public Point getGeometryN(int n) { - return geometries[n]; + public DefaultRawMultiPoint(CoordinateReferenceSystem fallbackCRS, Point[] geometries) { + super(fallbackCRS, geometries); } } diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultReversedCurve.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultReversedCurve.java new file mode 100644 index 0000000000..fd1541ebb2 --- /dev/null +++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultReversedCurve.java @@ -0,0 +1,132 @@ +/* + * 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.internal.shared; + +import java.util.Objects; +import org.opengis.geometry.Envelope; +import org.opengis.referencing.crs.CoordinateReferenceSystem; +import org.apache.sis.geometries.AttributesType; +import org.apache.sis.geometries.Curve; +import org.apache.sis.geometries.CurveInterpolation; +import org.apache.sis.geometries.Orientable; +import org.apache.sis.geometries.Point; +import org.apache.sis.geometries.Primitive; + + +/** + * A curve traversed in the opposite direction to the one it is defined in. + * + * @author Johann Sorel (Geomatys) + */ +public class DefaultReversedCurve extends AbstractGeometry implements Curve { + + private final Curve base; + + public DefaultReversedCurve(Curve base) { + this.base = Objects.requireNonNull(base); + } + + @Override + public Sign getOrientationSign() { + return Sign.NEGATIVE; + } + + @Override + public Primitive getPrimitive() { + return base; + } + + @Override + public Orientable getProxy() { + return base; + } + + @Override + public Curve getReverse() { + return base; + } + + /** + * Returns the geometry type of the base curve: reversing a curve does not change what kind of + * curve it is. + */ + @Override + public String getGeometryType() { + return base.getGeometryType(); + } + + /** + * Returns the end point of the base curve, which is where this curve starts. + */ + @Override + public Point getStartPoint() { + return base.getEndPoint(); + } + + /** + * Returns the start point of the base curve, which is where this curve ends. + */ + @Override + public Point getEndPoint() { + return base.getStartPoint(); + } + + @Override + public CurveInterpolation getInterpolation() { + return base.getInterpolation(); + } + + @Override + public double getLength() { + return base.getLength(); + } + + @Override + public boolean isClosed() { + return base.isClosed(); + } + + @Override + public boolean isEmpty() { + return base.isEmpty(); + } + + @Override + public CoordinateReferenceSystem getCoordinateReferenceSystem() { + return base.getCoordinateReferenceSystem(); + } + + @Override + public void setCoordinateReferenceSystem(CoordinateReferenceSystem cs) throws IllegalArgumentException { + base.setCoordinateReferenceSystem(cs); + } + + @Override + public AttributesType getAttributesType() { + return base.getAttributesType(); + } + + @Override + public Envelope getEnvelope() { + return base.getEnvelope(); + } + + @Override + public String asText() { + return base.asText(); + } +} diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultReversedSurface.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultReversedSurface.java new file mode 100644 index 0000000000..c7cf50c7a1 --- /dev/null +++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultReversedSurface.java @@ -0,0 +1,107 @@ +/* + * 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.internal.shared; + +import java.util.Objects; +import org.opengis.geometry.Envelope; +import org.opengis.referencing.crs.CoordinateReferenceSystem; +import org.apache.sis.geometries.AttributesType; +import org.apache.sis.geometries.Orientable; +import org.apache.sis.geometries.Primitive; +import org.apache.sis.geometries.Surface; + + +/** + * A surface whose up-normal points the opposite way to the one it is defined with. + * + * @author Johann Sorel (Geomatys) + */ +public class DefaultReversedSurface extends AbstractGeometry implements Surface { + + private final Surface base; + + public DefaultReversedSurface(Surface base) { + this.base = Objects.requireNonNull(base); + } + + @Override + public Sign getOrientationSign() { + return Sign.NEGATIVE; + } + + @Override + public Primitive getPrimitive() { + return base; + } + + @Override + public Orientable getProxy() { + return base; + } + + @Override + public Orientable getReverse() { + return base; + } + + /** + * Returns the geometry type of the base surface: reversing a surface does not change what kind + * of surface it is. + */ + @Override + public String getGeometryType() { + return base.getGeometryType(); + } + + /** + * Returns the area of the base surface. Area is unsigned, so the orientation does not affect it. + */ + @Override + public double getArea() { + return base.getArea(); + } + + @Override + public boolean isEmpty() { + return base.isEmpty(); + } + + @Override + public CoordinateReferenceSystem getCoordinateReferenceSystem() { + return base.getCoordinateReferenceSystem(); + } + + @Override + public void setCoordinateReferenceSystem(CoordinateReferenceSystem cs) throws IllegalArgumentException { + base.setCoordinateReferenceSystem(cs); + } + + @Override + public AttributesType getAttributesType() { + return base.getAttributesType(); + } + + @Override + public Envelope getEnvelope() { + return base.getEnvelope(); + } + + @Override + public String asText() { + return base.asText(); + } +} diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultMultiCurve.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultTriangulatedSurface.java similarity index 56% copy from incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultMultiCurve.java copy to incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultTriangulatedSurface.java index 1085be62aa..f9b3458733 100644 --- a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultMultiCurve.java +++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultTriangulatedSurface.java @@ -17,42 +17,38 @@ package org.apache.sis.geometries.internal.shared; import org.opengis.referencing.crs.CoordinateReferenceSystem; -import org.apache.sis.geometries.Curve; -import org.apache.sis.geometries.MultiCurve; +import org.apache.sis.geometries.TIN; +import org.apache.sis.geometries.Triangle; /** + * A surface made entirely of triangular patches. * * @author Johann Sorel (Geomatys) */ -public class DefaultMultiCurve<T extends Curve> extends AbstractGeometry implements MultiCurve<T> { +public class DefaultTriangulatedSurface extends DefaultPolyhedralSurface<Triangle> implements TIN { - private final T[] curves; - - public DefaultMultiCurve(T[] geometries) { - this.curves = geometries; - } - - @Override - public CoordinateReferenceSystem getCoordinateReferenceSystem() { - return curves[0].getCoordinateReferenceSystem(); + public DefaultTriangulatedSurface(Triangle... patches) { + super(null, patches); } - @Override - public void setCoordinateReferenceSystem(CoordinateReferenceSystem cs) throws IllegalArgumentException { - for (Curve c : curves) { - c.setCoordinateReferenceSystem(cs); - } + public DefaultTriangulatedSurface(CoordinateReferenceSystem fallbackCRS, Triangle[] patches) { + super(fallbackCRS, patches); } + /** + * Returns {@value TIN#TYPE}, not {@code "POLYHEDRALSURFACE"}. + */ @Override - public int getNumGeometries() { - return curves.length; + public String getGeometryType() { + return TIN.TYPE; } + /** + * Delegates to {@link TIN#asText()}, which formats the triangles as a WKT {@code TIN}. + */ @Override - public T getGeometryN(int n) { - return curves[n]; + public String asText() { + return TIN.super.asText(); } - }
