Author: desruisseaux
Date: Wed Jul 29 17:51:29 2015
New Revision: 1693323

URL: http://svn.apache.org/r1693323
Log:
Add a tolerance threshold when checking if a "synthetic" matrix computed during 
WKT formatting is the identity.
Add comments explaining why the tolerance threshold is set to ANGULAR_TOLERANCE 
for those particular matrices.

Modified:
    
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ContextualParameters.java

Modified: 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ContextualParameters.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ContextualParameters.java?rev=1693323&r1=1693322&r2=1693323&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ContextualParameters.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ContextualParameters.java
 [UTF-8] Wed Jul 29 17:51:29 2015
@@ -37,6 +37,7 @@ import org.opengis.referencing.operation
 import org.opengis.referencing.operation.MathTransformFactory;
 import org.apache.sis.internal.referencing.ExtendedPrecisionMatrix;
 import org.apache.sis.internal.referencing.WKTUtilities;
+import org.apache.sis.internal.referencing.Formulas;
 import org.apache.sis.internal.metadata.WKTKeywords;
 import org.apache.sis.internal.system.Loggers;
 import org.apache.sis.internal.util.DoubleDouble;
@@ -703,11 +704,31 @@ public class ContextualParameters extend
          * At this point "userDefined" is the affine transform to show to user 
instead of the
          * "before" affine transform. Replaces "before" by "userDefined" 
locally (but not yet
          * in the list), or set it to null (meaning that it will be removed 
from the list) if
-         * it is identity, which happen quite often. Note that in the former 
(non-null) case,
-         * the coefficients are often either 0 or 1 since the transform is 
often for changing
-         * axis order, so it is worth to attempt rounding coefficents.
+         * it is identity, which happen quite often.
+         *
+         * Note on rounding error: the coefficients are often either 0 or 1 
since the transform
+         * is often for changing axis order. Thanks to double-double 
arithmetic in SIS matrices,
+         * the non-zero values are usually accurate. But the values that 
should be zero are much
+         * harder to get right. Sometime we see small values (around 1E-12) in 
the last column of
+         * the 'before' matrix below. Since this column contains translation 
terms, those numbers
+         * are in the unit of measurement of input values of the MathTransform 
after the matrix.
+         *
+         *   - For forward map projections, those values are conceptually in 
decimal degrees
+         *     (in fact the values are converted to radians but not by this 
'before' matrix).
+         *
+         *   - For inverse map projections, those values are conceptually in 
metres (in fact
+         *     converted to distances on a unitary ellipsoid but not by this 
'before' matrix).
+         *
+         *   - Geographic/Geocentric transformations behave like map 
projections in regard to units.
+         *     Molodensky transformations conceptually use always decimal 
degrees. There is not much
+         *     other cases since this mechanism is internal to SIS (not in 
public API).
+         *
+         * Consequently we set the tolerance threshold to ANGULAR_TOLERANCE. 
We do not bother (at least
+         * for now) to identify the cases where we could use LINEAR_TOLERANCE 
because just checking the
+         * 'inverse' flag is not sufficient (e.g. the Molodensky case). Since 
the angular tolerance is
+         * smaller than the linear one, unconditional usage of 
ANGULAR_TOLERANCE is more conservative.
          */
-        before = userDefined.isIdentity() ? null : userDefined;
+        before = Matrices.isIdentity(userDefined, Formulas.ANGULAR_TOLERANCE) 
? null : userDefined;
         /*
          * Compute the "after" affine transform in a way similar than the 
"before" affine.
          * Note that if this operation fails, we will cancel everything we 
would have done
@@ -723,7 +744,23 @@ public class ContextualParameters extend
         if (hasAfter) {
             userDefined = Matrices.multiply(after, userDefined);
         }
-        after = userDefined.isIdentity() ? null : userDefined;
+        /*
+         * Note on rounding error: same discussion than the "note on rounding 
error" of the 'before' matrix,
+         * with the following differences:
+         *
+         *   - For forward map projections, unit of measurements of 
translation terms are conceptually
+         *     metres (instead than degrees) multiplied by the scale factors 
in the 'after' matrix.
+         *
+         *   - For inverse map projections, unit of measurements of 
translation terms are conceptually
+         *     degrees (instead than metres) multiplied by the scale factors 
in the 'after' matrix.
+         *
+         *   - And so on for all cases: swap the units of the forward and 
inverse cases, then multiply
+         *     by the scale factor. Note that the multiplication step does not 
exist in the 'before' case.
+         *
+         * Since we are seeking for the identity matrix, the scale factor is 
1. We do not bother to distinguish
+         * the ANGULAR_TOLERANCE and LINEAR_TOLERANCE cases for the same 
reasons than for the 'before' matrix.
+         */
+        after = Matrices.isIdentity(userDefined, Formulas.ANGULAR_TOLERANCE) ? 
null : userDefined;
         /*
          * At this point we have computed all the affine transforms to show to 
the user.
          * We can replace the elements in the list. The transform referenced 
by transforms.get(index)


Reply via email to