Author: desruisseaux
Date: Tue Mar 29 15:02:20 2016
New Revision: 1737010

URL: http://svn.apache.org/viewvc?rev=1737010&view=rev
Log:
Add more tests. For easier debugging, provide a SIS-specific WKT format for 
ConcatenatedOperation (this case does not seem to be described by WKT 2 format).

Modified:
    
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java
    
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationInference.java
    
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.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/AbstractCoordinateOperation.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java?rev=1737010&r1=1737009&r2=1737010&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java
 [UTF-8] Tue Mar 29 15:02:20 2016
@@ -32,6 +32,7 @@ import org.opengis.metadata.quality.Posi
 import org.opengis.referencing.IdentifiedObject;
 import org.opengis.referencing.crs.GeneralDerivedCRS;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.referencing.operation.ConcatenatedOperation;
 import org.opengis.referencing.operation.CoordinateOperation;
 import org.opengis.referencing.operation.OperationMethod;
 import org.opengis.referencing.operation.MathTransform;
@@ -857,32 +858,45 @@ check:      for (int isTarget=0; ; isTar
     protected String formatTo(final Formatter formatter) {
         super.formatTo(formatter);
         formatter.newLine();
-        append(formatter, getSourceCRS(), WKTKeywords.SourceCRS);
-        append(formatter, getTargetCRS(), WKTKeywords.TargetCRS);
-        formatter.append(DefaultOperationMethod.castOrCopy(getMethod()));
-        ParameterValueGroup parameters;
-        try {
-            parameters = getParameterValues();
-        } catch (UnsupportedOperationException e) {
-            final IdentifiedObject c = getParameterDescriptors();
-            formatter.setInvalidWKT(c != null ? c : this, e);
-            parameters = null;
+        /*
+         * If the WKT is a component of a ConcatenatedOperation, do not format 
the source and target CRS.
+         * This decision SIS-specific since the WKT 2 specification does not 
define concatenated operations.
+         * The choice of content to omit may change in any future version.
+         */
+        final boolean isComponent = (formatter.getEnclosingElement(1) 
instanceof ConcatenatedOperation);
+        if (!isComponent) {
+            append(formatter, getSourceCRS(), WKTKeywords.SourceCRS);
+            append(formatter, getTargetCRS(), WKTKeywords.TargetCRS);
         }
-        if (parameters != null) {
-            formatter.newLine();
-            for (final GeneralParameterValue param : parameters.values()) {
-                WKTUtilities.append(param, formatter);
+        final OperationMethod method = getMethod();
+        if (method != null) {
+            formatter.append(DefaultOperationMethod.castOrCopy(method));
+            ParameterValueGroup parameters;
+            try {
+                parameters = getParameterValues();
+            } catch (UnsupportedOperationException e) {
+                final IdentifiedObject c = getParameterDescriptors();
+                formatter.setInvalidWKT(c != null ? c : this, e);
+                parameters = null;
             }
-        }
-        append(formatter, getInterpolationCRS(), WKTKeywords.InterpolationCRS);
-        final double accuracy = getLinearAccuracy();
-        if (accuracy > 0) {
-            formatter.append(new FormattableObject() {
-                @Override protected String formatTo(final Formatter formatter) 
{
-                    formatter.append(accuracy);
-                    return WKTKeywords.OperationAccuracy;
+            if (parameters != null) {
+                formatter.newLine();
+                for (final GeneralParameterValue param : parameters.values()) {
+                    WKTUtilities.append(param, formatter);
                 }
-            });
+            }
+        }
+        if (!isComponent) {
+            append(formatter, getInterpolationCRS(), 
WKTKeywords.InterpolationCRS);
+            final double accuracy = getLinearAccuracy();
+            if (accuracy > 0) {
+                formatter.append(new FormattableObject() {
+                    @Override protected String formatTo(final Formatter 
formatter) {
+                        formatter.append(accuracy);
+                        return WKTKeywords.OperationAccuracy;
+                    }
+                });
+            }
         }
         if (formatter.getConvention().majorVersion() == 1) {
             formatter.setInvalidWKT(this, null);

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=1737010&r1=1737009&r2=1737010&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] Tue Mar 29 15:02:20 2016
@@ -783,11 +783,29 @@ public class CoordinateOperationInferenc
         if (step2.getName() == AXIS_CHANGES && mt2.getSourceDimensions() == 
mt2.getTargetDimensions()) main = step1;
         if (main instanceof SingleOperation) {
             final MathTransform mt = 
factorySIS.getMathTransformFactory().createConcatenatedTransform(mt1, mt2);
-            return createFromMathTransform(new 
HashMap<>(IdentifiedObjects.getProperties(main)),
+            main = createFromMathTransform(new 
HashMap<>(IdentifiedObjects.getProperties(main)),
                    sourceCRS, targetCRS, mt, ((SingleOperation) 
main).getMethod(),
                    (main instanceof Transformation) ? Transformation.class : 
SingleOperation.class);
+        } else {
+            main = factory.createConcatenatedOperation(defaultName(sourceCRS, 
targetCRS), step1, step2);
         }
-        return factory.createConcatenatedOperation(defaultName(sourceCRS, 
targetCRS), step1, step2);
+        /*
+         * Sometime we get a concatenated operation made of an operation 
followed by its inverse.
+         * We can identity those case when the associated MathTransform is the 
identity transform.
+         * In such case, simplify by replacing the ConcatenatedTransform by a 
SingleTransform.
+         */
+        if (main instanceof ConcatenatedOperation && 
main.getMathTransform().isIdentity()) {
+            Class<? extends CoordinateOperation> type = null;
+            for (final CoordinateOperation component : 
((ConcatenatedOperation) main).getOperations()) {
+                if (component instanceof Transformation) {
+                    type = Transformation.class;
+                    break;
+                }
+            }
+            main = createFromMathTransform(new 
HashMap<>(IdentifiedObjects.getProperties(main)),
+                    main.getSourceCRS(), main.getTargetCRS(), 
main.getMathTransform(), null, type);
+        }
+        return main;
     }
 
     /**

Modified: 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java?rev=1737010&r1=1737009&r2=1737010&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java
 [UTF-8] Tue Mar 29 15:02:20 2016
@@ -46,6 +46,7 @@ import static org.apache.sis.util.Utilit
 
 // Branch-dependent imports
 import java.util.Objects;
+import org.apache.sis.io.wkt.Formatter;
 
 
 /**
@@ -325,6 +326,23 @@ final class DefaultConcatenatedOperation
         return super.computeHashCode() + 37 * Objects.hashCode(operations);
     }
 
+    /**
+     * Formats this coordinate operation in pseudo-WKT. This is specific to 
Apache SIS since
+     * there is no concatenated operation in the Well Known Text (WKT) version 
2 format.
+     *
+     * @param  formatter The formatter to use.
+     * @return {@code "ConcatenatedOperation"}.
+     */
+    @Override
+    protected String formatTo(final Formatter formatter) {
+        super.formatTo(formatter);
+        for (final CoordinateOperation component : operations) {
+            formatter.append(castOrCopy(component));
+        }
+        formatter.setInvalidWKT(this, null);
+        return "ConcatenatedOperation";
+    }
+
 
 
 

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=1737010&r1=1737009&r2=1737010&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] Tue Mar 29 15:02:20 2016
@@ -22,6 +22,7 @@ import org.opengis.parameter.ParameterVa
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.opengis.referencing.operation.CoordinateOperation;
 import org.opengis.referencing.operation.SingleOperation;
+import org.opengis.referencing.operation.Conversion;
 import org.opengis.referencing.operation.Projection;
 import org.opengis.referencing.operation.TransformException;
 import org.apache.sis.referencing.CommonCRS;
@@ -79,11 +80,41 @@ public final strictfp class CoordinateOp
     /**
      * Creates a new {@link DefaultCoordinateOperationFactory} to use for 
testing purpose.
      * The same factory will be used for all tests in this class.
+     *
+     * @throws ParseException if an error occurred while preparing the WKT 
parser.
      */
     @BeforeClass
-    public static void createFactory() {
+    public static void createFactory() throws ParseException {
         factory = new DefaultCoordinateOperationFactory();
         parser  = new WKTFormat(null, null);
+        /*
+         * The fist keyword in WKT below should be "GeodeticCRS" in WKT 2, but 
we use the WKT 1 keyword ("GEOGCS")
+         * for allowing inclusion in ProjectedCRS.  SIS is okay with mixed WKT 
versions, but this is of course not
+         * something to recommend in production.
+         */
+        parser.addFragment("Sphere",
+                "GEOGCS[“Sphere”,\n" +
+                "  Datum[“Sphere”, Ellipsoid[“Sphere”, 6370997, 0]],\n" +
+                "  CS[ellipsoidal, 2],\n" +
+                "  Axis[“Longitude (λ)”, EAST],\n" +
+                "  Axis[“Latitude (φ)”, NORTH],\n" +
+                "  Unit[“degree”, 0.017453292519943295]]");
+        /*
+         * NAD27 (EPSG:4267), defined in WKT instead than relying on the 
CommonCRS.NAD27 constant in order to fix
+         * the TOWGS84[…] parameter to values that we control. Note that 
TOWGS84[…] is not a legal WKT 2 element.
+         * We could mix WKT 1 and WKT 2 elements (SIS allows that), but we 
nevertheless use WKT 1 for the whole
+         * string as a matter of principle.
+         */
+        parser.addFragment("NAD27",
+                "GEOGCS[“Sphere”,\n" +
+                "  DATUM[“North American Datum 1927”,\n" +
+                "    SPHEROID[“Clarke 1866”, 6378206.4, 294.9786982138982],\n" 
+
+                "    TOWGS84[-10, 158, 187]]," +
+                "    PRIMEM[“Greenwich”, 0.0]," +
+                "  UNIT[“degree”, 0.017453292519943295],\n" +
+                "  AXIS[“Latitude (φ)”, NORTH],\n" +
+                "  AXIS[“Longitude (λ)”, EAST],\n" +
+                "  AUTHORITY[“EPSG”, “4267”]]");
     }
 
     /**
@@ -125,36 +156,52 @@ public final strictfp class CoordinateOp
         assertSame("sourceCRS",  crs, operation.getSourceCRS());
         assertSame("targetCRS",  crs, operation.getTargetCRS());
         assertTrue("isIdentity", operation.getMathTransform().isIdentity());
+        assertInstanceOf("operation", Conversion.class, operation);
+    }
+
+    /**
+     * Tests a transformation that requires a datum shift.
+     *
+     * @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("testIdentityTransform")
+    public void testDatumShift() throws ParseException, FactoryException, 
TransformException {
+        final CoordinateReferenceSystem sourceCRS = parse("$NAD27");
+        final CoordinateReferenceSystem targetCRS = 
CommonCRS.WGS84.geographic();
+        final CoordinateOperation operation = 
factory.createOperation(sourceCRS, targetCRS);
+        assertSame(sourceCRS, operation.getSourceCRS());
+        assertSame(targetCRS, operation.getTargetCRS());
+        transform  = operation.getMathTransform();
+        tolerance  = ANGULAR_TOLERANCE;
+        λDimension = new int[] {1};
+        verifyTransform(new double[] {
+            39,          -85,
+            38.26,       -80.58
+        }, new double[] {
+            39.00011150, -84.99995603,
+            38.26011883, -80.57981725
+        });
+        validate();
     }
 
     /**
      * Tests conversion from a geographic to a projected CRS without datum of 
axis changes.
      *
-     * @throws ParseException if the CRS used in this test can not be parsed.
+     * @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("testIdentityTransform")
     public void testGeographicToProjected() throws ParseException, 
FactoryException, TransformException {
-        /*
-         * The fist keyword in WKT below should be "GeodeticCRS" in WKT 2, but 
we use the WKT 1 keyword ("GEOGCS")
-         * for allowing inclusion in ProjectedCRS.  SIS is okay with mixed WKT 
versions, but this is of course not
-         * something to recommend in production.
-         */
-        parser.addFragment("Sphere",
-                "GEOGCS[“Sphere”,\n" +
-                "  Datum[“Sphere”, Ellipsoid[“Sphere”, 6370997, 0]],\n" +
-                "  CS[ellipsoidal, 2],\n" +
-                "  Axis[“Longitude (λ)”, EAST],\n" +
-                "  Axis[“Latitude (φ)”, NORTH],\n" +
-                "  Unit[“degree”, 0.017453292519943295]]");
-
         final CoordinateReferenceSystem sourceCRS = parse("$Sphere");
         final CoordinateReferenceSystem targetCRS = parse(
-                "ProjectedCRS[“UTM”,\n" +
+                "ProjectedCRS[“TM”,\n" +
                 "  $Sphere,\n" +
-                "  Conversion[“UTM”,\n" +
+                "  Conversion[“TM”,\n" +
                 "    Method[“Transverse Mercator”],\n" +
                 "    Parameter[“Longitude of natural origin”, 170],\n" +
                 "    Parameter[“Latitude of natural origin”, 50],\n" +
@@ -183,8 +230,9 @@ public final strictfp class CoordinateOp
         verifyTransform(new double[] {170, 50}, new double[] {0, 0});
         validate();
 
-        transform = transform.inverse();
-        tolerance = LINEAR_TOLERANCE;
+        transform  = transform.inverse();
+        tolerance  = LINEAR_TOLERANCE;
+        λDimension = new int[] {0};
         verifyTransform(new double[] {0, 0}, new double[] {170, 50});
         validate();
     }


Reply via email to