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)