sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1540196 - in /sis/branches/JDK7/core: sis-referencing/src/main/java/org/apache/sis/referencing/datum/ sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/ sis-referencing/src/test/java/org/apache/sis/referencing/datum...
Date Fri, 08 Nov 2013 21:35:42 GMT
Author: desruisseaux
Date: Fri Nov  8 21:35:42 2013
New Revision: 1540196

URL: http://svn.apache.org/r1540196
Log:
BursaWolfParameters.getPositionVectorTransformation() now uses double-double arithmetic.

Modified:
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/BursaWolfParameters.java
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/GeneralMatrix.java
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrices.java
    sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/datum/BursaWolfParametersTest.java
    sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/MatricesTest.java
    sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/NonSquareMatrixTest.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/DoubleDouble.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/math/MathFunctions.java

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/BursaWolfParameters.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/BursaWolfParameters.java?rev=1540196&r1=1540195&r2=1540196&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/BursaWolfParameters.java
[UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/BursaWolfParameters.java
[UTF-8] Fri Nov  8 21:35:42 2013
@@ -363,7 +363,7 @@ public class BursaWolfParameters extends
      * This is identified as operation method 1033 in the EPSG database.
      *
      * {@section Inverse transformation}
-     * The inverse transformation can be computed by reversing the sign of the 7 parameters
before to use
+     * The inverse transformation can be approximated by reversing the sign of the 7 parameters
before to use
      * them in the above matrix. Note that both the direct and inverse transformations are
approximations.
      * Multiplication of direct and inverse transformation matrices results in a matrix close
to the identity,
      * but not necessarily strictly equals.
@@ -374,20 +374,39 @@ public class BursaWolfParameters extends
      * @see DefaultGeodeticDatum#getPositionVectorTransformation(GeodeticDatum)
      */
     public Matrix getPositionVectorTransformation(final boolean inverse) {
-        if (!isTranslation()) {
-            final double sgn = inverse ? -1 : +1;
-            final DoubleDouble S = new DoubleDouble(PPM, 0);
-            S.inverseDivide(sgn*dS, 0);
-            // TODO: finish computation using double-double arithmetic.
-        }
         final double sgn = inverse ? -1 : +1;
-        final double   S = 1 + sgn*dS / PPM;
-        final double  RS = sgn*TO_RADIANS * S;
-        return new Matrix4(
-                 S,  -rZ*RS,  +rY*RS,  sgn*tX,
-            +rZ*RS,       S,  -rX*RS,  sgn*tY,
-            -rY*RS,  +rX*RS,       S,  sgn*tZ,
-                 0,       0,       0,      1);
+        if (isTranslation()) {
+            final Matrix4 matrix = new Matrix4();
+            matrix.m03 = sgn*tX;
+            matrix.m13 = sgn*tY;
+            matrix.m13 = sgn*tZ;
+            return matrix;
+        }
+        /*
+         * Above was an optimization for the common case where the Bursa-Wolf parameters
contain only
+         * translation terms. If we have rotation or scale terms, then use double-double
arithmetic.
+         */
+        final DoubleDouble RS = DoubleDouble.createSecondsToRadians();
+        final DoubleDouble S = new DoubleDouble(dS);
+        if (inverse) {
+            RS.negate();
+            S.negate();
+        }
+        S.divide(PPM, 0);
+        S.add(1, 0);        // S = 1 + sgn*dS / PPM;
+        RS.multiply(S);     // RS = sgn*secondsToRadians * S;
+        final DoubleDouble  X = new DoubleDouble(rX); X.multiply(RS);
+        final DoubleDouble  Y = new DoubleDouble(rY); Y.multiply(RS);
+        final DoubleDouble  Z = new DoubleDouble(rZ); Z.multiply(RS);
+        final DoubleDouble mX = new DoubleDouble( X); mX.negate();
+        final DoubleDouble mY = new DoubleDouble( Y); mY.negate();
+        final DoubleDouble mZ = new DoubleDouble( Z); mZ.negate();
+        final Integer       O = 0; // Fetch Integer instance only once.
+        return Matrices.create(4, 4, new Number[] {
+                 S,  mZ,   Y,  Double.valueOf(sgn*tX),
+                 Z,   S,  mX,  Double.valueOf(sgn*tY),
+                mY,   X,   S,  Double.valueOf(sgn*tZ),
+                 O,   O,   O,  1});
     }
 
     /**

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/GeneralMatrix.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/GeneralMatrix.java?rev=1540196&r1=1540195&r2=1540196&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/GeneralMatrix.java
[UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/GeneralMatrix.java
[UTF-8] Fri Nov  8 21:35:42 2013
@@ -20,6 +20,7 @@ import java.util.Arrays;
 import org.opengis.referencing.operation.Matrix;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.ArraysExt;
+import org.apache.sis.util.resources.Errors;
 import org.apache.sis.internal.util.DoubleDouble;
 
 
@@ -129,6 +130,7 @@ class GeneralMatrix extends MatrixSIS {
 
     /**
      * Creates a new extended precision matrix of the given size.
+     * Matrices elements are initialized to zero (not to the matrix identity).
      *
      * @param numRow Number of rows.
      * @param numCol Number of columns.
@@ -306,6 +308,69 @@ class GeneralMatrix extends MatrixSIS {
     }
 
     /**
+     * Sets all matrix elements like {@link #setElements(double)}, but from an array of {@code
Number} instead
+     * of {@code double}. The main purpose of this method is to fetch the {@link DoubleDouble#error}
terms when
+     * such instances are found.
+     *
+     * <p><b>Restrictions:</b></p>
+     * <ul>
+     *   <li>This matrix must use extended-precision elements, as by {@link #createExtendedPrecision(int,
int)}.</li>
+     *   <li>If this method returns {@code false}, then error terms are <strong>not</strong>
initialized - they
+     *       may have any values.</li>
+     * </ul>
+     *
+     * @param  elements The new matrix elements in a row-major array.
+     * @return {@code true} if at leat one {@link DoubleDouble} instance has been found,
in which case all
+     *         errors terms have been initialized, or {@code false} otherwise, in which case
no error term
+     *         has been initialized (this is a <cite>all or nothing</cite> operation).
+     * @throws IllegalArgumentException If the given array does not have the expected length.
+     *
+     * @see Matrices#create(int, int, Number[])
+     */
+    final boolean setElements(final Number[] newValues) {
+        final int numRow = this.numRow; // Protection against accidental changes.
+        final int numCol = this.numCol;
+        final int length = numRow * numCol;
+        if (newValues.length != length) {
+            throw new IllegalArgumentException(Errors.format(
+                    Errors.Keys.UnexpectedArrayLength_2, length, newValues.length));
+        }
+        boolean isExtended = false;
+        for (int i=0; i<length; i++) {
+            final Number value = newValues[i];
+            final double element = value.doubleValue();
+            elements[i] = element;
+            final double error;
+            if (value instanceof DoubleDouble) {
+                error = ((DoubleDouble) value).error;
+                /*
+                 * If this is the first time that we found an explicit error term, then we
need to
+                 * initialize all elements before the current one because they were left
unitialized
+                 * (i.e. we perform lazy initialization).
+                 */
+                if (!isExtended) {
+                    isExtended = true;
+                    for (int j=0; j<i; j++) {
+                        elements[j + length] = DoubleDouble.errorForWellKnownValue(elements[j]);
+                    }
+                }
+            } else {
+                /*
+                 * For any kind of numbers other than DoubleDoube, calculate the error term
only if we know
+                 * that the final matrix will use extended precision (i.e. we previously
found at least one
+                 * DoubleDouble instance). Otherwise skip the error calculation since maybe
it will be discarded.
+                 */
+                if (!isExtended) {
+                    continue;
+                }
+                error = DoubleDouble.errorForWellKnownValue(element);
+            }
+            elements[i + length] = error;
+        }
+        return isExtended;
+    }
+
+    /**
      * {@inheritDoc}
      *
      * <p>This method does not check the error terms, because those terms are not visible
to the user

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrices.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrices.java?rev=1540196&r1=1540195&r2=1540196&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrices.java
[UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrices.java
[UTF-8] Fri Nov  8 21:35:42 2013
@@ -182,6 +182,29 @@ public final class Matrices extends Stat
     }
 
     /**
+     * Creates a matrix of size {@code numRow} × {@code numCol} initialized to the given
numbers.
+     * The elements array size must be equals to {@code numRow*numCol}. Column indices vary
fastest.
+     *
+     * @param  numRow   Number of rows.
+     * @param  numCol   Number of columns.
+     * @param  elements The matrix elements in a row-major array. Column indices vary fastest.
+     * @return A matrix initialized to the given elements.
+     */
+    public static MatrixSIS create(final int numRow, final int numCol, final Number[] elements)
{
+        ArgumentChecks.ensureNonNull("elements", elements);
+        final GeneralMatrix matrix = GeneralMatrix.createExtendedPrecision(numRow, numCol);
+        if (matrix.setElements(elements)) {
+            /*
+             * At least one org.apache.sis.internal.util.DoubleDouble instance has been found,
+             * in which case the matrix uses double-double arithmetic.  This case is the
main
+             * purpose of this method.
+             */
+            return matrix;
+        }
+        return create(numRow, numCol, matrix.getElements());
+    }
+
+    /**
      * Implementation of {@code createTransform(…)} public methods expecting envelopes
and/or axis directions.
      * Argument validity shall be verified by the caller.
      *

Modified: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/datum/BursaWolfParametersTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/datum/BursaWolfParametersTest.java?rev=1540196&r1=1540195&r2=1540196&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/datum/BursaWolfParametersTest.java
[UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/datum/BursaWolfParametersTest.java
[UTF-8] Fri Nov  8 21:35:42 2013
@@ -41,21 +41,23 @@ public final strictfp class BursaWolfPar
     private static final double TO_RADIANS = Math.PI / (180 * 60 * 60);
 
     /**
-     * Same implementation than {@link BursaWolfParameters#getPositionVectorTransformation(boolean)}
-     * using only {@code double} arithmetic, for verification purpose.
+     * Invokes {@link BursaWolfParameters#getPositionVectorTransformation(boolean)} and compares
+     * with our own matrix calculated using double arithmetic.
      */
-    private static Matrix4 getPositionVectorTransformation(final BursaWolfParameters p, final
boolean inverse) {
+    private static MatrixSIS getPositionVectorTransformation(final BursaWolfParameters p,
final boolean inverse) {
         final double sgn = inverse ? -1 : +1;
         final double   S = 1 + sgn*p.dS / BursaWolfParameters.PPM;
         final double  RS = sgn*TO_RADIANS * S;
-        return new Matrix4(
+        final Matrix4 expected = new Matrix4(
                    S,  -p.rZ*RS,  +p.rY*RS,  sgn*p.tX,
             +p.rZ*RS,         S,  -p.rX*RS,  sgn*p.tY,
             -p.rY*RS,  +p.rX*RS,         S,  sgn*p.tZ,
                    0,         0,         0,      1);
-    }
 
-    // TODO: use above method for checking BursaWolfParameters calculations.
+        final MatrixSIS matrix = MatrixSIS.castOrCopy(p.getPositionVectorTransformation(inverse));
+        assertMatrixEquals("getPositionVectorTransformation", expected, matrix, p.isTranslation()
? 0 : 1E-14);
+        return matrix;
+    }
 
     /**
      * Tests {@link BursaWolfParameters#getPositionVectorTransformation(boolean)}.
@@ -65,8 +67,8 @@ public final strictfp class BursaWolfPar
     @Test
     public void testGetPositionVectorTransformation() {
         final BursaWolfParameters bursaWolf = new BursaWolfParameters(0, 0, 4.5, 0, 0, 0.554,
0.219, null);
-        final MatrixSIS toWGS84 = MatrixSIS.castOrCopy(bursaWolf.getPositionVectorTransformation(false));
-        final MatrixSIS toWGS72 = MatrixSIS.castOrCopy(bursaWolf.getPositionVectorTransformation(true));
+        final MatrixSIS toWGS84 = getPositionVectorTransformation(bursaWolf, false);
+        final MatrixSIS toWGS72 = getPositionVectorTransformation(bursaWolf, true);
         final MatrixSIS source  = Matrices.create(4, 1, new double[] {3657660.66, 255768.55,
5201382.11, 1});
         final MatrixSIS target  = Matrices.create(4, 1, new double[] {3657660.78, 255778.43,
5201387.75, 1});
         assertMatrixEquals("toWGS84", target, toWGS84.multiply(source), 0.01);
@@ -82,8 +84,8 @@ public final strictfp class BursaWolfPar
     public void testP() {
         final BursaWolfParameters bursaWolf = new BursaWolfParameters(
                 -82.981, -99.719, -110.709, -0.5076, 0.1503, 0.3898, -0.3143, null);
-        final MatrixSIS toWGS84 = MatrixSIS.castOrCopy(bursaWolf.getPositionVectorTransformation(false));
-        final MatrixSIS toED87  = MatrixSIS.castOrCopy(bursaWolf.getPositionVectorTransformation(true));
+        final MatrixSIS toWGS84 = getPositionVectorTransformation(bursaWolf, false);
+        final MatrixSIS toED87  = getPositionVectorTransformation(bursaWolf, true);
         final MatrixSIS product = toWGS84.multiply(toED87);
         /*
          * The error is below 1E-11 for all elements except the translation terms.

Modified: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/MatricesTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/MatricesTest.java?rev=1540196&r1=1540195&r2=1540196&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/MatricesTest.java
[UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/MatricesTest.java
[UTF-8] Fri Nov  8 21:35:42 2013
@@ -19,9 +19,11 @@ package org.apache.sis.referencing.opera
 import org.opengis.geometry.Envelope;
 import org.opengis.referencing.operation.Matrix;
 import org.opengis.referencing.cs.AxisDirection;
+import org.apache.sis.internal.util.DoubleDouble;
 import org.apache.sis.geometry.Envelope2D;
 import org.apache.sis.geometry.GeneralEnvelope;
 import org.apache.sis.util.iso.Types;
+import org.apache.sis.util.ComparisonMode;
 import org.apache.sis.test.DependsOnMethod;
 import org.apache.sis.test.DependsOn;
 import org.apache.sis.test.TestCase;
@@ -50,6 +52,45 @@ import static org.opengis.referencing.cs
 })
 public final strictfp class MatricesTest extends TestCase {
     /**
+     * Tests {@link Matrices#create(int, int, Number[])}.
+     */
+    public void testCreateFromNumbers() {
+        final double SENTINEL_VALUE = Double.MIN_VALUE;
+        final int    SIZE           = Matrix3.SIZE;
+        final Matrix3 expected = new Matrix3(
+                  1,    2,    3,
+                0.1,  0.2,  0.3,
+                 -1,   -2,   -3);
+        final Number[] elements = {
+                  1,    2,    3,
+                0.1,  0.2,  0.3,
+                 -1,   -2,   -3};
+        /*
+         * Mix of Integer and Double objects but without DoubleDouble objects.
+         * The result shall be a matrix using the standard double Java type.
+         */
+        assertEquals(expected, Matrices.create(SIZE, SIZE, elements));
+        /*
+         * Now put some DoubleDouble instances in the diagonal. We set the error term to
+         * Double.MIN_VALUE in order to differentiate them from automatically calculated
+         * error terms. The result shall use double-double arithmetic, and we should be
+         * able to find back our error terms.
+         */
+        for (int i = 0; i < elements.length; i += SIZE+1) {
+            elements[i] = new DoubleDouble(elements[i].doubleValue(), SENTINEL_VALUE);
+        }
+        final MatrixSIS matrix = Matrices.create(SIZE, SIZE, elements);
+        assertInstanceOf("Created with DoubleDouble elements", GeneralMatrix.class, matrix);
+        assertFalse(expected.equals(matrix)); // Because not the same type.
+        assertTrue(Matrices.equals(expected, matrix, ComparisonMode.BY_CONTRACT));
+        final double[] errors = ((GeneralMatrix) matrix).elements;
+        for (int i = 0; i < SIZE*SIZE; i++) {
+            // Only elements on the diagonal shall be our sentinel value.
+            assertEquals((i % (SIZE+1)) == 0, errors[i + SIZE*SIZE] == SENTINEL_VALUE);
+        }
+    }
+
+    /**
      * Tests {@link Matrices#createTransform(AxisDirection[], AxisDirection[])} with the
same sequence of axes.
      * The result shall be an identity matrix.
      *

Modified: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/NonSquareMatrixTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/NonSquareMatrixTest.java?rev=1540196&r1=1540195&r2=1540196&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/NonSquareMatrixTest.java
[UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/NonSquareMatrixTest.java
[UTF-8] Fri Nov  8 21:35:42 2013
@@ -75,6 +75,8 @@ public final strictfp class NonSquareMat
 
     /**
      * Tests {@link NonSquareMatrix#inverse()} with a non-square matrix.
+     *
+     * @throws NoninvertibleMatrixException Should never happen.
      */
     @Override
     public void testInverse() throws NoninvertibleMatrixException {
@@ -84,6 +86,8 @@ public final strictfp class NonSquareMat
 
     /**
      * Tests {@link NonSquareMatrix#solve(Matrix)} with a non-square matrix.
+     *
+     * @throws NoninvertibleMatrixException Should never happen.
      */
     @Override
     public void testSolve() throws NoninvertibleMatrixException {

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/DoubleDouble.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/DoubleDouble.java?rev=1540196&r1=1540195&r2=1540196&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/DoubleDouble.java
[UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/DoubleDouble.java
[UTF-8] Fri Nov  8 21:35:42 2013
@@ -189,6 +189,27 @@ public final class DoubleDouble extends 
     }
 
     /**
+     * Creates a new value initialized to the given value.
+     *
+     * @param other The other value to copy.
+     */
+    public DoubleDouble(final DoubleDouble other) {
+        value = other.value;
+        error = other.error;
+    }
+
+    /**
+     * Creates a new value initialized to the given value and an error term inferred by
+     * {@link #errorForWellKnownValue(double)}.
+     *
+     * @param value The initial value.
+     */
+    public DoubleDouble(final double value) {
+        this.value = value;
+        this.error = errorForWellKnownValue(value);
+    }
+
+    /**
      * Creates a new value initialized to the given value and error.
      * It is caller's responsibility to ensure that the (value, error) pair is normalized.
      *
@@ -398,7 +419,7 @@ public final class DoubleDouble extends 
     }
 
     /**
-     * Set this number to {@code -this}.
+     * Sets this number to {@code -this}.
      */
     public void negate() {
         value = -value;

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/math/MathFunctions.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/math/MathFunctions.java?rev=1540196&r1=1540195&r2=1540196&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/math/MathFunctions.java
[UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/math/MathFunctions.java
[UTF-8] Fri Nov  8 21:35:42 2013
@@ -60,6 +60,7 @@ import static org.apache.sis.internal.ut
  * @version 0.4
  * @module
  *
+ * @see DecimalFunctions
  * @see org.apache.sis.util.Numbers
  */
 public final class MathFunctions extends Static {



Mime
View raw message