sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1737101 [4/7] - in /sis/branches/JDK6: ./ application/sis-console/src/main/artifact/conf/ core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/ core/sis-meta...
Date Wed, 30 Mar 2016 11:25:07 GMT
Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrices.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrices.java?rev=1737101&r1=1737100&r2=1737101&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrices.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrices.java [UTF-8] Wed Mar 30 11:25:06 2016
@@ -69,7 +69,7 @@ import org.apache.sis.internal.jdk7.Obje
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.4
- * @version 0.6
+ * @version 0.7
  * @module
  *
  * @see org.apache.sis.parameter.TensorParameters
@@ -736,7 +736,7 @@ public final class Matrices extends Stat
      */
     public static MatrixSIS multiply(final Matrix m1, final Matrix m2) throws MismatchedMatrixSizeException {
         if (m1 instanceof MatrixSIS) {
-            return ((MatrixSIS) m1).multiply(m2);  // Maybe the subclass override that method.
+            return ((MatrixSIS) m1).multiply(m2);           // Maybe the subclass overrides that method.
         }
         final int nc = m2.getNumCol();
         MatrixSIS.ensureNumRowMatch(m1.getNumCol(), m2.getNumRow(), nc);
@@ -777,7 +777,6 @@ public final class Matrices extends Stat
      * @return {@code true} if the matrix represents an affine transform.
      *
      * @see MatrixSIS#isAffine()
-     * @see AffineTransforms2D#castOrCopy(Matrix)
      */
     public static boolean isAffine(final Matrix matrix) {
         if (matrix instanceof MatrixSIS) {
@@ -788,6 +787,32 @@ public final class Matrices extends Stat
     }
 
     /**
+     * Returns {@code true} if the given matrix represents a translation.
+     * This method returns {@code true} if the given matrix {@linkplain #isAffine(Matrix) is affine}
+     * and differs from the identity matrix only in the last column.
+     *
+     * @param matrix The matrix to test.
+     * @return {@code true} if the matrix represents a translation.
+     *
+     * @since 0.7
+     */
+    public static boolean isTranslation(final Matrix matrix) {
+        if (!isAffine(matrix)) {
+            return false;
+        }
+        final int numRow = matrix.getNumRow() - 1;      // Excluding translation column.
+        final int numCol = matrix.getNumCol() - 1;      // Excluding last row in affine transform.
+        for (int j=0; j<numRow; j++) {
+            for (int i=0; i<numCol; i++) {
+                if (matrix.getElement(j,i) != ((i == j) ? 1 : 0)) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    /**
      * Returns {@code true} if the given matrix is close to an identity matrix, given a tolerance threshold.
      * This method is equivalent to computing the difference between the given matrix and an identity matrix
      * of identical size, and returning {@code true} if and only if all differences are smaller than or equal

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/NonSquareMatrix.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/NonSquareMatrix.java?rev=1737101&r1=1737100&r2=1737101&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/NonSquareMatrix.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/NonSquareMatrix.java [UTF-8] Wed Mar 30 11:25:06 2016
@@ -227,28 +227,39 @@ next:   do {
     }
 
     /**
-     * Inverse a matrix for a transform where target points has more ordinates than source points.
+     * Inverses a matrix for a transform where target points has more ordinates than source points.
      * In other words, the target matrices will be a transform that discard some ordinate values.
      * We will discard the ones for which the row contains only 0 or NaN elements.
+     *
+     * <p>In the special case where the last row is of the form [0 0 … 0 1] as in affine transforms,
+     * this method also omits rows that contain only a translation term. We allow that because if we
+     * do not omit those rows, then the matrix will be non-invertible anyway. This is true only when
+     * the last row contains only zero except in the last column ([0 0 … 0 n] where <var>n</var> can
+     * be any value). We restrict <var>n</var> to 1 for now because a different value may indicate a
+     * matrix created for another purpose than coordinate conversions.</p>
      */
     private MatrixSIS inverseDimensionIncrease() throws NoninvertibleMatrixException {
-        final int numRow = this.numRow; // Protection against accidental changes.
+        final int numRow = this.numRow;                     // Protection against accidental changes.
         final int numCol = this.numCol;
         int j  = numRow;
-        int oi = numRow - numCol; // Initialized to the maximal amount of rows that we may discard.
+        int oi = numRow - numCol;   // Initialized to the maximal amount of rows that we may discard.
         final int[] omitted = new int[oi];
+        final boolean ignoreTranslation = isAffine(false);
+        if (ignoreTranslation) j--;                         // Last row already verified by isAffine().
 next:   do {
             if (--j < 0) {
-                throw nonInvertible(); // Not enough rows that we can omit.
+                throw nonInvertible();                      // Not enough rows that we can omit.
             }
             final int offset = j * numCol;
-            for (int i=offset + numCol; --i >= offset;) {
+            int i = offset + numCol;
+            if (ignoreTranslation) i--;
+            while (--i >= offset) {
                 final double element = elements[i];
                 if (element != 0 && !Double.isNaN(element)) {
                     continue next;
                 }
             }
-            omitted[--oi] = j; // Found a row which contains only 0 or NaN elements.
+            omitted[--oi] = j;                  // Found a row which contains only 0 or NaN elements.
         } while (oi != 0);
         /*
          * Found enough rows containing only zero elements. Create a square matrix omitting those rows,
@@ -258,7 +269,7 @@ next:   do {
         int i = 0;
         for (j=0; j<numRow; j++) {
             if (oi != omitted.length && j == omitted[oi]) oi++;
-            else copyRow(this, j, squareMatrix, i++); // Copy only if not skipped.
+            else copyRow(this, j, squareMatrix, i++);                   // Copy only if not skipped.
         }
         if (indexOfErrors(numRow, numCol, elements) == 0) {
             inferErrors(squareMatrix.elements);
@@ -329,6 +340,7 @@ next:   do {
      * {@inheritDoc}
      */
     @Override
+    @SuppressWarnings("CloneDoesntCallSuperClone")
     public MatrixSIS clone() {
         return new NonSquareMatrix(this);
     }

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Solver.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Solver.java?rev=1737101&r1=1737100&r2=1737101&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Solver.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Solver.java [UTF-8] Wed Mar 30 11:25:06 2016
@@ -38,7 +38,7 @@ import org.apache.sis.util.ArraysExt;
  * @module
  */
 @SuppressWarnings("CloneInNonCloneableClass")
-final class Solver implements Matrix { // Not Cloneable, despite the clone() method.
+final class Solver implements Matrix {                          // Not Cloneable, despite the clone() method.
     /**
      * The size of the (i, j, s) tuples used internally by {@link #solve(Matrix, Matrix, double[], int, int)}
      * for storing information about the NaN values.
@@ -143,7 +143,7 @@ final class Solver implements Matrix { /
         if (Y instanceof GeneralMatrix) {
             eltY = ((GeneralMatrix) Y).elements;
             if (eltY.length == size * innerSize) {
-                eltY = null; // Matrix does not contains error terms.
+                eltY = null;                            // Matrix does not contains error terms.
             }
         }
         return solve(X, Y, eltY, size, innerSize, true);
@@ -248,7 +248,7 @@ searchNaN:  for (int flatIndex = (size -
                     }
                     indexOfNaN[indexCount++] = i;
                     indexOfNaN[indexCount++] = j;
-                    indexOfNaN[indexCount++] = columnOfScale; // May be -1 (while uncommon)
+                    indexOfNaN[indexCount++] = columnOfScale;                   // May be -1 (while uncommon)
                     assert (indexCount % TUPLE_SIZE) == 0;
                 }
             }
@@ -262,7 +262,7 @@ searchNaN:  for (int flatIndex = (size -
                 final int j = indexOfNaN[k+1];
                 final int flatIndex = j*size + i;
                 LU[flatIndex] = (i == lastRowOrColumn) ? 0 : 1;
-                LU[flatIndex + size*size] = 0; // Error term (see 'errorLU') in next method.
+                LU[flatIndex + size*size] = 0;                      // Error term (see 'errorLU') in next method.
             }
         }
         /*
@@ -280,9 +280,9 @@ searchNaN:  for (int flatIndex = (size -
             final int s = indexOfNaN[k++];
             if (i != lastRowOrColumn) {
                 // Found a scale factor to set to NaN.
-                matrix.setElement(i, j, Double.NaN); // Note that i,j indices are interchanged.
+                matrix.setElement(i, j, Double.NaN);                      // Note that i,j indices are interchanged.
                 if (matrix.getElement(i, lastRowOrColumn) != 0) {
-                    matrix.setElement(i, lastRowOrColumn, Double.NaN); // = -offset/scale, so 0 stay 0.
+                    matrix.setElement(i, lastRowOrColumn, Double.NaN);    // = -offset/scale, so 0 stay 0.
                 }
             } else if (s >= 0) {
                 // Found a translation factory to set to NaN.
@@ -323,17 +323,17 @@ searchNaN:  for (int flatIndex = (size -
         for (int j=0; j<size; j++) {
            pivot[j] = j;
         }
-        final double[]  column = new double[size * 2]; // [0 … size-1] : column values; [size … 2*size-1] : error terms.
-        final DoubleDouble acc = new DoubleDouble();   // Temporary variable for sum ("accumulator") and subtraction.
-        final DoubleDouble rat = new DoubleDouble();   // Temporary variable for products and ratios.
+        final double[]  column = new double[size * 2];  // [0 … size-1] : column values; [size … 2*size-1] : error terms.
+        final DoubleDouble acc = new DoubleDouble();    // Temporary variable for sum ("accumulator") and subtraction.
+        final DoubleDouble rat = new DoubleDouble();    // Temporary variable for products and ratios.
         for (int i=0; i<size; i++) {
             /*
              * Make a copy of the i-th column.
              */
             for (int j=0; j<size; j++) {
                 final int k = j*size + i;
-                column[j]        = LU[k];            // Value
-                column[j + size] = LU[k + errorLU];  // Error
+                column[j]        = LU[k];               // Value
+                column[j + size] = LU[k + errorLU];     // Error
             }
             /*
              * Apply previous transformations. This part is equivalent to the following code,
@@ -372,7 +372,7 @@ searchNaN:  for (int flatIndex = (size -
             if (p != i) {
                 final int pRow = p*size;
                 final int iRow = i*size;
-                for (int k=0; k<size; k++) { // Swap two full rows.
+                for (int k=0; k<size; k++) {                                // Swap two full rows.
                     DoubleDouble.swap(LU, pRow + k, iRow + k, errorLU);
                 }
                 ArraysExt.swap(pivot, p, i);
@@ -435,10 +435,10 @@ searchNaN:  for (int flatIndex = (size -
          *     elements[loRowOffset + i] -= (elements[rowOffset + i] * LU[luRowOffset + k]);
          */
         for (int k=0; k<size; k++) {
-            final int rowOffset = k*innerSize;          // Offset of row computed by current iteration.
+            final int rowOffset = k*innerSize;              // Offset of row computed by current iteration.
             for (int j=k; ++j < size;) {
-                final int loRowOffset = j*innerSize;    // Offset of some row after the current row.
-                final int luRowOffset = j*size;         // Offset of the corresponding row in the LU matrix.
+                final int loRowOffset = j*innerSize;        // Offset of some row after the current row.
+                final int luRowOffset = j*size;             // Offset of the corresponding row in the LU matrix.
                 for (int i=0; i<innerSize; i++) {
                     acc.setFrom (elements, loRowOffset + i, errorOffset);
                     rat.setFrom (elements, rowOffset   + i, errorOffset);

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/UnmodifiableMatrix.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/UnmodifiableMatrix.java?rev=1737101&r1=1737100&r2=1737101&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/UnmodifiableMatrix.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/UnmodifiableMatrix.java [UTF-8] Wed Mar 30 11:25:06 2016
@@ -17,6 +17,7 @@
 package org.apache.sis.referencing.operation.matrix;
 
 import org.opengis.referencing.operation.Matrix;
+import org.apache.sis.internal.referencing.ExtendedPrecisionMatrix;
 import org.apache.sis.util.resources.Errors;
 
 
@@ -26,10 +27,10 @@ import org.apache.sis.util.resources.Err
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.6
- * @version 0.6
+ * @version 0.7
  * @module
  */
-final class UnmodifiableMatrix extends MatrixSIS {
+final class UnmodifiableMatrix extends MatrixSIS implements ExtendedPrecisionMatrix {
     /**
      * For cross-version compatibility.
      */
@@ -91,6 +92,18 @@ final class UnmodifiableMatrix extends M
         }
     }
 
+    /**
+     * Returns elements together with their error terms if available, or just the elements otherwise.
+     */
+    @Override
+    public double[] getExtendedElements() {
+        if (matrix instanceof ExtendedPrecisionMatrix) {
+            return ((ExtendedPrecisionMatrix) matrix).getExtendedElements();
+        } else {
+            return getElements();
+        }
+    }
+
     /**
      * Returns the exception to throw when a setter method is invoked.
      */

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/package-info.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/package-info.java?rev=1737101&r1=1737100&r2=1737101&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/package-info.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/package-info.java [UTF-8] Wed Mar 30 11:25:06 2016
@@ -53,6 +53,43 @@
  *     for converting the longitude axis of source and target CRS to degrees before this operation is applied.</li>
  * </ul>
  *
+ * <div class="section"><cite>Early binding</cite> versus <cite>late binding</cite> implementations</div>
+ * There is sometime multiple ways of transforming coordinates for a given pair of source and target CRS.
+ * For example the {@linkplain org.apache.sis.referencing.datum.BursaWolfParameters Bursa-Wolf parameters}
+ * may vary depending on the area of interest, like in the transformations from NAD27 to NAD83.
+ * Even for a fixed set of Bursa-Wolf parameter, there is various ways to use them (<cite>Molodensky</cite>,
+ * <cite>Abridged Molodensky</cite>, <cite>Geocentric translation</cite>, <cite>etc.</cite>).
+ *
+ * <p>EPSG identifies two approaches for addressing this multiplicity problem.
+ * Quoting the GIGS guideline:</p>
+ *
+ * <blockquote>
+ * <ul class="verbose">
+ *   <li><b>Early binding:</b>
+ *     A priori association of a coordinate transformation with a geodetic CRS.
+ *     The association is usually made at start-up of the session or project, as that is defined in the software,
+ *     but always before any data is associated with the ‘CRS’. In general the ‘coordinate transformation’ specified
+ *     uses the ‘CRS’ of the data as the source ‘CRS’ and WGS 84 as the target ‘CRS’.</li>
+ *
+ *   <li><b>Late binding:</b>
+ *     Association at run time of a coordinate transformation with a CRS.
+ *     Late binding allows the user to select the appropriate transformation upon import of ‘geospatial data’
+ *     or merge of two geospatial datasets. This means that, in cases where there are multiple existing transformations,
+ *     the user can choose the appropriate one, possibly aided by additional information.</li>
+ * </ul>
+ * <p style="text-align:right; font-size:small"><b>Source:</b>
+ * <u>Geospatial Integrity of Geoscience Software Part 1 – GIGS guidelines.</u>
+ * <i>OGP publication, Report No. 430-1, September 2011</i></p>
+ * </blockquote>
+ *
+ * Apache SIS is a <cite>late binding</cite> implementation, while a little trace for <cite>early binding</cite>
+ * exists in the form of the {@link org.apache.sis.referencing.datum.DefaultGeodeticDatum#getBursaWolfParameters()}
+ * method for those who really need it. This means that when searching for a coordinate operation between a given
+ * pair of CRS, Apache SIS will query {@link org.apache.sis.referencing.factory.sql.EPSGFactory} before to try to
+ * {@linkplain org.apache.sis.referencing.operation.CoordinateOperationInference infer the operation path by itelf}.
+ * The {@link org.apache.sis.referencing.operation.CoordinateOperationContext} can be used for further refinements,
+ * for example by specifying the area of interest.
+ *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @version 0.7
  * @since   0.6

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform.java?rev=1737101&r1=1737100&r2=1737101&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform.java [UTF-8] Wed Mar 30 11:25:06 2016
@@ -251,6 +251,8 @@ public abstract class AbstractMathTransf
      *   <li>Delegates to the {@link #transform(double[], int, double[], int, boolean)} method.</li>
      * </ul>
      *
+     * This method does not update the associated {@link org.opengis.referencing.crs.CoordinateReferenceSystem} value.
+     *
      * @param  ptSrc the coordinate point to be transformed.
      * @param  ptDst the coordinate point that stores the result of transforming {@code ptSrc}, or {@code null}.
      * @return the coordinate point after transforming {@code ptSrc} and storing the result in {@code ptDst},

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConcatenatedTransform.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConcatenatedTransform.java?rev=1737101&r1=1737100&r2=1737101&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConcatenatedTransform.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConcatenatedTransform.java [UTF-8] Wed Mar 30 11:25:06 2016
@@ -316,8 +316,7 @@ class ConcatenatedTransform extends Abst
             }
         }
         /*
-         * If one transform is the inverse of the
-         * other, returns the identity transform.
+         * If one transform is the inverse of the other, return the identity transform.
          */
         if (areInverse(tr1, tr2) || areInverse(tr2, tr1)) {
             assert tr1.getSourceDimensions() == tr2.getTargetDimensions();
@@ -325,7 +324,7 @@ class ConcatenatedTransform extends Abst
             return MathTransforms.identity(tr1.getSourceDimensions());          // Returns a cached instance.
         }
         /*
-         * Gives a chance to AbstractMathTransform to returns an optimized object.
+         * Give a chance to AbstractMathTransform to returns an optimized object.
          * The main use case is Logarithmic vs Exponential transforms.
          */
         if (tr1 instanceof AbstractMathTransform) {
@@ -348,17 +347,17 @@ class ConcatenatedTransform extends Abst
      * Returns a name for the specified math transform.
      */
     private static String getName(final MathTransform transform) {
+        ParameterValueGroup params = null;
         if (transform instanceof AbstractMathTransform) {
-            ParameterValueGroup params;
             params = ((AbstractMathTransform) transform).getContextualParameters();
-            if (params == null) {
-                params = ((AbstractMathTransform) transform).getParameterValues();
-                if (params != null) {
-                    String name = params.getDescriptor().getName().getCode();
-                    if (name != null && !(name = name.trim()).isEmpty()) {
-                        return name;
-                    }
-                }
+        }
+        if (params == null && (transform instanceof Parameterized)) {
+            params = ((Parameterized) transform).getParameterValues();
+        }
+        if (params != null) {
+            String name = params.getDescriptor().getName().getCode();
+            if (name != null && !(name = name.trim()).isEmpty()) {
+                return name;
             }
         }
         return Classes.getShortClassName(transform);

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ContextualParameters.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ContextualParameters.java?rev=1737101&r1=1737100&r2=1737101&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ContextualParameters.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ContextualParameters.java [UTF-8] Wed Mar 30 11:25:06 2016
@@ -462,7 +462,7 @@ public class ContextualParameters extend
             offset = new DoubleDouble(-λ0);
             offset.multiply(toRadians);
         }
-        final MatrixSIS normalize = (MatrixSIS) this.normalize;  // Must be the same instance, not a copy.
+        final MatrixSIS normalize = (MatrixSIS) this.normalize;         // Must be the same instance, not a copy.
         normalize.convertBefore(0, toRadians, offset);
         normalize.convertBefore(1, toRadians, null);
         return normalize;
@@ -487,7 +487,7 @@ public class ContextualParameters extend
     public synchronized MatrixSIS denormalizeGeographicOutputs(final double λ0) {
         ensureModifiable();
         final DoubleDouble toDegrees = DoubleDouble.createRadiansToDegrees();
-        final MatrixSIS denormalize = (MatrixSIS) this.denormalize;  // Must be the same instance, not a copy.
+        final MatrixSIS denormalize = (MatrixSIS) this.denormalize;         // Must be the same instance, not a copy.
         denormalize.convertAfter(0, toDegrees, (λ0 != 0) ? λ0 : null);
         denormalize.convertAfter(1, toDegrees, null);
         return denormalize;
@@ -552,7 +552,7 @@ public class ContextualParameters extend
                 new IdentityHashMap<ParameterDescriptor<?>, ParameterValue<?>>(values.length);
         for (ParameterValue<?> p : values) {
             if (p == null) {
-                break;  // The first null value in the array indicates the end of sequence.
+                break;                      // The first null value in the array indicates the end of sequence.
             }
             p = DefaultParameterValue.unmodifiable(p);
             final ParameterDescriptor<?> desc = p.getDescriptor();

Copied: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CoordinateSystemTransform.java (from r1737089, sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CoordinateSystemTransform.java)
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CoordinateSystemTransform.java?p2=sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CoordinateSystemTransform.java&p1=sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CoordinateSystemTransform.java&r1=1737089&r2=1737101&rev=1737101&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CoordinateSystemTransform.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CoordinateSystemTransform.java [UTF-8] Wed Mar 30 11:25:06 2016
@@ -204,7 +204,9 @@ abstract class CoordinateSystemTransform
                 return factory.createConcatenatedTransform(before,
                        factory.createConcatenatedTransform(tr, after));
             }
-        } catch (IllegalArgumentException | ConversionException e) {
+        } catch (IllegalArgumentException e) {
+            cause = e;
+        } catch (ConversionException e) {
             cause = e;
         }
         throw new OperationNotFoundException(Errors.format(Errors.Keys.CoordinateOperationNotFound_2,

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java?rev=1737101&r1=1737100&r2=1737101&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java [UTF-8] Wed Mar 30 11:25:06 2016
@@ -26,6 +26,8 @@ import java.util.concurrent.atomic.Atomi
 import java.util.logging.Level;
 import java.util.logging.LogRecord;
 import java.lang.reflect.Constructor;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.io.Serializable;
 import javax.measure.quantity.Length;
 import javax.measure.unit.SI;
@@ -451,13 +453,18 @@ public class DefaultMathTransformFactory
      * {@link DefaultMathTransformFactory} uses this information for:
      *
      * <ul>
-     *   <li>Complete some parameters if they were not provided. In particular, the {@linkplain #getSourceEllipsoid()
+     *   <li>Completing some parameters if they were not provided. In particular, the {@linkplain #getSourceEllipsoid()
      *       source ellipsoid} can be used for providing values for the {@code "semi_major"} and {@code "semi_minor"}
      *       parameters in map projections.</li>
-     *   <li>{@linkplain CoordinateSystems#swapAndScaleAxes Swap and scale axes} if the source or the target
+     *   <li>{@linkplain CoordinateSystems#swapAndScaleAxes Swapping and scaling axes} if the source or the target
      *       coordinate systems are not {@linkplain AxesConvention#NORMALIZED normalized}.</li>
      * </ul>
      *
+     * By default this class does <strong>not</strong> handle change of
+     * {@linkplain org.apache.sis.referencing.datum.DefaultGeodeticDatum#getPrimeMeridian() prime meridian}
+     * or anything else related to datum. Datum changes have dedicated {@link OperationMethod},
+     * for example <cite>"Longitude rotation"</cite> (EPSG:9601) for changing the prime meridian.
+     *
      * @author  Martin Desruisseaux (Geomatys)
      * @version 0.7
      * @since   0.7
@@ -503,17 +510,6 @@ public class DefaultMathTransformFactory
         }
 
         /**
-         * Sets the source ellipsoid to the given value.
-         * The source coordinate system is unconditionally set to {@code null}.
-         *
-         * @param ellipsoid The ellipsoid to set as the source (can be {@code null}).
-         */
-        public void setSource(final Ellipsoid ellipsoid) {
-            sourceEllipsoid = ellipsoid;
-            sourceCS = null;
-        }
-
-        /**
          * Sets the source coordinate system to the given value.
          * The source ellipsoid is unconditionally set to {@code null}.
          *
@@ -525,26 +521,23 @@ public class DefaultMathTransformFactory
         }
 
         /**
-         * Sets the source ellipsoid and coordinate system to values inferred from the given CRS.
-         * The source ellipsoid will be non-null only if the given CRS is geographic (not geocentric).
+         * Sets the source coordinate system and its associated ellipsoid to the given value.
          *
-         * @param crs The source coordinate reference system (can be {@code null}).
-         */
-        public void setSource(final CoordinateReferenceSystem crs) {
-            sourceCS = (crs != null) ? crs.getCoordinateSystem() : null;
-            sourceEllipsoid = ReferencingUtilities.getEllipsoidOfGeographicCRS(crs);
-            // Ellipsoid is intentionally null for GeocentricCRS.
-        }
-
-        /**
-         * Sets the target ellipsoid to the given value.
-         * The target coordinate system is unconditionally set to {@code null}.
+         * <div class="note"><b>Design note:</b>
+         * ellipsoidal coordinate systems and ellipsoids are associated indirectly, through a geodetic CRS.
+         * However this method expects those two components to be given explicitely instead than inferring
+         * them from a {@code CoordinateReferenceSystem} for making clear that {@code MathTransformFactory}
+         * does not perform any {@linkplain org.apache.sis.referencing.datum.DefaultGeodeticDatum geodetic
+         * datum} analysis. For coordinate operations that take datum changes in account (including change
+         * of prime meridian), see {@link org.apache.sis.referencing.operation.DefaultCoordinateOperationFactory}.
+         * This policy helps to enforce a separation of concerns.</div>
          *
-         * @param ellipsoid The ellipsoid to set as the target (can be {@code null}).
+         * @param cs The coordinate system to set as the source, or {@code null}.
+         * @param ellipsoid The ellipsoid associated to the given coordinate system, or {@code null}.
          */
-        public void setTarget(final Ellipsoid ellipsoid) {
-            targetEllipsoid = ellipsoid;
-            targetCS = null;
+        public void setSource(final EllipsoidalCS cs, final Ellipsoid ellipsoid) {
+            sourceCS = cs;
+            sourceEllipsoid = ellipsoid;
         }
 
         /**
@@ -559,15 +552,17 @@ public class DefaultMathTransformFactory
         }
 
         /**
-         * Sets the target ellipsoid and coordinate system to values inferred from the given CRS.
-         * The target ellipsoid will be non-null only if the given CRS is geographic (not geocentric).
+         * Sets the target coordinate system and its associated ellipsoid to the given value.
+         *
+         * <div class="note"><b>Design note:</b>
+         * see {@link #setSource(EllipsoidalCS, Ellipsoid)}.</div>
          *
-         * @param crs The target coordinate reference system (can be {@code null}).
+         * @param cs The coordinate system to set as the source, or {@code null}.
+         * @param ellipsoid The ellipsoid associated to the given coordinate system, or {@code null}.
          */
-        public void setTarget(final CoordinateReferenceSystem crs) {
-            targetCS = (crs != null) ? crs.getCoordinateSystem() : null;
-            targetEllipsoid = ReferencingUtilities.getEllipsoidOfGeographicCRS(crs);
-            // Ellipsoid is intentionally null for GeocentricCRS.
+        public void setTarget(final EllipsoidalCS cs, final Ellipsoid ellipsoid) {
+            targetCS = cs;
+            targetEllipsoid = ellipsoid;
         }
 
         /**
@@ -609,6 +604,68 @@ public class DefaultMathTransformFactory
         }
 
         /**
+         * Returns the matrix that represent the affine transform to concatenate before or after
+         * the parameterized transform. The {@code role} argument specifies which matrix is desired:
+         *
+         * <ul class="verbose">
+         *   <li>{@link org.apache.sis.referencing.operation.transform.ContextualParameters.MatrixRole#NORMALIZATION
+         *       NORMALIZATION} for the conversion from the {@linkplain #getSourceCS() source coordinate system} to
+         *       a {@linkplain AxesConvention#NORMALIZED normalized} coordinate system, usually with
+         *       (<var>longitude</var>, <var>latitude</var>) axis order in degrees or
+         *       (<var>easting</var>, <var>northing</var>) in metres.
+         *       This normalization needs to be applied <em>before</em> the parameterized transform.</li>
+         *
+         *   <li>{@link org.apache.sis.referencing.operation.transform.ContextualParameters.MatrixRole#DENORMALIZATION
+         *       DENORMALIZATION} for the conversion from a normalized coordinate system to the
+         *       {@linkplain #getTargetCS() target coordinate system}, for example with
+         *       (<var>latitude</var>, <var>longitude</var>) axis order.
+         *       This denormalization needs to be applied <em>after</em> the parameterized transform.</li>
+         *
+         *   <li>{@link org.apache.sis.referencing.operation.transform.ContextualParameters.MatrixRole#INVERSE_NORMALIZATION INVERSE_NORMALIZATION} and
+         *       {@link org.apache.sis.referencing.operation.transform.ContextualParameters.MatrixRole#INVERSE_DENORMALIZATION INVERSE_DENORMALIZATION}
+         *       are also supported but rarely used.</li>
+         * </ul>
+         *
+         * This method is invoked by {@link DefaultMathTransformFactory#swapAndScaleAxes(MathTransform, Context)}.
+         * Users an override this method if they need to customize the normalization process.
+         *
+         * @param  role Whether the normalization or denormalization matrix is desired.
+         * @return The requested matrix, or {@code null} if this {@code Context} has no information about the coordinate system.
+         * @throws FactoryException if an error occurred while computing the matrix.
+         *
+         * @see DefaultMathTransformFactory#createAffineTransform(Matrix)
+         * @see DefaultMathTransformFactory#createParameterizedTransform(ParameterValueGroup, Context)
+         */
+        @SuppressWarnings("fallthrough")
+        public Matrix getMatrix(final ContextualParameters.MatrixRole role) throws FactoryException {
+            final CoordinateSystem specified;
+            boolean inverse = false;
+            switch (role) {
+                default: throw new IllegalArgumentException(Errors.format(Errors.Keys.IllegalArgumentValue_2, "role", role));
+                case INVERSE_NORMALIZATION:   inverse   = true;          // Fall through
+                case NORMALIZATION:           specified = getSourceCS(); break;
+                case INVERSE_DENORMALIZATION: inverse   = true;          // Fall through
+                case DENORMALIZATION:         inverse   = !inverse;
+                                              specified = getTargetCS(); break;
+            }
+            if (specified == null) {
+                return null;
+            }
+            final CoordinateSystem normalized = CoordinateSystems.replaceAxes(specified, AxesConvention.NORMALIZED);
+            try {
+                if (inverse) {
+                    return CoordinateSystems.swapAndScaleAxes(normalized, specified);
+                } else {
+                    return CoordinateSystems.swapAndScaleAxes(specified, normalized);
+                }
+            } catch (IllegalArgumentException cause) {
+                throw new InvalidGeodeticParameterException(cause.getLocalizedMessage(), cause);
+            } catch (ConversionException cause) {
+                throw new InvalidGeodeticParameterException(cause.getLocalizedMessage(), cause);
+            }
+        }
+
+        /**
          * Returns the parameter values used for the math transform creation, including the parameters completed
          * by the factory.
          *
@@ -968,7 +1025,7 @@ public class DefaultMathTransformFactory
 
     /**
      * Given a transform between normalized spaces,
-     * create a transform taking in account axis directions and units of measurement.
+     * creates a transform taking in account axis directions, units of measurement and longitude rotation.
      * This method {@linkplain #createConcatenatedTransform concatenates} the given parameterized transform
      * with any other transform required for performing units changes and ordinates swapping.
      *
@@ -984,6 +1041,10 @@ public class DefaultMathTransformFactory
      * both of them with ({@linkplain org.opengis.referencing.cs.AxisDirection#EAST East},
      * {@linkplain org.opengis.referencing.cs.AxisDirection#NORTH North}) axis orientations.</div>
      *
+     * <div class="section">Controlling the normalization process</div>
+     * Users who need a different normalized space than the default one way find more convenient to
+     * override the {@link Context#getMatrix Context.getMatrix(ContextualParameters.MatrixRole)} method.
+     *
      * @param  parameterized A transform for normalized input and output coordinates.
      * @param  context Source and target coordinate systems in which the transform is going to be used.
      * @return A transform taking in account unit conversions and axis swapping.
@@ -991,27 +1052,20 @@ public class DefaultMathTransformFactory
      *
      * @see org.apache.sis.referencing.cs.AxesConvention#NORMALIZED
      * @see org.apache.sis.referencing.operation.DefaultConversion#DefaultConversion(Map, OperationMethod, MathTransform, ParameterValueGroup)
+     *
+     * @since 0.7
      */
     public MathTransform swapAndScaleAxes(final MathTransform parameterized, final Context context) throws FactoryException {
         ArgumentChecks.ensureNonNull("parameterized", parameterized);
         ArgumentChecks.ensureNonNull("context", context);
-        final CoordinateSystem sourceCS = context.getSourceCS();
-        final CoordinateSystem targetCS = context.getTargetCS();
         /*
          * Computes matrix for swapping axis and performing units conversion.
          * There is one matrix to apply before projection on (longitude,latitude)
          * coordinates, and one matrix to apply after projection on (easting,northing)
          * coordinates.
          */
-        final Matrix swap1, swap3;
-        try {
-            swap1 = (sourceCS != null) ? CoordinateSystems.swapAndScaleAxes(sourceCS, CoordinateSystems.replaceAxes(sourceCS, AxesConvention.NORMALIZED)) : null;
-            swap3 = (targetCS != null) ? CoordinateSystems.swapAndScaleAxes(CoordinateSystems.replaceAxes(targetCS, AxesConvention.NORMALIZED), targetCS) : null;
-        } catch (IllegalArgumentException cause) {
-            throw new InvalidGeodeticParameterException(cause.getLocalizedMessage(), cause);
-        } catch (ConversionException cause) {
-            throw new FactoryException(cause);
-        }
+        final Matrix swap1 = context.getMatrix(ContextualParameters.MatrixRole.NORMALIZATION);
+        final Matrix swap3 = context.getMatrix(ContextualParameters.MatrixRole.DENORMALIZATION);
         /*
          * Prepares the concatenation of the matrices computed above and the projection.
          * Note that at this stage, the dimensions between each step may not be compatible.
@@ -1091,8 +1145,7 @@ public class DefaultMathTransformFactory
         ArgumentChecks.ensureNonNull("baseCRS",    baseCRS);
         ArgumentChecks.ensureNonNull("parameters", parameters);
         ArgumentChecks.ensureNonNull("derivedCS",  derivedCS);
-        final Context context = new Context();
-        context.setSource(baseCRS);
+        final Context context = ReferencingUtilities.createTransformContext(baseCRS, null, null);
         context.setTarget(derivedCS);
         return createParameterizedTransform(parameters, context);
     }
@@ -1127,6 +1180,25 @@ public class DefaultMathTransformFactory
     }
 
     /**
+     * Creates a math transform that represent a change of coordinate system.
+     *
+     * @param source the source coordinate system.
+     * @param target the target coordinate system.
+     * @return a conversion from the given source to the given target coordinate system.
+     * @throws FactoryException if the conversion can not be created.
+     *
+     * @since 0.7
+     */
+    public MathTransform createCoordinateSystemChange(final CoordinateSystem source, final CoordinateSystem target)
+            throws FactoryException
+    {
+        ArgumentChecks.ensureNonNull("source", source);
+        ArgumentChecks.ensureNonNull("target", target);
+        return CoordinateSystemTransform.create(this, source, target);
+        // No need to use unique(…) here.
+    }
+
+    /**
      * Creates an affine transform from a matrix. If the transform input dimension is {@code M},
      * and output dimension is {@code N}, then the matrix will have size {@code [N+1][M+1]}. The
      * +1 in the matrix dimensions allows the matrix to do a shift, as well as a rotation. The
@@ -1142,7 +1214,11 @@ public class DefaultMathTransformFactory
      */
     @Override
     public MathTransform createAffineTransform(final Matrix matrix) throws FactoryException {
-        lastMethod.remove(); // To be strict, we should set the ProjectiveTransform provider.
+        /*
+         * Performance note: we could set lastMethod to the "Affine" operation method provider, but we do not
+         * because setting this value is not free (e.g. it depends on matrix size) and it is rarely needed.
+         */
+        lastMethod.remove();
         return unique(MathTransforms.linear(matrix));
     }
 
@@ -1237,7 +1313,7 @@ public class DefaultMathTransformFactory
      *
      * @param  text Math transform encoded in Well-Known Text format.
      * @return The math transform (never {@code null}).
-     * @throws FactoryException if the Well-Known Text can't be parsed,
+     * @throws FactoryException if the Well-Known Text can not be parsed,
      *         or if the math transform creation failed from some other reason.
      */
     @Override
@@ -1249,7 +1325,13 @@ public class DefaultMathTransformFactory
             if (c == null) {
                 c = Class.forName("org.apache.sis.io.wkt.MathTransformParser").asSubclass(Parser.class)
                          .getConstructor(MathTransformFactory.class);
-                c.setAccessible(true);
+                final Constructor<?> cp = c;     // For allowing use in inner class or lambda expression.
+                AccessController.doPrivileged(new PrivilegedAction<Void>() {
+                    @Override public Void run() {
+                        cp.setAccessible(true);
+                        return null;
+                    }
+                });
                 parserConstructor = c;
             }
             p = c.newInstance(this);

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/EllipsoidToCentricTransform.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/EllipsoidToCentricTransform.java?rev=1737101&r1=1737100&r2=1737101&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/EllipsoidToCentricTransform.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/EllipsoidToCentricTransform.java [UTF-8] Wed Mar 30 11:25:06 2016
@@ -46,6 +46,7 @@ import org.apache.sis.internal.referenci
 import org.apache.sis.internal.referencing.provider.GeocentricToGeographic;
 import org.apache.sis.internal.referencing.provider.GeographicToGeocentric;
 import org.apache.sis.internal.referencing.provider.Geographic3Dto2D;
+import org.apache.sis.internal.metadata.ReferencingServices;
 import org.apache.sis.parameter.DefaultParameterDescriptorGroup;
 import org.apache.sis.metadata.iso.ImmutableIdentifier;
 import org.apache.sis.referencing.operation.matrix.Matrix3;
@@ -347,6 +348,19 @@ public class EllipsoidToCentricTransform
             final double semiMajor, final double semiMinor, final Unit<Length> unit,
             final boolean withHeight, final TargetType target) throws FactoryException
     {
+        if (Math.abs(semiMajor - semiMinor) <= semiMajor * (Formulas.LINEAR_TOLERANCE / ReferencingServices.AUTHALIC_RADIUS)) {
+            /*
+             * If semi-major axis length is almost equal to semi-minor axis length, uses spherical equations instead.
+             * We need to add the sphere radius to the elevation before to perform spherical to Cartesian conversion.
+             */
+            final MatrixSIS translate = Matrices.createDiagonal(4, withHeight ? 4 : 3);
+            translate.setElement(2, withHeight ? 3 : 2, semiMajor);
+            if (!withHeight) {
+                translate.setElement(3, 2, 1);
+            }
+            final MathTransform tr = SphericalToCartesian.INSTANCE.completeTransform(factory);
+            return factory.createConcatenatedTransform(factory.createAffineTransform(translate), tr);
+        }
         EllipsoidToCentricTransform tr = new EllipsoidToCentricTransform(semiMajor, semiMinor, unit, withHeight, target);
         return tr.context.completeTransform(factory, tr);
     }
@@ -615,7 +629,7 @@ public class EllipsoidToCentricTransform
     /*
      * NOTE: we do not bother to override the methods expecting a 'float' array because those methods should
      *       be rarely invoked. Since there is usually LinearTransforms before and after this transform, the
-     *       conversion between float and double will be handle by those LinearTransforms.   If nevertheless
+     *       conversion between float and double will be handled by those LinearTransforms.  If nevertheless
      *       this EllipsoidToCentricTransform is at the beginning or the end of a transformation chain,
      *       the methods inherited from the subclass will work (but may be slightly slower).
      */

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/InterpolatedMolodenskyTransform.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/InterpolatedMolodenskyTransform.java?rev=1737101&r1=1737100&r2=1737101&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/InterpolatedMolodenskyTransform.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/InterpolatedMolodenskyTransform.java [UTF-8] Wed Mar 30 11:25:06 2016
@@ -305,7 +305,7 @@ public class InterpolatedMolodenskyTrans
     /*
      * NOTE: we do not bother to override the methods expecting a 'float' array because those methods should
      *       be rarely invoked. Since there is usually LinearTransforms before and after this transform, the
-     *       conversion between float and double will be handle by those LinearTransforms.   If nevertheless
+     *       conversion between float and double will be handled by those LinearTransforms.  If nevertheless
      *       this MolodenskyTransform is at the beginning or the end of a transformation chain,  the methods
      *       inherited from the subclass will work (but may be slightly slower).
      */

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/InterpolatedTransform.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/InterpolatedTransform.java?rev=1737101&r1=1737100&r2=1737101&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/InterpolatedTransform.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/InterpolatedTransform.java [UTF-8] Wed Mar 30 11:25:06 2016
@@ -347,7 +347,7 @@ public class InterpolatedTransform exten
     /*
      * NOTE: we do not bother to override the methods expecting a 'float' array because those methods should
      *       be rarely invoked. Since there is usually LinearTransforms before and after this transform, the
-     *       conversion between float and double will be handle by those LinearTransforms.   If nevertheless
+     *       conversion between float and double will be handled by those LinearTransforms.  If nevertheless
      *       this MolodenskyTransform is at the beginning or the end of a transformation chain,  the methods
      *       inherited from the subclass will work (but may be slightly slower).
      */

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/MathTransforms.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/MathTransforms.java?rev=1737101&r1=1737100&r2=1737101&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/MathTransforms.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/MathTransforms.java [UTF-8] Wed Mar 30 11:25:06 2016
@@ -32,10 +32,9 @@ import org.apache.sis.internal.referenci
 import org.apache.sis.internal.referencing.j2d.AffineTransform2D;
 import org.apache.sis.referencing.operation.matrix.AffineTransforms2D;
 import org.apache.sis.referencing.operation.matrix.Matrices;
+import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.Static;
 
-import static org.apache.sis.util.ArgumentChecks.*;
-
 
 /**
  * Utility methods creating or working on {@link MathTransform} instances.
@@ -78,7 +77,7 @@ public final class MathTransforms extend
      * @return An identity transform of the specified dimension.
      */
     public static LinearTransform identity(final int dimension) {
-        ensureStrictlyPositive("dimension", dimension);
+        ArgumentChecks.ensureStrictlyPositive("dimension", dimension);
         return IdentityTransform.create(dimension);
     }
 
@@ -113,7 +112,7 @@ public final class MathTransforms extend
      * @see DefaultMathTransformFactory#createAffineTransform(Matrix)
      */
     public static LinearTransform linear(final Matrix matrix) {
-        ensureNonNull("matrix", matrix);
+        ArgumentChecks.ensureNonNull("matrix", matrix);
         final int sourceDimension = matrix.getNumCol() - 1;
         final int targetDimension = matrix.getNumRow() - 1;
         if (sourceDimension == targetDimension) {
@@ -170,12 +169,12 @@ public final class MathTransforms extend
      * @since 0.6
      */
     public static MathTransform compound(final MathTransform... transforms) {
-        ensureNonNull("transforms", transforms);
+        ArgumentChecks.ensureNonNull("transforms", transforms);
         int sum = 0;
         final int[] dimensions = new int[transforms.length];
         for (int i=0; i<transforms.length; i++) {
             final MathTransform tr = transforms[i];
-            ensureNonNullElement("transforms", i, tr);
+            ArgumentChecks.ensureNonNullElement("transforms", i, tr);
             sum += (dimensions[i] = tr.getSourceDimensions());
         }
         MathTransform compound = null;
@@ -209,8 +208,8 @@ public final class MathTransforms extend
     public static MathTransform concatenate(final MathTransform tr1, final MathTransform tr2)
             throws MismatchedDimensionException
     {
-        ensureNonNull("tr1", tr1);
-        ensureNonNull("tr2", tr2);
+        ArgumentChecks.ensureNonNull("tr1", tr1);
+        ArgumentChecks.ensureNonNull("tr2", tr2);
         final MathTransform tr;
         try {
             tr = ConcatenatedTransform.create(tr1, tr2, null);
@@ -269,9 +268,9 @@ public final class MathTransforms extend
     public static MathTransform concatenate(MathTransform tr1, MathTransform tr2, MathTransform tr3)
             throws MismatchedDimensionException
     {
-        ensureNonNull("tr1", tr1);
-        ensureNonNull("tr2", tr2);
-        ensureNonNull("tr3", tr3);
+        ArgumentChecks.ensureNonNull("tr1", tr1);
+        ArgumentChecks.ensureNonNull("tr2", tr2);
+        ArgumentChecks.ensureNonNull("tr3", tr3);
         return concatenate(concatenate(tr1, tr2), tr3);
     }
 

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/MolodenskyTransform.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/MolodenskyTransform.java?rev=1737101&r1=1737100&r2=1737101&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/MolodenskyTransform.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/MolodenskyTransform.java [UTF-8] Wed Mar 30 11:25:06 2016
@@ -362,7 +362,7 @@ public class MolodenskyTransform extends
     /*
      * NOTE: we do not bother to override the methods expecting a 'float' array because those methods should
      *       be rarely invoked. Since there is usually LinearTransforms before and after this transform, the
-     *       conversion between float and double will be handle by those LinearTransforms.   If nevertheless
+     *       conversion between float and double will be handled by those LinearTransforms.  If nevertheless
      *       this MolodenskyTransform is at the beginning or the end of a transformation chain,  the methods
      *       inherited from the subclass will work (but may be slightly slower).
      */

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ProjectiveTransform.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ProjectiveTransform.java?rev=1737101&r1=1737100&r2=1737101&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ProjectiveTransform.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ProjectiveTransform.java [UTF-8] Wed Mar 30 11:25:06 2016
@@ -92,6 +92,9 @@ class ProjectiveTransform extends Abstra
      * Otherwise returns {@code this} unchanged.
      */
     final LinearTransform optimize() {
+        if (numCol < numRow) {
+            return this;
+        }
         final int n = (numRow - 1) * numCol;
         for (int i = 0; i != numCol;) {
             if (elt[n + i] != (++i == numCol ? 1 : 0)) {

Modified: sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/internal/metadata/AxisDirectionsTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/internal/metadata/AxisDirectionsTest.java?rev=1737101&r1=1737100&r2=1737101&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/internal/metadata/AxisDirectionsTest.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/internal/metadata/AxisDirectionsTest.java [UTF-8] Wed Mar 30 11:25:06 2016
@@ -32,6 +32,9 @@ import org.junit.Test;
 import static org.junit.Assert.*;
 import static java.lang.StrictMath.abs;
 import static org.opengis.referencing.cs.AxisDirection.*;
+import static org.apache.sis.internal.metadata.AxisDirections.AWAY_FROM;
+import static org.apache.sis.internal.metadata.AxisDirections.CLOCKWISE;
+import static org.apache.sis.internal.metadata.AxisDirections.COUNTER_CLOCKWISE;
 
 
 /**
@@ -63,6 +66,9 @@ public final strictfp class AxisDirectio
         assertEquals(UP,                AxisDirections.absolute(DOWN));
         assertEquals(FUTURE,            AxisDirections.absolute(FUTURE));
         assertEquals(FUTURE,            AxisDirections.absolute(PAST));
+        assertEquals(AWAY_FROM,         AxisDirections.absolute(AWAY_FROM));
+        assertEquals(COUNTER_CLOCKWISE, AxisDirections.absolute(CLOCKWISE));
+        assertEquals(COUNTER_CLOCKWISE, AxisDirections.absolute(COUNTER_CLOCKWISE));
     }
 
     /**
@@ -82,6 +88,9 @@ public final strictfp class AxisDirectio
         assertEquals(UP,                AxisDirections.opposite(DOWN));
         assertEquals(PAST,              AxisDirections.opposite(FUTURE));
         assertEquals(FUTURE,            AxisDirections.opposite(PAST));
+        assertEquals(COUNTER_CLOCKWISE, AxisDirections.opposite(CLOCKWISE));
+        assertEquals(CLOCKWISE,         AxisDirections.opposite(COUNTER_CLOCKWISE));
+        assertNull  (                   AxisDirections.opposite(AWAY_FROM));
     }
 
     /**
@@ -381,7 +390,10 @@ public final strictfp class AxisDirectio
         assertEquals("φ′",  AxisDirections.suggestAbbreviation("Spherical latitude",     NORTH,         NonSI.DEGREE_ANGLE));
         assertEquals("h",   AxisDirections.suggestAbbreviation("Ellipsoidal height",     UP,               SI.METRE));
         assertEquals("H",   AxisDirections.suggestAbbreviation("Gravity-related height", UP,               SI.METRE));
-        assertEquals("r",   AxisDirections.suggestAbbreviation("Geocentric radius",      UP,               SI.METRE));
+        assertEquals("φ",   AxisDirections.suggestAbbreviation("Elevation",              UP,               SI.METRE));
+        assertEquals("R",   AxisDirections.suggestAbbreviation("Geocentric radius",      UP,               SI.METRE));
+        assertEquals("r",   AxisDirections.suggestAbbreviation("Distance",               AWAY_FROM,        SI.METRE));
+        assertEquals("θ",   AxisDirections.suggestAbbreviation("Bearing",                CLOCKWISE,     NonSI.DEGREE_ANGLE));
         assertEquals("X",   AxisDirections.suggestAbbreviation("not needed",             GEOCENTRIC_X,     SI.METRE));
         assertEquals("Y",   AxisDirections.suggestAbbreviation("not needed",             GEOCENTRIC_Y,     SI.METRE));
         assertEquals("Z",   AxisDirections.suggestAbbreviation("not needed",             GEOCENTRIC_Z,     SI.METRE));

Modified: sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/BuilderTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/BuilderTest.java?rev=1737101&r1=1737100&r2=1737101&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/BuilderTest.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/BuilderTest.java [UTF-8] Wed Mar 30 11:25:06 2016
@@ -296,9 +296,9 @@ public final strictfp class BuilderTest
         assertNull(properties.put(AbstractIdentifiedObject.REMARKS_KEY,     "Some remarks"));
         final BuilderMock builder = new BuilderMock(new AbstractIdentifiedObject(properties));
 
-        assertEquals("Expected only name and remarks.", 2, builder.properties.size());
+        assertEquals("Expected only name, remarks and deprecated status.", 3, builder.properties.size());
         builder.onCreate(false);
-        assertEquals("Expected name, aliases, identifiers and remarks.", 4, builder.properties.size());
+        assertEquals("Expected name, aliases, identifiers and remarks.", 5, builder.properties.size());
 
         assertEquals(AbstractIdentifiedObject.NAME_KEY, "Dummy object",
                 builder.properties.get(AbstractIdentifiedObject.NAME_KEY).toString());

Modified: sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/CommonCRSTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/CommonCRSTest.java?rev=1737101&r1=1737100&r2=1737101&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/CommonCRSTest.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/CommonCRSTest.java [UTF-8] Wed Mar 30 11:25:06 2016
@@ -40,7 +40,7 @@ import org.apache.sis.test.DependsOn;
 import org.apache.sis.test.TestCase;
 import org.junit.Test;
 
-import static org.junit.Assert.*;
+import static org.opengis.test.Assert.*;
 import static org.apache.sis.test.TestUtilities.*;
 
 
@@ -100,7 +100,7 @@ public final strictfp class CommonCRSTes
     public void testGeographic3D() {
         final GeographicCRS crs = CommonCRS.WGS72.geographic3D();
         Validators.validate(crs);
-        assertEquals("WGS 72", crs.getName().getCode());
+        assertEquals ("WGS 72", crs.getName().getCode());
         assertSame   (CommonCRS.WGS72.geographic().getDatum(), crs.getDatum());
         assertNotSame(CommonCRS.WGS84.geographic().getDatum(), crs.getDatum());
 
@@ -108,9 +108,7 @@ public final strictfp class CommonCRSTes
         final String name = cs.getName().getCode();
         assertTrue(name, name.startsWith("Ellipsoidal 3D"));
         assertEquals("dimension", 3, cs.getDimension());
-        assertEquals(AxisDirection.NORTH, cs.getAxis(0).getDirection());
-        assertEquals(AxisDirection.EAST,  cs.getAxis(1).getDirection());
-        assertEquals(AxisDirection.UP,    cs.getAxis(2).getDirection());
+        assertAxisDirectionsEqual(name, cs, AxisDirection.NORTH, AxisDirection.EAST, AxisDirection.UP);
         assertSame("Cached value", crs, CommonCRS.WGS72.geographic3D());
     }
 
@@ -122,7 +120,7 @@ public final strictfp class CommonCRSTes
     public void testGeocentric() {
         final GeocentricCRS crs = CommonCRS.WGS72.geocentric();
         Validators.validate(crs);
-        assertEquals("WGS 72", crs.getName().getCode());
+        assertEquals ("WGS 72", crs.getName().getCode());
         assertSame   (CommonCRS.WGS72.geographic().getDatum(), crs.getDatum());
         assertNotSame(CommonCRS.WGS84.geographic().getDatum(), crs.getDatum());
 
@@ -130,13 +128,32 @@ public final strictfp class CommonCRSTes
         final String name = cs.getName().getCode();
         assertTrue(name, name.startsWith("Earth centred"));
         assertEquals("dimension", 3, cs.getDimension());
-        assertEquals(AxisDirection.GEOCENTRIC_X, cs.getAxis(0).getDirection());
-        assertEquals(AxisDirection.GEOCENTRIC_Y, cs.getAxis(1).getDirection());
-        assertEquals(AxisDirection.GEOCENTRIC_Z, cs.getAxis(2).getDirection());
+        assertAxisDirectionsEqual(name, cs, AxisDirection.GEOCENTRIC_X,
+                AxisDirection.GEOCENTRIC_Y, AxisDirection.GEOCENTRIC_Z);
         assertSame("Cached value", crs, CommonCRS.WGS72.geocentric());
     }
 
     /**
+     * Tests the {@link CommonCRS#spherical()} method.
+     */
+    @Test
+    @DependsOnMethod("testGeographic3D")
+    public void testSpherical() {
+        final GeocentricCRS crs = CommonCRS.ETRS89.spherical();
+        Validators.validate(crs);
+        assertEquals ("ETRS89", crs.getName().getCode());
+        assertSame   (CommonCRS.ETRS89.geographic().getDatum(), crs.getDatum());
+        assertNotSame(CommonCRS.WGS84 .geographic().getDatum(), crs.getDatum());
+
+        final CoordinateSystem cs = crs.getCoordinateSystem();
+        final String name = cs.getName().getCode();
+        assertTrue(name, name.startsWith("Spherical"));
+        assertEquals("dimension", 3, cs.getDimension());
+        assertAxisDirectionsEqual(name, cs, AxisDirection.NORTH, AxisDirection.EAST, AxisDirection.UP);
+        assertSame("Cached value", crs, CommonCRS.ETRS89.spherical());
+    }
+
+    /**
      * Verifies the vertical datum enumeration.
      */
     @Test

Modified: sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/StandardDefinitionsTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/StandardDefinitionsTest.java?rev=1737101&r1=1737100&r2=1737101&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/StandardDefinitionsTest.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/StandardDefinitionsTest.java [UTF-8] Wed Mar 30 11:25:06 2016
@@ -150,12 +150,15 @@ public final strictfp class StandardDefi
      */
     @Test
     public void testCreateAxis() {
-        for (final short code : new short[] {1, 2, 106, 107, 110, 114, 113}) {
+        for (final short code : new short[] {1, 2, 60, 61, 62, 106, 107, 110, 114, 113}) {
             final CoordinateSystemAxis actual = StandardDefinitions.createAxis(code);
             Validators.validate(actual);
             switch (code) {
                 case   1: compare(HardCodedAxes.EASTING,                actual); break;
                 case   2: compare(HardCodedAxes.NORTHING,               actual); break;
+                case  60: compare(HardCodedAxes.SPHERICAL_LATITUDE,     actual); break;
+                case  61: compare(HardCodedAxes.SPHERICAL_LONGITUDE,    actual); break;
+                case  62: compare(HardCodedAxes.GEOCENTRIC_RADIUS,      actual); break;
                 case 106: compare(HardCodedAxes.GEODETIC_LATITUDE,      actual); break;
                 case 107: compare(HardCodedAxes.GEODETIC_LONGITUDE,     actual); break;
                 case 110: compare(HardCodedAxes.ELLIPSOIDAL_HEIGHT,     actual); break;

Modified: sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/DefaultEngineeringCRSTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/DefaultEngineeringCRSTest.java?rev=1737101&r1=1737100&r2=1737101&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/DefaultEngineeringCRSTest.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/DefaultEngineeringCRSTest.java [UTF-8] Wed Mar 30 11:25:06 2016
@@ -86,7 +86,7 @@ public final strictfp class DefaultEngin
                 "  CS[spherical, 3],\n" +
                 "    AXIS[“Spherical latitude (U)”, north, ORDER[1], ANGLEUNIT[“degree”, 0.017453292519943295]],\n" +
                 "    AXIS[“Spherical longitude (V)”, east, ORDER[2], ANGLEUNIT[“degree”, 0.017453292519943295]],\n" +
-                "    AXIS[“Geocentric radius (r)”, up, ORDER[3], LENGTHUNIT[“metre”, 1]]]",
+                "    AXIS[“Geocentric radius (R)”, up, ORDER[3], LENGTHUNIT[“metre”, 1]]]",
                 crs);
     }
 
@@ -102,7 +102,7 @@ public final strictfp class DefaultEngin
                 "  CS[spherical, 3],\n" +
                 "    Axis[“Spherical latitude (U)”, north, Unit[“degree”, 0.017453292519943295]],\n" +
                 "    Axis[“Spherical longitude (V)”, east, Unit[“degree”, 0.017453292519943295]],\n" +
-                "    Axis[“Geocentric radius (r)”, up, Unit[“metre”, 1]]]",
+                "    Axis[“Geocentric radius (R)”, up, Unit[“metre”, 1]]]",
                 crs);
     }
 
@@ -192,7 +192,7 @@ public final strictfp class DefaultEngin
                 "    <gml:axis>\n" +
                 "      <gml:CoordinateSystemAxis uom=\"urn:ogc:def:uom:EPSG::9001\" gml:id=\"GeocentricRadius\">\n" +
                 "        <gml:name>Geocentric radius</gml:name>\n" +
-                "        <gml:axisAbbrev>r</gml:axisAbbrev>\n" +
+                "        <gml:axisAbbrev>R</gml:axisAbbrev>\n" +
                 "        <gml:axisDirection codeSpace=\"EPSG\">up</gml:axisDirection>\n" +
                 "        <gml:minimumValue>0.0</gml:minimumValue>\n" +
                 "        <gml:rangeMeaning codeSpace=\"EPSG\">exact</gml:rangeMeaning>\n" +
@@ -222,6 +222,6 @@ public final strictfp class DefaultEngin
         assertEquals("cs.axis[2].name", "Geocentric radius",   cs.getAxis(2).getName().getCode());
         assertEquals("cs.axis[0].abbreviation", "φ′",          cs.getAxis(0).getAbbreviation());
         assertEquals("cs.axis[1].abbreviation", "θ",           cs.getAxis(1).getAbbreviation());
-        assertEquals("cs.axis[2].abbreviation", "r",           cs.getAxis(2).getAbbreviation());
+        assertEquals("cs.axis[2].abbreviation", "R",           cs.getAxis(2).getAbbreviation());
     }
 }

Modified: sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/DefaultGeocentricCRSTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/DefaultGeocentricCRSTest.java?rev=1737101&r1=1737100&r2=1737101&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/DefaultGeocentricCRSTest.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/DefaultGeocentricCRSTest.java [UTF-8] Wed Mar 30 11:25:06 2016
@@ -18,12 +18,16 @@ package org.apache.sis.referencing.crs;
 
 import javax.measure.unit.SI;
 import org.opengis.referencing.cs.CartesianCS;
+import org.opengis.referencing.cs.CoordinateSystem;
+import org.opengis.referencing.cs.CoordinateSystemAxis;
 import org.apache.sis.io.wkt.Convention;
 import org.apache.sis.referencing.IdentifiedObjects;
+import org.apache.sis.referencing.cs.AxesConvention;
 import org.apache.sis.internal.referencing.Legacy;
 import org.apache.sis.test.DependsOn;
 import org.apache.sis.test.DependsOnMethod;
 import org.apache.sis.test.TestCase;
+import org.opengis.test.Validators;
 import org.junit.Test;
 
 import static org.apache.sis.test.MetadataAssert.*;
@@ -34,7 +38,7 @@ import static org.apache.sis.test.Metada
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.4
- * @version 0.6
+ * @version 0.7
  * @module
  */
 @DependsOn({
@@ -42,6 +46,48 @@ import static org.apache.sis.test.Metada
 })
 public final strictfp class DefaultGeocentricCRSTest extends TestCase {
     /**
+     * Tests the {@link DefaultGeocentricCRS#forConvention(AxesConvention)} method
+     * for {@link AxesConvention#RIGHT_HANDED}.
+     *
+     * @since 0.7
+     */
+    @Test
+    public void testRightHanded() {
+        final DefaultGeocentricCRS crs = DefaultGeocentricCRS.castOrCopy(HardCodedCRS.SPHERICAL);
+        final DefaultGeocentricCRS normalized = crs.forConvention(AxesConvention.RIGHT_HANDED);
+        assertNotSame(crs, normalized);
+        final CoordinateSystem cs = normalized.getCoordinateSystem();
+        final CoordinateSystem ref = crs.getCoordinateSystem();
+        assertSame("longitude", ref.getAxis(1), cs.getAxis(0));
+        assertSame("latitude",  ref.getAxis(0), cs.getAxis(1));
+        assertSame("height",    ref.getAxis(2), cs.getAxis(2));
+    }
+
+    /**
+     * Tests the {@link DefaultGeocentricCRS#forConvention(AxesConvention)} method
+     * for {@link AxesConvention#POSITIVE_RANGE}.
+     *
+     * @since 0.7
+     */
+    @Test
+    public void testShiftLongitudeRange() {
+        final DefaultGeocentricCRS crs = HardCodedCRS.SPHERICAL;
+        CoordinateSystemAxis axis = crs.getCoordinateSystem().getAxis(1);
+        assertEquals("longitude.minimumValue", -180.0, axis.getMinimumValue(), STRICT);
+        assertEquals("longitude.maximumValue", +180.0, axis.getMaximumValue(), STRICT);
+
+        final DefaultGeocentricCRS shifted =  crs.forConvention(AxesConvention.POSITIVE_RANGE);
+        assertNotSame("Expected a new CRS.", crs, shifted);
+        Validators.validate(shifted);
+
+        axis = shifted.getCoordinateSystem().getAxis(1);
+        assertEquals("longitude.minimumValue",      0.0, axis.getMinimumValue(), STRICT);
+        assertEquals("longitude.maximumValue",    360.0, axis.getMaximumValue(), STRICT);
+        assertSame("Expected a no-op.",         shifted, shifted.forConvention(AxesConvention.POSITIVE_RANGE));
+        assertSame("Expected cached instance.", shifted, crs    .forConvention(AxesConvention.POSITIVE_RANGE));
+    }
+
+    /**
      * Tests WKT 1 formatting.
      * Axis directions Geocentric X, Y and Z shall be replaced be Other, East and North respectively,
      * for conformance with legacy WKT 1 practice.

Modified: sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/cs/CoordinateSystemsTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/cs/CoordinateSystemsTest.java?rev=1737101&r1=1737100&r2=1737101&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/cs/CoordinateSystemsTest.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/cs/CoordinateSystemsTest.java [UTF-8] Wed Mar 30 11:25:06 2016
@@ -294,6 +294,19 @@ public final strictfp class CoordinateSy
             }
 
             @Override
+            public Unit<?> getUnitReplacement(CoordinateSystemAxis axis, Unit<?> unit) {
+                if (Units.isAngular(unit)) {
+                    unit = NonSI.GRADE;
+                }
+                return unit;
+            }
+
+            @Override
+            public AxisDirection getDirectionReplacement(CoordinateSystemAxis axis, final AxisDirection direction) {
+                return direction;
+            }
+
+            @Override
             public AxisDirection getDirectionReplacement(final AxisDirection direction) {
                 return direction;
             }
@@ -325,6 +338,16 @@ public final strictfp class CoordinateSy
             public AxisDirection getDirectionReplacement(final AxisDirection direction) {
                 return direction;
             }
+
+            @Override
+            public Unit<?> getUnitReplacement(CoordinateSystemAxis axis, final Unit<?> unit) {
+                return unit;
+            }
+
+            @Override
+            public AxisDirection getDirectionReplacement(CoordinateSystemAxis axis, final AxisDirection direction) {
+                return direction;
+            }
         });
         assertEqualsIgnoreMetadata(targetCS, actualCS);
     }

Modified: sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/cs/DefaultCartesianCSTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/cs/DefaultCartesianCSTest.java?rev=1737101&r1=1737100&r2=1737101&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/cs/DefaultCartesianCSTest.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/cs/DefaultCartesianCSTest.java [UTF-8] Wed Mar 30 11:25:06 2016
@@ -170,8 +170,8 @@ public final strictfp class DefaultCarte
      * Then ensures that swapping the axes and applying conventional orientation gives back the original CS.
      */
     private static void testConventionalOrientation(final String x, final String y) {
-        assertConventionallyOrientedEquals(x, y, x, y); // Expect no-op.
-        assertConventionallyOrientedEquals(x, y, y, x); // Expect normalization.
+        assertConventionallyOrientedEquals(x, y, x, y);         // Expect no-op.
+        assertConventionallyOrientedEquals(x, y, y, x);         // Expect normalization.
     }
 
     /**

Modified: sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/cs/DefaultSphericalCSTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/cs/DefaultSphericalCSTest.java?rev=1737101&r1=1737100&r2=1737101&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/cs/DefaultSphericalCSTest.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/cs/DefaultSphericalCSTest.java [UTF-8] Wed Mar 30 11:25:06 2016
@@ -17,12 +17,13 @@
 package org.apache.sis.referencing.cs;
 
 import java.util.Collections;
+import org.opengis.referencing.cs.AxisDirection;
+import org.apache.sis.internal.metadata.AxisDirections;
 import org.apache.sis.test.TestCase;
 import org.apache.sis.test.DependsOn;
 import org.junit.Test;
 
-import static org.apache.sis.test.Assert.*;
-import static org.apache.sis.referencing.cs.HardCodedCS.*;
+import static org.opengis.test.Assert.*;
 
 
 /**
@@ -30,23 +31,63 @@ import static org.apache.sis.referencing
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.4
- * @version 0.5
+ * @version 0.7
  * @module
  */
 @DependsOn(AbstractCSTest.class)
 public final strictfp class DefaultSphericalCSTest extends TestCase {
     /**
-     * Tests the conventional orientation of a coordinate system.
+     * Tests a spherical CRS conforms to EPSG:8.9:6404 definition.
+     * Expected axes are:
+     *
+     * <ol>
+     *   <li>Spherical latitude (φ′)</li>
+     *   <li>Spherical longitude (θ)</li>
+     *   <li>Geocentric radius (R)</li>
+     * </ol>
      */
     @Test
-    public void testConventionalOrientation() {
-        final AbstractCS normalized = SPHERICAL.forConvention(AxesConvention.CONVENTIONALLY_ORIENTED);
-        assertNotSame(SPHERICAL, normalized);
+    public void testGeodetic() {
+        final DefaultSphericalCS cs = HardCodedCS.SPHERICAL;
+        assertEquals("EPSG abbreviation for geocentric radius should be upper-case", "R", cs.getAxis(2).getAbbreviation());
+
+        final DefaultSphericalCS normalized = cs.forConvention(AxesConvention.CONVENTIONALLY_ORIENTED);
+        assertNotSame("Should create a new CoordinateSystem.", cs, normalized);
+        assertAxisDirectionsEqual("Normalized", normalized,
+                AxisDirection.EAST,
+                AxisDirection.NORTH,
+                AxisDirection.UP);
+
         assertEquals(new DefaultSphericalCS(
-            Collections.singletonMap(AbstractCS.NAME_KEY, "Spherical CS: East (°), North (°), Up (m)."),
-            HardCodedAxes.SPHERICAL_LONGITUDE,
-            HardCodedAxes.SPHERICAL_LATITUDE,
-            HardCodedAxes.GEOCENTRIC_RADIUS
-        ), normalized);
+                Collections.singletonMap(AbstractCS.NAME_KEY, "Spherical CS: East (°), North (°), Up (m)."),
+                HardCodedAxes.SPHERICAL_LONGITUDE,
+                HardCodedAxes.SPHERICAL_LATITUDE,
+                HardCodedAxes.GEOCENTRIC_RADIUS), normalized);
+    }
+
+    /**
+     * Tests a spherical CRS conforms to the example given in ISO 19162.
+     * Expected axes are:
+     *
+     * <ol>
+     *   <li>Distance (r)</li>
+     *   <li>Longitude</li>
+     *   <li>Elevation</li>
+     * </ol>
+     *
+     * This order is not exactly the usual engineering axis order.
+     * But this is the order expected by the {@code SphericalToCartesian} transform.
+     */
+    @Test
+    public void testEngineering() {
+        final DefaultSphericalCS cs = HardCodedCS.SPHERICAL_ENGINEERING;
+        assertEquals("Abbreviation for distance should be lower-case", "r", cs.getAxis(0).getAbbreviation());
+
+        final DefaultSphericalCS normalized = cs.forConvention(AxesConvention.NORMALIZED);
+        assertNotSame("Should create a new CoordinateSystem.", cs, normalized);
+        assertAxisDirectionsEqual("Normalized", normalized,
+                AxisDirections.COUNTER_CLOCKWISE,
+                AxisDirection.UP,
+                AxisDirections.AWAY_FROM);
     }
 }



Mime
View raw message