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


The following commit(s) were added to refs/heads/geoapi-4.0 by this push:
     new a37595c  `CRS.findOperation(…)` should accept `EngineeringCRS` with 
same datum but different axis directions.
a37595c is described below

commit a37595ce05c6df1a018169e1c4144ffa83843cec
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Sat Mar 6 21:24:36 2021 +0100

    `CRS.findOperation(…)` should accept `EngineeringCRS` with same datum but 
different axis directions.
---
 .../operation/CoordinateOperationFinder.java       | 20 ++++++++
 .../operation/CoordinateOperationFinderTest.java   | 60 +++++++++++++++++++++-
 .../src/main/java/org/apache/sis/util/Classes.java | 14 ++---
 3 files changed, 86 insertions(+), 8 deletions(-)

diff --git 
a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationFinder.java
 
b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationFinder.java
index f31c746..dd4988e 100644
--- 
a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationFinder.java
+++ 
b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationFinder.java
@@ -353,6 +353,26 @@ public class CoordinateOperationFinder extends 
CoordinateOperationRegistry {
         }
         
////////////////////////////////////////////////////////////////////////////////
         ////                                                                   
     ////
+        ////                Any single CRS  ↔  CRS of the same type            
     ////
+        ////                                                                   
     ////
+        
////////////////////////////////////////////////////////////////////////////////
+        if (sourceCRS instanceof SingleCRS && targetCRS instanceof SingleCRS) {
+            final Datum sourceDatum = ((SingleCRS) sourceCRS).getDatum();
+            final Datum targetDatum = ((SingleCRS) targetCRS).getDatum();
+            if (equalsIgnoreMetadata(sourceDatum, targetDatum)) try {
+                /*
+                 * Because the CRS type is determined by the datum type 
(sometime completed by the CS type),
+                 * having equivalent datum and compatible CS should be a 
sufficient criterion.
+                 */
+                return asList(createFromAffineTransform(AXIS_CHANGES, 
sourceCRS, targetCRS,
+                                
CoordinateSystems.swapAndScaleAxes(sourceCRS.getCoordinateSystem(),
+                                                                   
targetCRS.getCoordinateSystem())));
+            } catch (IllegalArgumentException | IncommensurableException e) {
+                throw new FactoryException(notFoundMessage(sourceCRS, 
targetCRS), e);
+            }
+        }
+        
////////////////////////////////////////////////////////////////////////////////
+        ////                                                                   
     ////
         ////                        Compound  ↔  various CRS                   
     ////
         ////                                                                   
     ////
         
////////////////////////////////////////////////////////////////////////////////
diff --git 
a/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/CoordinateOperationFinderTest.java
 
b/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/CoordinateOperationFinderTest.java
index 3ab3dea..4b19d48 100644
--- 
a/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/CoordinateOperationFinderTest.java
+++ 
b/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/CoordinateOperationFinderTest.java
@@ -23,6 +23,7 @@ import java.util.Collections;
 import java.text.ParseException;
 import org.opengis.util.FactoryException;
 import org.opengis.parameter.ParameterValueGroup;
+import org.opengis.referencing.cs.AxisDirection;
 import org.opengis.referencing.crs.GeographicCRS;
 import org.opengis.referencing.crs.GeocentricCRS;
 import org.opengis.referencing.crs.VerticalCRS;
@@ -42,11 +43,16 @@ import 
org.apache.sis.internal.referencing.PositionalAccuracyConstant;
 import org.apache.sis.referencing.operation.transform.LinearTransform;
 import org.apache.sis.referencing.operation.transform.MathTransforms;
 import org.apache.sis.referencing.operation.matrix.Matrices;
+import org.apache.sis.referencing.cs.DefaultCartesianCS;
+import org.apache.sis.referencing.cs.DefaultCoordinateSystemAxis;
+import org.apache.sis.referencing.datum.DefaultEngineeringDatum;
+import org.apache.sis.referencing.crs.DefaultEngineeringCRS;
 import org.apache.sis.referencing.crs.DefaultCompoundCRS;
 import org.apache.sis.referencing.crs.DefaultDerivedCRS;
 import org.apache.sis.referencing.CommonCRS;
 import org.apache.sis.referencing.CRS;
 import org.apache.sis.io.wkt.WKTFormat;
+import org.apache.sis.measure.Units;
 
 import static org.apache.sis.internal.referencing.Formulas.LINEAR_TOLERANCE;
 import static org.apache.sis.internal.referencing.Formulas.ANGULAR_TOLERANCE;
@@ -887,7 +893,15 @@ public final strictfp class CoordinateOperationFinderTest 
extends MathTransformT
      * Convenience method for creating a compound CRS.
      */
     private static CompoundCRS compound(final String name, final 
CoordinateReferenceSystem... components) {
-        return new 
DefaultCompoundCRS(Collections.singletonMap(CompoundCRS.NAME_KEY, name), 
components);
+        return new DefaultCompoundCRS(properties(name), components);
+    }
+
+    /**
+     * Returns property map with a value assigned to the "name" property.
+     * This is a convenience method for construction of geodetic objects.
+     */
+    private static Map<String,String> properties(final String name) {
+        return Collections.singletonMap(CoordinateReferenceSystem.NAME_KEY, 
name);
     }
 
     /**
@@ -1025,4 +1039,48 @@ public final strictfp class 
CoordinateOperationFinderTest extends MathTransformT
         }), ((LinearTransform) transform).getMatrix(), STRICT);
         validate();
     }
+
+    /**
+     * Tests conversion between two engineering CRS.
+     *
+     * @throws FactoryException if the operation can not be created.
+     */
+    @Test
+    public void testEngineeringCRS() throws FactoryException {
+        DefaultEngineeringCRS sourceCRS = createEngineering("Screen display", 
AxisDirection.DISPLAY_DOWN);
+        DefaultEngineeringCRS targetCRS = createEngineering("Another device", 
AxisDirection.DISPLAY_DOWN);
+        try {
+            finder.createOperation(sourceCRS, targetCRS);
+            fail("Should not create operation between CRS of different 
datum.");
+        } catch (OperationNotFoundException e) {
+            final String message = e.getMessage();
+            assertTrue(message, message.contains("A test CRS"));
+        }
+        targetCRS = createEngineering("Screen display", 
AxisDirection.DISPLAY_UP);
+        final CoordinateOperation operation = 
finder.createOperation(sourceCRS, targetCRS);
+        assertSame("sourceCRS", sourceCRS, operation.getSourceCRS());
+        assertSame("targetCRS", targetCRS, operation.getTargetCRS());
+
+        transform = operation.getMathTransform();
+        assertInstanceOf("transform", LinearTransform.class, transform);
+        assertEquals("sourceDimensions", 2, transform.getSourceDimensions());
+        assertEquals("targetDimensions", 2, transform.getTargetDimensions());
+        Assert.assertMatrixEquals("transform.matrix", Matrices.create(3, 3, 
new double[] {
+            1,  0,  0,
+            0, -1,  0,
+            0,  0,  1
+        }), ((LinearTransform) transform).getMatrix(), STRICT);
+        validate();
+    }
+
+    /**
+     * Constructs an axis the given abbreviation and axis direction.
+     */
+    private static DefaultEngineeringCRS createEngineering(final String 
datumName, final AxisDirection yDirection) {
+        return new DefaultEngineeringCRS(properties("A test CRS"),
+                new DefaultEngineeringDatum(properties(datumName)),
+                new DefaultCartesianCS(properties("A test CS"),
+                        new DefaultCoordinateSystemAxis(properties("x"), "x", 
AxisDirection.DISPLAY_RIGHT, Units.METRE),
+                        new DefaultCoordinateSystemAxis(properties("y"), "y", 
yDirection, Units.METRE)));
+    }
 }
diff --git a/core/sis-utility/src/main/java/org/apache/sis/util/Classes.java 
b/core/sis-utility/src/main/java/org/apache/sis/util/Classes.java
index 4cfa397..5924b87 100644
--- a/core/sis-utility/src/main/java/org/apache/sis/util/Classes.java
+++ b/core/sis-utility/src/main/java/org/apache/sis/util/Classes.java
@@ -574,9 +574,9 @@ next:       for (final Class<?> candidate : candidates) {
     }
 
     /**
-     * Returns {@code true} if the two specified objects implements exactly 
the same set
-     * of interfaces. Only interfaces assignable to {@code baseInterface} are 
compared.
-     * Declaration order doesn't matter.
+     * Returns {@code true} if the two specified objects implements exactly 
the same set of interfaces.
+     * Only interfaces assignable to {@code baseInterface} are compared.
+     * Declaration order does not matter.
      *
      * <div class="note"><b>Example:</b>
      * in ISO 19111, different interfaces exist for different coordinate 
system (CS) geometries
@@ -585,14 +585,14 @@ next:       for (final Class<?> candidate : candidates) {
      *
      * {@preformat java
      *     if (implementSameInterfaces(cs1, cs2, CoordinateSystem.class)) {
-     *         // The two Coordinate System are of the same kind.
+     *         // The two Coordinate Systems are of the same kind.
      *     }
      * }
      * </div>
      *
-     * @param object1  the first object to check for interfaces.
-     * @param object2  the second object to check for interfaces.
-     * @param baseInterface  the parent of all interfaces to check.
+     * @param  object1  the first object to check for interfaces.
+     * @param  object2  the second object to check for interfaces.
+     * @param  baseInterface  the parent of all interfaces to check.
      * @return {@code true} if both objects implement the same set of 
interfaces,
      *         considering only sub-interfaces of {@code baseInterface}.
      */

Reply via email to