sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1713527 [3/4] - in /sis/branches/JDK7: ./ core/sis-build-helper/src/main/java/org/apache/sis/internal/book/ core/sis-build-helper/src/main/resources/org/apache/sis/internal/book/ core/sis-feature/src/main/java/org/apache/sis/feature/ core/...
Date Mon, 09 Nov 2015 19:57:42 GMT
Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform.java?rev=1713527&r1=1713526&r2=1713527&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform.java [UTF-8] Mon Nov  9 19:57:39 2015
@@ -234,8 +234,8 @@ public abstract class AbstractMathTransf
      * @param expected  The expected dimension.
      * @param dimension The wrong dimension.
      */
-    static String mismatchedDimension(final String argument, final int expected, final int dimension) {
-        return Errors.format(Errors.Keys.MismatchedDimension_3, argument, expected, dimension);
+    static MismatchedDimensionException mismatchedDimension(final String argument, final int expected, final int dimension) {
+        return new MismatchedDimensionException(Errors.format(Errors.Keys.MismatchedDimension_3, argument, expected, dimension));
     }
 
     /**
@@ -341,8 +341,8 @@ public abstract class AbstractMathTransf
      * @param derivate {@code true} for computing the derivative, or {@code false} if not needed.
      * @return The matrix of the transform derivative at the given source position,
      *         or {@code null} if the {@code derivate} argument is {@code false}.
-     * @throws TransformException If the point can not be transformed or if a problem occurred while calculating the
-     *         derivative.
+     * @throws TransformException if the point can not be transformed or
+     *         if a problem occurred while calculating the derivative.
      *
      * @see #derivative(DirectPosition)
      * @see #transform(DirectPosition, DirectPosition)
@@ -759,7 +759,7 @@ public abstract class AbstractMathTransf
         final int dimSource = getSourceDimensions();
         final double[] coordinate = point.getCoordinate();
         if (coordinate.length != dimSource) {
-            throw new MismatchedDimensionException(mismatchedDimension("point", coordinate.length, dimSource));
+            throw mismatchedDimension("point", dimSource, coordinate.length);
         }
         final Matrix derivative = transform(coordinate, 0, null, 0, true);
         if (derivative == null) {
@@ -908,6 +908,10 @@ public abstract class AbstractMathTransf
             if (mode.isIgnoringMetadata()) {
                 return true;
             }
+            /*
+             * We do not compare getParameters() because they usually duplicate the internal fields.
+             * Contextual parameters, on the other hand, typically contain new information.
+             */
             return Utilities.deepEquals(this.getContextualParameters(),
                                         that.getContextualParameters(), mode);
         }
@@ -1095,13 +1099,18 @@ public abstract class AbstractMathTransf
          */
         @Override
         final int beforeFormat(final List<Object> transforms, final int index, final boolean inverse) {
-            return AbstractMathTransform.this.beforeFormat(transforms, index, !inverse);
+            final ContextualParameters parameters = getContextualParameters();
+            if (parameters != null) {
+                return parameters.beforeFormat(transforms, index, inverse);
+            } else {
+                return AbstractMathTransform.this.beforeFormat(transforms, index, !inverse);
+            }
         }
 
         /**
          * Formats the inner part of a <cite>Well Known Text</cite> version 1 (WKT 1) element.
-         * If this inverse math transform has any parameter values, then this method format the
-         * WKT as in the {@linkplain AbstractMathTransform#formatWKT super-class method}.
+         * If this inverse math transform has any parameter values, then this method formats
+         * the WKT as in the {@linkplain AbstractMathTransform#formatWKT super-class method}.
          * Otherwise this method formats the math transform as an {@code "Inverse_MT"} entity.
          *
          * <div class="note"><b>Compatibility note:</b>

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform2D.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform2D.java?rev=1713527&r1=1713526&r2=1713527&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform2D.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform2D.java [UTF-8] Mon Nov  9 19:57:39 2015
@@ -105,7 +105,7 @@ public abstract class AbstractMathTransf
     }
 
     /**
-     * Implementation of {@link #transform(DirectPosition, DirectPosition)} shared by the inverse transform.
+     * Implementation of {@link #transform(Point2D, Point2D)} shared by the inverse transform.
      */
     static Point2D transform(final AbstractMathTransform tr, final Point2D ptSrc, final Point2D ptDst) throws TransformException {
         final double[] ord = new double[] {ptSrc.getX(), ptSrc.getY()};

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConcatenatedTransform.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConcatenatedTransform.java?rev=1713527&r1=1713526&r2=1713527&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConcatenatedTransform.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConcatenatedTransform.java [UTF-8] Mon Nov  9 19:57:39 2015
@@ -31,6 +31,7 @@ import org.opengis.referencing.operation
 import org.opengis.referencing.operation.NoninvertibleTransformException;
 import org.apache.sis.parameter.Parameterized;
 import org.apache.sis.referencing.operation.matrix.Matrices;
+import org.apache.sis.internal.referencing.provider.GeocentricAffine;
 import org.apache.sis.internal.metadata.WKTKeywords;
 import org.apache.sis.internal.system.Semaphores;
 import org.apache.sis.util.Classes;
@@ -53,7 +54,7 @@ import org.apache.sis.util.resources.Err
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.5
- * @version 0.5
+ * @version 0.7
  * @module
  *
  * @see org.opengis.referencing.operation.MathTransformFactory#createConcatenatedTransform(MathTransform, MathTransform)
@@ -327,11 +328,15 @@ class ConcatenatedTransform extends Abst
      */
     private static String getName(final MathTransform transform) {
         if (transform instanceof AbstractMathTransform) {
-            ParameterValueGroup params = ((AbstractMathTransform) transform).getParameterValues();
-            if (params != null) {
-                String name = params.getDescriptor().getName().getCode();
-                if (name != null && !(name = name.trim()).isEmpty()) {
-                    return name;
+            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;
+                    }
                 }
             }
         }
@@ -454,6 +459,11 @@ class ConcatenatedTransform extends Abst
                 after = null;
             }
         }
+        /*
+         * Special case for datum shifts. Need to be done only after we processed
+         * 'beforeFormat(…)' for all objects and concatenated the affine transforms.
+         */
+        GeocentricAffine.asDatumShift(transforms);
         return transforms;
     }
 

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ContextualParameters.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ContextualParameters.java?rev=1713527&r1=1713526&r2=1713527&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ContextualParameters.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ContextualParameters.java [UTF-8] Mon Nov  9 19:57:39 2015
@@ -24,8 +24,6 @@ import java.util.Iterator;
 import java.util.Objects;
 import java.io.Serializable;
 import org.opengis.util.FactoryException;
-import org.opengis.referencing.operation.MathTransform;
-import org.opengis.referencing.operation.OperationMethod;
 import org.opengis.parameter.GeneralParameterValue;
 import org.opengis.parameter.GeneralParameterDescriptor;
 import org.opengis.parameter.ParameterValue;
@@ -33,7 +31,9 @@ import org.opengis.parameter.ParameterVa
 import org.opengis.parameter.ParameterDescriptor;
 import org.opengis.parameter.ParameterDescriptorGroup;
 import org.opengis.parameter.ParameterNotFoundException;
+import org.opengis.referencing.operation.OperationMethod;
 import org.opengis.referencing.operation.Matrix;
+import org.opengis.referencing.operation.MathTransform;
 import org.opengis.referencing.operation.MathTransformFactory;
 import org.apache.sis.internal.referencing.ExtendedPrecisionMatrix;
 import org.apache.sis.internal.referencing.WKTUtilities;
@@ -108,7 +108,7 @@ import static org.apache.sis.util.Argume
  *     and gives the linear parameters to the {@link #normalizeGeographicInputs normalizeGeographicInputs(…)} and
  *     {@link MatrixSIS#convertAfter MatrixSIS.convertAfter(…)} methods, which will create the matrices show above.
  *     The projection constructor is free to apply additional operations on the two affine transforms
- *     ({@linkplain #getMatrix(boolean) normalize / denormalize}) before or after the above-cited
+ *     ({@linkplain #getMatrix(MatrixRole) normalize / denormalize}) before or after the above-cited
  *     methods have been invoked.</li>
  *
  *   <li>After all parameter values have been set and the normalize / denormalize matrices defined,
@@ -126,7 +126,7 @@ import static org.apache.sis.util.Argume
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.6
- * @version 0.6
+ * @version 0.7
  * @module
  *
  * @see org.apache.sis.referencing.operation.projection.NormalizedProjection
@@ -134,13 +134,57 @@ import static org.apache.sis.util.Argume
  */
 public class ContextualParameters extends Parameters implements Serializable {
     /**
+     * Whether a matrix is used for <cite>normalization</cite> or <cite>denormalization</cite>
+     * before or after a non-linear operation.
+     *
+     * @author  Martin Desruisseaux (Geomatys)
+     * @since   0.7
+     * @version 0.7
+     * @module
+     *
+     * @see ContextualParameters#getMatrix(MatrixRole)
+     */
+    public static enum MatrixRole {
+        /**
+         * Matrix for converting angular degrees to radians, or any other linear operations needed
+         * before to apply a non-linear operation. For example in a map projection, this matrix is
+         * typically (but not necessarily) as below:
+         *
+         * <center>{@include formulas.html#NormalizeGeographic}</center>
+         */
+        NORMALIZATION,
+
+        /**
+         * Inverse of the {@link #NORMALIZATION} matrix.
+         * For example in a map projection, this matrix is typically (but not necessarily) as below:
+         *
+         * <center>{@include formulas.html#DeormalizeGeographic}</center>
+         */
+        INVERSE_NORMALIZATION,
+
+        /**
+         * Matrix for scaling Cartesian coordinates to the size of the planet, or any other linear operations needed
+         * after execution of a non-linear operation. For example in a map projection, this matrix is typically
+         * (but not necessarily) as below:
+         *
+         * <center>{@include formulas.html#DenormalizeCartesian}</center>
+         */
+        DENORMALIZATION,
+
+        /**
+         * Inverse of the {@link #DENORMALIZATION} matrix.
+         */
+        INVERSE_DENORMALIZATION
+    }
+
+    /**
      * For cross-version compatibility.
      */
-    private static final long serialVersionUID = 4899134192407586472L;
+    private static final long serialVersionUID = 6769546741493459341L;
 
     /**
      * The parameters that represents the sequence of transforms as a whole. The parameter values may be used
-     * in the {@linkplain #getMatrix(boolean) (de)normalization} transforms, in the kernel, or both.
+     * in the {@linkplain #getMatrix(MatrixRole) (de)normalization} transforms, in the kernel, or both.
      *
      * @see #getDescriptor()
      */
@@ -149,11 +193,11 @@ public class ContextualParameters extend
     /**
      * The affine transform to be applied before (<cite>normalize</cite>) and after (<cite>denormalize</cite>)
      * the kernel operation. On {@code ContextualParameters} construction, those affines are initially identity
-     * transforms, to be modified in-place by callers of {@link #getMatrix(boolean)} or related methods.
+     * transforms, to be modified in-place by callers of {@link #getMatrix(MatrixRole)} or related methods.
      * After the {@link #completeTransform(MathTransformFactory, MathTransform)} method has been invoked,
      * those matrices are typically (but not necessarily) replaced by the {@link LinearTransform} instances itself.
      *
-     * @see #getMatrix(boolean)
+     * @see #getMatrix(MatrixRole)
      */
     private Matrix normalize, denormalize;
 
@@ -167,8 +211,16 @@ public class ContextualParameters extend
     private ParameterValue<?>[] values;
 
     /**
+     * If the inverse coordinate operation can be described by another {@code ContextualParameters} instance,
+     * a reference to that instance. Otherwise {@code null}.
+     */
+    private ContextualParameters inverse;
+
+    /**
      * {@code false} if this parameter group is modifiable, or {@code true} if it has been made unmodifiable
      * (frozen) by a call to {@link #completeTransform(MathTransformFactory, MathTransform)}.
+     *
+     * @see #freeze()
      */
     private boolean isFrozen;
 
@@ -181,7 +233,7 @@ public class ContextualParameters extend
      * <ul>
      *   <li>Set the relevant parameter values by calls to
      *     <code>{@linkplain #parameter(String) parameter(…)}.setValue(…)</code>.</li>
-     *   <li>Modify the element values in {@linkplain #getMatrix(boolean) normalization / denormalization}
+     *   <li>Modify the element values in {@linkplain #getMatrix(MatrixRole) normalization / denormalization}
      *     affine transforms, optionally by calls to the convenience methods in this class.</li>
      *   <li>Get the complete transforms chain with a call
      *     {@link #completeTransform(MathTransformFactory, MathTransform) completeTransform(…)}</li>
@@ -200,9 +252,38 @@ public class ContextualParameters extend
     }
 
     /**
+     * Equivalent to the public constructor, but avoid the need for an {@link OperationMethod} instance.
+     *
+     * @param descriptor The parameter descriptor.
+     * @param srcSize    Size of the normalization matrix: source dimensions + 1.
+     * @param tgtSize    Size of the denormalization matrix: target dimensions + 1.
+     */
+    ContextualParameters(final ParameterDescriptorGroup descriptor, final int srcSize, final int tgtSize) {
+        this.descriptor  = descriptor;
+        this.normalize   = Matrices.create(srcSize, srcSize, ExtendedPrecisionMatrix.IDENTITY);
+        this.denormalize = Matrices.create(tgtSize, tgtSize, ExtendedPrecisionMatrix.IDENTITY);
+        this.values      = new ParameterValue<?>[descriptor.descriptors().size()];
+    }
+
+    /**
+     * Creates a {@code ContextualParameters} for the inverse operation.
+     *
+     * @param  desc    Descriptor of the inverse operation.
+     * @param  forward The parameters created for the forward operation.
+     */
+    private ContextualParameters(final ParameterDescriptorGroup desc, final ContextualParameters forward) {
+        descriptor  = desc;
+        normalize   = forward.getMatrix(MatrixRole.INVERSE_DENORMALIZATION);
+        denormalize = forward.getMatrix(MatrixRole.INVERSE_NORMALIZATION);
+        values      = forward.values;
+        inverse     = forward;
+        isFrozen    = true;
+    }
+
+    /**
      * Creates a matrix for a linear step of the transforms chain.
      * It is important that the matrices created here are instances of {@link MatrixSIS}, in order
-     * to allow {@link #getMatrix(boolean)} to return the reference to the (de)normalize matrices.
+     * to allow {@link #getMatrix(MatrixRole)} to return the reference to the (de)normalize matrices.
      */
     private static MatrixSIS linear(final String name, final Integer size) {
         if (size == null) {
@@ -213,19 +294,36 @@ public class ContextualParameters extend
     }
 
     /**
+     * Creates a {@code ContextualParameters} for the inverse operation.
+     *
+     * @param  desc Descriptor of the inverse operation.
+     * @return Parameters for the inverse operation.
+     */
+    final synchronized ContextualParameters inverse(final ParameterDescriptorGroup desc) {
+        if (inverse == null) {
+            if (!isFrozen) {
+                freeze();
+            }
+            inverse = new ContextualParameters(desc, this);
+        }
+        assert inverse.descriptor == desc;
+        return inverse;
+    }
+
+    /**
      * Returns the parameters for the <cite>normalize</cite> → <cite>non-linear kernel</cite> →
      * <cite>denormalize</cite> sequence as a whole. This is the parameter descriptor of the
      * {@linkplain org.apache.sis.referencing.operation.DefaultOperationMethod operation method}
      * given to the constructor.
      *
      * <p>The values for those parameters is given by the {@link #values()} method. Those values may be used in
-     * the {@linkplain #getMatrix(boolean) normalization / denormalization} transforms, in the kernel, or both.</p>
+     * the {@linkplain #getMatrix(MatrixRole) normalization / denormalization} transforms, in the kernel, or both.</p>
      *
      * <div class="note"><b>Note:</b>
      * The definition of "kernel" is left to implementors.
      * In the particular case of Apache SIS implementation of map projections,
-     * kernels are subclasses of {@link org.apache.sis.referencing.operation.projection.NormalizedProjection}.
-     * </div>
+     * kernels are instances of {@link org.apache.sis.referencing.operation.projection.NormalizedProjection}.
+     * Other "kernels" in SIS are {@link EllipsoidalToCartesianTransform} and {@link MolodenskyTransform}.</div>
      *
      * @return The description of the parameters.
      */
@@ -235,17 +333,27 @@ public class ContextualParameters extend
     }
 
     /**
-     * Ensures that this instance is modifiable.
+     * Ensures that this {@code ContextualParameters} instance is modifiable.
      *
      * @throws IllegalStateException if this {@code ContextualParameter} has been made unmodifiable.
      */
     private void ensureModifiable() throws IllegalStateException {
+        assert Thread.holdsLock(this);
         if (isFrozen) {
             throw new IllegalStateException(Errors.format(Errors.Keys.UnmodifiableObject_1, getClass()));
         }
     }
 
     /**
+     * Returns the given matrix as an unmodifiable one if this {@code ContextualParameters} instance is unmodifiable.
+     * Note that if this instance is modifiable, then we <strong>must</strong> return a direct reference to the matrix,
+     * not a wrapper, because the caller may need to modify it.
+     */
+    private MatrixSIS toMatrixSIS(final Matrix m) {
+        return isFrozen ? Matrices.unmodifiable(m) : (MatrixSIS) m;
+    }
+
+    /**
      * Returns the affine transforms to be applied before or after the non-linear kernel operation.
      * Immediately after {@linkplain #ContextualParameters(OperationMethod) construction}, those matrices
      * are modifiable identity matrices. Callers can modify the matrix element values, typically by calls to
@@ -261,33 +369,68 @@ public class ContextualParameters extend
      * invoked, the matrices returned by this method are {@linkplain Matrices#unmodifiable(Matrix) unmodifiable}.
      *
      *
-     * <div class="section">Application to map projections</div>
-     * After {@link org.apache.sis.referencing.operation.projection.NormalizedProjection} construction, the matrices
+     * <div class="note"><b>Application to map projections:</b>
+     * after {@link org.apache.sis.referencing.operation.projection.NormalizedProjection} construction, the matrices
      * returned by {@code projection.getContextualParameters().getMatrix(…)} are initialized to the values shown below.
      * Note that some {@code NormalizedProjection} subclasses apply further modifications to those matrices.
      *
      * <table class="sis">
-     *   <caption>Initial matrix coefficients after construction</caption>
+     *   <caption>Initial matrix coefficients after {@code NormalizedProjection} construction</caption>
      *   <tr>
-     *     <th>{@code getMatrix(true)}</th>
-     *     <th class="sep">{@code getMatrix(false)}</th>
+     *     <th>{@code getMatrix(NORMALIZATION)}</th>
+     *     <th class="sep">{@code getMatrix(DENORMALIZATION)}</th>
      *   </tr><tr>
      *     <td>{@include formulas.html#NormalizeGeographic}</td>
      *     <td class="sep">{@include formulas.html#DenormalizeCartesian}</td>
      *   </tr>
      * </table>
+     * </div>
+     *
+     * @param  role {@code NORMALIZATION} for fetching the <cite>normalization</cite> transform to apply before the kernel,
+     *         {@code DENORMALIZATION} for the <cite>denormalization</cite> transform to apply after the kernel,
+     *         or {@code INVERSE_*} for the inverse of the above-cited matrices.
+     * @return The matrix for the requested normalization or denormalization affine transform.
+     *
+     * @since 0.7
+     */
+    public final MatrixSIS getMatrix(MatrixRole role) {
+        final Matrix fallback;
+        final ContextualParameters inverse;
+        synchronized (this) {
+            switch (role) {
+                default:                      throw new AssertionError(role);
+                case NORMALIZATION:           return toMatrixSIS(normalize);
+                case DENORMALIZATION:         return toMatrixSIS(denormalize);
+                case INVERSE_NORMALIZATION:   role = MatrixRole.DENORMALIZATION; fallback = normalize; break;
+                case INVERSE_DENORMALIZATION: role = MatrixRole.NORMALIZATION; fallback = denormalize; break;
+            }
+            inverse = this.inverse;     // Copy the reference while we are inside the synchronized block.
+        }
+        /*
+         * Following must be outside the synchronized block in order to avoid potential deadlock while invoking
+         * inverse.getMatrix(role). We do not cache the matrix here, but 'inverse' is likely to have cached it.
+         */
+        final Matrix m;
+        if (inverse != null) {
+            m = inverse.getMatrix(role);
+        } else try {
+            m = Matrices.inverse(fallback);
+        } catch (NoninvertibleMatrixException e) {
+            throw new IllegalStateException(Errors.format(Errors.Keys.CanNotCompute_1, role), e);
+        }
+        return Matrices.unmodifiable(m);
+    }
+
+    /**
+     * @deprecated Replaced by {@link #getMatrix(MatrixRole)}.
      *
      * @param  norm {@code true} for fetching the <cite>normalization</cite> transform to apply before the kernel,
      *         or {@code false} for the <cite>denormalization</cite> transform to apply after the kernel.
      * @return The matrix for the requested normalization ({@code true}) or denormalization ({@code false}) affine transform.
      */
+    @Deprecated
     public final MatrixSIS getMatrix(final boolean norm) {
-        final Matrix m = norm ? normalize : denormalize;
-        if (!isFrozen) {
-            return (MatrixSIS) m;       // Must be the same instance, not a copy.
-        } else {
-            return Matrices.unmodifiable(m);
-        }
+        return getMatrix(norm ? MatrixRole.NORMALIZATION : MatrixRole.DENORMALIZATION);
     }
 
     /**
@@ -305,7 +448,7 @@ public class ContextualParameters extend
      *         Callers can change that matrix directly if they want to apply additional normalization operations.
      * @throws IllegalStateException if this {@code ContextualParameter} has been made unmodifiable.
      */
-    public MatrixSIS normalizeGeographicInputs(final double λ0) {
+    public synchronized MatrixSIS normalizeGeographicInputs(final double λ0) {
         ensureModifiable();
         /*
          * In theory the check for (λ0 != 0) is useless. However Java has a notion of negative zero, and we want
@@ -339,7 +482,7 @@ public class ContextualParameters extend
      *         Callers can change that matrix directly if they want to apply additional denormalization operations.
      * @throws IllegalStateException if this {@code ContextualParameter} has been made unmodifiable.
      */
-    public MatrixSIS denormalizeGeographicOutputs(final double λ0) {
+    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.
@@ -351,7 +494,7 @@ public class ContextualParameters extend
     /**
      * Marks this {@code ContextualParameter} as unmodifiable and creates the
      * <cite>normalize</cite> → {@code kernel} → <cite>denormalize</cite> transforms chain.
-     * This method shall be invoked only after the {@linkplain #getMatrix(boolean) (de)normalization}
+     * This method shall be invoked only after the {@linkplain #getMatrix(MatrixRole) (de)normalization}
      * matrices have been set to their final values.
      *
      * <p>The transforms chain created by this method does not include any step for
@@ -368,52 +511,14 @@ public class ContextualParameters extend
      * @throws FactoryException if an error occurred while creating a math transform instance.
      *
      * @see org.apache.sis.referencing.operation.projection.NormalizedProjection#createMapProjection(MathTransformFactory)
+     * @see EllipsoidalToCartesianTransform#createGeodeticConversion(MathTransformFactory, double, double, Unit, boolean)
      */
     @SuppressWarnings("AssignmentToForLoopParameter")
-    public MathTransform completeTransform(final MathTransformFactory factory, final MathTransform kernel)
+    public synchronized MathTransform completeTransform(final MathTransformFactory factory, final MathTransform kernel)
             throws FactoryException
     {
         if (!isFrozen) {
-            isFrozen = true;
-            /*
-             * Sort the parameter values in the same order than the parameter descriptor. This is not essential,
-             * but makes easier to read 'toString()' output by ensuring a consistent order for most projections.
-             * Some WKT parsers other than SIS may also require the parameter values to be listed in that specific
-             * order. We proceed by first copying all parameters in a temporary HashMap:
-             */
-            final Map<ParameterDescriptor<?>, ParameterValue<?>> parameters = new IdentityHashMap<>(values.length);
-            for (ParameterValue<?> p : values) {
-                if (p == null) {
-                    break;  // The first null value in the array indicates the end of sequence.
-                }
-                p = DefaultParameterValue.unmodifiable(p);
-                final ParameterDescriptor<?> desc = p.getDescriptor();
-                if (parameters.put(desc, p) != null) {
-                    // Should never happen unless ParameterValue.descriptor changed (contract violation).
-                    throw new IllegalStateException(Errors.format(Errors.Keys.ElementAlreadyPresent_1, desc.getName()));
-                }
-            }
-            /*
-             * Then, copy all HashMap values back to the 'values' array in the order they are declared in the
-             * descriptor. Implementation note: the iteration termination condition uses the values array, not
-             * the descriptors list, because the former is often shorter than the later. We should never reach
-             * the end of descriptors list before the end of values array because 'descriptors' contains all
-             * 'parameters' keys. This is verified by the 'assert' below.
-             */
-            values = new ParameterValue<?>[parameters.size()];
-            assert descriptor.descriptors().containsAll(parameters.keySet());
-            final Iterator<GeneralParameterDescriptor> it = descriptor.descriptors().iterator();
-            for (int i=0; i < values.length;) {
-                /*
-                 * No need to check for it.hasNext(), since a NoSuchElementException below would be a bug in
-                 * our algorithm (or a concurrent change in the 'descriptor.descriptors()' list, which would
-                 * be a contract violation). See above 'assert'.
-                 */
-                final ParameterValue<?> p = parameters.get(it.next());
-                if (p != null) {
-                    values[i++] = p;
-                }
-            }
+            freeze();
         }
         /*
          * Creates the ConcatenatedTransform, letting the factory returns the cached instance
@@ -428,6 +533,54 @@ public class ContextualParameters extend
     }
 
     /**
+     * Marks this contextual parameter as unmodifiable.
+     *
+     * @see #ensureModifiable()
+     */
+    private void freeze() {
+        isFrozen = true;
+        /*
+         * Sort the parameter values in the same order than the parameter descriptor. This is not essential,
+         * but makes easier to read 'toString()' output by ensuring a consistent order for most projections.
+         * Some WKT parsers other than SIS may also require the parameter values to be listed in that specific
+         * order. We proceed by first copying all parameters in a temporary HashMap:
+         */
+        final Map<ParameterDescriptor<?>, ParameterValue<?>> parameters = new IdentityHashMap<>(values.length);
+        for (ParameterValue<?> p : values) {
+            if (p == null) {
+                break;  // The first null value in the array indicates the end of sequence.
+            }
+            p = DefaultParameterValue.unmodifiable(p);
+            final ParameterDescriptor<?> desc = p.getDescriptor();
+            if (parameters.put(desc, p) != null) {
+                // Should never happen unless ParameterValue.descriptor changed (contract violation).
+                throw new IllegalStateException(Errors.format(Errors.Keys.ElementAlreadyPresent_1, desc.getName()));
+            }
+        }
+        /*
+         * Then, copy all HashMap values back to the 'values' array in the order they are declared in the
+         * descriptor. Implementation note: the iteration termination condition uses the values array, not
+         * the descriptors list, because the former is often shorter than the later. We should never reach
+         * the end of descriptors list before the end of values array because 'descriptors' contains all
+         * 'parameters' keys. This is verified by the 'assert' below.
+         */
+        values = new ParameterValue<?>[parameters.size()];
+        assert descriptor.descriptors().containsAll(parameters.keySet());
+        final Iterator<GeneralParameterDescriptor> it = descriptor.descriptors().iterator();
+        for (int i=0; i < values.length;) {
+            /*
+             * No need to check for it.hasNext(), since a NoSuchElementException below would be a bug in
+             * our algorithm (or a concurrent change in the 'descriptor.descriptors()' list, which would
+             * be a contract violation). See above 'assert'.
+             */
+            final ParameterValue<?> p = parameters.get(it.next());
+            if (p != null) {
+                values[i++] = p;
+            }
+        }
+    }
+
+    /**
      * Returns the parameter value of the given name.
      * Before the call to {@link #completeTransform completeTransform(…)},
      * this method can be used for setting parameter values like below:
@@ -443,7 +596,7 @@ public class ContextualParameters extend
      * @throws ParameterNotFoundException if there is no parameter of the given name.
      */
     @Override
-    public ParameterValue<?> parameter(final String name) throws ParameterNotFoundException {
+    public synchronized ParameterValue<?> parameter(final String name) throws ParameterNotFoundException {
         final GeneralParameterDescriptor desc = descriptor.descriptor(name);
         if (!(desc instanceof ParameterDescriptor<?>)) {
             throw parameterNotFound(name);
@@ -490,7 +643,7 @@ public class ContextualParameters extend
      */
     @Override
     @SuppressWarnings("unchecked")
-    public List<GeneralParameterValue> values() {
+    public synchronized List<GeneralParameterValue> values() {
         int upper = values.length;
         while (upper != 0 && values[upper - 1] == null) {
             upper--;
@@ -534,7 +687,7 @@ public class ContextualParameters extend
      * @return A clone of this parameter value group.
      */
     @Override
-    public ContextualParameters clone() {
+    public synchronized ContextualParameters clone() {
         /*
          * Creates a new parameter array with enough room for adding new parameters.
          * Then replace each element by a modifiable clone.
@@ -549,6 +702,7 @@ public class ContextualParameters extend
         }
         /*
          * Now proceed to the clone of this ContextualParameters instance.
+         * We do not clone inverseFoo fields since they shall be null for modifiable instances.
          */
         final ContextualParameters clone = (ContextualParameters) super.clone();
         clone.values      = param;
@@ -562,7 +716,7 @@ public class ContextualParameters extend
      * implementation-dependent and may change in any future version.
      */
     @Override
-    public int hashCode() {
+    public synchronized int hashCode() {
         return (normalize.hashCode() + 31*denormalize.hashCode()) ^ Arrays.hashCode(values) ^ (int) serialVersionUID;
     }
 
@@ -573,7 +727,7 @@ public class ContextualParameters extend
      * @return {@code true} if the given object is equal to this one.
      */
     @Override
-    public boolean equals(final Object object) {
+    public synchronized boolean equals(final Object object) {
         if (object != null && object.getClass() == getClass()) {
             final ContextualParameters that = (ContextualParameters) object;
             return Objects.equals(descriptor,  that.descriptor)  &&
@@ -688,17 +842,17 @@ public class ContextualParameters extend
          * in order to apply a change of axis order). We need to separate the "user-defined"
          * step from the "normalize" step.
          */
-        Matrix userDefined = inverse ? denormalize : normalize;
-        if (!inverse) try {
-            userDefined = Matrices.inverse(userDefined);
-        } catch (NoninvertibleMatrixException e) {
+        MatrixSIS userDefined;
+        try {
+            userDefined = getMatrix(inverse ? MatrixRole.DENORMALIZATION : MatrixRole.INVERSE_NORMALIZATION);
+        } catch (IllegalStateException e) {
             // Should never happen. But if it does, we abandon the attempt to change
             // the list elements and will format the objects in their "raw" format.
             unexpectedException(e);
             return index;
         }
         if (hasBefore) {
-            userDefined = Matrices.multiply(userDefined, before);
+            userDefined = userDefined.multiply(before);
         }
         /*
          * At this point "userDefined" is the affine transform to show to user instead of the
@@ -734,10 +888,9 @@ public class ContextualParameters extend
          * Note that if this operation fails, we will cancel everything we would have done
          * in this method (i.e. we do not touch the transforms list at all).
          */
-        userDefined = inverse ? normalize : denormalize;
         if (!inverse) try {
-            userDefined = Matrices.inverse(userDefined);
-        } catch (NoninvertibleMatrixException e) {
+            userDefined = getMatrix(inverse ? MatrixRole.NORMALIZATION : MatrixRole.INVERSE_DENORMALIZATION);
+        } catch (IllegalStateException e) {
             unexpectedException(e);
             return index;
         }
@@ -808,7 +961,7 @@ public class ContextualParameters extend
      * because this error should occurs only in the context of WKT formatting of a concatenated
      * transform.</p>
      */
-    private static void unexpectedException(final NoninvertibleMatrixException e) {
-        Logging.unexpectedException(Logging.getLogger(Loggers.WKT), ConcatenatedTransform.class, "formatTo", e);
+    private static void unexpectedException(final IllegalStateException e) {
+        Logging.unexpectedException(Logging.getLogger(Loggers.WKT), ConcatenatedTransform.class, "formatTo", e.getCause());
     }
 }

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CopyTransform.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CopyTransform.java?rev=1713527&r1=1713526&r2=1713527&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CopyTransform.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CopyTransform.java [UTF-8] Mon Nov  9 19:57:39 2015
@@ -17,7 +17,6 @@
 package org.apache.sis.referencing.operation.transform;
 
 import java.util.Arrays;
-import java.io.Serializable;
 import org.opengis.geometry.DirectPosition;
 import org.opengis.referencing.operation.Matrix;
 import org.opengis.referencing.operation.MathTransform;
@@ -39,10 +38,10 @@ import org.apache.sis.referencing.operat
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.5
- * @version 0.6
+ * @version 0.7
  * @module
  */
-final class CopyTransform extends AbstractLinearTransform implements Serializable {
+final class CopyTransform extends AbstractLinearTransform {
     /**
      * Serial number for inter-operability with different versions.
      */
@@ -61,11 +60,6 @@ final class CopyTransform extends Abstra
     private final int[] indices;
 
     /**
-     * The inverse transform. Will be created only when first needed.
-     */
-    private transient MathTransform inverse;
-
-    /**
      * Creates a new transform.
      *
      * @param srcDim The dimension of source coordinates.
@@ -339,8 +333,9 @@ final class CopyTransform extends Abstra
     public synchronized MathTransform inverse() throws NoninvertibleTransformException {
         if (inverse == null) {
             /*
-             * Note: we do not perform the following optimization, because MathTransforms.linear(…)
-             *       should never instantiate this class in the identity case.
+             * Note: no need to perform the following check as this point because MathTransforms.linear(…)
+             *       should never instantiate this class in the identity case and because we perform an
+             *       equivalent check later anyway.
              *
              *       if (isIdentity()) {
              *           inverse = this;
@@ -361,7 +356,7 @@ final class CopyTransform extends Abstra
             for (int j=srcDim; --j>=0;) {
                 if (reverse[j] < 0) {
                     final MatrixSIS matrix = Matrices.createZero(srcDim + 1, dstDim + 1);
-                    for (j=0; j<srcDim; j++) { // NOSONAR: the outer loop will not continue.
+                    for (j=0; j<srcDim; j++) {      // Okay to reuse 'j' since the outer loop will not continue.
                         final int i = reverse[j];
                         if (i >= 0) {
                             matrix.setElement(j, i, 1);
@@ -371,14 +366,16 @@ final class CopyTransform extends Abstra
                     }
                     matrix.setElement(srcDim, dstDim, 1);
                     inverse = MathTransforms.linear(matrix);
-                    if (inverse instanceof ProjectiveTransform) {
-                        ((ProjectiveTransform) inverse).inverse = this;
+                    if (inverse instanceof AbstractLinearTransform) {
+                        ((AbstractLinearTransform) inverse).inverse = this;
                     }
                     return inverse;
                 }
             }
             /*
-             * At this point, we known that we can create the inverse transform.
+             * At this point, we know that we can create the inverse transform.
+             * If this transform is the identity transform (we should never happen,
+             * but we are paranoiac), then the old and new arrays would be equal.
              */
             CopyTransform copyInverse = this;
             if (!Arrays.equals(reverse, indices)) {

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java?rev=1713527&r1=1713526&r2=1713527&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java [UTF-8] Mon Nov  9 19:57:39 2015
@@ -558,7 +558,7 @@ public class DefaultMathTransformFactory
              * NormalizedProjection class (our base class for all map projection implementations)
              * to known that the ellipsoid definitive parameter is the inverse flattening factor
              * instead than the semi-major axis length. It makes a small difference in the accuracy
-             * of the excentricity parameter.
+             * of the eccentricity parameter.
              */
             if (isIvfDefinitive) try {
                 parameters.parameter(Constants.INVERSE_FLATTENING).setValue(ellipsoid.getInverseFlattening());

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/IdentityTransform.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/IdentityTransform.java?rev=1713527&r1=1713526&r2=1713527&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/IdentityTransform.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/IdentityTransform.java [UTF-8] Mon Nov  9 19:57:39 2015
@@ -16,7 +16,6 @@
  */
 package org.apache.sis.referencing.operation.transform;
 
-import java.io.Serializable;
 import org.opengis.geometry.DirectPosition;
 import org.opengis.referencing.operation.Matrix;
 import org.opengis.referencing.operation.MathTransform;
@@ -37,7 +36,7 @@ import org.apache.sis.internal.referenci
  * @version 0.6
  * @module
  */
-final class IdentityTransform extends AbstractLinearTransform implements Serializable {
+final class IdentityTransform extends AbstractLinearTransform {
     /**
      * Serial number for inter-operability with different versions.
      */

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ProjectiveTransform.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ProjectiveTransform.java?rev=1713527&r1=1713526&r2=1713527&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ProjectiveTransform.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ProjectiveTransform.java [UTF-8] Mon Nov  9 19:57:39 2015
@@ -17,7 +17,6 @@
 package org.apache.sis.referencing.operation.transform;
 
 import java.util.Arrays;
-import java.io.Serializable;
 import org.opengis.geometry.DirectPosition;
 import org.opengis.referencing.operation.Matrix;
 import org.opengis.referencing.operation.MathTransform;
@@ -38,14 +37,12 @@ import org.apache.sis.util.ArgumentCheck
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.5
- * @version 0.5
+ * @version 0.7
  * @module
  *
  * @see java.awt.geom.AffineTransform
  */
-class ProjectiveTransform extends AbstractLinearTransform implements LinearTransform, ExtendedPrecisionMatrix,
-        Serializable // Not Cloneable, despite the clone() method.
-{
+class ProjectiveTransform extends AbstractLinearTransform implements ExtendedPrecisionMatrix {
     /**
      * Serial number for inter-operability with different versions.
      */
@@ -70,13 +67,6 @@ class ProjectiveTransform extends Abstra
     private final double[] elt;
 
     /**
-     * The inverse transform. Will be created only when first needed. This field is part of the serialization form
-     * in order to avoid rounding errors if a user asks for the inverse of the inverse (i.e. the original transform)
-     * after deserialization.
-     */
-    AbstractMathTransform inverse;
-
-    /**
      * Constructs a transform from the specified matrix.
      * The matrix is usually square and affine, but this is not enforced.
      *
@@ -158,7 +148,7 @@ class ProjectiveTransform extends Abstra
      * instead than using a factory method.</div>
      */
     @Override
-    public boolean isIdentity() {
+    public final boolean isIdentity() {
         if (numRow != numCol) {
             return false;
         }
@@ -180,9 +170,9 @@ class ProjectiveTransform extends Abstra
      * @return {@inheritDoc}
      */
     @Override
-    public Matrix transform(final double[] srcPts, final int srcOff,
-                            final double[] dstPts, final int dstOff,
-                            final boolean derivate)
+    public final Matrix transform(final double[] srcPts, final int srcOff,
+                                  final double[] dstPts, final int dstOff,
+                                  final boolean derivate)
     {
         transform(srcPts, srcOff, dstPts, dstOff, 1);
         return derivate ? derivative((DirectPosition) null) : null;
@@ -205,7 +195,7 @@ class ProjectiveTransform extends Abstra
      * @param numPts The number of points to be transformed.
      */
     @Override
-    public void transform(double[] srcPts, int srcOff, double[] dstPts, int dstOff, int numPts) {
+    public final void transform(double[] srcPts, int srcOff, double[] dstPts, int dstOff, int numPts) {
         final int srcDim, dstDim;
         int srcInc = srcDim = numCol - 1; // The last ordinate will be assumed equal to 1.
         int dstInc = dstDim = numRow - 1;
@@ -276,7 +266,7 @@ class ProjectiveTransform extends Abstra
      * @param numPts The number of points to be transformed.
      */
     @Override
-    public void transform(float[] srcPts, int srcOff, float[] dstPts, int dstOff, int numPts) {
+    public final void transform(float[] srcPts, int srcOff, float[] dstPts, int dstOff, int numPts) {
         final int srcDim, dstDim;
         int srcInc = srcDim = numCol-1;
         int dstInc = dstDim = numRow-1;
@@ -332,7 +322,7 @@ class ProjectiveTransform extends Abstra
      * @param numPts The number of points to be transformed.
      */
     @Override
-    public void transform(double[] srcPts, int srcOff, float[] dstPts, int dstOff, int numPts) {
+    public final void transform(double[] srcPts, int srcOff, float[] dstPts, int dstOff, int numPts) {
         final int srcDim = numCol-1;
         final int dstDim = numRow-1;
         final double[] buffer = new double[numRow];
@@ -367,7 +357,7 @@ class ProjectiveTransform extends Abstra
      * @param numPts The number of points to be transformed.
      */
     @Override
-    public void transform(float[] srcPts, int srcOff, double[] dstPts, int dstOff, int numPts) {
+    public final void transform(float[] srcPts, int srcOff, double[] dstPts, int dstOff, int numPts) {
         final int srcDim = numCol - 1;
         final int dstDim = numRow - 1;
         final double[] buffer = new double[numRow];
@@ -399,7 +389,7 @@ class ProjectiveTransform extends Abstra
      * @param point Ignored (can be {@code null}).
      */
     @Override
-    public Matrix derivative(final DirectPosition point) {
+    public final Matrix derivative(final DirectPosition point) {
         final int srcDim = numCol - 1;
         final int dstDim = numRow - 1;
         final MatrixSIS matrix = Matrices.createZero(dstDim, srcDim);
@@ -420,29 +410,23 @@ class ProjectiveTransform extends Abstra
     public synchronized MathTransform inverse() throws NoninvertibleTransformException {
         if (inverse == null) {
             /*
-             * Note: we do not perform the following optimization, because MathTransforms.linear(…)
-             *       should never instantiate this class in the identity case.
-             *
-             *       if (isIdentity()) {
-             *           inverse = this;
-             *       } else { ... }
+             * Should never be the identity transform at this point (except during tests) because
+             * MathTransforms.linear(…) should never instantiate this class in the identity case.
+             * But we check anyway as a paranoiac safety.
              */
-            ProjectiveTransform inv = createInverse(Matrices.inverse(this));
-            inv.inverse = this;
-            inverse = inv;
+            if (isIdentity()) {
+                inverse = this;
+            } else {
+                inverse = MathTransforms.linear(Matrices.inverse(this));
+                if (inverse instanceof AbstractLinearTransform) {
+                    ((AbstractLinearTransform) inverse).inverse = this;
+                }
+            }
         }
         return inverse;
     }
 
     /**
-     * Creates an inverse transform using the specified matrix.
-     * To be overridden by {@link GeocentricTranslation}.
-     */
-    ProjectiveTransform createInverse(final Matrix matrix) {
-        return new ProjectiveTransform(matrix);
-    }
-
-    /**
      * {@inheritDoc}
      *
      * @return {@inheritDoc}

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ProjectiveTransform2D.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ProjectiveTransform2D.java?rev=1713527&r1=1713526&r2=1713527&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ProjectiveTransform2D.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ProjectiveTransform2D.java [UTF-8] Mon Nov  9 19:57:39 2015
@@ -89,12 +89,4 @@ final class ProjectiveTransform2D extend
     public MathTransform2D inverse() throws NoninvertibleTransformException {
         return (MathTransform2D) super.inverse();
     }
-
-    /**
-     * Creates an inverse transform using the specified matrix.
-     */
-    @Override
-    ProjectiveTransform2D createInverse(final Matrix matrix) {
-        return new ProjectiveTransform2D(matrix);
-    }
 }

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/package-info.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/package-info.java?rev=1713527&r1=1713526&r2=1713527&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/package-info.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/package-info.java [UTF-8] Mon Nov  9 19:57:39 2015
@@ -62,7 +62,7 @@
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @author  Adrian Custer (Geomatys)
  * @since   0.5
- * @version 0.6
+ * @version 0.7
  * @module
  */
 package org.apache.sis.referencing.operation.transform;

Modified: sis/branches/JDK7/core/sis-referencing/src/main/resources/META-INF/services/org.opengis.referencing.operation.OperationMethod
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/resources/META-INF/services/org.opengis.referencing.operation.OperationMethod?rev=1713527&r1=1713526&r2=1713527&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/resources/META-INF/services/org.opengis.referencing.operation.OperationMethod [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/resources/META-INF/services/org.opengis.referencing.operation.OperationMethod [UTF-8] Mon Nov  9 19:57:39 2015
@@ -2,6 +2,19 @@
 # Heavier classes (e.g. having more dependencies) or classes less likely to be used, should be last.
 org.apache.sis.internal.referencing.provider.Affine
 org.apache.sis.internal.referencing.provider.LongitudeRotation
+org.apache.sis.internal.referencing.provider.GeocentricTranslation
+org.apache.sis.internal.referencing.provider.PositionVector7Param
+org.apache.sis.internal.referencing.provider.CoordinateFrameRotation
+org.apache.sis.internal.referencing.provider.GeographicToGeocentric
+org.apache.sis.internal.referencing.provider.GeocentricToGeographic
+org.apache.sis.internal.referencing.provider.GeocentricTranslation2D
+org.apache.sis.internal.referencing.provider.GeocentricTranslation3D
+org.apache.sis.internal.referencing.provider.PositionVector7Param2D
+org.apache.sis.internal.referencing.provider.PositionVector7Param3D
+org.apache.sis.internal.referencing.provider.CoordinateFrameRotation2D
+org.apache.sis.internal.referencing.provider.CoordinateFrameRotation3D
+org.apache.sis.internal.referencing.provider.Molodensky
+org.apache.sis.internal.referencing.provider.AbridgedMolodensky
 org.apache.sis.internal.referencing.provider.Equirectangular
 org.apache.sis.internal.referencing.provider.Mercator1SP
 org.apache.sis.internal.referencing.provider.Mercator2SP

Modified: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/AllProvidersTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/AllProvidersTest.java?rev=1713527&r1=1713526&r2=1713527&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/AllProvidersTest.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/AllProvidersTest.java [UTF-8] Mon Nov  9 19:57:39 2015
@@ -53,6 +53,19 @@ public final strictfp class AllProviders
         return new Class<?>[] {
             Affine.class,
             LongitudeRotation.class,
+            CoordinateFrameRotation.class,
+            CoordinateFrameRotation2D.class,
+            CoordinateFrameRotation3D.class,
+            PositionVector7Param.class,
+            PositionVector7Param2D.class,
+            PositionVector7Param3D.class,
+            GeocentricTranslation.class,
+            GeocentricTranslation2D.class,
+            GeocentricTranslation3D.class,
+            GeographicToGeocentric.class,
+            GeocentricToGeographic.class,
+            Molodensky.class,
+            AbridgedMolodensky.class,
             Equirectangular.class,
             Mercator1SP.class,
             Mercator2SP.class,

Modified: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/LongitudeRotationTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/LongitudeRotationTest.java?rev=1713527&r1=1713526&r2=1713527&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/LongitudeRotationTest.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/LongitudeRotationTest.java [UTF-8] Mon Nov  9 19:57:39 2015
@@ -46,7 +46,7 @@ public final strictfp class LongitudeRot
     public void testCreateMathTransform() {
         final LongitudeRotation provider = new LongitudeRotation();
         ParameterValueGroup p = provider.getParameters().createValue();
-        p.parameter(LongitudeRotation.NAME).setValue(2.5969213, NonSI.GRADE);   // Paris meridian
+        p.parameter("Longitude offset").setValue(2.5969213, NonSI.GRADE);   // Paris meridian
         final MathTransform mt = provider.createMathTransform(null, p);
         /*
          * Verify the full matrix. Note that the longitude offset is expected to be in degrees.
@@ -69,7 +69,7 @@ public final strictfp class LongitudeRot
     public void testWKT() {
         final LongitudeRotation provider = new LongitudeRotation();
         final ParameterValueGroup p = provider.getParameters().createValue();
-        p.parameter(LongitudeRotation.NAME).setValue(2.5969213, NonSI.GRADE);
+        p.parameter("Longitude offset").setValue(2.5969213, NonSI.GRADE);
         assertWktEquals(
                 "PARAM_MT[“Affine parametric transformation”,\n" +
                 "  PARAMETER[“A2”, 2.33722917, ID[“EPSG”, 8625]]]", provider.createMathTransform(null, p));

Modified: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/io/wkt/WKTParserTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/io/wkt/WKTParserTest.java?rev=1713527&r1=1713526&r2=1713527&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/io/wkt/WKTParserTest.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/io/wkt/WKTParserTest.java [UTF-8] Mon Nov  9 19:57:39 2015
@@ -281,8 +281,8 @@ public final strictfp class WKTParserTes
      *  BASEGEODCRS[“NAD83(86)”,
      *    DATUM[“North American Datum 1983”,
      *      ELLIPSOID[“GRS 1980”,6378137,298.257222101]],
-     *    ANGLEUNIT[“degree”,0.0174532925199433]],
-     *    PRIMEM[“Greenwich”,0],
+     *    ANGLEUNIT[“degree”,0.0174532925199433],
+     *    PRIMEM[“Greenwich”,0]],
      *  CONVERSION[“UTM zone 10N”,ID[“EPSG”,16010],
      *    METHOD[“Transverse Mercator”],
      *    PARAMETER[“Latitude of natural origin”,0.0],

Modified: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/parameter/DefaultParameterValueTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/parameter/DefaultParameterValueTest.java?rev=1713527&r1=1713526&r2=1713527&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/parameter/DefaultParameterValueTest.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/parameter/DefaultParameterValueTest.java [UTF-8] Mon Nov  9 19:57:39 2015
@@ -607,9 +607,15 @@ public final strictfp class DefaultParam
     @Test
     @DependsOnMethod("testWKT")
     public void testWKT_withUnformattableUnit() {
-        final DefaultParameterValue<Double> p = create("Angle", 10.3, Units.valueOfEPSG(9111));
+        final Unit<?> degreesAndMinutes = Units.valueOfEPSG(9111);
+        DefaultParameterValue<Double> p = create("Angle", 10.3, degreesAndMinutes);
         assertWktEquals(Convention.WKT1,     "PARAMETER[“Angle”, 10.3]", p);  // 10.3 DM  ==  10.5°
         assertWktEquals(Convention.WKT2,     "PARAMETER[“Angle”, 10.5, ANGLEUNIT[“degree”, 0.017453292519943295]]", p);
+        assertWktEquals(Convention.INTERNAL, "Parameter[“Angle”, 10.3]", p);   // Value in same unit than descriptor.
+
+        p = create("Angle", 0, NonSI.DEGREE_ANGLE);
+        p.setValue(10.3, degreesAndMinutes);  // Can not be formatted in WKT1.
+        assertWktEquals(Convention.WKT2,     "PARAMETER[“Angle”, 10.5, ANGLEUNIT[“degree”, 0.017453292519943295]]", p);
         assertWktEquals(Convention.INTERNAL, "Parameter[“Angle”, 10.3, Unit[“D.M”, 0.017453292519943295, Id[“EPSG”, 9111]]]", p);
     }
 

Modified: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/datum/DefaultEllipsoidTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/datum/DefaultEllipsoidTest.java?rev=1713527&r1=1713526&r2=1713527&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/datum/DefaultEllipsoidTest.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/datum/DefaultEllipsoidTest.java [UTF-8] Mon Nov  9 19:57:39 2015
@@ -38,7 +38,7 @@ import static org.apache.sis.test.Metada
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.4
- * @version 0.4
+ * @version 0.7
  * @module
  */
 @DependsOn({
@@ -70,6 +70,46 @@ public final strictfp class DefaultEllip
     }
 
     /**
+     * Tests {@link DefaultEllipsoid#getEccentricity()}.
+     *
+     * @since 0.7
+     */
+    @Test
+    public void testGetEccentricity() {
+        final DefaultEllipsoid e = new DefaultEllipsoid(GeodeticDatumMock.WGS84.getEllipsoid());
+        assertEquals("semiMajorAxis",       6378137.0,            e.getSemiMajorAxis(),       STRICT);   // By definition
+        assertEquals("inverseFlattening",   298.257223563,        e.getInverseFlattening(),   STRICT);   // By definition
+        assertEquals("eccentricitySquared", 0.006694379990141317, e.getEccentricitySquared(), STRICT);
+        assertEquals("eccentricity",        0.0818191908426215,   e.getEccentricity(),        STRICT);
+    }
+
+    /**
+     * Tests {@link DefaultEllipsoid#semiMajorAxisDifference(Ellipsoid)}. This test uses the data provided
+     * in §2.4.4.2 of IOGP Publication 373-7-2 – Geomatics Guidance Note number 7, part 2 – April 2015.
+     *
+     * @since 0.7
+     */
+    @Test
+    public void testSemiMajorAxisDifference() {
+        final DefaultEllipsoid e = new DefaultEllipsoid(GeodeticDatumMock.WGS84.getEllipsoid());
+        assertEquals("semiMajorAxisDifference",   0, e.semiMajorAxisDifference(GeodeticDatumMock.WGS84.getEllipsoid()), STRICT);
+        assertEquals("semiMajorAxisDifference", 251, e.semiMajorAxisDifference(GeodeticDatumMock.ED50 .getEllipsoid()), STRICT);
+    }
+
+    /**
+     * Tests {@link DefaultEllipsoid#flatteningDifference(Ellipsoid)}. This test uses the data provided
+     * in §2.4.4.2 of IOGP Publication 373-7-2 – Geomatics Guidance Note number 7, part 2 – April 2015.
+     *
+     * @since 0.7
+     */
+    @Test
+    public void testFlatteningDifference() {
+        final DefaultEllipsoid e = new DefaultEllipsoid(GeodeticDatumMock.WGS84.getEllipsoid());
+        assertEquals("flatteningDifference", 0.0,         e.flatteningDifference(GeodeticDatumMock.WGS84.getEllipsoid()), STRICT);
+        assertEquals("flatteningDifference", 1.41927E-05, e.flatteningDifference(GeodeticDatumMock.ED50 .getEllipsoid()), 1E-10);
+    }
+
+    /**
      * Tests the orthodromic distances computed by {@link DefaultEllipsoid}. There is actually two algorithms:
      * one for the ellipsoidal model, and a simpler one for spherical model. This method tests the ellipsoidal
      * model using known values of nautical mile at different latitude.

Modified: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/MatricesTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/MatricesTest.java?rev=1713527&r1=1713526&r2=1713527&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/MatricesTest.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/MatricesTest.java [UTF-8] Mon Nov  9 19:57:39 2015
@@ -364,6 +364,45 @@ public final strictfp class MatricesTest
     }
 
     /**
+     * Tests {@link Matrices#removeRows(Matrix, int, int)}
+     */
+    @Test
+    public void testRemoveRows() {
+        Matrix matrix = Matrices.create(4, 5, new double[] {
+            1, 2, 7, 8, 9,
+            3, 4, 6, 7, 8,
+            9, 8, 7, 6, 5,
+            4, 3, 2, 1, 0
+        });
+        matrix = Matrices.removeRows(matrix, 3, 4);
+        assertEquals(Matrices.create(3, 5, new double[] {
+            1, 2, 7, 8, 9,
+            3, 4, 6, 7, 8,
+            9, 8, 7, 6, 5
+        }), matrix);
+    }
+
+    /**
+     * Tests {@link Matrices#removeColumns(Matrix, int, int)}
+     */
+    @Test
+    public void testRemoveColumns() {
+        Matrix matrix = Matrices.create(4, 5, new double[] {
+            1, 2, 7, 8, 9,
+            3, 4, 6, 7, 8,
+            9, 8, 7, 6, 5,
+            4, 3, 2, 1, 0
+        });
+        matrix = Matrices.removeColumns(matrix, 2, 4);
+        assertEquals(Matrices.create(4, 3, new double[] {
+            1, 2, 9,
+            3, 4, 8,
+            9, 8, 5,
+            4, 3, 0
+        }), matrix);
+    }
+
+    /**
      * Tests {@link Matrices#copy(Matrix)}
      */
     @Test

Modified: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/ConformalProjectionTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/ConformalProjectionTest.java?rev=1713527&r1=1713526&r2=1713527&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/ConformalProjectionTest.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/ConformalProjectionTest.java [UTF-8] Mon Nov  9 19:57:39 2015
@@ -154,7 +154,7 @@ public final strictfp class ConformalPro
      * @return {@code Math.exp} of the Mercator projection of the given latitude.
      */
     private static double expOfNorthing(final ConformalProjection projection, final double φ) {
-        return projection.expOfNorthing(φ, projection.excentricity * sin(φ));
+        return projection.expOfNorthing(φ, projection.eccentricity * sin(φ));
     }
 
     /**
@@ -300,7 +300,7 @@ public final strictfp class ConformalPro
     @Test
     public void compareWithSeriesExpansion() throws ProjectionException {
         final ConformalProjection projection = new NoOp(true);
-        final MercatorMethodComparison comparator = new MercatorMethodComparison(projection.excentricitySquared);
+        final MercatorMethodComparison comparator = new MercatorMethodComparison(projection.eccentricitySquared);
         final Random random = TestUtilities.createRandomNumberGenerator();
         final int numSamples = 2000;
         for (int i=0; i<numSamples; i++) {

Modified: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/LambertConicConformalTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/LambertConicConformalTest.java?rev=1713527&r1=1713526&r2=1713527&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/LambertConicConformalTest.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/LambertConicConformalTest.java [UTF-8] Mon Nov  9 19:57:39 2015
@@ -91,10 +91,10 @@ public final strictfp class LambertConic
 
     /**
      * Tests the WKT formatting of {@link NormalizedProjection}. For the Lambert Conformal projection, we expect
-     * the internal {@code n} parameter in addition to the excentricity.
+     * the internal {@code n} parameter in addition to the eccentricity.
      *
      * <div class="section">Note on accuracy</div>
-     * The value of the excentricity parameter should be fully accurate because it is calculated using only the
+     * The value of the eccentricity parameter should be fully accurate because it is calculated using only the
      * {@link Math#sqrt(double)} function (ignoring basic algebraic operations) which, according javadoc, must
      * give the result closest to the true mathematical result. But the functions involved in the calculation of
      * <var>n</var> do not have such strong guarantees. So we use a regular expression in this test for ignoring
@@ -103,9 +103,9 @@ public final strictfp class LambertConic
     @Test
     public void testNormalizedWKT() {
         createNormalizedProjection(true, 40);
-        assertWktEqualsRegex("\\Q" +
+        assertWktEqualsRegex("(?m)\\Q" +
                 "PARAM_MT[“Lambert conic conformal”,\n" +
-                "  PARAMETER[“excentricity”, 0.0818191908426215],\n" +
+                "  PARAMETER[“eccentricity”, 0.0818191908426215],\n" +
                 "  PARAMETER[“n”, 0.64278760968653\\E\\d*\\]\\]");  // 0.6427876096865393 in the original test.
     }
 
@@ -138,7 +138,7 @@ public final strictfp class LambertConic
         assertEquals ("Inverse -∞", +PI/2, inverseTransform(-INF), NORMALIZED_TOLERANCE);
 
         // Like the north case, but with sign inversed.
-        createNormalizedProjection(((LambertConicConformal) transform).excentricity != 0, -40);
+        createNormalizedProjection(((LambertConicConformal) transform).eccentricity != 0, -40);
         validate();
 
         assertEquals ("Not a number",     NaN, transform(NaN),            NORMALIZED_TOLERANCE);

Modified: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MercatorMethodComparison.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MercatorMethodComparison.java?rev=1713527&r1=1713526&r2=1713527&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MercatorMethodComparison.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MercatorMethodComparison.java [UTF-8] Mon Nov  9 19:57:39 2015
@@ -41,16 +41,16 @@ import static java.lang.Math.*;     // N
  *
  * In our measurements, both the iterative process (USGS) and the series expansion (EPSG) have the
  * same accuracy when applied on the WGS84 ellipsoid. However the EPSG formula is 2 times faster.
- * On the other hand, accuracy of the EPSG formula decreases when we increase the excentricity,
+ * On the other hand, accuracy of the EPSG formula decreases when we increase the eccentricity,
  * while the iterative process keeps its accuracy (at the cost of more iterations).
- * For the Earth (excentricity of about 0.082) the errors are less than 0.01 millimetres.
+ * For the Earth (eccentricity of about 0.082) the errors are less than 0.01 millimetres.
  * But the errors become centimetric (for a hypothetical planet of the size of the Earth)
- * before excentricity 0.2 and increase quickly after excentricity 0.3.
+ * before eccentricity 0.2 and increase quickly after eccentricity 0.3.
  *
  * <p>For the WGS84 ellipsoid and the iteration tolerance given by the {@link NormalizedProjection#ITERATION_TOLERANCE}
  * constant (currently about 0.25 cm on Earth), the two methods have equivalent precision. Computing φ values for
  * millions of random numbers and verifying which method is the most accurate give fifty-fifty results: each method
- * win in about 50% of cases. But as we increase the excentricity, the iterative method wins more often.</p>
+ * win in about 50% of cases. But as we increase the eccentricity, the iterative method wins more often.</p>
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.6
@@ -65,9 +65,9 @@ public final class MercatorMethodCompari
     private static final PrintStream out = System.out;
 
     /**
-     * Ellipsoid excentricity. Value 0 means that the ellipsoid is spherical.
+     * Ellipsoid eccentricity. Value 0 means that the ellipsoid is spherical.
      */
-    private final double excentricity;
+    private final double eccentricity;
 
     /**
      * Coefficients used in the series expansion.
@@ -76,34 +76,34 @@ public final class MercatorMethodCompari
 
     /**
      * Creates a new instance for the excentricty of the WGS84 ellipsoid, which is approximatively 0.08181919084262157.
-     * Reminder: the excentricity of a sphere is 0.
+     * Reminder: the eccentricity of a sphere is 0.
      */
     public MercatorMethodComparison() {
-        this(0.00669437999014133);  // Squared excentricity.
+        this(0.00669437999014133);  // Squared eccentricity.
     }
 
     /**
-     * Creates a new instance for the same excentricity than the given projection.
+     * Creates a new instance for the same eccentricity than the given projection.
      *
-     * @param projection the projection from which to take the excentricity.
+     * @param projection the projection from which to take the eccentricity.
      */
     public MercatorMethodComparison(final NormalizedProjection projection) {
-        this(projection.excentricitySquared);
+        this(projection.eccentricitySquared);
     }
 
     /**
-     * Creates a new instance for the given squared excentricity.
+     * Creates a new instance for the given squared eccentricity.
      *
-     * @param e2 the square of the excentricity.
+     * @param e2 the square of the eccentricity.
      */
     public MercatorMethodComparison(final double e2) {
-        excentricity = sqrt(e2);
+        eccentricity = sqrt(e2);
         final double e4 = e2 * e2;
         final double e6 = e2 * e4;
         final double e8 = e4 * e4;
         /*
          * For each line below, add the smallest values first in order to reduce rounding errors.
-         * The smallest values are the one using the excentricity raised to the highest power.
+         * The smallest values are the one using the eccentricity raised to the highest power.
          */
         c2χ  =    13/   360.* e8  +   1/ 12.* e6  +  5/24.* e4  +  e2/2;
         c4χ  =   811/ 11520.* e8  +  29/240.* e6  +  7/48.* e4;
@@ -159,12 +159,12 @@ public final class MercatorMethodCompari
      * @throws ProjectionException if the iteration does not converge.
      */
     public double byIterativeMethod(final double t) throws ProjectionException {
-        final double hℯ = 0.5 * excentricity;
-        double φ = (PI/2) - 2*atan(t);                                      // Snyder (7-11)
-        for (int i=0; i<NormalizedProjection.MAXIMUM_ITERATIONS; i++) {     // Iteratively solve equation (7-9) from Snyder
-            final double ℯsinφ = excentricity * sin(φ);
-            final double Δφ = abs(φ - (φ = PI/2 - 2*atan(t * pow((1 - ℯsinφ)/(1 + ℯsinφ), hℯ))));
-            if (Δφ <= NormalizedProjection.ITERATION_TOLERANCE) {
+        final double hℯ = 0.5 * eccentricity;
+        double φ = (PI/2) - 2*atan(t);                                          // Snyder (7-11)
+        for (int it=0; it < NormalizedProjection.MAXIMUM_ITERATIONS; it++) {    // Iteratively solve equation (7-9) from Snyder
+            final double ℯsinφ = eccentricity * sin(φ);
+            final double Δφ = φ - (φ = PI/2 - 2*atan(t * pow((1 - ℯsinφ)/(1 + ℯsinφ), hℯ)));
+            if (abs(Δφ) <= NormalizedProjection.ITERATION_TOLERANCE) {
                 return φ;
             }
         }
@@ -178,8 +178,8 @@ public final class MercatorMethodCompari
      * Basically a copy of {@link ConformalProjection#expOfNorthing(double, double)}.
      */
     final double expOfNorthing(final double φ) {
-        final double ℯsinφ = excentricity * sin(φ);
-        return tan(PI/4 + 0.5*φ) * pow((1 - ℯsinφ) / (1 + ℯsinφ), 0.5*excentricity);
+        final double ℯsinφ = eccentricity * sin(φ);
+        return tan(PI/4 + 0.5*φ) * pow((1 - ℯsinφ) / (1 + ℯsinφ), 0.5*eccentricity);
     }
 
     /**
@@ -221,13 +221,13 @@ public final class MercatorMethodCompari
             }
         }
         /*
-         * At this point we finished to collect the statistics for the excentricity of this particular
+         * At this point we finished to collect the statistics for the eccentricity of this particular
          * MercatorMethodComparison instance. If this method call is only part of a longer calculation
          * for various excentricty values, print a summary in a single line.
          * Otherwise print more verbose results.
          */
         if (summarize != null) {
-            summarize.append(String.valueOf(excentricity));                     summarize.nextColumn();
+            summarize.append(String.valueOf(eccentricity));                     summarize.nextColumn();
             summarize.append(String.valueOf(iterativeMethodErrors.mean()));     summarize.nextColumn();
             summarize.append(String.valueOf(iterativeMethodErrors.maximum()));  summarize.nextColumn();
             summarize.append(String.valueOf(seriesExpansionErrors.mean()));     summarize.nextColumn();
@@ -242,7 +242,7 @@ public final class MercatorMethodCompari
             if (projection == null) {
                 stats = ArraysExt.remove(stats, 2, 1);
             }
-            out.println("Comparison of different ways to compute φ for excentricity " + excentricity + '.');
+            out.println("Comparison of different ways to compute φ for eccentricity " + eccentricity + '.');
             out.println("Values are in units of " + NormalizedProjection.ITERATION_TOLERANCE + " radians (about "
                     + round(toDegrees(NormalizedProjection.ITERATION_TOLERANCE) * 60 * ReferencingServices.NAUTICAL_MILE * 1000)
                     + " mm on Earth).");
@@ -258,21 +258,21 @@ public final class MercatorMethodCompari
     }
 
     /**
-     * Prints the error of the two methods for various excentricity values.
-     * The intend of this method is to find an excentricity threshold value where we consider the errors too high.
+     * Prints the error of the two methods for various eccentricity values.
+     * The intend of this method is to find an eccentricity threshold value where we consider the errors too high.
      *
-     * <p>This method is used for determining empirically a value for {@link ConformalProjection#EXCENTRICITY_THRESHOLD}.
+     * <p>This method is used for determining empirically a value for {@link ConformalProjection#ECCENTRICITY_THRESHOLD}.
      * The current threshold value is shown by inserting a horizontal line separator in the table when that threshold
      * is crossed.</p>
      *
-     * @param min The first excentricity value to test.
-     * @param max The maximal excentricity value to test.
+     * @param min The first eccentricity value to test.
+     * @param max The maximal eccentricity value to test.
      * @throws ProjectionException if an error occurred in {@link #φ(double)}.
      */
     public static void printErrorForExcentricities(final double min, final double max) throws ProjectionException {
         final TableAppender table = new TableAppender(out);
         table.appendHorizontalSeparator();
-        table.append("Excentricity");            table.nextColumn();
+        table.append("Eccentricity");            table.nextColumn();
         table.append("Mean iterative error");    table.nextColumn();
         table.append("Maximal iterative error"); table.nextColumn();
         table.append("Mean series error");       table.nextColumn();
@@ -280,13 +280,13 @@ public final class MercatorMethodCompari
         table.appendHorizontalSeparator();
         boolean crossThreshold = false;
         final double step = 0.01;
-        double excentricity;
-        for (int i=0; (excentricity = min + step*i) < max; i++) {
-            if (!crossThreshold && excentricity >= ConformalProjection.EXCENTRICITY_THRESHOLD) {
+        double eccentricity;
+        for (int i=0; (eccentricity = min + step*i) < max; i++) {
+            if (!crossThreshold && eccentricity >= ConformalProjection.ECCENTRICITY_THRESHOLD) {
                 crossThreshold = true;
                 table.appendHorizontalSeparator();
             }
-            final MercatorMethodComparison alt = new MercatorMethodComparison(excentricity * excentricity);
+            final MercatorMethodComparison alt = new MercatorMethodComparison(eccentricity * eccentricity);
             alt.compare(null, 10000, table);
         }
         table.appendHorizontalSeparator();
@@ -339,7 +339,7 @@ public final class MercatorMethodCompari
      * @throws InterruptedException if the thread has been interrupted between two benchmarks.
      */
     public static void main(String[] args) throws ProjectionException, InterruptedException {
-        out.println("Comparison of the errors of series expension and iterative method for various excentricity values.");
+        out.println("Comparison of the errors of series expension and iterative method for various eccentricity values.");
         printErrorForExcentricities(0.08, 0.3);
 
         out.println();
@@ -351,7 +351,7 @@ public final class MercatorMethodCompari
         c.compare(projection, 10000, null);
 
         out.println();
-        out.println("Comparison of the errors for the WGS84 excentricity.");
+        out.println("Comparison of the errors for the WGS84 eccentricity.");
         out.println("The 'ConformalProjection' errors should be the same than the series expansion errors:");
         out.println();
         projection = new NoOp(true);
@@ -359,7 +359,7 @@ public final class MercatorMethodCompari
         c.compare(projection, 1000000, null);
 
         out.println();
-        out.println("Comparison of the errors for the excentricity of an imaginary ellipsoid.");
+        out.println("Comparison of the errors for the eccentricity of an imaginary ellipsoid.");
         out.println("The 'ConformalProjection' errors should be the close to the iterative method errors:");
         out.println();
         projection = new NoOp(100, 95);

Modified: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MercatorTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MercatorTest.java?rev=1713527&r1=1713526&r2=1713527&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MercatorTest.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MercatorTest.java [UTF-8] Mon Nov  9 19:57:39 2015
@@ -66,7 +66,7 @@ public final strictfp class MercatorTest
 
     /**
      * Tests the WKT formatting of {@link NormalizedProjection}. For the Mercator projection, we expect only
-     * the ellipsoid excentricity. We expect nothing else because all other parameters are used
+     * the ellipsoid eccentricity. We expect nothing else because all other parameters are used
      * by the (de)normalization affine transforms instead than the {@link Mercator} class itself.
      *
      * @see LambertConicConformalTest#testNormalizedWKT()
@@ -76,7 +76,7 @@ public final strictfp class MercatorTest
         createNormalizedProjection(true);
         assertWktEquals(
                 "PARAM_MT[“Mercator”,\n" +
-                "  PARAMETER[“excentricity”, 0.0818191908426215]]");
+                "  PARAMETER[“eccentricity”, 0.0818191908426215]]");
     }
 
     /**

Modified: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NormalizedProjectionTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NormalizedProjectionTest.java?rev=1713527&r1=1713526&r2=1713527&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NormalizedProjectionTest.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NormalizedProjectionTest.java [UTF-8] Mon Nov  9 19:57:39 2015
@@ -62,13 +62,13 @@ public final strictfp class NormalizedPr
     }
 
     /**
-     * Tests the {@link NormalizedProjection#excentricity} value.
+     * Tests the {@link NormalizedProjection#eccentricity} value.
      */
     @Test
-    public void testExcentricity() {
+    public void testEccentricity() {
         NormalizedProjection projection;
         transform = projection = new NoOp(false);
-        assertEquals("excentricity", 0.0, projection.excentricity, 0.0);
+        assertEquals("eccentricity", 0.0, projection.eccentricity, 0.0);
         /*
          * Tested methods. Note the similarity between (1) and (3).
          *
@@ -77,9 +77,9 @@ public final strictfp class NormalizedPr
          *  (3) Using double-double arithmetic and flattening:    0.0818191908426215
          */
         transform = projection = new NoOp(true, false);
-        assertEquals("excentricity", 0.08181919084262244, projection.excentricity, 0.0);
+        assertEquals("eccentricity", 0.08181919084262244, projection.eccentricity, 0.0);
 
         transform = projection = new NoOp(true, true);
-        assertEquals("excentricity", 0.0818191908426215, projection.excentricity, 0.0);
+        assertEquals("eccentricity", 0.0818191908426215, projection.eccentricity, 0.0);
     }
 }




Mime
View raw message