Author: desruisseaux
Date: Wed Apr  6 14:39:32 2016
New Revision: 1737990

URL: http://svn.apache.org/viewvc?rev=1737990&view=rev
Log:
Fix operation between CompoundCRS having a ProjectedCRS, and add corresponding 
test.

Added:
    
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/SubOperationInfo.java
      - copied, changed from r1737989, 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/SourceComponent.java
Removed:
    
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/SourceComponent.java
Modified:
    
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationInference.java
    
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/CoordinateOperationInferenceTest.java

Modified: 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationInference.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationInference.java?rev=1737990&r1=1737989&r2=1737990&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationInference.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationInference.java
 [UTF-8] Wed Apr  6 14:39:32 2016
@@ -314,7 +314,8 @@ public class CoordinateOperationInferenc
         ////                                                                   
     ////
         
////////////////////////////////////////////////////////////////////////////////
         if (sourceCRS instanceof CompoundCRS || targetCRS instanceof 
CompoundCRS) {
-            return decompose(sourceCRS, targetCRS);
+            return createOperationStep(sourceCRS, 
CRS.getSingleComponents(sourceCRS),
+                                       targetCRS, 
CRS.getSingleComponents(targetCRS));
         }
         throw new OperationNotFoundException(notFoundMessage(sourceCRS, 
targetCRS));
     }
@@ -732,19 +733,20 @@ public class CoordinateOperationInferenc
      * various combinations of source and target components. A preference is 
given for components of the same
      * type (e.g. source {@link GeodeticCRS} with target {@code GeodeticCRS}, 
<i>etc.</i>).
      *
-     * @param  sourceCRS  input coordinate reference system.
-     * @param  targetCRS  output coordinate reference system.
+     * @param  sourceCRS        input coordinate reference system.
+     * @param  sourceComponents components of the source CRS.
+     * @param  targetCRS        output coordinate reference system.
+     * @param  targetComponents components of the target CRS.
      * @return a coordinate operation from {@code sourceCRS} to {@code 
targetCRS}.
      * @throws FactoryException if the operation can not be constructed.
      */
-    private CoordinateOperation decompose(final CoordinateReferenceSystem 
sourceCRS,
-                                          final CoordinateReferenceSystem 
targetCRS)
+    protected CoordinateOperation createOperationStep(
+            final CoordinateReferenceSystem sourceCRS, final List<? extends 
SingleCRS> sourceComponents,
+            final CoordinateReferenceSystem targetCRS, final List<? extends 
SingleCRS> targetComponents)
             throws FactoryException
     {
-        final List<SingleCRS> sources = CRS.getSingleComponents(sourceCRS);
-        final List<SingleCRS> targets = CRS.getSingleComponents(targetCRS);
-        final SourceComponent[] infos = new SourceComponent[targets.size()];
-        final boolean[]  sourceIsUsed = new boolean[sources.size()];
+        final SubOperationInfo[] infos = new 
SubOperationInfo[targetComponents.size()];
+        final boolean[]   sourceIsUsed = new boolean[sourceComponents.size()];
         final CoordinateReferenceSystem[] stepComponents = new 
CoordinateReferenceSystem[infos.length];
         /*
          * Operations found are stored in 'infos', but are not yet wrapped in 
PassThroughOperations.
@@ -752,7 +754,7 @@ public class CoordinateOperationInferenc
          * order. We also need to know if any source ordinates should be 
dropped.
          */
         for (int i=0; i<infos.length; i++) {
-            if ((infos[i] = SourceComponent.create(this, sourceIsUsed, 
sources, targets.get(i))) == null) {
+            if ((infos[i] = SubOperationInfo.create(this, sourceIsUsed, 
sourceComponents, targetComponents.get(i))) == null) {
                 throw new 
OperationNotFoundException(notFoundMessage(sourceCRS, targetCRS));
             }
             stepComponents[i] = infos[i].operation.getSourceCRS();
@@ -765,10 +767,10 @@ public class CoordinateOperationInferenc
          * operations that we just found.
          */
         int remainingSourceDimensions = 0;
-        for (final SourceComponent component : infos) {
+        for (final SubOperationInfo component : infos) {
             remainingSourceDimensions += component.endAtDimension - 
component.startAtDimension;
         }
-        final Matrix select = SourceComponent.sourceToSelected(
+        final Matrix select = SubOperationInfo.sourceToSelected(
                 sourceCRS.getCoordinateSystem().getDimension(), 
remainingSourceDimensions, infos);
         /*
          * First, we need a CRS matching the above-cited rearrangement. That 
CRS will be named 'stepSourceCRS'
@@ -793,13 +795,13 @@ public class CoordinateOperationInferenc
          * For each sub-operation, create a PassThroughOperation for the 
(stepSourceCRS → stepTargetCRS) operation.
          * Each source CRS inside this loop will be for dimensions at indices 
[startAtDimension … endAtDimension-1].
          * Note that those indices are not necessarily the same than the 
indices in the fields of the same name in
-         * SourceComponent, because those indices are not relative to the same 
CompoundCRS.
+         * SubOperationInfo, because those indices are not relative to the 
same CompoundCRS.
          */
         int endAtDimension = 0;
-        final int startOfIdentity = SourceComponent.startOfIdentity(infos);
+        final int startOfIdentity = SubOperationInfo.startOfIdentity(infos);
         for (int i=0; i<stepComponents.length; i++) {
             final CoordinateReferenceSystem source = stepComponents[i];
-            final CoordinateReferenceSystem target = targets.get(i);
+            final CoordinateReferenceSystem target = targetComponents.get(i);
             CoordinateOperation subOperation = infos[i].operation;
             final MathTransform subTransform = subOperation.getMathTransform();
             /*

Copied: 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/SubOperationInfo.java
 (from r1737989, 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/SourceComponent.java)
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/SubOperationInfo.java?p2=sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/SubOperationInfo.java&p1=sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/SourceComponent.java&r1=1737989&r2=1737990&rev=1737990&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/SourceComponent.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/SubOperationInfo.java
 [UTF-8] Wed Apr  6 14:39:32 2016
@@ -36,7 +36,7 @@ import org.apache.sis.referencing.operat
  * @version 0.7
  * @module
  */
-final class SourceComponent {
+final class SubOperationInfo {
     /**
      * Types of target CRS, together with the type of CRS that may be used as 
the source for that target.
      * For each array {@code COMPATIBLE_TYPES[i]}, the first element (i.e. 
{@code COMPATIBLE_TYPES[i][0]})
@@ -88,7 +88,7 @@ final class SourceComponent {
     /**
      * Creates a new instance containing the given information.
      */
-    private SourceComponent(final CoordinateOperation operation, final int 
startAtDimension, final int endAtDimension) {
+    private SubOperationInfo(final CoordinateOperation operation, final int 
startAtDimension, final int endAtDimension) {
         this.operation        = operation;
         this.startAtDimension = startAtDimension;
         this.endAtDimension   = endAtDimension;
@@ -105,8 +105,8 @@ final class SourceComponent {
      * @return information about a coordinate operation from a source CRS to 
the given target CRS, or {@code null}.
      * @throws FactoryException if an error occurred while grabbing a 
coordinate operation.
      */
-    static SourceComponent create(final CoordinateOperationInference caller, 
final boolean[] sourceIsUsed,
-            final List<SingleCRS> sources, final SingleCRS target) throws 
FactoryException
+    static SubOperationInfo create(final CoordinateOperationInference caller, 
final boolean[] sourceIsUsed,
+            final List<? extends SingleCRS> sources, final SingleCRS target) 
throws FactoryException
     {
         OperationNotFoundException failure = null;
         final Class<?> targetType = type(target);
@@ -119,7 +119,7 @@ final class SourceComponent {
                         final SingleCRS source = sources.get(i);
                         startAtDimension = endAtDimension;
                         endAtDimension += 
source.getCoordinateSystem().getDimension();
-                        if (!sourceIsUsed[i] && sourceType.isInstance(source)) 
{
+                        if (!sourceIsUsed[i] && 
sourceType.isAssignableFrom(type(source))) {
                             final CoordinateOperation operation;
                             try {
                                 operation = caller.createOperation(source, 
target);
@@ -151,7 +151,7 @@ final class SourceComponent {
                                 
Logging.recoverableException(Logging.getLogger(Loggers.COORDINATE_OPERATION),
                                         CoordinateOperationInference.class, 
"decompose", failure);
                             }
-                            return new SourceComponent(operation, 
startAtDimension, endAtDimension);
+                            return new SubOperationInfo(operation, 
startAtDimension, endAtDimension);
                         }
                     }
                 }
@@ -166,7 +166,7 @@ final class SourceComponent {
     /**
      * Returns the dimension from which all remaining operations are identity.
      */
-    static int startOfIdentity(final SourceComponent[] selected) {
+    static int startOfIdentity(final SubOperationInfo[] selected) {
         int n = selected.length;
         while (n != 0) {
             if (!selected[--n].operation.getMathTransform().isIdentity()) {
@@ -184,11 +184,11 @@ final class SourceComponent {
      * @param selectedDimensions  number of source dimensions needed by the 
coordinate operations.
      * @param selected all {@code SourceComponent} instances needed for the 
target {@code CompoundCRS}.
      */
-    static Matrix sourceToSelected(final int sourceDimensions, final int 
selectedDimensions, final SourceComponent[] selected) {
+    static Matrix sourceToSelected(final int sourceDimensions, final int 
selectedDimensions, final SubOperationInfo[] selected) {
         final Matrix select = Matrices.createZero(selectedDimensions + 1, 
sourceDimensions + 1);
         select.setElement(selectedDimensions, sourceDimensions, 1);
         int j = 0;
-        for (final SourceComponent component : selected) {
+        for (final SubOperationInfo component : selected) {
             for (int i=component.startAtDimension; i<component.endAtDimension; 
i++) {
                 select.setElement(j++, i, 1);
             }

Modified: 
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/CoordinateOperationInferenceTest.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/CoordinateOperationInferenceTest.java?rev=1737990&r1=1737989&r2=1737990&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/CoordinateOperationInferenceTest.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/CoordinateOperationInferenceTest.java
 [UTF-8] Wed Apr  6 14:39:32 2016
@@ -21,7 +21,6 @@ import java.util.Collections;
 import java.text.ParseException;
 import org.opengis.util.FactoryException;
 import org.opengis.parameter.ParameterValueGroup;
-import org.opengis.referencing.crs.SingleCRS;
 import org.opengis.referencing.crs.GeographicCRS;
 import org.opengis.referencing.crs.GeocentricCRS;
 import org.opengis.referencing.crs.VerticalCRS;
@@ -621,12 +620,62 @@ public final strictfp class CoordinateOp
     /**
      * Convenience method for creating a compound CRS.
      */
-    private static CompoundCRS compound(final String name, final SingleCRS... 
components) {
+    private static CompoundCRS compound(final String name, final 
CoordinateReferenceSystem... components) {
         return new 
DefaultCompoundCRS(Collections.singletonMap(CompoundCRS.NAME_KEY, name), 
components);
     }
 
     /**
-     * Tests transformation from three-dimensional geographic CRS to 
four-dimensional compound CRS
+     * Tests conversion from four-dimensional compound CRS to two-dimensional 
projected CRS.
+     *
+     * @throws ParseException if a CRS used in this test can not be parsed.
+     * @throws FactoryException if the operation can not be created.
+     * @throws TransformException if an error occurred while converting the 
test points.
+     */
+    @Test
+    @DependsOnMethod("testTemporalConversion")
+    public void testProjected4D_to_2D() throws ParseException, 
FactoryException, TransformException {
+        final CoordinateReferenceSystem targetCRS = parse(
+                "ProjectedCRS[“WGS 84 / World Mercator”,\n" +
+                "  BaseGeodCRS[“WGS 84”,\n" +
+                "    Datum[“World Geodetic System 1984”,\n" +
+                "      Ellipsoid[“WGS 84”, 6378137.0, 298.257223563]]],\n" +
+                "  Conversion[“WGS 84 / World Mercator”,\n" +
+                "    Method[“Mercator (1SP)”]],\n" +
+                "  CS[Cartesian, 2],\n" +
+                "    Axis[“Easting”, EAST],\n" +
+                "    Axis[“Northing”, NORTH],\n" +
+                "    Unit[“m”, 1],\n" +
+                "  Id[“EPSG”, “3395”]]");
+
+        CoordinateReferenceSystem sourceCRS = targetCRS;
+        sourceCRS = compound("Mercator 3D", sourceCRS, 
CommonCRS.Vertical.ELLIPSOIDAL.crs());
+        sourceCRS = compound("Mercator 4D", sourceCRS, 
CommonCRS.Temporal.MODIFIED_JULIAN.crs());
+
+        final CoordinateOperation operation = 
factory.createOperation(sourceCRS, targetCRS);
+        assertSame("sourceCRS", sourceCRS, operation.getSourceCRS());
+        assertSame("targetCRS", targetCRS, operation.getTargetCRS());
+
+        transform = operation.getMathTransform();
+        assertFalse("transform.isIdentity", transform.isIdentity());
+        assertInstanceOf("The somewhat complex MathTransform chain should have 
been simplified " +
+                         "to a single affine transform.", 
LinearTransform.class, transform);
+        assertInstanceOf("The operation should be a simple axis change, not a 
complex" +
+                         "chain of ConcatenatedOperations.", Conversion.class, 
operation);
+
+        tolerance = 1E-12;
+        isInverseTransformSupported = false;
+        verifyTransform(new double[] {
+               0,     0,  0,    0,
+            1000, -2000, 20, 4000
+        }, new double[] {
+               0,     0,
+            1000, -2000
+        });
+        validate();
+    }
+
+    /**
+     * Tests conversion from three-dimensional geographic CRS to 
four-dimensional compound CRS
      * where the last dimension is time.
      *
      * @throws FactoryException if the operation can not be created.


Reply via email to