sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1541022 - in /sis/branches/JDK7/core/sis-referencing/src: main/java/org/apache/sis/referencing/datum/ test/java/org/apache/sis/referencing/datum/
Date Tue, 12 Nov 2013 12:07:33 GMT
Author: desruisseaux
Date: Tue Nov 12 12:07:32 2013
New Revision: 1541022

URL: http://svn.apache.org/r1541022
Log:
Let BursaWolfParameters be mutable (make defensive clones instead) in order to simplify their
construction,
make the code easier to read (easier to see which values are assigned to which fields), and
protect the
setPositionVectorTransformation(...) method from future constructor changes if any. The need
to simplify
the construction became more apparent with our first draft of time-dependent parameters.

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/datum/DefaultGeodeticDatum.java
    sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/datum/BursaWolfParametersTest.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=1541022&r1=1541021&r2=1541022&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] Tue Nov 12 12:07:32 2013
@@ -26,7 +26,6 @@ import org.apache.sis.referencing.operat
 import org.apache.sis.referencing.operation.matrix.Matrices;
 import org.apache.sis.io.wkt.FormattableObject;
 import org.apache.sis.io.wkt.Formatter;
-import org.apache.sis.util.Immutable;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.internal.util.Numerics;
 import org.apache.sis.internal.util.DoubleDouble;
@@ -169,8 +168,7 @@ import java.util.Objects;
  * @see DefaultGeodeticDatum#getBursaWolfParameters()
  * @see <a href="http://en.wikipedia.org/wiki/Helmert_transformation">Wikipedia: Helmert
transformation</a>
  */
-@Immutable
-public class BursaWolfParameters extends FormattableObject implements Serializable {
+public class BursaWolfParameters extends FormattableObject implements Cloneable, Serializable
{
     /**
      * Serial number for inter-operability with different versions.
      */
@@ -185,37 +183,37 @@ public class BursaWolfParameters extends
      * X-axis translation in metres (EPSG:8605).
      * The legacy OGC parameter name is {@code "dx"}.
      */
-    public final double tX;
+    public double tX;
 
     /**
      * Y-axis translation in metres (EPSG:8606).
      * The legacy OGC parameter name is {@code "dy"}.
      */
-    public final double tY;
+    public double tY;
 
     /**
      * Z-axis translation in metres (EPSG:8607).
      * The legacy OGC parameter name is {@code "dz"}.
      */
-    public final double tZ;
+    public double tZ;
 
     /**
      * X-axis rotation in arc seconds (EPSG:8608), sign following the <cite>Position
Vector</cite> convention.
      * The legacy OGC parameter name is {@code "ex"}.
      */
-    public final double rX;
+    public double rX;
 
     /**
      * Y-axis rotation in arc seconds (EPSG:8609), sign following the <cite>Position
Vector</cite> convention.
      * The legacy OGC parameter name is {@code "ey"}.
      */
-    public final double rY;
+    public double rY;
 
     /**
      * Z-axis rotation in arc seconds (EPSG:8610), sign following the <cite>Position
Vector</cite> convention.
      * The legacy OGC parameter name is {@code "ez"}.
      */
-    public final double rZ;
+    public double rZ;
 
     /**
      * The scale difference in parts per million (EPSG:8611).
@@ -225,7 +223,7 @@ public class BursaWolfParameters extends
      *           of 100.001 km in the target coordinate reference system, the scale difference
is 1 ppm
      *           (the ratio being 1.000001).}
      */
-    public final double dS;
+    public double dS;
 
     /**
      * The target datum for this set of parameters, or {@code null} if unspecified.
@@ -249,40 +247,28 @@ public class BursaWolfParameters extends
     private final Extent domainOfValidity;
 
     /**
-     * Creates a new instance with the given parameters.
+     * Creates a new instance for the given target datum and domain of validity.
+     * All numerical parameters are initialized to 0, which correspond to an identity transform.
+     * Callers can assign numerical values to the public fields of interest after construction.
+     * For example, many coordinate transformations will provide values only for the translation
+     * terms ({@link #tX}, {@link #tY}, {@link #tZ}).
+     *
+     * <p>Alternatively, numerical fields can also be initialized by a call to
+     * {@link #setPositionVectorTransformation(Matrix, double)}.</p>
      *
-     * @param tX X-axis translation in metres.
-     * @param tY Y-axis translation in metres.
-     * @param tZ Z-axis translation in metres.
-     * @param rX X-axis rotation in arc seconds.
-     * @param rY Y-axis rotation in arc seconds.
-     * @param rZ Z-axis rotation in arc seconds.
-     * @param dS The scale difference in parts per million.
      * @param targetDatum The target datum (usually WGS 84) for this set of parameters, or
{@code null} if unspecified.
      * @param domainOfValidity Area or region in which a coordinate transformation based
on those Bursa-Wolf parameters
      *        is valid, or {@code null} is unspecified.
      */
-    public BursaWolfParameters(final double tX, final double tY, final double tZ,
-                               final double rX, final double rY, final double rZ,
-                               final double dS, final GeodeticDatum targetDatum,
-                               Extent domainOfValidity)
-    {
-        this.tX = tX;
-        this.tY = tY;
-        this.tZ = tZ;
-        this.rX = rX;
-        this.rY = rY;
-        this.rZ = rZ;
-        this.dS = dS;
+    public BursaWolfParameters(final GeodeticDatum targetDatum, final Extent domainOfValidity)
{
         this.targetDatum = targetDatum;
         this.domainOfValidity = domainOfValidity;
-        verify();
     }
 
     /**
-     * Verifies parameters validity after construction.
+     * Verifies parameters validity after initialization.
      */
-    private void verify() {
+    final void verify() {
         ensureFinite("tX", tX);
         ensureFinite("tY", tY);
         ensureFinite("tZ", tZ);
@@ -293,99 +279,6 @@ public class BursaWolfParameters extends
     }
 
     /**
-     * Creates Bursa-Wolf parameters from the given <cite>Position Vector transformation</cite>
matrix.
-     * The matrix shall comply to the following constraints:
-     *
-     * <ul>
-     *   <li>The matrix shall be {@linkplain org.apache.sis.referencing.operation.matrix.MatrixSIS#isAffine()
affine}.</li>
-     *   <li>The sub-matrix defined by {@code matrix} without the last row and last
column shall be
-     *       <a href="http://en.wikipedia.org/wiki/Skew-symmetric_matrix">skew-symmetric</a>
(a.k.a. antisymmetric).</li>
-     * </ul>
-     *
-     * @param  matrix The matrix to fit as a Bursa-Wolf construct.
-     * @param  tolerance The tolerance error for the skew-symmetric matrix test, in units
of PPM or arc-seconds (e.g. 1E-8).
-     * @param  targetDatum The target datum (usually WGS 84) for this set of parameters,
or {@code null} if unspecified.
-     * @param  domainOfValidity Area or region in which a coordinate transformation based
on those Bursa-Wolf parameters
-     *         is valid, or {@code null} is unspecified.
-     * @throws IllegalArgumentException if the specified matrix does not meet the conditions.
-     *
-     * @see #getPositionVectorTransformation(Date)
-     */
-    public BursaWolfParameters(final Matrix matrix, final double tolerance, final GeodeticDatum
targetDatum,
-            Extent domainOfValidity) throws IllegalArgumentException
-    {
-        final int numRow = matrix.getNumRow();
-        final int numCol = matrix.getNumCol();
-        if (numRow != SIZE || numCol != SIZE) {
-            final Integer n = SIZE;
-            throw new IllegalArgumentException(Errors.format(Errors.Keys.MismatchedMatrixSize_4,
n, n, numRow, numCol));
-        }
-        if (!Matrices.isAffine(matrix)) {
-            throw new IllegalArgumentException(Errors.format(Errors.Keys.NotAnAffineTransform));
-        }
-        /*
-         * Translation terms, taken "as-is".
-         */
-        tX = matrix.getElement(0,3);
-        tY = matrix.getElement(1,3);
-        tZ = matrix.getElement(2,3);
-        /*
-         * Scale factor: take the average of elements on the diagonal. All those
-         * elements should have the same value, but we tolerate slight deviation
-         * (this will be verified later).
-         */
-        final DoubleDouble S = new DoubleDouble(getNumber(matrix, 0,0));
-        S.add(getNumber(matrix, 1,1));
-        S.add(getNumber(matrix, 2,2));
-        S.divide(3, 0);
-        /*
-         * Computes: RS = S * toRadians(1″)
-         *           dS = (S-1) * PPM
-         */
-        final DoubleDouble RS = DoubleDouble.createSecondsToRadians();
-        RS.multiply(S);
-        S.add(-1, 0);
-        S.multiply(PPM, 0);
-        dS = S.value;
-        /*
-         * Rotation terms. Each rotation terms appear twice, with one value being the negative
of the other value.
-         * We verify this skew symmetric aspect in the loop. We also opportunistically verify
that the scale terms
-         * are uniform.
-         */
-        double rX=0, rY=0, rZ=0;
-        for (int j=0; j < SIZE-1; j++) {
-            if (!(abs((matrix.getElement(j,j) - 1)*PPM - dS) <= tolerance)) {
-                throw new IllegalArgumentException(Errors.format(Errors.Keys.NonUniformScale));
-            }
-            for (int i = j+1; i < SIZE-1; i++) {
-                S.setFrom(RS);
-                S.inverseDivide(getNumber(matrix, j,i)); // Negative rotation term.
-                double value = S.value;
-                double error = S.error;
-                S.setFrom(RS);
-                S.inverseDivide(getNumber(matrix, i,j)); // Positive rotation term.
-                if (!(abs(value + S.value) <= tolerance)) { // We expect r1 ≈ -r2
-                    throw new IllegalArgumentException(Errors.format(Errors.Keys.NotASkewSymmetricMatrix));
-                }
-                S.subtract(value, error);
-                S.multiply(0.5, 0);
-                value = S.value; // Average of the two rotation terms.
-                switch (j*SIZE + i) {
-                    case 1: rZ =  value; break;
-                    case 2: rY = -value; break;
-                    case 6: rX =  value; break;
-                }
-            }
-        }
-        this.rX = rX;
-        this.rY = rY;
-        this.rZ = rZ;
-        this.targetDatum = targetDatum;
-        this.domainOfValidity = domainOfValidity;
-        verify();
-    }
-
-    /**
      * Returns the target datum for this set of parameters, or {@code null} if unspecified.
      * This is usually the WGS 84 datum, but other targets are allowed. We recommend the
target datum
      * to have a world-wide {@linkplain DefaultGeodeticDatum#getDomainOfValidity() domain
of validity},
@@ -504,6 +397,87 @@ public class BursaWolfParameters extends
     }
 
     /**
+     * Sets all Bursa-Wolf parameters from the given <cite>Position Vector transformation</cite>
matrix.
+     * The matrix shall comply to the following constraints:
+     *
+     * <ul>
+     *   <li>The matrix shall be {@linkplain org.apache.sis.referencing.operation.matrix.MatrixSIS#isAffine()
affine}.</li>
+     *   <li>The sub-matrix defined by {@code matrix} without the last row and last
column shall be
+     *       <a href="http://en.wikipedia.org/wiki/Skew-symmetric_matrix">skew-symmetric</a>
(a.k.a. antisymmetric).</li>
+     * </ul>
+     *
+     * @param  matrix The matrix from which to get Bursa-Wolf parameters.
+     * @param  tolerance The tolerance error for the skew-symmetric matrix test, in units
of PPM or arc-seconds (e.g. 1E-8).
+     * @throws IllegalArgumentException if the specified matrix does not meet the conditions.
+     *
+     * @see #getPositionVectorTransformation(Date)
+     */
+    public void setPositionVectorTransformation(final Matrix matrix, final double tolerance)
throws IllegalArgumentException {
+        final int numRow = matrix.getNumRow();
+        final int numCol = matrix.getNumCol();
+        if (numRow != SIZE || numCol != SIZE) {
+            final Integer n = SIZE;
+            throw new IllegalArgumentException(Errors.format(Errors.Keys.MismatchedMatrixSize_4,
n, n, numRow, numCol));
+        }
+        if (!Matrices.isAffine(matrix)) {
+            throw new IllegalArgumentException(Errors.format(Errors.Keys.NotAnAffineTransform));
+        }
+        /*
+         * Translation terms, taken "as-is".
+         */
+        tX = matrix.getElement(0,3);
+        tY = matrix.getElement(1,3);
+        tZ = matrix.getElement(2,3);
+        /*
+         * Scale factor: take the average of elements on the diagonal. All those
+         * elements should have the same value, but we tolerate slight deviation
+         * (this will be verified later).
+         */
+        final DoubleDouble S = new DoubleDouble(getNumber(matrix, 0,0));
+        S.add(getNumber(matrix, 1,1));
+        S.add(getNumber(matrix, 2,2));
+        S.divide(3, 0);
+        /*
+         * Computes: RS = S * toRadians(1″)
+         *           dS = (S-1) * PPM
+         */
+        final DoubleDouble RS = DoubleDouble.createSecondsToRadians();
+        RS.multiply(S);
+        S.add(-1, 0);
+        S.multiply(PPM, 0);
+        dS = S.value;
+        /*
+         * Rotation terms. Each rotation terms appear twice, with one value being the negative
of the other value.
+         * We verify this skew symmetric aspect in the loop. We also opportunistically verify
that the scale terms
+         * are uniform.
+         */
+        for (int j=0; j < SIZE-1; j++) {
+            if (!(abs((matrix.getElement(j,j) - 1)*PPM - dS) <= tolerance)) {
+                throw new IllegalArgumentException(Errors.format(Errors.Keys.NonUniformScale));
+            }
+            for (int i = j+1; i < SIZE-1; i++) {
+                S.setFrom(RS);
+                S.inverseDivide(getNumber(matrix, j,i)); // Negative rotation term.
+                double value = S.value;
+                double error = S.error;
+                S.setFrom(RS);
+                S.inverseDivide(getNumber(matrix, i,j)); // Positive rotation term.
+                if (!(abs(value + S.value) <= tolerance)) { // We expect r1 ≈ -r2
+                    throw new IllegalArgumentException(Errors.format(Errors.Keys.NotASkewSymmetricMatrix));
+                }
+                S.subtract(value, error);
+                S.multiply(0.5, 0);
+                value = S.value; // Average of the two rotation terms.
+                switch (j*SIZE + i) {
+                    case 1: rZ =  value; break;
+                    case 2: rY = -value; break;
+                    case 6: rX =  value; break;
+                }
+            }
+        }
+    }
+
+    /**
      * Returns the region or timeframe in which a coordinate transformation based on those
Bursa-Wolf parameters is
      * valid, or {@code null} if unspecified. If an extent was specified at {@linkplain #BursaWolfParameters(double,
      * double, double, double, double, double, double, GeodeticDatum, Extent) construction
time}, then that extent
@@ -522,6 +496,21 @@ public class BursaWolfParameters extends
     }
 
     /**
+     * Returns a copy of this object.
+     *
+     * @return A copy of all parameters.
+     */
+    @Override
+    public BursaWolfParameters clone() {
+        try {
+            return (BursaWolfParameters) super.clone();
+        }  catch (CloneNotSupportedException exception) {
+            // Should not happen, since we are cloneable.
+            throw new AssertionError(exception);
+        }
+    }
+
+    /**
      * Compares the specified object with this object for equality.
      *
      * @param object The object to compare with the parameters.

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultGeodeticDatum.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultGeodeticDatum.java?rev=1541022&r1=1541021&r2=1541022&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultGeodeticDatum.java
[UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultGeodeticDatum.java
[UTF-8] Tue Nov 12 12:07:32 2013
@@ -41,6 +41,7 @@ import org.apache.sis.io.wkt.Formatter;
 
 import static org.apache.sis.util.Utilities.deepEquals;
 import static org.apache.sis.util.ArgumentChecks.ensureNonNull;
+import static org.apache.sis.util.ArgumentChecks.ensureNonNullElement;
 
 // Related to JDK7
 import java.util.Objects;
@@ -184,6 +185,13 @@ public class DefaultGeodeticDatum extend
         this.primeMeridian = primeMeridian;
         bursaWolf = CollectionsExt.nonEmpty(CollectionsExt.nonNullArraySet(
                 BURSA_WOLF_KEY, properties.get(BURSA_WOLF_KEY), EMPTY_ARRAY));
+        for (int i=0; i<bursaWolf.length; i++) {
+            BursaWolfParameters param = bursaWolf[i];
+            ensureNonNullElement("bursaWolf", i, param);
+            param = param.clone();
+            param.verify();
+            bursaWolf[i] = param;
+        }
     }
 
     /**
@@ -247,7 +255,14 @@ public class DefaultGeodeticDatum extend
      * @return The Bursa-Wolf parameters, or an empty array if none.
      */
     public BursaWolfParameters[] getBursaWolfParameters() {
-        return (bursaWolf != null) ? bursaWolf.clone() : EMPTY_ARRAY;
+        if (bursaWolf == null) {
+            return null;
+        }
+        final BursaWolfParameters[] copy = bursaWolf.clone();
+        for (int i=0; i<copy.length; i++) {
+            copy[i] = copy[i].clone();
+        }
+        return copy;
     }
 
     /**

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=1541022&r1=1541021&r2=1541022&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] Tue Nov 12 12:07:32 2013
@@ -47,7 +47,16 @@ public final strictfp class BursaWolfPar
      * Returns the parameters for the <cite>ED87 to WGS 84</cite> transformation
(EPSG:1146).
      */
     private static BursaWolfParameters createForNorthSea() {
-        return new BursaWolfParameters(-82.981, -99.719, -110.709, -0.5076, 0.1503, 0.3898,
-0.3143, null, null);
+        final BursaWolfParameters bursaWolf = new BursaWolfParameters(null, null);
+        bursaWolf.tX =  -82.981;
+        bursaWolf.tY =  -99.719;
+        bursaWolf.tZ = -110.709;
+        bursaWolf.rX =   -0.5076;
+        bursaWolf.rY =    0.1503;
+        bursaWolf.rZ =    0.3898;
+        bursaWolf.dS =   -0.3143;
+        bursaWolf.verify();
+        return bursaWolf;
     }
 
     /**
@@ -77,7 +86,10 @@ public final strictfp class BursaWolfPar
      */
     @Test
     public void testGetPositionVectorTransformation() throws NoninvertibleMatrixException
{
-        final BursaWolfParameters bursaWolf = new BursaWolfParameters(0, 0, 4.5, 0, 0, 0.554,
0.219, null, null);
+        final BursaWolfParameters bursaWolf = new BursaWolfParameters(null, null);
+        bursaWolf.tZ = 4.5;
+        bursaWolf.rZ = 0.554;
+        bursaWolf.dS = 0.219;
         final MatrixSIS toWGS84 = getPositionVectorTransformation(bursaWolf);
         final MatrixSIS toWGS72 = getPositionVectorTransformation(bursaWolf).inverse();
         final MatrixSIS source  = Matrices.create(4, 1, new double[] {3657660.66, 255768.55,
5201382.11, 1});
@@ -104,14 +116,16 @@ public final strictfp class BursaWolfPar
     }
 
     /**
-     * Tests the {@link BursaWolfParameters#BursaWolfParameters(Matrix, double, GeodeticDatum,
Extent)} constructor.
+     * Tests the {@link BursaWolfParameters#setPositionVectorTransformation(Matrix, double)}
constructor.
+     * This is an internal consistency test.
      */
     @Test
     @DependsOnMethod("testGetPositionVectorTransformation")
-    public void testCreateFromPositionVectorTransformation() {
+    public void testSetPositionVectorTransformation() {
         final BursaWolfParameters bursaWolf = createForNorthSea();
         final Matrix matrix = bursaWolf.getPositionVectorTransformation(null);
-        final BursaWolfParameters actual = new BursaWolfParameters(matrix, 1E-10, null, null);
+        final BursaWolfParameters actual = new BursaWolfParameters(null, null);
+        actual.setPositionVectorTransformation(matrix, 1E-10);
         assertEquals(bursaWolf, actual);
     }
 



Mime
View raw message