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 <johann.so...@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>

Reply via email to