You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sis.apache.org by de...@apache.org on 2013/11/08 22:35:42 UTC
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...
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 {