sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1813016 - in /sis/branches/JDK8/core/sis-referencing/src: main/java/org/apache/sis/internal/referencing/ main/java/org/apache/sis/referencing/operation/ test/java/org/apache/sis/geometry/ test/java/org/apache/sis/test/
Date Mon, 23 Oct 2017 13:05:13 GMT
Author: desruisseaux
Date: Mon Oct 23 13:05:13 2017
New Revision: 1813016

URL: http://svn.apache.org/viewvc?rev=1813016&view=rev
Log:
Bug fix the [0 … 360]° when a source or target CRS is of kind CompoundCRS.

Modified:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/CoordinateOperations.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationFinder.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/geometry/EnvelopesTest.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/geometry/Shapes2DTest.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/geometry/TransformTestCase.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/ReferencingAssert.java

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/CoordinateOperations.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/CoordinateOperations.java?rev=1813016&r1=1813015&r2=1813016&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/CoordinateOperations.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/CoordinateOperations.java
[UTF-8] Mon Oct 23 13:05:13 2017
@@ -18,6 +18,7 @@ package org.apache.sis.internal.referenc
 
 import java.util.List;
 import java.util.Objects;
+import java.util.Collections;
 import javax.measure.UnitConverter;
 import javax.measure.IncommensurableException;
 import org.opengis.referencing.cs.RangeMeaning;
@@ -25,9 +26,11 @@ import org.opengis.referencing.cs.Coordi
 import org.opengis.referencing.cs.CoordinateSystemAxis;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.opengis.referencing.crs.GeneralDerivedCRS;
-import org.apache.sis.internal.metadata.AxisDirections;
+import org.opengis.referencing.operation.CoordinateOperation;
 import org.opengis.referencing.operation.CoordinateOperationFactory;
 import org.apache.sis.referencing.operation.DefaultCoordinateOperationFactory;
+import org.apache.sis.referencing.operation.AbstractCoordinateOperation;
+import org.apache.sis.internal.metadata.AxisDirections;
 import org.apache.sis.internal.system.DefaultFactories;
 import org.apache.sis.internal.system.Modules;
 import org.apache.sis.internal.system.SystemListener;
@@ -115,6 +118,30 @@ public final class CoordinateOperations
     }
 
     /**
+     * Returns indices of target dimensions where "wrap around" may happen as a result of
a coordinate operation.
+     * This is usually the longitude axis when the source CRS uses the [-180 … +180]°
range and the target CRS
+     * uses the [0 … 360]° range, or the converse.
+     *
+     * @param  op  the coordinate operation for which to get "wrap around" target dimensions.
+     * @return list of target dimensions where "wrap around" may happen, or an empty list
if none.
+     *
+     * @see AbstractCoordinateOperation#getWrapAroundChanges()
+     */
+    public static List<Integer> wrapAroundChanges(final CoordinateOperation op) {
+        if (op instanceof AbstractCoordinateOperation) {
+            return ((AbstractCoordinateOperation) op).getWrapAroundChanges();
+        } else if (op != null) {
+            final CoordinateReferenceSystem source, target;
+            if ((source = op.getSourceCRS()) != null &&
+                (target = op.getTargetCRS()) != null)
+            {
+                return wrapAroundChanges(source, target.getCoordinateSystem());
+            }
+        }
+        return Collections.emptyList();
+    }
+
+    /**
      * Computes indices of target dimensions where "wrap around" may happen as a result of
a coordinate operation.
      * This is usually the longitude axis when the source CRS uses the [-180 … +180]°
range and the target CRS uses
      * the [0 … 360]° range, or the converse.

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationFinder.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationFinder.java?rev=1813016&r1=1813015&r2=1813016&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationFinder.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationFinder.java
[UTF-8] Mon Oct 23 13:05:13 2017
@@ -33,6 +33,7 @@ import org.opengis.metadata.Identifier;
 import org.opengis.metadata.extent.GeographicBoundingBox;
 import org.opengis.parameter.ParameterValueGroup;
 import org.apache.sis.internal.metadata.AxisDirections;
+import org.apache.sis.internal.referencing.CoordinateOperations;
 import org.apache.sis.internal.referencing.ReferencingUtilities;
 import org.apache.sis.internal.referencing.provider.Geographic2Dto3D;
 import org.apache.sis.internal.referencing.provider.Geographic3Dto2D;
@@ -947,10 +948,13 @@ public class CoordinateOperationFinder e
          * trivial operations.
          */
         CoordinateOperation main = null;
-        final boolean isAxisChange1 = (step1.getName() == AXIS_CHANGES);
-        final boolean isAxisChange2 = (step2.getName() == AXIS_CHANGES);
+        final boolean isAxisChange1 = canHide(step1.getName());
+        final boolean isAxisChange2 = canHide(step2.getName());
         if (isAxisChange1 && isAxisChange2 && isAffine(step1) &&
isAffine(step2)) {
             main = step2;                                           // Arbitrarily take the
last step.
+            if (main.getName() == IDENTITY && step1.getName() != IDENTITY) {
+                main = step1;
+            }
         } else {
             if (isAxisChange1 && mt1.getSourceDimensions() == mt1.getTargetDimensions())
main = step2;
             if (isAxisChange2 && mt2.getSourceDimensions() == mt2.getTargetDimensions())
main = step1;
@@ -1003,8 +1007,8 @@ public class CoordinateOperationFinder e
         if (isIdentity(step1)) return concatenate(step2, step3);
         if (isIdentity(step2)) return concatenate(step1, step3);
         if (isIdentity(step3)) return concatenate(step1, step2);
-        if (step1.getName() == AXIS_CHANGES) return concatenate(concatenate(step1, step2),
step3);
-        if (step3.getName() == AXIS_CHANGES) return concatenate(step1, concatenate(step2,
step3));
+        if (canHide(step1.getName())) return concatenate(concatenate(step1, step2), step3);
+        if (canHide(step3.getName())) return concatenate(step1, concatenate(step2, step3));
         final Map<String,?> properties = defaultName(step1.getSourceCRS(), step3.getTargetCRS());
         return factory.createConcatenatedOperation(properties, step1, step2, step3);
     }
@@ -1028,7 +1032,22 @@ public class CoordinateOperationFinder e
      * are usually datum shift and must be visible.
      */
     private static boolean isIdentity(final CoordinateOperation operation) {
-        return (operation == null) || ((operation instanceof Conversion) && operation.getMathTransform().isIdentity());
+        if (operation == null) {
+            return true;
+        }
+        if ((operation instanceof Conversion) && operation.getMathTransform().isIdentity())
{
+            return CoordinateOperations.wrapAroundChanges(operation).isEmpty();
+        }
+        return false;
+    }
+
+    /**
+     * Returns {@code true} if a coordinate operation of the given name can be hidden
+     * in the list of operations. Note that the {@code MathTransform} will still take
+     * the operation in account however.
+     */
+    private static boolean canHide(final Identifier id) {
+        return (id == AXIS_CHANGES) || (id == IDENTITY);
     }
 
     /**

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java?rev=1813016&r1=1813015&r2=1813016&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java
[UTF-8] Mon Oct 23 13:05:13 2017
@@ -112,7 +112,7 @@ class CoordinateOperationRegistry {
     /**
      * The identifier for an identity operation.
      */
-    private static final Identifier IDENTITY = createIdentifier(Vocabulary.Keys.Identity);
+    static final Identifier IDENTITY = createIdentifier(Vocabulary.Keys.Identity);
 
     /**
      * The identifier for conversion using an affine transform for axis swapping and/or unit
conversions.

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/geometry/EnvelopesTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/geometry/EnvelopesTest.java?rev=1813016&r1=1813015&r2=1813016&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/geometry/EnvelopesTest.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/geometry/EnvelopesTest.java
[UTF-8] Mon Oct 23 13:05:13 2017
@@ -30,6 +30,7 @@ import org.apache.sis.referencing.crs.Ha
 import org.apache.sis.referencing.cs.AxesConvention;
 import org.apache.sis.referencing.CRS;
 import org.apache.sis.test.DependsOn;
+import org.apache.sis.test.DependsOnMethod;
 import org.junit.Test;
 
 import static org.apache.sis.test.ReferencingAssert.*;
@@ -176,7 +177,10 @@ public final strictfp class EnvelopesTes
     }
 
     /**
-     * Tests a transformation where only the range of longitude axis is changed.
+     * Tests a transformation from a three-dimensional CRS where the range of longitude axis
is changed.
+     * This is the same test than {@link #testAxisRangeChange()} but using a compound CRS
as the source.
+     * Internally, this results in the concatenation of transforms. We want to ensure that
information
+     * about axis range changes are not lost in this process.
      *
      * @throws FactoryException if an error occurred while creating the operation.
      * @throws TransformException if an error occurred while transforming the envelope.
@@ -184,12 +188,21 @@ public final strictfp class EnvelopesTes
      * @since 0.8
      */
     @Test
-    public void testAxisRangeChange() throws FactoryException, TransformException {
-        final GeographicCRS sourceCRS = HardCodedCRS.WGS84;
-        final GeographicCRS targetCRS = HardCodedCRS.WGS84.forConvention(AxesConvention.POSITIVE_RANGE);
-        final GeneralEnvelope rectangle = createFromExtremums(sourceCRS, -178, -70, 165,
80);
-        final GeneralEnvelope expected  = createFromExtremums(targetCRS,  182, -70, 165,
80);
-        final GeneralEnvelope actual    = transform(CRS.findOperation(sourceCRS, targetCRS,
null), rectangle);
-        assertGeometryEquals(expected, actual, STRICT, STRICT);
+    @DependsOnMethod("testAxisRangeChange")
+    public void testAxisRangeChange3D() throws FactoryException, TransformException {
+        final GeneralEnvelope envelope  = new GeneralEnvelope(new double[] { -0.5, -90, 1000},
+                                                              new double[] {354.5, +90, 1002});
+        envelope.setCoordinateReferenceSystem(CRS.compound(
+                HardCodedCRS.WGS84.forConvention(AxesConvention.POSITIVE_RANGE), HardCodedCRS.TIME));
+        final GeographicCRS  targetCRS = HardCodedCRS.WGS84;
+        final GeneralEnvelope expected = createFromExtremums(targetCRS, -0.5, -90, -5.5,
90);
+        assertEnvelopeEquals(expected, Envelopes.transform(envelope, targetCRS), STRICT,
STRICT);
+        /*
+         * When the envelope to transform span the full longitude range,
+         * target envelope should unconditionally be [-180 … +180]°.
+         */
+        envelope.setRange(0, -0.5, 359.5);
+        expected.setRange(0, -180, 180);
+        assertEnvelopeEquals(expected, Envelopes.transform(envelope, targetCRS), STRICT,
STRICT);
     }
 }

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/geometry/Shapes2DTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/geometry/Shapes2DTest.java?rev=1813016&r1=1813015&r2=1813016&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/geometry/Shapes2DTest.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/geometry/Shapes2DTest.java
[UTF-8] Mon Oct 23 13:05:13 2017
@@ -17,17 +17,12 @@
 package org.apache.sis.geometry;
 
 import java.awt.geom.Rectangle2D;
-import org.opengis.util.FactoryException;
-import org.opengis.referencing.crs.GeographicCRS;
+import org.opengis.referencing.cs.CoordinateSystemAxis;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.opengis.referencing.operation.CoordinateOperation;
 import org.opengis.referencing.operation.MathTransform2D;
 import org.opengis.referencing.operation.TransformException;
-import org.apache.sis.referencing.cs.AxesConvention;
-import org.apache.sis.referencing.CRS;
-import org.apache.sis.referencing.crs.HardCodedCRS;
 import org.apache.sis.test.DependsOn;
-import org.junit.Test;
 
 import static org.apache.sis.test.ReferencingAssert.*;
 
@@ -48,6 +43,12 @@ public final strictfp class Shapes2DTest
      */
     @Override
     Rectangle2D createFromExtremums(CoordinateReferenceSystem crs, double xmin, double ymin,
double xmax, double ymax) {
+        if (xmin > xmax) {
+            // This implementation does not support spanning anti-meridian.
+            final CoordinateSystemAxis axis = crs.getCoordinateSystem().getAxis(0);
+            xmin = axis.getMinimumValue();
+            xmax = axis.getMaximumValue();
+        }
         return new Rectangle2D.Double(xmin, ymin, xmax - xmin, ymax - ymin);
     }
 
@@ -84,22 +85,4 @@ public final strictfp class Shapes2DTest
     void assertGeometryEquals(Rectangle2D expected, Rectangle2D actual, double tolx, double
toly) {
         assertRectangleEquals(expected, actual, tolx, toly);
     }
-
-    /**
-     * Tests a transformation where only the range of longitude axis is changed.
-     *
-     * @throws FactoryException if an error occurred while creating the operation.
-     * @throws TransformException if an error occurred while transforming the envelope.
-     *
-     * @since 0.8
-     */
-    @Test
-    public void testAxisRangeChange() throws FactoryException, TransformException {
-        final GeographicCRS sourceCRS = HardCodedCRS.WGS84;
-        final GeographicCRS targetCRS = HardCodedCRS.WGS84.forConvention(AxesConvention.POSITIVE_RANGE);
-        final Rectangle2D rectangle = createFromExtremums(sourceCRS, -178, -70, 165, 80);
-        final Rectangle2D expected  = createFromExtremums(targetCRS,    0, -70, 360, 80);
-        final Rectangle2D actual    = transform(CRS.findOperation(sourceCRS, targetCRS, null),
rectangle);
-        assertGeometryEquals(expected, actual, STRICT, STRICT);
-    }
 }

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/geometry/TransformTestCase.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/geometry/TransformTestCase.java?rev=1813016&r1=1813015&r2=1813016&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/geometry/TransformTestCase.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/geometry/TransformTestCase.java
[UTF-8] Mon Oct 23 13:05:13 2017
@@ -28,8 +28,10 @@ import org.opengis.util.FactoryException
 import org.apache.sis.referencing.CRS;
 import org.apache.sis.referencing.CommonCRS;
 import org.apache.sis.referencing.IdentifiedObjects;
+import org.apache.sis.referencing.cs.AxesConvention;
 import org.apache.sis.referencing.operation.DefaultConversion;
 import org.apache.sis.referencing.operation.HardCodedConversions;
+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;
@@ -83,6 +85,12 @@ public abstract strictfp class Transform
     abstract void assertGeometryEquals(G expected, G actual, double tolx, double toly);
 
     /**
+     * Allows sub-classing in same package only.
+     */
+    TransformTestCase() {
+    }
+
+    /**
      * Tests the transformation of an envelope or rectangle. This is a relatively simple
test case
      * working in the two-dimensional space only, with a coordinate operation of type "conversion"
      * (not a "transformation") and with no need to adjust for poles.
@@ -223,7 +231,7 @@ public abstract strictfp class Transform
      */
     @Test
     @DependsOnMethod("testTransform")
-    public void testTransformOverAntiMeridian() throws TransformException {
+    public final void testTransformOverAntiMeridian() throws TransformException {
         final ProjectedCRS  sourceCRS  = HardCodedConversions.mercator();
         final GeographicCRS targetCRS  = sourceCRS.getBaseCRS();
         final Conversion    conversion = inverse(sourceCRS.getConversionFromBase());
@@ -244,4 +252,22 @@ public abstract strictfp class Transform
         return new DefaultConversion(IdentifiedObjects.getProperties(conversion), conversion.getTargetCRS(),
                 conversion.getSourceCRS(), null, conversion.getMethod(), conversion.getMathTransform().inverse());
     }
+
+    /**
+     * Tests a transformation where only the range of longitude axis is changed.
+     *
+     * @throws FactoryException if an error occurred while creating the operation.
+     * @throws TransformException if an error occurred while transforming the envelope.
+     *
+     * @since 0.8
+     */
+    @Test
+    public final void testAxisRangeChange() throws FactoryException, TransformException {
+        final GeographicCRS sourceCRS = HardCodedCRS.WGS84;
+        final GeographicCRS targetCRS = HardCodedCRS.WGS84.forConvention(AxesConvention.POSITIVE_RANGE);
+        final G rectangle = createFromExtremums(sourceCRS, -178, -70, 165, 80);
+        final G expected  = createFromExtremums(targetCRS,  182, -70, 165, 80);
+        final G actual    = transform(CRS.findOperation(sourceCRS, targetCRS, null), rectangle);
+        assertGeometryEquals(expected, actual, STRICT, STRICT);
+    }
 }

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/ReferencingAssert.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/ReferencingAssert.java?rev=1813016&r1=1813015&r2=1813016&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/ReferencingAssert.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/ReferencingAssert.java
[UTF-8] Mon Oct 23 13:05:13 2017
@@ -22,6 +22,7 @@ import java.awt.geom.RectangularShape;
 import java.awt.geom.AffineTransform;
 import javax.measure.Unit;
 import org.opengis.geometry.Envelope;
+import org.opengis.geometry.DirectPosition;
 import org.opengis.metadata.Identifier;
 import org.opengis.parameter.GeneralParameterValue;
 import org.opengis.parameter.ParameterDescriptor;
@@ -51,7 +52,7 @@ import static java.lang.StrictMath.*;
  * from other modules and libraries.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 0.7
+ * @version 0.8
  * @since   0.3
  * @module
  */
@@ -281,15 +282,19 @@ public strictfp class ReferencingAssert
     public static void assertEnvelopeEquals(final Envelope expected, final Envelope actual,
final double... tolerances) {
         final int dimension = expected.getDimension();
         assertEquals("dimension", dimension, actual.getDimension());
+        final DirectPosition expectedLower = expected.getLowerCorner();
+        final DirectPosition expectedUpper = expected.getUpperCorner();
+        final DirectPosition actualLower   = actual  .getLowerCorner();
+        final DirectPosition actualUpper   = actual  .getUpperCorner();
         double tolerance = 0;
         for (int i=0; i<dimension; i++) {
             if (i < tolerances.length) {
                 tolerance = tolerances[i];
             }
-            if (abs(expected.getMinimum(i) - actual.getMinimum(i)) > tolerance ||
-                abs(expected.getMaximum(i) - actual.getMaximum(i)) > tolerance)
+            if (abs(expectedLower.getOrdinate(i) - actualLower.getOrdinate(i)) > tolerance
||
+                abs(expectedUpper.getOrdinate(i) - actualUpper.getOrdinate(i)) > tolerance)
             {
-                fail("Envelopes are not equal:\n"
+                fail("Envelopes are not equal in dimension " + i + ":\n"
                         + "expected " + Envelopes.toString(expected) + "\n"
                         + " but got " + Envelopes.toString(actual));
             }



Mime
View raw message