This is an automated email from the ASF dual-hosted git repository.

desruisseaux pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git

commit dbc1185a239ac2cf6b0ad20f73db836e474f6601
Author: Martin Desruisseaux <martin.desruisse...@geomatys.com>
AuthorDate: Sat Jul 31 10:47:01 2021 +0200

    Review the fix about axis order change: we still need to adapt the CRS for 
a change in number of dimensions.
    Some complexity about calculation of x and y dimensions are not needed 
anymore.
    The test is effective only if tested with an envelope of more than 2 
dimensions.
---
 .../apache/sis/internal/feature/Geometries.java    | 71 ++++++++++++----------
 .../sis/internal/feature/GeometriesTestCase.java   | 14 +++--
 .../apache/sis/geometry/AbstractEnvelopeTest.java  |  8 +--
 .../org/apache/sis/geometry/ArrayEnvelopeTest.java |  3 +-
 .../org/apache/sis/geometry/Envelope2DTest.java    |  2 +-
 .../sis/geometry/GeneralDirectPositionTest.java    |  2 +-
 .../apache/sis/geometry/GeneralEnvelopeTest.java   |  9 +--
 .../apache/sis/geometry/ImmutableEnvelopeTest.java |  2 +-
 .../org/apache/sis/geometry/SubEnvelopeTest.java   |  2 +-
 .../apache/sis/referencing/crs/HardCodedCRS.java   | 10 +--
 10 files changed, 65 insertions(+), 58 deletions(-)

diff --git 
a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Geometries.java
 
b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Geometries.java
index fd8f124..91506e4 100644
--- 
a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Geometries.java
+++ 
b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Geometries.java
@@ -21,23 +21,23 @@ import java.io.Serializable;
 import java.nio.ByteBuffer;
 import java.util.Optional;
 import java.util.Iterator;
-import org.apache.sis.geometry.ImmutableEnvelope;
-import org.apache.sis.referencing.cs.AxesConvention;
-import org.apache.sis.util.UnconvertibleObjectException;
 import org.opengis.geometry.DirectPosition;
 import org.opengis.geometry.Envelope;
 import org.opengis.metadata.extent.GeographicBoundingBox;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.opengis.referencing.cs.CoordinateSystem;
-import org.opengis.referencing.cs.AxisDirection;
 import org.apache.sis.geometry.AbstractEnvelope;
 import org.apache.sis.geometry.GeneralEnvelope;
+import org.apache.sis.geometry.ImmutableEnvelope;
 import org.apache.sis.geometry.WraparoundMethod;
+import org.apache.sis.referencing.CRS;
+import org.apache.sis.referencing.cs.AxesConvention;
 import org.apache.sis.internal.referencing.AxisDirections;
 import org.apache.sis.math.Vector;
 import org.apache.sis.setup.GeometryLibrary;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.Classes;
+import org.apache.sis.util.UnconvertibleObjectException;
 
 
 /**
@@ -382,17 +382,17 @@ public abstract class Geometries<G> implements 
Serializable {
      * The sequence of points describes each corner, going in clockwise 
direction and repeating the starting
      * point to properly close the ring.
      *
-     * @param  x  dimension of first axis.
-     * @param  y  dimension of second axis.
+     * @param  xd  dimension of first axis.
+     * @param  yd  dimension of second axis.
      * @return a polyline made of a sequence of 5 points describing the given 
rectangle.
      */
-    private GeometryWrapper<G> createGeometry2D(final Envelope envelope, final 
int x, final int y) {
+    private GeometryWrapper<G> createGeometry2D(final Envelope envelope, final 
int xd, final int yd) {
         final DirectPosition lc = envelope.getLowerCorner();
         final DirectPosition uc = envelope.getUpperCorner();
-        final double xmin = lc.getOrdinate(x);
-        final double ymin = lc.getOrdinate(y);
-        final double xmax = uc.getOrdinate(x);
-        final double ymax = uc.getOrdinate(y);
+        final double xmin = lc.getOrdinate(xd);
+        final double ymin = lc.getOrdinate(yd);
+        final double xmax = uc.getOrdinate(xd);
+        final double ymax = uc.getOrdinate(yd);
         return createWrapper(createPolyline(true, BIDIMENSIONAL, 
Vector.create(new double[] {
                              xmin, ymin,  xmin, ymax,  xmax, ymax,  xmax, 
ymin,  xmin, ymin})));
     }
@@ -403,30 +403,35 @@ public abstract class Geometries<G> implements 
Serializable {
      * should be two-dimensional (see for example {@link 
GeneralEnvelope#horizontal()}) but
      * the coordinates does not need to be in (longitude, latitude) order; 
this method will
      * preserve envelope horizontal axis order. It means that any non-2D axis 
will be ignored,
-     * and the first horizontal axis in the envelope will be the first axis 
(x) in the resulting
-     * geometry. To force {@link AxesConvention#RIGHT_HANDED}, you have to 
transform your bounding
-     * box before calling this method.
+     * and the first horizontal axis in the envelope will be the first axis 
(x) in the resulting geometry.
+     * To force {@link AxesConvention#RIGHT_HANDED}, should transform the 
bounding box before calling this method.
      *
      * @param  envelope  the envelope to convert.
      * @param  strategy  how to resolve wrap-around ambiguities on the 
envelope.
      * @return the envelope as a polygon, or potentially as two polygons in 
{@link WraparoundMethod#SPLIT} case.
      */
     public GeometryWrapper<G> toGeometry2D(final Envelope envelope, final 
WraparoundMethod strategy) {
-        final CoordinateReferenceSystem crs = 
envelope.getCoordinateReferenceSystem();
-        int x = 0, y = 1;
-        if (crs != null && envelope.getDimension() > 2) {
-            final CoordinateSystem cs = crs.getCoordinateSystem();
-            int cx = AxisDirections.indexOfColinear(cs, AxisDirection.EAST);
-            int cy = AxisDirections.indexOfColinear(cs, AxisDirection.NORTH);
-            if (cx >= 0 || cy >= 0) {
-                if ((cx < 0 && (cx = cy - 1) < 0 && (cx = cy + 1) >= 
cs.getDimension()) ||
-                    (cy < 0 && (cy = cx + 1) >= cs.getDimension() && (cy = cx 
- 1) < 0))
-                {
-                    // May happen if the CRS has only one dimension.
-                    throw new 
IllegalArgumentException(Errors.format(Errors.Keys.EmptyEnvelope2D));
-                }
-                x = Math.min(cx, cy);
-                y = Math.max(cy, cx);
+        int xd = 0, yd = 1;
+        CoordinateReferenceSystem crs = 
envelope.getCoordinateReferenceSystem();
+        final int dimension = envelope.getDimension();
+        if (dimension != BIDIMENSIONAL) {
+            if (dimension < BIDIMENSIONAL) {
+                throw new 
IllegalArgumentException(Errors.format(Errors.Keys.EmptyEnvelope2D));
+            }
+            final CoordinateReferenceSystem crsND = crs;
+            crs = CRS.getHorizontalComponent(crsND);
+            if (crs == null) {
+                crs = CRS.getComponentAt(crsND, 0, BIDIMENSIONAL);
+            } else if (crs != crsND) {
+                final CoordinateSystem csND = crsND.getCoordinateSystem();
+                final CoordinateSystem cs   = crs  .getCoordinateSystem();
+                xd = AxisDirections.indexOfColinear(csND, 
cs.getAxis(0).getDirection());
+                yd = AxisDirections.indexOfColinear(csND, 
cs.getAxis(1).getDirection());
+                if (xd == yd) yd++;    // Paranoiac check (e.g. CS with 2 
temporal axes).
+                /*
+                 * `indexOfColinear` returns -1 if the axis has not been 
found, but it should never
+                 * happen here because we ask for axis directions that are 
known to exist in the CRS.
+                 */
             }
         }
         final GeometryWrapper<G> result;
@@ -435,26 +440,26 @@ public abstract class Geometries<G> implements 
Serializable {
                 throw new IllegalArgumentException();
             }
             case NONE: {
-                result = createGeometry2D(envelope, x, y);
+                result = createGeometry2D(envelope, xd, yd);
                 break;
             }
             default: {
                 final GeneralEnvelope ge = new GeneralEnvelope(envelope);
                 ge.normalize();
                 ge.wraparound(strategy);
-                result = createGeometry2D(ge, x, y);
+                result = createGeometry2D(ge, xd, yd);
                 break;
             }
             case SPLIT: {
                 final Envelope[] parts = 
AbstractEnvelope.castOrCopy(envelope).toSimpleEnvelopes();
                 if (parts.length == 1) {
-                    result = createGeometry2D(parts[0], x, y);
+                    result = createGeometry2D(parts[0], xd, yd);
                     break;
                 }
                 @SuppressWarnings({"unchecked", "rawtypes"})
                 final GeometryWrapper<G>[] polygons = new 
GeometryWrapper[parts.length];
                 for (int i=0; i<parts.length; i++) {
-                    polygons[i] = createGeometry2D(parts[i], x, y);
+                    polygons[i] = createGeometry2D(parts[i], xd, yd);
                     polygons[i].setCoordinateReferenceSystem(crs);
                 }
                 result = createMultiPolygon(polygons);
diff --git 
a/core/sis-feature/src/test/java/org/apache/sis/internal/feature/GeometriesTestCase.java
 
b/core/sis-feature/src/test/java/org/apache/sis/internal/feature/GeometriesTestCase.java
index cabd0d4..73a9d0c 100644
--- 
a/core/sis-feature/src/test/java/org/apache/sis/internal/feature/GeometriesTestCase.java
+++ 
b/core/sis-feature/src/test/java/org/apache/sis/internal/feature/GeometriesTestCase.java
@@ -36,6 +36,7 @@ import static org.junit.Assert.*;
  * Base class of Java2D, ESRI and JTS implementation tests.
  *
  * @author  Martin Desruisseaux (Geomatys)
+ * @author  Alexis Manin (Geomatys)
  * @version 1.1
  * @since   1.0
  * @module
@@ -207,13 +208,16 @@ public abstract strictfp class GeometriesTestCase extends 
TestCase {
     }
 
     /**
-     * Tests {@link Geometries#toGeometry2D(Envelope, WraparoundMethod)} and 
ensure <em>no</em> axis swapping is done.
+     * Tests {@link Geometries#toGeometry2D(Envelope, WraparoundMethod)} from 
a four-dimensional envelope.
+     * Ensures that the horizontal component is identified, but otherwise 
<em>no</em> axis swapping is done.
      */
     @Test
-    public void testToGeometryAxisOrderIsPreserved() {
-        final GeneralEnvelope e = new 
GeneralEnvelope(HardCodedCRS.WGS84_LATITUDE_FIRST);
-        e.setRange(0,  2,  3);
-        e.setRange(1, 89, 19);
+    public void testToGeometryFrom4D() {
+        final GeneralEnvelope e = new 
GeneralEnvelope(HardCodedCRS.GEOID_4D_MIXED_ORDER);
+        e.setRange(0,  -20,   12);      // Height
+        e.setRange(1, 1000, 1007);      // Time
+        e.setRange(2,    2,    3);      // Latitude
+        e.setRange(3,   89,   19);      // Longitude (span anti-meridian).
         assertToGeometryEquals(e, WraparoundMethod.NONE,       2,   89, 2,  
19, 3,  19, 3,   89, 2,   89);
         assertToGeometryEquals(e, WraparoundMethod.CONTIGUOUS, 2, -271, 2,  
19, 3,  19, 3, -271, 2, -271);
         assertToGeometryEquals(e, WraparoundMethod.EXPAND,     2, -180, 2, 
180, 3, 180, 3, -180, 2, -180);
diff --git 
a/core/sis-referencing/src/test/java/org/apache/sis/geometry/AbstractEnvelopeTest.java
 
b/core/sis-referencing/src/test/java/org/apache/sis/geometry/AbstractEnvelopeTest.java
index b6a7700..1a99906 100644
--- 
a/core/sis-referencing/src/test/java/org/apache/sis/geometry/AbstractEnvelopeTest.java
+++ 
b/core/sis-referencing/src/test/java/org/apache/sis/geometry/AbstractEnvelopeTest.java
@@ -19,8 +19,6 @@ package org.apache.sis.geometry;
 import java.awt.geom.Rectangle2D;
 import org.opengis.geometry.Envelope;
 import org.opengis.geometry.DirectPosition;
-import org.apache.sis.referencing.crs.DefaultGeographicCRS;
-import org.apache.sis.referencing.crs.HardCodedCRS;
 import org.apache.sis.test.DependsOnMethod;
 import org.apache.sis.test.DependsOn;
 import org.apache.sis.test.TestCase;
@@ -29,6 +27,7 @@ import org.junit.Test;
 import static java.lang.Double.NaN;
 import static org.opengis.test.Validators.*;
 import static org.apache.sis.test.ReferencingAssert.*;
+import static org.apache.sis.referencing.crs.HardCodedCRS.WGS84;
 
 
 /**
@@ -49,11 +48,6 @@ public final strictfp class AbstractEnvelopeTest extends 
TestCase {
     private static final int GENERAL=0, IMMUTABLE=1, RECTANGLE=2, 
SUBENVELOPE=3, LAST=4;
 
     /**
-     * The coordinate reference system used for the tests.
-     */
-    static final DefaultGeographicCRS WGS84 = HardCodedCRS.WGS84;
-
-    /**
      * Creates an envelope of the given type. The type shall be one of the
      * {@link #GENERAL}, {@link #IMMUTABLE} or {@link #RECTANGLE} constants.
      */
diff --git 
a/core/sis-referencing/src/test/java/org/apache/sis/geometry/ArrayEnvelopeTest.java
 
b/core/sis-referencing/src/test/java/org/apache/sis/geometry/ArrayEnvelopeTest.java
index 25d44e1..7afbb8f 100644
--- 
a/core/sis-referencing/src/test/java/org/apache/sis/geometry/ArrayEnvelopeTest.java
+++ 
b/core/sis-referencing/src/test/java/org/apache/sis/geometry/ArrayEnvelopeTest.java
@@ -22,6 +22,7 @@ import org.apache.sis.test.TestCase;
 import org.junit.Test;
 
 import static org.apache.sis.test.ReferencingAssert.*;
+import static org.apache.sis.referencing.crs.HardCodedCRS.WGS84;
 
 
 /**
@@ -73,7 +74,7 @@ public final strictfp class ArrayEnvelopeTest extends 
TestCase {
         ArrayEnvelope envelope = new ArrayEnvelope(new double[] {4, -10, 50, 
2});
         assertWktEquals("BOX[ 4 -10,\n" +
                         "    50   2]", envelope);
-        envelope.crs = AbstractEnvelopeTest.WGS84;
+        envelope.crs = WGS84;
         assertWktEquals("BOX[ 4.00000000 -10.00000000,\n" +
                         "    50.00000000   2.00000000]", envelope);
 
diff --git 
a/core/sis-referencing/src/test/java/org/apache/sis/geometry/Envelope2DTest.java
 
b/core/sis-referencing/src/test/java/org/apache/sis/geometry/Envelope2DTest.java
index 2373e63..f4a469b 100644
--- 
a/core/sis-referencing/src/test/java/org/apache/sis/geometry/Envelope2DTest.java
+++ 
b/core/sis-referencing/src/test/java/org/apache/sis/geometry/Envelope2DTest.java
@@ -24,7 +24,7 @@ import org.junit.Test;
 
 import static org.opengis.test.Validators.*;
 import static org.apache.sis.test.ReferencingAssert.*;
-import static org.apache.sis.geometry.AbstractEnvelopeTest.WGS84;
+import static org.apache.sis.referencing.crs.HardCodedCRS.WGS84;
 
 
 /**
diff --git 
a/core/sis-referencing/src/test/java/org/apache/sis/geometry/GeneralDirectPositionTest.java
 
b/core/sis-referencing/src/test/java/org/apache/sis/geometry/GeneralDirectPositionTest.java
index 3f73317..0476893 100644
--- 
a/core/sis-referencing/src/test/java/org/apache/sis/geometry/GeneralDirectPositionTest.java
+++ 
b/core/sis-referencing/src/test/java/org/apache/sis/geometry/GeneralDirectPositionTest.java
@@ -24,7 +24,7 @@ import org.junit.Test;
 
 import static org.apache.sis.test.Assert.*;
 import static org.opengis.test.Validators.*;
-import static org.apache.sis.geometry.AbstractEnvelopeTest.WGS84;
+import static org.apache.sis.referencing.crs.HardCodedCRS.WGS84;
 
 
 /**
diff --git 
a/core/sis-referencing/src/test/java/org/apache/sis/geometry/GeneralEnvelopeTest.java
 
b/core/sis-referencing/src/test/java/org/apache/sis/geometry/GeneralEnvelopeTest.java
index 1bd3ae0..d2e44c1 100644
--- 
a/core/sis-referencing/src/test/java/org/apache/sis/geometry/GeneralEnvelopeTest.java
+++ 
b/core/sis-referencing/src/test/java/org/apache/sis/geometry/GeneralEnvelopeTest.java
@@ -31,7 +31,8 @@ import org.junit.Test;
 import static java.lang.Double.NaN;
 import static org.opengis.test.Validators.*;
 import static org.apache.sis.test.ReferencingAssert.*;
-import static org.apache.sis.geometry.AbstractEnvelopeTest.WGS84;
+import static org.apache.sis.referencing.crs.HardCodedCRS.WGS84;
+import static org.apache.sis.referencing.crs.HardCodedCRS.WGS84_LATITUDE_FIRST;
 
 
 /**
@@ -652,11 +653,11 @@ public strictfp class GeneralEnvelopeTest extends 
TestCase {
      */
     @Test
     public void testHorizontal() {
-        GeneralEnvelope envelope = new GeneralEnvelope(new double[] {4, 5, 
-8}, new double[] {8, 7, -3});
-        envelope.setCoordinateReferenceSystem(HardCodedCRS.GEOID_HEIGHT_FIRST);
+        GeneralEnvelope envelope = new GeneralEnvelope(new double[] {4, 12, 5, 
-8}, new double[] {8, 19, 7, -3});
+        
envelope.setCoordinateReferenceSystem(HardCodedCRS.GEOID_4D_MIXED_ORDER);
         envelope = envelope.horizontal();
         assertEnvelopeEquals(envelope, 5, -8, 7, -3);
-        assertSame(WGS84, envelope.getCoordinateReferenceSystem());
+        assertSame(WGS84_LATITUDE_FIRST, 
envelope.getCoordinateReferenceSystem());
     }
 
     /**
diff --git 
a/core/sis-referencing/src/test/java/org/apache/sis/geometry/ImmutableEnvelopeTest.java
 
b/core/sis-referencing/src/test/java/org/apache/sis/geometry/ImmutableEnvelopeTest.java
index 46eb724..f9f5d1d 100644
--- 
a/core/sis-referencing/src/test/java/org/apache/sis/geometry/ImmutableEnvelopeTest.java
+++ 
b/core/sis-referencing/src/test/java/org/apache/sis/geometry/ImmutableEnvelopeTest.java
@@ -22,7 +22,7 @@ import org.junit.Test;
 
 import static org.opengis.test.Validators.*;
 import static org.apache.sis.test.ReferencingAssert.*;
-import static org.apache.sis.geometry.AbstractEnvelopeTest.WGS84;
+import static org.apache.sis.referencing.crs.HardCodedCRS.WGS84;
 
 
 /**
diff --git 
a/core/sis-referencing/src/test/java/org/apache/sis/geometry/SubEnvelopeTest.java
 
b/core/sis-referencing/src/test/java/org/apache/sis/geometry/SubEnvelopeTest.java
index d32f09b..6b6d8b6 100644
--- 
a/core/sis-referencing/src/test/java/org/apache/sis/geometry/SubEnvelopeTest.java
+++ 
b/core/sis-referencing/src/test/java/org/apache/sis/geometry/SubEnvelopeTest.java
@@ -22,7 +22,7 @@ import org.apache.sis.test.DependsOn;
 import static java.lang.Double.NaN;
 import static org.junit.Assert.*;
 import static org.opengis.test.Validators.validate;
-import static org.apache.sis.geometry.AbstractEnvelopeTest.WGS84;
+import static org.apache.sis.referencing.crs.HardCodedCRS.WGS84;
 
 
 /**
diff --git 
a/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/HardCodedCRS.java
 
b/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/HardCodedCRS.java
index e0a85a0..af947fe 100644
--- 
a/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/HardCodedCRS.java
+++ 
b/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/HardCodedCRS.java
@@ -288,6 +288,7 @@ public final strictfp class HardCodedCRS {
             getProperties(HardCodedCS.DAYS), HardCodedDatum.MODIFIED_JULIAN, 
HardCodedCS.DAYS);
 
     static {
+        // Declared here because otherwise it would be illegal forward 
references.
         WGS84_4D = new DefaultCompoundCRS(properties("WGS 84 (3D) + time", 
null), WGS84_3D, TIME);
         WGS84_4D_TIME_FIRST = new DefaultCompoundCRS(properties("time + WGS 84 
(3D)", null), TIME, WGS84_3D);
     }
@@ -321,12 +322,13 @@ public final strictfp class HardCodedCRS {
             properties("WGS 84 + height + time", null), WGS84, 
GRAVITY_RELATED_HEIGHT, TIME);
 
     /**
-     * A (H,λ,φ) CRS where <var>H</var> is the {@link #GRAVITY_RELATED_HEIGHT}.
-     * This is the same CRS than {@link #GEOID_3D} but with height first.
+     * A (H,t,φ,λ) CRS where <var>H</var> is the {@link 
#GRAVITY_RELATED_HEIGHT}.
      * Such axis order is unusual but we use it as a way to verify that SIS is 
robust to arbitrary axis order.
+     *
+     * @since 1.1
      */
-    public static final DefaultCompoundCRS GEOID_HEIGHT_FIRST = new 
DefaultCompoundCRS(
-            properties("height + WGS 84", null), GRAVITY_RELATED_HEIGHT, 
WGS84);
+    public static final DefaultCompoundCRS GEOID_4D_MIXED_ORDER = new 
DefaultCompoundCRS(
+            properties("height + time + WGS 84 (φ,λ)", null), 
GRAVITY_RELATED_HEIGHT, TIME, WGS84_LATITUDE_FIRST);
 
     /**
      * A (λ,φ,H,t) CRS as a nested compound CRS.

Reply via email to