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 00f87381916ed315b27af3523e8f89ffad1b3830 Author: jsorel <[email protected]> AuthorDate: Wed Sep 9 17:00:09 2026 +0200 feat(Geometry): add Surface and Solid javadoc --- .../main/org/apache/sis/geometries/Solid.java | 131 ++++++++++++-- .../main/org/apache/sis/geometries/Surface.java | 193 ++++++++++++++++++--- .../sis/geometries/adapter/ShapeConverter.java | 4 +- .../internal/shared/DefaultCurvePolygon.java | 3 +- .../internal/shared/DefaultNurbSurface.java | 5 +- .../geometries/internal/shared/DefaultPolygon.java | 7 +- .../internal/shared/DefaultPolyhedron.java | 5 +- .../internal/shared/DefaultReversedSurface.java | 3 +- .../sis/geometries/solid/ParametricCurveSolid.java | 3 +- .../org/apache/sis/geometries/solid/Sphere.java | 5 +- .../sis/geometries/surface/BSplineSurface.java | 3 +- .../sis/geometries/surface/MultiSurface.java | 17 +- .../geometries/surface/ParametricCurveSurface.java | 2 +- .../sis/geometries/surface/PolyhedralSurface.java | 23 ++- .../apache/sis/geometries/surface/Triangle.java | 7 +- 15 files changed, 351 insertions(+), 60 deletions(-) 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 3b9f2f0848..e922560591 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 @@ -27,55 +27,162 @@ import org.opengis.geometry.DirectPosition; /** + * A 3-dimensional geometric primitive, bounded by a set of simple closed surfaces called shells. * - * @author Johann Sorel (Geomatys + * <p>In a 3-dimensional space a solid is fully determined by its boundary, which is the usual + * boundary representation (B-REP). An internal {@linkplain #getInterpolation() interpolation} is + * only needed to describe a non-homogeneous interior, as found in coverages or in solid modelling.</p> + * + * <p>Constraints:</p> + * <ul> + * <li>The topological dimension is 3, therefore a solid only exists in a coordinate system + * having three spatial dimensions.</li> + * <li>A solid is connected: any two of its interior positions can be joined by a curve which + * stays entirely inside the solid.</li> + * <li>A solid is always bounded: it has a finite envelope and contains no point at infinity.</li> + * <li>The solid lies below every one of its shells, as given by the upward surface normal.</li> + * <li>Every shell is simple, neither self-intersecting nor self-tangent, and closed.</li> + * <li>Two shells of the same solid may be tangent to each other at a single position or along a + * simple non-closed curve, lower side against lower side, meaning their upward normals point + * in opposite directions at the contact.</li> + * </ul> + * + * <p>In a 3-dimensional coordinate system each shell splits the space in a bounded and an unbounded + * region per the Jordan-Schönflies theorem, so the shell with the largest envelope is the exterior + * one and the others are interior. Each shell defines the volume opposite to its upward normal.</p> + * + * @author Johann Sorel (Geomatys) + * + * @see ISO 19107:2019 - 6.4.28 */ -@UML(identifier="Solid", specification=ISO_19107) // section 6.4.28 +@UML(identifier="Solid", specification=ISO_19107) public sealed interface Solid extends Primitive permits ParametricCurveSolid, Polyhedron { /** - * Returns 3: a polyhedron bounds a volume. + * Returns 3: a solid bounds a volume. + * + * @see ISO 19107:2019 - 6.4.4.22 */ @Override public default int getTopologicDimension() { return 3; } - @UML(identifier="boundary", specification=ISO_19107) // section 6.4.28.2 + /** + * Shells bounding this solid, each of them a closed surface without boundary. + * + * <p>Constraints:</p> + * <ul> + * <li>At least one shell.</li> + * <li>Every shell is a cycle, therefore a closed composite surface having an empty boundary.</li> + * <li>The shells are oriented outward: the upward normal of each of them faces away from the + * interior of this solid.</li> + * <li>The shell with the largest envelope is the exterior one, which is well defined only + * because the enclosing coordinate space is a 3-dimensional Euclidean space.</li> + * </ul> + * + * @return boundary of this solid. + * + * @see ISO 19107:2019 - 6.4.28.2 + */ + @UML(identifier="boundary", specification=ISO_19107) default Geometry getBoundary() { throw new UnsupportedOperationException(); } - @UML(identifier="area", specification=ISO_19107) // section 6.4.28.3 + /** + * Sum of the areas of all the boundary surfaces of this solid. + * + * @return area of the boundary of this solid. + * + * @see ISO 19107:2019 - 6.4.28.3 + */ + @UML(identifier="area", specification=ISO_19107) default Area getArea() { throw new UnsupportedOperationException(); } - @UML(identifier="volume", specification=ISO_19107) // section 6.4.28.4 + /** + * Volume enclosed by this solid, that is the volume interior to the exterior shell + * and exterior to any interior shell. + * + * @return volume of this solid. + * + * @see ISO 19107:2019 - 6.4.28.4 + */ + @UML(identifier="volume", specification=ISO_19107) default Volume getVolume() { throw new UnsupportedOperationException(); } - @UML(identifier="dataPoint", specification=ISO_19107) // section 6.4.28.5 - default List<DirectPosition> getDataPoints() { + /** + * Sample positions on the interior and on the boundary of this solid, as a point cloud. + * Subtypes may add requirements on this collection. + * + * <p>Difference with ISO 19107: the type has been changed from a list of direct positions + * to {@link DataPoints}, in order to accommodate additional attributes like in GLTF or GPU models.</p> + * + * @return solid data points, possibly empty. + * + * @see ISO 19107:2019 - 6.4.28.5 + */ + @UML(identifier="dataPoint", specification=ISO_19107) + default DataPoints getDataPoints() { throw new UnsupportedOperationException(); } - @UML(identifier="controlPoint", specification=ISO_19107) // section 6.4.28.6 + /** + * Positions used to build the geometry of this solid, the way they are used depending on the interpolation. + * + * <p>Constraints:</p> + * <ul> + * <li>Control points need not lie inside this solid.</li> + * <li>Interpolated values are only valid for the control points enclosed by the + * {@linkplain #getBoundary() boundary} of this solid.</li> + * </ul> + * + * @return solid control points, possibly empty. + * + * @see ISO 19107:2019 - 6.4.28.6 + */ + @UML(identifier="controlPoint", specification=ISO_19107) default List<DirectPosition> getControlPoints() { throw new UnsupportedOperationException(); } - @UML(identifier="interpolation", specification=ISO_19107) // section 6.4.28.7 + /** + * Interpolation mechanism defining the internal parameterization of this solid. + * The default is a boundary representation, which leaves the interior unspecified. + * + * @return interpolation used by this solid. + * + * @see ISO 19107:2019 - 6.4.28.7, 6.4.30 + */ + @UML(identifier="interpolation", specification=ISO_19107) default SolidInterpolation getInterpolation() { throw new UnsupportedOperationException(); } - @UML(identifier="knot", specification=ISO_19107) // section 6.4.28.8 - default double[] getKnots() { + /** + * Construction parameter values matching the {@linkplain #getDataPoints() data points}, + * one sequence for each of the three solid parameters. + * Needed only by parametric solids, such as 3-dimensional b-splines. + * + * <p>Constraints:</p> + * <ul> + * <li>Three sequences, in the horizontal, vertical and depth parameter order.</li> + * <li>Values in each sequence are monotonic.</li> + * </ul> + * + * @return knot values in the construction (knot) space, one sequence per solid parameter. + * + * @see ISO 19107:2019 - 6.4.28.8 + */ + @UML(identifier="knot", specification=ISO_19107) + default List<double[]> getKnots() { throw new UnsupportedOperationException(); } diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/Surface.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/Surface.java index a5e6eaaa8e..d755209064 100644 --- a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/Surface.java +++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/Surface.java @@ -17,6 +17,7 @@ package org.apache.sis.geometries; import java.util.List; +import javax.measure.quantity.Area; import javax.measure.quantity.Length; import org.apache.sis.geometries.internal.shared.DefaultReversedSurface; import org.apache.sis.geometries.surface.CurvePolygon; @@ -30,7 +31,35 @@ import org.opengis.geometry.DirectPosition; /** - * A Surface is a 2-dimensional geometric object. + * A 2-dimensional geometric primitive, bounded by a set of simple closed curves called rings. + * + * <p>The orientation of a surface picks an <cite>up</cite> direction, given by the + * {@linkplain #upNormal(DirectPosition) up-normal}: the side from which the exterior boundary + * appears counter-clockwise. Reversing the orientation reverses every boundary curve and swaps + * <cite>up</cite> and <cite>down</cite>. When the surface bounds a solid, <cite>up</cite> is + * also <cite>outward</cite>.</p> + * + * <p>Constraints:</p> + * <ul> + * <li>The topological dimension is 2.</li> + * <li>A surface is connected: any two of its interior positions can be joined by a curve which + * stays entirely inside the surface.</li> + * <li>A surface is always bounded: it has a finite envelope and contains no point at infinity.</li> + * <li>The surface lies on the left of every one of its rings.</li> + * <li>Every ring is simple, neither self-intersecting nor self-tangent, and closed.</li> + * <li>Two rings of the same surface may be tangent to each other, but only once per pair, + * at a single position, and left side against left side.</li> + * <li>A surface is orientable, therefore neither a Möbius strip nor a Klein bottle; + * such shapes can only be built as a geometric complex.</li> + * </ul> + * + * <p>In a 2-dimensional coordinate system the interpolation is necessarily planar, each ring + * splits the space in a bounded and an unbounded region per the Jordan theorem, the ring with the + * largest envelope is the exterior one and the surface is the intersection of the surfaces defined + * by its rings. On a bounded reference surface such as a sphere, no ring is exterior.</p> + * + * <p>Note: the following describes the OGC Simple Feature Access point of view, where the only + * instantiable subtypes are {@link Polygon} and {@link PolyhedralSurface}.</p> * * A simple Surface may consists of a single “patch” that is associated with one “exterior boundary” and 0 or more * “interior” boundaries. A single such Surface patch in 3-dimensional space is isometric to planar Surfaces, @@ -46,14 +75,15 @@ import org.opengis.geometry.DirectPosition; * The boundary of a simple Surface is the set of closed Curves corresponding to its “exterior” and “interior” * boundaries (Reference [1], section 3.12.9.4). * - * The only instantiable subclasses of Surface defined in this standard are Polygon and PolyhedralSurface. * A Polygon is a simple Surface that is planar. A PolyhedralSurface is a simple surface, consisting of some number * of Polygon patches or facets. If a PolyhedralSurface is closed, then it bounds a solid. * A MultiSurface containing a set of closed PolyhedralSurfaces can be used to represent a Solid object with holes. * * @author Johann Sorel (Geomatys) + * + * @see ISO 19107:2019 - 6.4.25 */ -@UML(identifier="Surface", specification=ISO_19107) // section 6.4.25 +@UML(identifier="Surface", specification=ISO_19107) public sealed interface Surface extends Orientable permits CurvePolygon, ParametricCurveSurface, @@ -65,20 +95,34 @@ public sealed interface Surface extends Orientable /** * The area of this Surface, as measured in the spatial reference system of this Surface. * - * Difference with ISO 19107 : should return an Area instance. + * <p>TODO / Limitation: implementations label the returned quantity in square metres, but its + * magnitude is computed in the units of the coordinate system axes. On a geographic coordinate + * reference system that magnitude is therefore an amount of square degrees reported as square + * metres. Computing a true area on the reference surface, as required by ISO 19107 REQ. 11, + * remains to be done.</p> * - * @see OGC Simple Feature Access 1.2.1 - 6.1.10.2 * @return area of the surface. + * + * @see OGC Simple Feature Access 1.2.1 - 6.1.10.2 + * @see ISO 19107:2019 - 6.4.25.7 */ - @UML(identifier="area", specification=ISO_19107) // section 6.4.25.7 - double getArea(); + @UML(identifier="area", specification=ISO_19107) + Area getArea(); /** * The mathematical centroid for this Surface as a Point. * The result is not guaranteed to be on this Surface. * - * @see OGC Simple Feature Access 1.2.1 - 6.1.10.2 + * <p>Constraints:</p> + * <ul> + * <li>The average is weighted by area.</li> + * <li>The centroid may fall outside the domain of validity of the coordinate reference system.</li> + * </ul> + * * @return centroid for this Surface + * + * @see OGC Simple Feature Access 1.2.1 - 6.1.10.2 + * @see ISO 19107:2019 - 6.4.4.8 */ @Override default Point getCentroid() { @@ -88,63 +132,172 @@ public sealed interface Surface extends Orientable /** * A Point guaranteed to be on this Surface. * - * @see OGC Simple Feature Access 1.2.1 - 6.1.10.2 + * <p>Difference with ISO 19107, which declares this operation on {@code Geometry}: + * see {@link Geometry#getRepresentativePoint()}.</p> + * * @return point guaranteed to be on this Surface. + * + * @see OGC Simple Feature Access 1.2.1 - 6.1.10.2 + * @see ISO 19107:2019 - 6.4.4.19 */ default Point getPointOnSurface() { throw new UnsupportedOperationException(); } - - @UML(identifier="boundary", specification=ISO_19107) // section 6.4.25.2 + /** + * Rings bounding this surface, each of them a simple closed curve having this surface on its left. + * + * <p>Constraints:</p> + * <ul> + * <li>At least one ring.</li> + * <li>Except on a plane, no ring is the exterior one, since the notion of unbounded exterior + * does not apply.</li> + * <li>In a 2-dimensional coordinate system the rings determine the surface completely, + * and may therefore be used to build it.</li> + * </ul> + * + * @return boundary of this surface. + * + * @see ISO 19107:2019 - 6.4.25.2 + */ + @UML(identifier="boundary", specification=ISO_19107) default Geometry getBoundary() { //TODO throw new UnsupportedOperationException(); } - @UML(identifier="interpolation", specification=ISO_19107) // section 6.4.25.3 + /** + * Interpolation mechanisms used between the data points of this surface. + * The default is a polygonal interpolation. + * + * <p>The interpolation combines the {@linkplain #getDataPoints() data points}, + * {@linkplain #getControlPoints() control points} and {@linkplain #getKnots() knots} + * to determine the positions of this surface.</p> + * + * @return interpolations used by this surface. + * + * @see ISO 19107:2019 - 6.4.25.3 + */ + @UML(identifier="interpolation", specification=ISO_19107) default List<SurfaceInterpolation> getInterpolation() { //TODO throw new UnsupportedOperationException(); } - @UML(identifier="numDerivativesBoundary", specification=ISO_19107) // section 6.4.25.4 + /** + * Number of continuous derivatives guaranteed across the {@linkplain #getBoundary() boundary}, + * therefore the continuity between this surface and the neighbours sharing a boundary curve with it. + * The default value 0 means simple continuity (C⁰), while a value <var>n</var> means that this + * surface and its <var>n</var> first derivatives are continuous (Cⁿ). + * + * @return number of continuous derivatives on the boundary, or {@code null} if unspecified. + * + * @see ISO 19107:2019 - 6.4.25.4 + */ + @UML(identifier="numDerivativesBoundary", specification=ISO_19107) default Integer getNumDerivativesBoundary() { //TODO throw new UnsupportedOperationException(); } - @UML(identifier="numDerivativeInterior", specification=ISO_19107) // section 6.4.25.5 + /** + * Minimal level of continuity guaranteed within the interior of this surface. + * The default value 0 means simple continuity (C⁰). + * + * @return number of continuous derivatives in the interior, or {@code null} if unspecified. + * + * @see ISO 19107:2019 - 6.4.25.5 + */ + @UML(identifier="numDerivativeInterior", specification=ISO_19107) default Integer getNumDerivativeInterior() { //TODO throw new UnsupportedOperationException(); } - @UML(identifier="perimeter", specification=ISO_19107) // section 6.4.25.6 + /** + * Sum of the lengths of all the boundary curves of this surface. + * + * @return perimeter of this surface. + * + * @see ISO 19107:2019 - 6.4.25.6 + */ + @UML(identifier="perimeter", specification=ISO_19107) default Length getPerimeter() { //TODO throw new UnsupportedOperationException(); } - @UML(identifier="dataPoint", specification=ISO_19107) // section 6.4.25.8 + /** + * Points lying on this surface. + * + * <p>Difference with ISO 19107: the type has been changed from a list of direct positions + * to {@link DataPoints}, in order to accommodate additional attributes like in GLTF or GPU models.</p> + * + * @return surface data points. + * + * @see ISO 19107:2019 - 6.4.25.8 + */ + @UML(identifier="dataPoint", specification=ISO_19107) default DataPoints getDataPoints() { //TODO throw new UnsupportedOperationException(); } - @UML(identifier="controlPoint", specification=ISO_19107) // section 6.4.25.9 + /** + * Positions used to build the geometry of this surface, the way they are used depending on the interpolation. + * Control points do not necessarily lie on the surface. + * + * @return surface control points, possibly empty. + * + * @see ISO 19107:2019 - 6.4.25.9 + */ + @UML(identifier="controlPoint", specification=ISO_19107) default List<DirectPosition> getControlPoints() { //TODO throw new UnsupportedOperationException(); } - @UML(identifier="knot", specification=ISO_19107) // section 6.4.25.10 - default double[] getKnots() { + /** + * Construction parameter values matching the {@linkplain #getDataPoints() data points}, + * one sequence for each of the two surface parameters. + * Needed only when the construction parameter space is not the default one. + * + * <p>Constraints:</p> + * <ul> + * <li>Two sequences, the first one for the horizontal parameter and the second one for + * the vertical parameter.</li> + * <li>Values in each sequence are monotonic.</li> + * </ul> + * + * @return knot values in the construction (knot) space, one sequence per surface parameter. + * + * @see ISO 19107:2019 - 6.4.25.10 + */ + @UML(identifier="knot", specification=ISO_19107) + default List<double[]> getKnots() { //TODO throw new UnsupportedOperationException(); } - @UML(identifier="upNormal", specification=ISO_19107) // section 6.4.25.11 + /** + * Returns the vector perpendicular to this surface at the given position, pointing upward. + * + * <p>Constraints:</p> + * <ul> + * <li>Normals are consistent over the whole surface, which therefore has two faces.</li> + * <li>In a 3-dimensional coordinate system, the returned vector is perpendicular to the + * tangent plane of this surface at the given position.</li> + * <li>In a 2-dimensional coordinate system, the returned vector lies in the enclosing + * 3-dimensional Cartesian space of the geometric reference surface.</li> + * <li>When this surface bounds a solid, the returned vector points away from that solid.</li> + * </ul> + * + * @param point position on this surface where to evaluate the normal. + * @return upward normal at the given position. + * + * @see ISO 19107:2019 - 6.4.25.11 + */ + @UML(identifier="upNormal", specification=ISO_19107) default Vector upNormal(DirectPosition point) { //TODO throw new UnsupportedOperationException(); diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/adapter/ShapeConverter.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/adapter/ShapeConverter.java index 0541eb6939..1bb7135d8e 100644 --- a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/adapter/ShapeConverter.java +++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/adapter/ShapeConverter.java @@ -286,8 +286,8 @@ public abstract class ShapeConverter { */ // Sort by area, bigger geometries are the outter rings. geometries.sort((Geometry o1, Geometry o2) -> { - double area1 = (o1 instanceof Surface s) ? s.getArea() : 0.0; - double area2 = (o2 instanceof Surface s) ? s.getArea() : 0.0; + double area1 = (o1 instanceof Surface s) ? s.getArea().getValue().doubleValue() : 0.0; + double area2 = (o2 instanceof Surface s) ? s.getArea().getValue().doubleValue() : 0.0; return java.lang.Double.compare(area2, area1); }); 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 index fc3c20fe44..dd808cbac7 100644 --- 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 @@ -18,6 +18,7 @@ package org.apache.sis.geometries.internal.shared; import java.util.List; import java.util.Objects; +import javax.measure.quantity.Area; import org.apache.sis.geometries.Curve; import org.apache.sis.geometries.Geometries; import org.apache.sis.geometries.surface.CurvePolygon; @@ -82,7 +83,7 @@ public non-sealed class DefaultCurvePolygon extends AbstractGeometry implements } @Override - public double getArea() { + public Area getArea() { throw new UnsupportedOperationException("Not supported yet."); } diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultNurbSurface.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultNurbSurface.java index 03caaed6f9..60c1b45172 100644 --- a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultNurbSurface.java +++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultNurbSurface.java @@ -18,6 +18,7 @@ package org.apache.sis.geometries.internal.shared; import java.util.Arrays; import java.util.List; +import javax.measure.quantity.Area; import org.apache.sis.geometries.BBox; import org.apache.sis.geometries.Curve; import org.apache.sis.geometries.DataPoints; @@ -316,7 +317,7 @@ public non-sealed class DefaultNurbSurface extends AbstractGeometry implements N } @Override - public double[] getKnots() { + public List<double[]> getKnots() { throw new UnsupportedOperationException("Not supported yet."); } @@ -336,7 +337,7 @@ public non-sealed class DefaultNurbSurface extends AbstractGeometry implements N } @Override - public double getArea() { + public Area getArea() { throw new UnsupportedOperationException("Not supported yet."); } diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultPolygon.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultPolygon.java index e491ac34cb..9530a19ebc 100644 --- a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultPolygon.java +++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultPolygon.java @@ -18,10 +18,13 @@ package org.apache.sis.geometries.internal.shared; import java.util.List; import java.util.Objects; +import javax.measure.quantity.Area; import org.apache.sis.geometries.Curve; import org.apache.sis.geometries.Geometries; import org.apache.sis.geometries.curve.LinearRing; import org.apache.sis.geometries.surface.Polygon; +import org.apache.sis.measure.Quantities; +import org.apache.sis.measure.Units; import org.locationtech.jts.geom.GeometryFactory; import org.opengis.geometry.Envelope; import org.opengis.referencing.crs.CoordinateReferenceSystem; @@ -84,9 +87,9 @@ public non-sealed class DefaultPolygon extends AbstractGeometry implements Polyg } @Override - public double getArea() { + public Area getArea() { //TODO : fallback on JTS until implemented - return Geometries.asJTS(this, false, new GeometryFactory()).getArea(); + return Quantities.create(Geometries.asJTS(this, false, new GeometryFactory()).getArea(), Units.SQUARE_METRE); } } 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 index 2eb69335a8..90bb2bd4b8 100644 --- 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 @@ -21,6 +21,7 @@ import java.util.List; import java.util.Objects; import javax.measure.quantity.Area; import javax.measure.quantity.Volume; +import org.apache.sis.geometries.DataPoints; import org.apache.sis.geometries.Geometry; import org.apache.sis.geometries.SolidInterpolation; import org.apache.sis.geometries.solid.Polyhedron; @@ -115,7 +116,7 @@ public non-sealed class DefaultPolyhedron extends AbstractGeometry implements Po } @Override - public List<DirectPosition> getDataPoints() { + public DataPoints getDataPoints() { throw new UnsupportedOperationException("Not supported yet."); } @@ -130,7 +131,7 @@ public non-sealed class DefaultPolyhedron extends AbstractGeometry implements Po } @Override - public double[] getKnots() { + public List<double[]> getKnots() { throw new UnsupportedOperationException("Not supported yet."); } } 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 index 6ad59cf4a2..b89cca5147 100644 --- 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 @@ -17,6 +17,7 @@ package org.apache.sis.geometries.internal.shared; import java.util.Objects; +import javax.measure.quantity.Area; import org.apache.sis.geometries.AttributesType; import org.apache.sis.geometries.Orientable; import org.apache.sis.geometries.Primitive; @@ -71,7 +72,7 @@ public non-sealed class DefaultReversedSurface extends AbstractGeometry implemen * Returns the area of the base surface. Area is unsigned, so the orientation does not affect it. */ @Override - public double getArea() { + public Area getArea() { return base.getArea(); } diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/solid/ParametricCurveSolid.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/solid/ParametricCurveSolid.java index 6440e45875..27fea22757 100644 --- a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/solid/ParametricCurveSolid.java +++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/solid/ParametricCurveSolid.java @@ -18,6 +18,7 @@ package org.apache.sis.geometries.solid; import java.util.List; import org.apache.sis.geometries.Curve; +import org.apache.sis.geometries.DataPoints; import org.apache.sis.geometries.GeometryType; import org.apache.sis.geometries.Solid; import static org.opengis.annotation.Specification.ISO_19107; @@ -54,7 +55,7 @@ public sealed interface ParametricCurveSolid extends Solid @UML(identifier="dataPoints", specification=ISO_19107) // section 9.3.1.3 @Override - List<DirectPosition> getDataPoints(); + DataPoints getDataPoints(); @UML(identifier="controlPoints", specification=ISO_19107) // section 9.3.1.3 @Override diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/solid/Sphere.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/solid/Sphere.java index 01e14f3a24..d3aa71a31f 100644 --- a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/solid/Sphere.java +++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/solid/Sphere.java @@ -17,6 +17,7 @@ package org.apache.sis.geometries.solid; import java.util.List; +import javax.measure.quantity.Area; import org.apache.sis.geometries.AttributesType; import org.apache.sis.geometries.BBox; import org.apache.sis.geometries.Curve; @@ -93,7 +94,7 @@ public final class Sphere extends AbstractGeometry implements ParametricCurveSur } @Override - public double getArea() { + public Area getArea() { throw new UnsupportedOperationException("Not supported."); } @@ -189,7 +190,7 @@ public final class Sphere extends AbstractGeometry implements ParametricCurveSur } @Override - public double[] getKnots() { + public List<double[]> getKnots() { throw new UnsupportedOperationException("Not supported yet."); } diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/surface/BSplineSurface.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/surface/BSplineSurface.java index 03a5569419..adb0eed96b 100644 --- a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/surface/BSplineSurface.java +++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/surface/BSplineSurface.java @@ -16,6 +16,7 @@ */ package org.apache.sis.geometries.surface; +import java.util.List; import org.apache.sis.geometries.AttributesType; import org.apache.sis.geometries.GeometryType; import org.apache.sis.geometries.curve.KnotType; @@ -38,7 +39,7 @@ public sealed interface BSplineSurface extends ParametricCurveSurface @UML(identifier="knot", specification=ISO_19107) // section 8.7.2.3 @Override - double[] getKnots(); + List<double[]> getKnots(); @UML(identifier="knotSpec", specification=ISO_19107) // section 8.7.2.5 KnotType getKnotSpec(); diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/surface/MultiSurface.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/surface/MultiSurface.java index 11b4dbcec9..f5718adb2b 100644 --- a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/surface/MultiSurface.java +++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/surface/MultiSurface.java @@ -16,10 +16,13 @@ */ package org.apache.sis.geometries.surface; +import javax.measure.quantity.Area; import org.apache.sis.geometries.GeometryCollection; import org.apache.sis.geometries.Point; import org.apache.sis.geometries.Surface; import org.apache.sis.geometries.internal.shared.DefaultMultiSurface; +import org.apache.sis.measure.Quantities; +import org.apache.sis.measure.Units; /** @@ -57,10 +60,14 @@ public sealed interface MultiSurface<T extends Surface> extends GeometryCollecti * @see OGC Simple Feature Access 1.2.1 - 6.1.13.2 * @return area of the surface. */ - default double getArea() { - double area = 0.0; - for (int i = 0, n = getNumGeometries(); i < n; i++) { - area += getGeometryN(i).getArea(); + default Area getArea() { + final int n = getNumGeometries(); + if (n == 0) { + return Quantities.create(0, Units.SQUARE_METRE); + } + Area area = getGeometryN(0).getArea(); + for (int i = 1; i < n; i++) { + area = Quantities.castOrCopy(area.add(getGeometryN(i).getArea())); } return area; } @@ -83,7 +90,7 @@ public sealed interface MultiSurface<T extends Surface> extends GeometryCollecti * @see OGC Simple Feature Access 1.2.1 - 6.1.13.2 * @return point guaranteed to be on this MultiSurface. */ - default double getPointOnSurface() { + default Point getPointOnSurface() { throw new UnsupportedOperationException(); } } diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/surface/ParametricCurveSurface.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/surface/ParametricCurveSurface.java index ec48f336a2..31c24b00f4 100644 --- a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/surface/ParametricCurveSurface.java +++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/surface/ParametricCurveSurface.java @@ -60,7 +60,7 @@ public sealed interface ParametricCurveSurface extends Surface, ReferenceSystem GeometryType getVerticalCurveType(); @Override - double[] getKnots(); + List<double[]> getKnots(); @UML(identifier="horizontalCurve", specification=ISO_19107) // section 8.3.2.9 Curve getHorizontalCurve(double v); diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/surface/PolyhedralSurface.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/surface/PolyhedralSurface.java index 68b8b262d6..3963395e96 100644 --- a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/surface/PolyhedralSurface.java +++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/surface/PolyhedralSurface.java @@ -16,11 +16,11 @@ */ package org.apache.sis.geometries.surface; -import java.util.stream.Collectors; -import java.util.stream.IntStream; -import java.util.stream.Stream; +import javax.measure.quantity.Area; import org.apache.sis.geometries.Surface; import org.apache.sis.geometries.internal.shared.DefaultPolyhedralSurface; +import org.apache.sis.measure.Quantities; +import org.apache.sis.measure.Units; import static org.opengis.annotation.Specification.ISO_19107; import org.opengis.annotation.UML; @@ -81,11 +81,22 @@ public sealed interface PolyhedralSurface<T extends Polygon> extends /*GeometryC */ T getPatchN(int n); + /** + * Returns the sum of the areas of the patches. + * The unit of measurement is the one of the first patch, + * or square metres if this surface has no patch. + */ @Override - public default double getArea() { - try (Stream<Surface> stream = IntStream.range(0, getNumPatches()).mapToObj(this::getPatchN)) { - return stream.collect(Collectors.summingDouble(Surface::getArea)); + public default Area getArea() { + final int n = getNumPatches(); + if (n == 0) { + return Quantities.create(0, Units.SQUARE_METRE); + } + Area area = getPatchN(0).getArea(); + for (int i = 1; i < n; i++) { + area = Quantities.castOrCopy(area.add(getPatchN(i).getArea())); } + return area; } /** diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/surface/Triangle.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/surface/Triangle.java index 5716a45f3d..7fc24edb41 100644 --- a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/surface/Triangle.java +++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/surface/Triangle.java @@ -18,6 +18,7 @@ package org.apache.sis.geometries.surface; import java.util.Collections; import java.util.List; +import javax.measure.quantity.Area; import org.apache.sis.geometries.AttributesType; import org.apache.sis.geometries.BBox; import org.apache.sis.geometries.DataPoints; @@ -33,6 +34,8 @@ import org.apache.sis.maths.Vector; import org.apache.sis.maths.Vector2D; import org.apache.sis.maths.Vector3D; import org.apache.sis.maths.Vectors; +import org.apache.sis.measure.Quantities; +import org.apache.sis.measure.Units; import static org.opengis.annotation.Specification.ISO_19107; import org.opengis.annotation.UML; import org.opengis.geometry.Envelope; @@ -94,7 +97,7 @@ public sealed interface Triangle extends Polygon } @Override - default double getArea() { + default Area getArea() { final DataPoints points = getExteriorRing().getDataPoints(); final Tuple<?> a = points.getPosition(0); final Tuple<?> b = points.getPosition(1); @@ -104,7 +107,7 @@ public sealed interface Triangle extends Polygon + b.get(0) * (c.get(1) - a.get(1)) + c.get(0) * (a.get(1) - b.get(1)) ) / 2.0; - return Math.abs(area); + return Quantities.create(Math.abs(area), Units.SQUARE_METRE); } /**
