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.