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
The following commit(s) were added to refs/heads/geoapi-4.0 by this push:
new 0d9d0a783d feat(Geometry): add jts fallbacks for getlength, getarea
and others
0d9d0a783d is described below
commit 0d9d0a783d5b6873784a3eb0a81e963c32d29bc7
Author: jsorel <[email protected]>
AuthorDate: Wed Oct 7 10:32:58 2026 +0200
feat(Geometry): add jts fallbacks for getlength, getarea and others
---
.../main/org/apache/sis/geometries/Geometries.java | 68 ++++++++++++++++++++
.../main/org/apache/sis/geometries/Surface.java | 10 +--
.../internal/shared/AbstractGeometry.java | 34 ++++++++++
.../internal/shared/DefaultGeometryCollection.java | 44 +++++++++++++
.../internal/shared/DefaultLineString.java | 42 ++++++++++++
.../internal/shared/DefaultLinearRing.java | 10 +++
.../internal/shared/DefaultMultiPoint.java | 44 +++++++++++++
.../internal/shared/DefaultMultiSurface.java | 11 ++++
.../geometries/internal/shared/DefaultPolygon.java | 74 +++++++++++++++++++++-
.../geometries/operation/GeometryProcessor.java | 27 ++++----
.../sis/geometries/operation/BufferTest.java | 42 ++++++++++--
11 files changed, 376 insertions(+), 30 deletions(-)
diff --git
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/Geometries.java
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/Geometries.java
index 205bb281a4..bc4b9bd5f0 100644
---
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/Geometries.java
+++
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/Geometries.java
@@ -697,6 +697,74 @@ public final class Geometries {
return primitive;
}
+ /**
+ * Returns the unit of measurement in which the coordinates of the given
geometry are expressed,
+ * taken from the first axis of its coordinate system. This is the unit in
which lengths computed
+ * on that geometry, such as a {@linkplain Curve#getLength() curve length}
or a
+ * {@linkplain Surface#getPerimeter() perimeter}, are expressed.
+ *
+ * @param geom the geometry from which to get the coordinate unit.
+ * @return unit of the first coordinate system axis, or {@link
Units#UNITY} if the geometry
+ * has no coordinate reference system.
+ */
+ @SuppressWarnings("rawtypes")
+ public static Unit getLinearUnit(final Geometry geom) {
+ return productOfAxisUnits(geom, 1);
+ }
+
+ /**
+ * Returns the unit in which an {@linkplain Surface#getArea() area}
computed on the given
+ * geometry is expressed, as the product of the units of the two first
coordinate system axes.
+ *
+ * @param geom the geometry from which to get the area unit.
+ * @return product of the units of the two first axes, or {@link
Units#UNITY} if the geometry
+ * has no coordinate reference system or if that system is not at
least 2-dimensional.
+ */
+ @SuppressWarnings("rawtypes")
+ public static Unit getAreaUnit(final Geometry geom) {
+ return productOfAxisUnits(geom, 2);
+ }
+
+ /**
+ * Returns the unit in which a {@linkplain Solid#getVolume() volume}
computed on the given
+ * geometry is expressed, as the product of the units of the three first
coordinate system axes.
+ *
+ * @param geom the geometry from which to get the volume unit.
+ * @return product of the units of the three first axes, or {@link
Units#UNITY} if the geometry
+ * has no coordinate reference system or if that system is not at
least 3-dimensional.
+ */
+ @SuppressWarnings("rawtypes")
+ public static Unit getVolumeUnit(final Geometry geom) {
+ return productOfAxisUnits(geom, 3);
+ }
+
+ /**
+ * Returns the product of the units of the {@code n} first axes of the
coordinate system of
+ * the given geometry. Each axis is read separately because nothing
requires the axes of a
+ * coordinate system to share a unit.
+ *
+ * @param geom the geometry from which to get the units.
+ * @param n number of leading axes to multiply.
+ * @return product of the units of the {@code n} first axes, or {@link
Units#UNITY} if the
+ * geometry has no coordinate reference system or has less than
{@code n} dimensions.
+ */
+ @SuppressWarnings("rawtypes")
+ private static Unit productOfAxisUnits(final Geometry geom, final int n) {
+ final CoordinateReferenceSystem crs =
geom.getCoordinateReferenceSystem();
+ if (crs == null) {
+ return Units.UNITY;
+ }
+ final CoordinateSystem cs = crs.getCoordinateSystem();
+ if (cs.getDimension() < n) {
+ return Units.UNITY;
+ }
+ Unit unit = cs.getAxis(0).getUnit();
+ for (int i = 1; i < n; i++) {
+ unit = unit.multiply(cs.getAxis(i).getUnit());
+ }
+ return unit;
+ }
+
/**
* Returns the sum of the two given quantities, expressed in the unit of
the first one,
* or dimensionless if either operand is dimensionless.
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 c6bffd8bde..cf1db7bac4 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
@@ -86,11 +86,11 @@ public sealed interface Surface extends Orientable
/**
* The area of this Surface, as measured in the spatial reference system
of this Surface.
*
- * <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>
+ * <p>TODO / Limitation: the area is computed as a planar area in the
units of the coordinate
+ * system axes, and the returned quantity is labelled with the square of
the unit of the first
+ * axis. On a geographic coordinate reference system the result is
therefore an amount of square
+ * degrees, reported as such. Computing a true area on the reference
surface, as required by
+ * ISO 19107 REQ. 11, remains to be done.</p>
*
* <p>Difference with ISO-19107, the Area type has been changed to
Quantity to
* handle temporal geometries and crs-less geometries.</p>
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 579e37c638..88d7c74fac 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
@@ -19,6 +19,7 @@ package org.apache.sis.geometries.internal.shared;
import java.util.HashMap;
import java.util.Map;
import org.opengis.geometry.Envelope;
+import org.apache.sis.geometries.Geometries;
import org.apache.sis.geometries.Geometry;
import org.apache.sis.geometry.GeneralEnvelope;
@@ -45,6 +46,39 @@ public abstract non-sealed class AbstractGeometry implements
Geometry {
return asText();
}
+ /**
+ * Returns a view of this geometry as a JTS geometry, for delegating to
JTS an operation
+ * which is not yet implemented in this package. The view shares the
coordinates of this
+ * geometry, no copy is performed.
+ *
+ * <p>Geometry types which have no JTS equivalent, such as the parametric
curves and the
+ * solids, cannot be delegated this way. For them this method reports the
operation as
+ * unsupported, which is the contract of the operations relying on this
fallback.</p>
+ *
+ * @return this geometry seen as a JTS geometry.
+ * @throws UnsupportedOperationException if this geometry has no JTS
equivalent.
+ */
+ protected final org.locationtech.jts.geom.Geometry asJTS() {
+ try {
+ return Geometries.asJTS(this, false, null);
+ } catch (IllegalArgumentException e) {
+ throw new UnsupportedOperationException(e.getMessage(), e);
+ }
+ }
+
+ /**
+ * Converts back to a geometry of this package the result of an operation
delegated to JTS.
+ * The JTS geometries produced by such an operation carry no reference
system, therefore the
+ * system of this geometry is assigned to the result.
+ *
+ * @param result the geometry computed by JTS.
+ * @return the result as a geometry of this package.
+ */
+ protected final Geometry fromJTS(final org.locationtech.jts.geom.Geometry
result) {
+ result.setUserData(getCoordinateReferenceSystem());
+ return Geometries.fromJTS(result, true);
+ }
+
/**
* Returns the union of the envelopes of the given geometries,
* or {@code null} if there is nothing to compute a union of.
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 ed109a5bd9..518b81ed1b 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
@@ -19,6 +19,8 @@ package org.apache.sis.geometries.internal.shared;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.apache.sis.geometries.Geometry;
import org.apache.sis.geometries.GeometryCollection;
+import org.apache.sis.geometries.GeometryFactory;
+import org.apache.sis.geometries.Point;
/**
@@ -72,4 +74,46 @@ public non-sealed class DefaultGeometryCollection<T extends
Geometry> extends Ab
return geometries[n];
}
+ @Override
+ public Point getCentroid() {
+ if (isEmpty()) {
+ // The centroid of the empty set is undefined.
+ return null;
+ }
+ //TODO : fallback on JTS until implemented
+ return (Point) fromJTS(asJTS().getCentroid());
+ }
+
+ @Override
+ public Point getRepresentativePoint() {
+ if (isEmpty()) {
+ // The empty set has no interior position.
+ return null;
+ }
+ //TODO : fallback on JTS until implemented
+ return (Point) fromJTS(asJTS().getInteriorPoint());
+ }
+
+ @Override
+ public Geometry boundary() {
+ if (isEmpty()) {
+ // The boundary of the empty set is empty.
+ return GeometryFactory.createEmpty(getCoordinateReferenceSystem());
+ }
+ //TODO : fallback on JTS until implemented
+ return fromJTS(asJTS().getBoundary());
+ }
+
+ @Override
+ public boolean isSimple() {
+ //TODO : fallback on JTS until implemented
+ return asJTS().isSimple();
+ }
+
+ @Override
+ public boolean isValid() {
+ //TODO : fallback on JTS until implemented
+ return asJTS().isValid();
+ }
+
}
diff --git
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultLineString.java
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultLineString.java
index 2e4388bee2..762200d7e1 100644
---
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultLineString.java
+++
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultLineString.java
@@ -16,8 +16,12 @@
*/
package org.apache.sis.geometries.internal.shared;
+import javax.measure.Quantity;
import org.apache.sis.geometries.DataPoints;
+import org.apache.sis.geometries.Geometries;
+import org.apache.sis.geometries.Point;
import org.apache.sis.geometries.curve.LineString;
+import org.apache.sis.measure.Quantities;
/**
@@ -42,4 +46,42 @@ public non-sealed class DefaultLineString extends
AbstractGeometry implements Li
return points;
}
+ @Override
+ public Quantity<?> getLength() {
+ //TODO : fallback on JTS until implemented
+ return Quantities.create(asJTS().getLength(),
Geometries.getLinearUnit(this));
+ }
+
+ @Override
+ public Point getCentroid() {
+ if (isEmpty()) {
+ // The centroid of the empty set is undefined.
+ return null;
+ }
+ //TODO : fallback on JTS until implemented
+ return (Point) fromJTS(asJTS().getCentroid());
+ }
+
+ @Override
+ public Point getRepresentativePoint() {
+ if (isEmpty()) {
+ // The empty set has no interior position.
+ return null;
+ }
+ //TODO : fallback on JTS until implemented
+ return (Point) fromJTS(asJTS().getInteriorPoint());
+ }
+
+ @Override
+ public boolean isSimple() {
+ //TODO : fallback on JTS until implemented
+ return asJTS().isSimple();
+ }
+
+ @Override
+ public boolean isValid() {
+ //TODO : fallback on JTS until implemented
+ return asJTS().isValid();
+ }
+
}
diff --git
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultLinearRing.java
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultLinearRing.java
index 4c2433550e..bbc405f4a6 100644
---
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultLinearRing.java
+++
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultLinearRing.java
@@ -31,4 +31,14 @@ public non-sealed class DefaultLinearRing extends
DefaultLineString implements L
super(points);
}
+ /**
+ * Returns {@code true}: a linear ring is simple by definition.
+ * This restores the value defined by {@link LinearRing#isSimple()}, which
the
+ * JTS fallback inherited from {@link DefaultLineString} would otherwise
hide.
+ */
+ @Override
+ public boolean isSimple() {
+ return true;
+ }
+
}
diff --git
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultMultiPoint.java
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultMultiPoint.java
index f082f0c1d5..7faad51e6b 100644
---
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultMultiPoint.java
+++
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/internal/shared/DefaultMultiPoint.java
@@ -20,6 +20,8 @@ import java.util.Objects;
import org.opengis.geometry.Envelope;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.apache.sis.geometries.DataPoints;
+import org.apache.sis.geometries.Geometry;
+import org.apache.sis.geometries.GeometryFactory;
import org.apache.sis.geometries.Point;
import org.apache.sis.geometries.DataPointsType;
import org.apache.sis.geometries.point.MultiPoint;
@@ -72,6 +74,48 @@ public non-sealed class DefaultMultiPoint extends
AbstractGeometry implements Mu
return points;
}
+ @Override
+ public Point getCentroid() {
+ if (isEmpty()) {
+ // The centroid of the empty set is undefined.
+ return null;
+ }
+ //TODO : fallback on JTS until implemented
+ return (Point) fromJTS(asJTS().getCentroid());
+ }
+
+ @Override
+ public Point getRepresentativePoint() {
+ if (isEmpty()) {
+ // The empty set has no interior position.
+ return null;
+ }
+ //TODO : fallback on JTS until implemented
+ return (Point) fromJTS(asJTS().getInteriorPoint());
+ }
+
+ @Override
+ public Geometry boundary() {
+ if (isEmpty()) {
+ // The boundary of the empty set is empty.
+ return GeometryFactory.createEmpty(getCoordinateReferenceSystem());
+ }
+ //TODO : fallback on JTS until implemented
+ return fromJTS(asJTS().getBoundary());
+ }
+
+ @Override
+ public boolean isSimple() {
+ //TODO : fallback on JTS until implemented
+ return asJTS().isSimple();
+ }
+
+ @Override
+ public boolean isValid() {
+ //TODO : fallback on JTS until implemented
+ return asJTS().isValid();
+ }
+
@Override
public int hashCode() {
return 13 * Objects.hashCode(points);
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 94ae975413..6d66de5cc8 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
@@ -17,6 +17,7 @@
package org.apache.sis.geometries.internal.shared;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.apache.sis.geometries.Point;
import org.apache.sis.geometries.Surface;
import org.apache.sis.geometries.surface.MultiSurface;
@@ -35,4 +36,14 @@ public non-sealed class DefaultMultiSurface<T extends
Surface> extends DefaultGe
super(fallbackCRS, geometries);
}
+ /**
+ * Returns the same point as {@link #getRepresentativePoint()}, which is
the name
+ * given by OGC Simple Feature Access to the operation ISO 19107 calls the
+ * representative point.
+ */
+ @Override
+ public Point getPointOnSurface() {
+ return getRepresentativePoint();
+ }
+
}
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 f9e559f428..bef2c94d4f 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,16 +18,17 @@ package org.apache.sis.geometries.internal.shared;
import java.util.List;
import java.util.Objects;
-import org.locationtech.jts.geom.GeometryFactory;
import javax.measure.Quantity;
import org.opengis.geometry.Envelope;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.apache.sis.geometries.Curve;
import org.apache.sis.geometries.Geometries;
+import org.apache.sis.geometries.Geometry;
+import org.apache.sis.geometries.GeometryFactory;
+import org.apache.sis.geometries.Point;
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;
/**
@@ -89,7 +90,74 @@ public non-sealed class DefaultPolygon extends
AbstractGeometry implements Polyg
@Override
public Quantity<?> getArea() {
//TODO : fallback on JTS until implemented
- return Quantities.create(Geometries.asJTS(this, false, new
GeometryFactory()).getArea(), Units.SQUARE_METRE);
+ return Quantities.create(asJTS().getArea(),
Geometries.getAreaUnit(this));
+ }
+
+ @Override
+ public Quantity<?> getPerimeter() {
+ //TODO : fallback on JTS until implemented
+ return Quantities.create(asJTS().getLength(),
Geometries.getLinearUnit(this));
+ }
+
+ @Override
+ public Point getCentroid() {
+ if (isEmpty()) {
+ // The centroid of the empty set is undefined.
+ return null;
+ }
+ //TODO : fallback on JTS until implemented
+ return (Point) fromJTS(asJTS().getCentroid());
+ }
+
+ @Override
+ public Point getPointOnSurface() {
+ if (isEmpty()) {
+ // The empty set has no interior position.
+ return null;
+ }
+ //TODO : fallback on JTS until implemented
+ return (Point) fromJTS(asJTS().getInteriorPoint());
+ }
+
+ /**
+ * Returns the same point as {@link #getPointOnSurface()}, which is the
name
+ * given by OGC Simple Feature Access to the operation ISO 19107 calls the
+ * representative point.
+ */
+ @Override
+ public Point getRepresentativePoint() {
+ return getPointOnSurface();
+ }
+
+ @Override
+ public Geometry getBoundary() {
+ if (isEmpty()) {
+ // The boundary of the empty set is empty.
+ return GeometryFactory.createEmpty(getCoordinateReferenceSystem());
+ }
+ //TODO : fallback on JTS until implemented
+ return fromJTS(asJTS().getBoundary());
+ }
+
+ /**
+ * Returns the same geometry as {@link #getBoundary()}, which is the name
given by
+ * {@link org.apache.sis.geometries.Surface} to the same ISO 19107
operation.
+ */
+ @Override
+ public Geometry boundary() {
+ return getBoundary();
+ }
+
+ @Override
+ public boolean isSimple() {
+ //TODO : fallback on JTS until implemented
+ return asJTS().isSimple();
+ }
+
+ @Override
+ public boolean isValid() {
+ //TODO : fallback on JTS until implemented
+ return asJTS().isValid();
}
}
diff --git
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/operation/GeometryProcessor.java
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/operation/GeometryProcessor.java
index 1ddc1a0fdf..7aa551d26a 100644
---
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/operation/GeometryProcessor.java
+++
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/operation/GeometryProcessor.java
@@ -25,7 +25,6 @@ import java.util.Map.Entry;
import java.util.function.Consumer;
import java.util.function.Function;
import javax.measure.Quantity;
-import javax.measure.Unit;
import static org.opengis.annotation.Specification.ISO_19107;
import org.opengis.annotation.UML;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
@@ -82,7 +81,9 @@ public final class GeometryProcessor {
// There is no position to grow a buffer around, whatever the
radius.
return geom;
}
- throw new UnsupportedOperationException();
+
+ //TODO : fallback on JTS until implemented, this loss the attributes !
+ return fromJTS(jts(geom).buffer(radius.getValue().doubleValue()),
geom);
}
/**
@@ -122,11 +123,11 @@ public final class GeometryProcessor {
* Because the geometries are closed, it is possible to find a point on
each geometric object involved, such that
* the distance between these 2 points is the returned distance between
their geometric objects.
*
- * <p>TODO / Limitation: the returned quantity is labelled in metres, but
its magnitude is the plain
- * Pythagorean distance computed in the units of the coordinate system
axes. On a geographic
- * coordinate reference system that magnitude is therefore an amount of
degrees reported as
- * metres. Computing a true geodesic distance on the reference surface, as
required by
- * ISO 19107 REQ. 11, remains to be done.</p>
+ * <p>TODO / Limitation: the magnitude is the plain Pythagorean distance
computed in the units
+ * of the coordinate system axes, and the returned quantity is labelled
with the unit of the
+ * first axis. On a geographic coordinate reference system the result is
therefore an amount
+ * of degrees, reported as such. Computing a true geodesic distance on the
reference surface,
+ * as required by ISO 19107 REQ. 11, remains to be done.</p>
*
* <p>Difference with ISO-19107, the Length type has been changed to
Quantity to
* handle temporal geometries and crs-less geometries.</p>
@@ -143,11 +144,12 @@ public final class GeometryProcessor {
}
if (geom1 instanceof Point pt1) {
if (geom2 instanceof Point pt2) {
- return Quantities.create(Distance.distance(pt1, pt2),
getUnit(pt1));
+ return Quantities.create(Distance.distance(pt1, pt2),
Geometries.getLinearUnit(pt1));
}
}
- throw new UnsupportedOperationException();
+ //TODO : fallback on JTS until implemented
+ return Quantities.create(jts(geom1).distance(jts(geom2)),
Geometries.getLinearUnit(geom1));
}
/**
@@ -615,11 +617,4 @@ public final class GeometryProcessor {
return Geometries.fromJTS(result, true);
}
- private static Unit getUnit(Geometry geometry) {
- return getUnit(geometry.getCoordinateReferenceSystem());
- }
-
- private static Unit getUnit(CoordinateReferenceSystem crs) {
- return crs.getCoordinateSystem().getAxis(0).getUnit();
- }
}
diff --git
a/incubator/src/org.apache.sis.geometry/test/org/apache/sis/geometries/operation/BufferTest.java
b/incubator/src/org.apache.sis.geometry/test/org/apache/sis/geometries/operation/BufferTest.java
index 6342e20221..ab33f01b8f 100644
---
a/incubator/src/org.apache.sis.geometry/test/org/apache/sis/geometries/operation/BufferTest.java
+++
b/incubator/src/org.apache.sis.geometry/test/org/apache/sis/geometries/operation/BufferTest.java
@@ -18,6 +18,7 @@ package org.apache.sis.geometries.operation;
import javax.measure.Quantity;
import org.apache.sis.geometries.Geometry;
+import org.apache.sis.geometries.Surface;
import org.apache.sis.measure.Quantities;
import org.apache.sis.measure.Units;
import static org.apache.sis.geometries.operation.TestData.EMPTY_1;
@@ -25,7 +26,10 @@ import static
org.apache.sis.geometries.operation.TestData.POINT_A;
// Test dependencies
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.Test;
@@ -62,12 +66,7 @@ public class BufferTest {
new TestCase(EMPTY_1, Quantities.create( 10, Units.METRE), EMPTY_1,
null),
new TestCase(EMPTY_1, Quantities.create( 0, Units.METRE), EMPTY_1,
null),
new TestCase(EMPTY_1, Quantities.create(-10, Units.METRE), EMPTY_1,
null),
- new TestCase(EMPTY_1, Quantities.create( 10, Units.UNITY), EMPTY_1,
null),
- /*
- * TODO
- */
- new TestCase(POINT_A, Quantities.create( 10, Units.METRE), null,
UnsupportedOperationException.class),
- new TestCase(POINT_A, Quantities.create( 0, Units.METRE), null,
UnsupportedOperationException.class)
+ new TestCase(EMPTY_1, Quantities.create( 10, Units.UNITY), EMPTY_1,
null)
};
/**
@@ -87,4 +86,35 @@ public class BufferTest {
}
}
}
+
+ /**
+ * Tests that growing a buffer around a point gives a surface
approximating a disk.
+ * The operation is delegated to JTS, which approximates the disk by a
polygon inscribed
+ * in it. The area of that polygon is therefore slightly less than the
area of the disk,
+ * by an amount which depends on the number of segments used by JTS for
each quadrant.
+ * This test verifies only that the result is close to the disk, not the
exact number
+ * of segments.
+ */
+ @Test
+ public void testBufferOfPoint() {
+ final double radius = 10;
+ final Geometry result = new GeometryProcessor().buffer(POINT_A,
Quantities.create(radius, Units.METRE));
+ assertFalse(result.isEmpty(), "The buffer of a point with a positive
radius is not empty.");
+
+ final Surface surface = assertInstanceOf(Surface.class, result, "The
buffer of a point is a surface.");
+ final double area = surface.getArea().getValue().doubleValue();
+ final double disk = Math.PI * radius * radius;
+ assertTrue(area <= disk, () -> "Inscribed polygon area " + area + "
cannot exceed disk area " + disk);
+ assertTrue(area >= 0.95 * disk, () -> "Area " + area + " is too far
from the disk area " + disk);
+ }
+
+ /**
+ * Tests that a buffer of radius zero around a point gives an empty
geometry:
+ * a point has no surface to preserve.
+ */
+ @Test
+ public void testBufferOfPointWithZeroRadius() {
+ final Geometry result = new GeometryProcessor().buffer(POINT_A,
Quantities.create(0, Units.METRE));
+ assertTrue(result.isEmpty(), "The buffer of a point with a radius of
zero is empty.");
+ }
}