You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sis.apache.org by js...@apache.org on 2021/11/26 16:33:02 UTC
[sis] 01/02: fix(JTS): check crs and geometry dimensions compatibility on affectation
This is an automated email from the ASF dual-hosted git repository.
jsorel pushed a commit to branch feat/postgis-raster
in repository https://gitbox.apache.org/repos/asf/sis.git
commit a83a03065f1fa6af737c2f671905a5cd4140c9a0
Author: jsorel <jo...@geomatys.com>
AuthorDate: Wed Nov 24 15:50:43 2021 +0100
fix(JTS): check crs and geometry dimensions compatibility on affectation
---
.../apache/sis/internal/feature/jts/Wrapper.java | 34 ++++++
.../apache/sis/internal/feature/jts/JTSTest.java | 114 +++++++++++++++++++++
2 files changed, 148 insertions(+)
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/jts/Wrapper.java b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/jts/Wrapper.java
index 5892025..5c52319 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/jts/Wrapper.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/jts/Wrapper.java
@@ -64,6 +64,7 @@ import org.locationtech.jts.simplify.TopologyPreservingSimplifier;
// Branch-dependent imports
import org.opengis.filter.SpatialOperatorName;
import org.opengis.filter.DistanceOperatorName;
+import org.opengis.geometry.MismatchedDimensionException;
/**
@@ -154,6 +155,11 @@ final class Wrapper extends GeometryWrapper<Geometry> {
if (dimension != Factory.BIDIMENSIONAL) {
ArgumentChecks.ensureDimensionMatches("crs",
(dimension <= Factory.BIDIMENSIONAL) ? Factory.BIDIMENSIONAL : 3, crs);
+ final int coordsDim = getCoordinatesDimension(geometry);
+ if (coordsDim < dimension) {
+ throw new MismatchedDimensionException(Errors.format(
+ Errors.Keys.MismatchedDimension_3, "crs", coordsDim, dimension));
+ }
}
JTS.setCoordinateReferenceSystem(geometry, crs);
}
@@ -692,4 +698,32 @@ add: for (Geometry next = geometry;;) {
public String formatWKT(final double flatness) {
return geometry.toText();
}
+
+ /**
+ * Extract geometry coordinates dimension.
+ */
+ private static int getCoordinatesDimension(Geometry geometry) {
+ switch (geometry.getGeometryType()) {
+ case Geometry.TYPENAME_POINT :
+ return ((Point) geometry).getCoordinateSequence().getDimension();
+ case Geometry.TYPENAME_LINESTRING :
+ case Geometry.TYPENAME_LINEARRING :
+ return ((LineString) geometry).getCoordinateSequence().getDimension();
+ case Geometry.TYPENAME_POLYGON :
+ return getCoordinatesDimension(((Polygon) geometry).getExteriorRing());
+ case Geometry.TYPENAME_MULTIPOINT :
+ case Geometry.TYPENAME_MULTILINESTRING :
+ case Geometry.TYPENAME_MULTIPOLYGON :
+ case Geometry.TYPENAME_GEOMETRYCOLLECTION :
+ final GeometryCollection gc = (GeometryCollection) geometry;
+ if (gc.getNumGeometries() == 0) {
+ //undefined coordinates, JTS assume 3 for empty geometries.
+ return 3;
+ } else {
+ return getCoordinatesDimension(gc.getGeometryN(0));
+ }
+ default :
+ throw new IllegalArgumentException("Unexpected JTS geometry type " + geometry.getGeometryType());
+ }
+ }
}
diff --git a/core/sis-feature/src/test/java/org/apache/sis/internal/feature/jts/JTSTest.java b/core/sis-feature/src/test/java/org/apache/sis/internal/feature/jts/JTSTest.java
index 3a1c386..265c58d 100644
--- a/core/sis-feature/src/test/java/org/apache/sis/internal/feature/jts/JTSTest.java
+++ b/core/sis-feature/src/test/java/org/apache/sis/internal/feature/jts/JTSTest.java
@@ -17,14 +17,19 @@
package org.apache.sis.internal.feature.jts;
import java.util.Collections;
+import org.apache.sis.geometry.GeneralEnvelope;
+import org.opengis.geometry.MismatchedDimensionException;
import org.opengis.util.FactoryException;
import org.opengis.referencing.operation.TransformException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.locationtech.jts.geom.Point;
import org.locationtech.jts.geom.Coordinate;
+import org.locationtech.jts.geom.CoordinateXY;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.GeometryFactory;
import org.apache.sis.referencing.CommonCRS;
+import org.apache.sis.internal.feature.Geometries;
+import org.apache.sis.internal.feature.GeometryWrapper;
import org.apache.sis.internal.referencing.j2d.AffineTransform2D;
import org.apache.sis.test.TestCase;
import org.junit.Test;
@@ -72,6 +77,115 @@ public final strictfp class JTSTest extends TestCase {
}
/**
+ * Tests {@link Wrapper#setCoordinateReferenceSystem(org.opengis.referencing.crs.CoordinateReferenceSystem)}.
+ *
+ * @throws FactoryException if an EPSG code can not be resolved.
+ */
+ @Test
+ public void testSetCoordinateReferenceSystem() throws FactoryException {
+ final GeometryFactory factory = new GeometryFactory();
+
+ { /*
+ * Test set a 2D CRS on a 2 dimensions geometry.
+ */
+ final CoordinateReferenceSystem crs = CommonCRS.ED50.geographic();
+ final Geometry geometry = factory.createPoint(new CoordinateXY(5, 6));
+ final GeometryWrapper<?> wrapper = Geometries.wrap(geometry).get();
+ wrapper.setCoordinateReferenceSystem(crs);
+ assertEquals(crs, wrapper.getCoordinateReferenceSystem());
+ }
+
+ { /*
+ * Test set a 2D CRS on a 3 dimensions geometry.
+ * This case is tolerate for backward compatibility.
+ */
+ final CoordinateReferenceSystem crs = CommonCRS.ED50.geographic();
+ final Geometry geometry = factory.createPoint(new Coordinate(5, 6, 7));
+ final GeometryWrapper<?> wrapper = Geometries.wrap(geometry).get();
+ wrapper.setCoordinateReferenceSystem(crs);
+ assertEquals(crs, wrapper.getCoordinateReferenceSystem());
+ }
+
+ { /*
+ * Test set a 3D CRS on a 3 dimensions geometry.
+ */
+ final CoordinateReferenceSystem crs = CommonCRS.WGS84.geographic3D();
+ final Geometry geometry = factory.createPoint(new Coordinate(5, 6, 7));
+ final GeometryWrapper<?> wrapper = Geometries.wrap(geometry).get();
+ wrapper.setCoordinateReferenceSystem(crs);
+ assertEquals(crs, wrapper.getCoordinateReferenceSystem());
+ }
+
+ { /*
+ * Test set a 3D CRS on a 2 dimensions geometry.
+ */
+ final CoordinateReferenceSystem crs = CommonCRS.WGS84.geographic3D();
+ final Geometry geometry = factory.createPoint(new CoordinateXY(5, 6));
+ GeometryWrapper<?> wrapper = Geometries.wrap(geometry).get();
+ try {
+ wrapper.setCoordinateReferenceSystem(crs);
+ fail("Setting a 3D crs on a 2D geometry must fail");
+ } catch (MismatchedDimensionException ex) {
+ //ok
+ }
+ }
+ }
+
+ /**
+ * Tests {@link Wrapper#getEnvelope()}.
+ *
+ * @throws FactoryException if an EPSG code can not be resolved.
+ */
+ @Test
+ public void testGetEnvelope() throws FactoryException {
+ final GeometryFactory factory = new GeometryFactory();
+
+ { /*
+ * Test 2D Envelope on a 2 dimensions geometry.
+ */
+ final CoordinateReferenceSystem crs = CommonCRS.ED50.geographic();
+ final Geometry geometry = factory.createPoint(new CoordinateXY(5, 6));
+ final GeometryWrapper<?> wrapper = Geometries.wrap(geometry).get();
+ wrapper.setCoordinateReferenceSystem(crs);
+ final GeneralEnvelope envelope = wrapper.getEnvelope();
+ assertEquals(crs, envelope.getCoordinateReferenceSystem());
+ assertArrayEquals(new double[]{5, 6}, envelope.getLowerCorner().getCoordinate(), STRICT);
+ assertArrayEquals(new double[]{5, 6}, envelope.getUpperCorner().getCoordinate(), STRICT);
+ }
+
+ { /*
+ * Test 2D Envelope on a 3 dimensions geometry.
+ * This case is tolerate for backward compatibility.
+ */
+ final CoordinateReferenceSystem crs = CommonCRS.ED50.geographic();
+ final Geometry geometry = factory.createPoint(new Coordinate(5, 6, 7));
+ final GeometryWrapper<?> wrapper = Geometries.wrap(geometry).get();
+ wrapper.setCoordinateReferenceSystem(crs);
+ final GeneralEnvelope envelope = wrapper.getEnvelope();
+ assertEquals(crs, envelope.getCoordinateReferenceSystem());
+ assertArrayEquals(new double[]{5, 6}, envelope.getLowerCorner().getCoordinate(), STRICT);
+ assertArrayEquals(new double[]{5, 6}, envelope.getUpperCorner().getCoordinate(), STRICT);
+ }
+
+ { /*
+ * Test 3D Envelope on a 3 dimensions geometry.
+ * TODO : JTS do not return 3D envelopes for geoemtry internal envelope
+ * should we loop on the full geometry ?
+ */
+ /*
+ final CoordinateReferenceSystem crs = CommonCRS.WGS84.geographic3D();
+ final Geometry geometry = factory.createPoint(new Coordinate(5, 6, 7));
+ final GeometryWrapper<?> wrapper = Geometries.wrap(geometry).get();
+ wrapper.setCoordinateReferenceSystem(crs);
+ final GeneralEnvelope envelope = wrapper.getEnvelope();
+ assertEquals(crs, envelope.getCoordinateReferenceSystem());
+ assertArrayEquals(new double[]{5, 6, 7}, envelope.getLowerCorner().getCoordinate(), STRICT);
+ assertArrayEquals(new double[]{5, 6, 7}, envelope.getUpperCorner().getCoordinate(), STRICT);
+ */
+ }
+ }
+
+ /**
* Tests various {@code transform} methods. This includes (sometime indirectly):
*
* <ul>