This is an automated email from the ASF dual-hosted git repository.

desruisseaux pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git

commit a7331c907e1a349650c4f0b30ae864d13bebc0b5
Author: Martin Desruisseaux <martin.desruisse...@geomatys.com>
AuthorDate: Sat Oct 28 19:10:10 2023 +0200

    Remove the deprecated `InterpolatedMolodenskyTransform` class.
---
 .../provider/FranceGeocentricInterpolation.java    |  23 +-
 .../provider/MolodenskyInterpolation.java          | 105 -----
 .../operation/transform/DatumShiftTransform.java   |  32 +-
 .../transform/InterpolatedGeocentricTransform.java |  30 +-
 .../transform/InterpolatedMolodenskyTransform.java | 458 ---------------------
 .../InterpolatedMolodenskyTransform2D.java         | 139 -------
 .../operation/transform/MolodenskyFormula.java     |  47 +--
 .../operation/transform/MolodenskyTransform.java   |   2 +-
 .../operation/transform/package-info.java          |   2 +-
 .../operation/provider/ProvidersTest.java          |   1 -
 .../InterpolatedMolodenskyTransformTest.java       | 130 ------
 11 files changed, 42 insertions(+), 927 deletions(-)

diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/FranceGeocentricInterpolation.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/FranceGeocentricInterpolation.java
index 81254b185f..8ecac1c44e 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/FranceGeocentricInterpolation.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/FranceGeocentricInterpolation.java
@@ -226,9 +226,8 @@ public class FranceGeocentricInterpolation extends 
GeodeticOperation {
     /**
      * Returns the provider for the specified combination of source and target 
dimensions.
      */
-    // TODO: make final after removal of deprecated `MolodenskyInterpolation` 
subclass.
     @Override
-    GeodeticOperation redimensioned(int indexOfDim) {
+    final GeodeticOperation redimensioned(int indexOfDim) {
         return REDIMENSIONED[indexOfDim];
     }
 
@@ -357,12 +356,11 @@ public class FranceGeocentricInterpolation extends 
GeodeticOperation {
             // NumberFormatException, ArithmeticException, 
NoSuchElementException, and more.
             throw DatumShiftGridLoader.canNotLoad(HEADER, file, e);
         }
-        MathTransform tr = createGeodeticTransformation(factory,
+        MathTransform tr = 
InterpolatedGeocentricTransform.createGeodeticTransformation(factory,
                 createEllipsoid(pg, Molodensky.TGT_SEMI_MAJOR,
-                                    Molodensky.TGT_SEMI_MINOR, 
CommonCRS.ETRS89.ellipsoid()),   // GRS 1980 ellipsoid
+                                    Molodensky.TGT_SEMI_MINOR, 
CommonCRS.ETRS89.ellipsoid()), withHeights,  // GRS 1980 ellipsoid
                 createEllipsoid(pg, Molodensky.SRC_SEMI_MAJOR,
-                                    Molodensky.SRC_SEMI_MINOR, null),          
                 // Clarke 1880 (IGN) ellipsoid
-                withHeights, grid);
+                                    Molodensky.SRC_SEMI_MINOR, null), 
withHeights, grid);                   // Clarke 1880 (IGN) ellipsoid
         try {
             tr = tr.inverse();
         } catch (NoninvertibleTransformException e) {
@@ -371,19 +369,6 @@ public class FranceGeocentricInterpolation extends 
GeodeticOperation {
         return tr;
     }
 
-    /**
-     * Creates the actual math transform. The default implementation delegates 
to the static method defined in
-     * {@link InterpolatedGeocentricTransform}, but the {@link 
MolodenskyInterpolation} subclass will rather
-     * delegate to {@link 
org.apache.sis.referencing.operation.transform.InterpolatedMolodenskyTransform}.
-     */
-    MathTransform createGeodeticTransformation(final MathTransformFactory 
factory,
-            final Ellipsoid source, final Ellipsoid target, final boolean 
withHeights,
-            final DatumShiftGridFile<Angle,Length> grid) throws 
FactoryException
-    {
-        return InterpolatedGeocentricTransform.createGeodeticTransformation(
-                factory, source, withHeights, target, withHeights, grid);
-    }
-
     /**
      * Returns the grid of the given name. This method returns the cached 
instance if it still exists,
      * or load the grid otherwise.
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/MolodenskyInterpolation.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/MolodenskyInterpolation.java
deleted file mode 100644
index 1630d9161a..0000000000
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/MolodenskyInterpolation.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.sis.referencing.operation.provider;
-
-import java.util.Arrays;
-import jakarta.xml.bind.annotation.XmlTransient;
-import javax.measure.quantity.Angle;
-import javax.measure.quantity.Length;
-import org.opengis.util.FactoryException;
-import org.opengis.referencing.datum.Ellipsoid;
-import org.opengis.referencing.operation.MathTransform;
-import org.opengis.referencing.operation.MathTransformFactory;
-import org.opengis.parameter.ParameterDescriptorGroup;
-import org.opengis.parameter.ParameterValueGroup;
-import org.apache.sis.util.internal.Constants;
-import 
org.apache.sis.referencing.operation.transform.InterpolatedMolodenskyTransform;
-
-
-/**
- * An approximation of geocentric interpolations which uses {@link 
InterpolatedMolodenskyTransform}
- * instead of {@link 
org.apache.sis.referencing.operation.transform.InterpolatedGeocentricTransform}.
- *
- * <p>This operation method is not standard, and as of SIS 0.7 not yet 
registered in the operation methods
- * provided by {@link 
org.apache.sis.referencing.operation.transform.DefaultMathTransformFactory}.
- * This class extends {@code FranceGeocentricInterpolation} for now because 
the latter is currently
- * the only operation performing interpolation in the geocentric domain.
- * However, this class hierarchy may be revisited in any future SIS 
version.</p>
- *
- * @author  Martin Desruisseaux (Geomatys)
- *
- * @see <a href="https://issues.apache.org/jira/browse/SIS-500";>Deprecate (for 
removal) InterpolatedMolodenskyTransform</a>
- */
-@XmlTransient
-@Deprecated(since="1.4", forRemoval=true)
-// Note: after removal, delete overrideable method in parent class.
-public final class MolodenskyInterpolation extends 
FranceGeocentricInterpolation {
-    /**
-     * Serial number for inter-operability with different versions.
-     */
-    private static final long serialVersionUID = 4265894749866901286L;
-
-    /**
-     * The providers for all combinations between 2D and 3D cases.
-     */
-    private static final MolodenskyInterpolation[] REDIMENSIONED = new 
MolodenskyInterpolation[4];
-    static {
-        final ParameterDescriptorGroup parameters = 
builder().setCodeSpace(null, Constants.SIS)
-                .addName("Molodensky 
interpolation").createGroupWithSameParameters(PARAMETERS);
-        Arrays.setAll(REDIMENSIONED, (i) -> new 
MolodenskyInterpolation(parameters, i));
-    }
-
-    /**
-     * Returns the provider for the specified combination of source and target 
dimensions.
-     */
-    @Override
-    final GeodeticOperation redimensioned(int indexOfDim) {
-        return REDIMENSIONED[indexOfDim];
-    }
-
-    /**
-     * Creates a copy of this provider.
-     *
-     * @deprecated This is a temporary constructor before replacement by a 
{@code provider()} method with JDK9.
-     */
-    @Deprecated
-    public MolodenskyInterpolation() {
-        super(REDIMENSIONED[INDEX_OF_2D]);
-    }
-
-    /**
-     * Constructs a provider for the given number of dimensions.
-     */
-    @SuppressWarnings("removal")
-    private MolodenskyInterpolation(ParameterDescriptorGroup parameters, int 
indexOfDim) {
-        super(parameters, indexOfDim);
-    }
-
-    /**
-     * Invoked by {@link #createMathTransform(MathTransformFactory, 
ParameterValueGroup)}
-     * after all parameters have been processed.
-     */
-    @Override
-    @SuppressWarnings("removal")
-    MathTransform createGeodeticTransformation(final MathTransformFactory 
factory,
-            final Ellipsoid source, final Ellipsoid target, final boolean 
withHeights,
-            final DatumShiftGridFile<Angle,Length> grid) throws 
FactoryException
-    {
-        return InterpolatedMolodenskyTransform.createGeodeticTransformation(
-                factory, source, withHeights, target, withHeights, grid);
-    }
-}
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/DatumShiftTransform.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/DatumShiftTransform.java
index 2a914108ce..578c24069d 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/DatumShiftTransform.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/DatumShiftTransform.java
@@ -27,15 +27,12 @@ import org.opengis.referencing.datum.Ellipsoid;
 import org.opengis.referencing.operation.Matrix;
 import org.opengis.parameter.ParameterValueGroup;
 import org.opengis.parameter.ParameterDescriptorGroup;
-import org.opengis.geometry.MismatchedDimensionException;
 import org.apache.sis.referencing.datum.DatumShiftGrid;
 import org.apache.sis.referencing.operation.matrix.Matrices;
-import org.apache.sis.referencing.internal.Resources;
 import org.apache.sis.referencing.operation.provider.Molodensky;
 import org.apache.sis.measure.Units;
 import org.apache.sis.util.ComparisonMode;
 import org.apache.sis.util.Debug;
-import org.apache.sis.util.resources.Errors;
 
 
 /**
@@ -65,15 +62,14 @@ import org.apache.sis.util.resources.Errors;
  *
  * <p>Some countries go one step further and allow the above geocentric 
translations to be non-constant.
  * Instead, a different geocentric translation is interpolated for each 
geographic input coordinates.
- * This case is handled by the {@link InterpolatedGeocentricTransform} 
subclass, or its
- * {@link InterpolatedMolodenskyTransform} variant if a few centimetres 
accuracy lost can be afforded.</p>
+ * This case is handled by the {@link InterpolatedGeocentricTransform} 
subclass.</p>
  *
  * <p>A simpler alternative to the above is to interpolate translations to 
apply directly on geographic coordinates.
  * This is the approach taken by NADCON and NTv2 grids.
  * SIS handles those datum shifts with the {@link InterpolatedTransform} 
subclass.</p>
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.0
+ * @version 1.5
  *
  * @see DatumShiftGrid
  *
@@ -204,30 +200,6 @@ public abstract class DatumShiftTransform extends 
AbstractMathTransform implemen
         return m.getElement(j, j);
     }
 
-    /**
-     * Ensures that the {@link #grid} performs geocentric translations in the 
given units.
-     * This method is invoked by constructor for validation of given arguments.
-     *
-     * <p>This method is defined here in order to ensure a consistent behavior 
of
-     * {@link InterpolatedGeocentricTransform} with {@link 
InterpolatedMolodenskyTransform}.</p>
-     *
-     * @param  grid  the grid to validate.
-     * @param  unit  the unit of semi-axis length of the 
<strong>source</strong> ellipsoid.
-     * @throws IllegalArgumentException if the given grid is not valid.
-     */
-    static void ensureGeocentricTranslation(final DatumShiftGrid<?,?> grid, 
final Unit<Length> unit)
-            throws IllegalArgumentException
-    {
-        final int dim = grid.getTranslationDimensions();
-        if (dim != 3) {
-            throw new 
MismatchedDimensionException(Errors.format(Errors.Keys.MismatchedDimension_3, 
"grid", 3, dim));
-        }
-        Object unitLabel = "ratio";
-        if (grid.isCellValueRatio() || (unitLabel = grid.getTranslationUnit()) 
!= unit) {
-            throw new 
IllegalArgumentException(Resources.format(Resources.Keys.IllegalUnitFor_2, 
"translation", unitLabel));
-        }
-    }
-
     /**
      * Sets the semi-axis length in the {@link #context} parameters.
      * This is a helper method for constructors in some (not all) subclasses.
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/InterpolatedGeocentricTransform.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/InterpolatedGeocentricTransform.java
index d122b52f1f..68135b8bf1 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/InterpolatedGeocentricTransform.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/InterpolatedGeocentricTransform.java
@@ -22,6 +22,7 @@ import javax.measure.quantity.Length;
 import org.opengis.util.FactoryException;
 import org.opengis.parameter.ParameterDescriptor;
 import org.opengis.parameter.ParameterDescriptorGroup;
+import org.opengis.geometry.MismatchedDimensionException;
 import org.opengis.referencing.datum.Ellipsoid;
 import org.opengis.referencing.operation.Matrix;
 import org.opengis.referencing.operation.MathTransform;
@@ -31,11 +32,13 @@ import org.opengis.referencing.operation.TransformException;
 import 
org.apache.sis.referencing.operation.provider.FranceGeocentricInterpolation;
 import org.apache.sis.referencing.operation.provider.Molodensky;
 import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.internal.Constants;
 import org.apache.sis.metadata.iso.citation.Citations;
 import org.apache.sis.parameter.ParameterBuilder;
 import org.apache.sis.referencing.datum.DatumShiftGrid;
 import org.apache.sis.referencing.operation.matrix.Matrices;
+import org.apache.sis.referencing.internal.Resources;
 
 
 /**
@@ -73,16 +76,10 @@ import org.apache.sis.referencing.operation.matrix.Matrices;
  * because the {@code DatumShiftGrid} inputs are geographic coordinates even 
if the interpolated
  * grid values are in geocentric space.</p>
  *
- * <h2>Performance consideration</h2>
- * {@link InterpolatedMolodenskyTransform} performs the same calculation more 
efficiently at the cost of
- * a few centimetres error. Both classes are instantiated in the same way and 
expect the same inputs.
- *
  * @author  Simon Reynard (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
  * @version 1.0
  *
- * @see InterpolatedMolodenskyTransform
- *
  * @since 0.7
  */
 public class InterpolatedGeocentricTransform extends DatumShiftTransform {
@@ -284,6 +281,27 @@ public class InterpolatedGeocentricTransform extends 
DatumShiftTransform {
         this.inverse = inverse;
     }
 
+    /**
+     * Ensures that the {@link #grid} performs geocentric translations in the 
given units.
+     * This method is invoked by constructor for validation of given arguments.
+     *
+     * @param  grid  the grid to validate.
+     * @param  unit  the unit of semi-axis length of the 
<strong>source</strong> ellipsoid.
+     * @throws IllegalArgumentException if the given grid is not valid.
+     */
+    private static void ensureGeocentricTranslation(final DatumShiftGrid<?,?> 
grid, final Unit<Length> unit)
+            throws IllegalArgumentException
+    {
+        final int dim = grid.getTranslationDimensions();
+        if (dim != 3) {
+            throw new 
MismatchedDimensionException(Errors.format(Errors.Keys.MismatchedDimension_3, 
"grid", 3, dim));
+        }
+        Object unitLabel = "ratio";
+        if (grid.isCellValueRatio() || (unitLabel = grid.getTranslationUnit()) 
!= unit) {
+            throw new 
IllegalArgumentException(Resources.format(Resources.Keys.IllegalUnitFor_2, 
"translation", unitLabel));
+        }
+    }
+
     /**
      * Delegates to {@link 
ContextualParameters#completeTransform(MathTransformFactory, MathTransform)}
      * for this transformation and for its dependencies as well.
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/InterpolatedMolodenskyTransform.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/InterpolatedMolodenskyTransform.java
deleted file mode 100644
index 512dae1395..0000000000
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/InterpolatedMolodenskyTransform.java
+++ /dev/null
@@ -1,458 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.sis.referencing.operation.transform;
-
-import java.util.Arrays;
-import javax.measure.Unit;
-import javax.measure.quantity.Angle;
-import javax.measure.quantity.Length;
-import org.opengis.util.FactoryException;
-import org.opengis.parameter.ParameterDescriptor;
-import org.opengis.parameter.ParameterDescriptorGroup;
-import org.opengis.referencing.datum.Ellipsoid;
-import org.opengis.referencing.operation.Matrix;
-import org.opengis.referencing.operation.MathTransform;
-import org.opengis.referencing.operation.MathTransformFactory;
-import org.opengis.referencing.operation.TransformException;
-import 
org.apache.sis.referencing.operation.provider.FranceGeocentricInterpolation;
-import org.apache.sis.referencing.operation.provider.Molodensky;
-import org.apache.sis.util.ArgumentChecks;
-import org.apache.sis.util.Debug;
-import org.apache.sis.util.internal.Constants;
-import org.apache.sis.metadata.iso.citation.Citations;
-import org.apache.sis.parameter.Parameters;
-import org.apache.sis.parameter.ParameterBuilder;
-import org.apache.sis.referencing.datum.DatumShiftGrid;
-import org.apache.sis.measure.Units;
-
-
-/**
- * Transforms between two geographic CRS by performing geocentric translations 
interpolated from a grid file, but using
- * Molodensky approximation. This transformation is conceptually defined as a 
translation in geocentric coordinates
- * as performed by {@link InterpolatedGeocentricTransform}, but uses the 
{@linkplain MolodenskyTransform Molodensy}
- * (non-abridged) approximation for performance reasons.
- * Errors are less than 3 centimetres for the <cite>"France geocentric 
interpolation"</cite> (ESPG:9655).
- * By comparison, the finest accuracy reported in the grid file for France is 
5 centimetres.
- *
- * <h2>Algorithm</h2>
- * This class transforms two- or three- dimensional coordinates from a 
geographic CRS to another geographic CRS.
- * The changes between source and target coordinates are small (usually less 
than 400 metres), but vary for every
- * position. Those changes are provided in a {@linkplain DatumShiftGrid datum 
shift grid}, usually loaded from one
- * or two files.
- *
- * <p>Many datum shift grids like NADCON and NTv2 apply the interpolated 
translations directly on geographic coordinates.
- * This relatively simple case is handled by {@link InterpolatedTransform}.
- * But in the {@code InterpolatedMolodenskyTransform} case, the interpolated 
translations are rather the
- * ({@linkplain #tX}, {@linkplain #tY}, {@linkplain #tZ}) parameters of a 
Molodensky transformation.</p>
- *
- * @deprecated This operation method is non-standard, of little use and has 
greater errors than intended.
- *
- * @author  Martin Desruisseaux (Geomatys)
- * @version 1.0
- *
- * @see <a href="https://issues.apache.org/jira/browse/SIS-500";>Deprecate (for 
removal) InterpolatedMolodenskyTransform</a>
- * @see InterpolatedGeocentricTransform
- *
- * @since 0.7
- */
-@Deprecated(since="1.4", forRemoval=true)
-public class InterpolatedMolodenskyTransform extends MolodenskyFormula {
-    /**
-     * Serial number for inter-operability with different versions.
-     */
-    private static final long serialVersionUID = -5691721806681489940L;
-
-    /**
-     * Parameter descriptor to use with the contextual parameters for the 
forward and inverse transformations.
-     * We do not use directly the <cite>"France geocentric 
interpolation"</cite> (ESPG:9655) descriptor because
-     * this {@code InterpolatedMolodenskyTransform} is an approximation of 
{@link InterpolatedGeocentricTransform}
-     * and the conventions used by SIS are different than EPSG:9655 ones.
-     */
-    private static final ParameterDescriptorGroup DESCRIPTOR, INVERSE;
-    static {
-        final ParameterBuilder builder = new ParameterBuilder()
-                .setRequired(true).setCodeSpace(Citations.SIS, Constants.SIS);
-        DESCRIPTOR = builder.addName("Molodensky interpolation")
-                
.createGroupWithSameParameters(InterpolatedGeocentricTransform.DESCRIPTOR);
-        INVERSE = builder.addName("Molodensky inverse interpolation")
-                
.createGroupWithSameParameters(InterpolatedGeocentricTransform.DESCRIPTOR);
-    }
-
-    /**
-     * The inverse of this interpolated Molodensky transform.
-     *
-     * @see #inverse()
-     */
-    private final InterpolatedMolodenskyTransform inverse;
-
-    /**
-     * Constructs the inverse of an interpolated Molodensky transform.
-     *
-     * @param inverse  the transform for which to create the inverse.
-     * @param source   the source ellipsoid of the given {@code inverse} 
transform.
-     * @param target   the target ellipsoid of the given {@code inverse} 
transform.
-     */
-    InterpolatedMolodenskyTransform(final InterpolatedMolodenskyTransform 
inverse, Ellipsoid source, Ellipsoid target) {
-        super(inverse, source, target, INVERSE);
-        this.inverse = inverse;
-    }
-
-    /**
-     * Creates a transform from the specified parameters.
-     * This {@code InterpolatedMolodenskyTransform} class expects coordinate 
values in the following order and units:
-     * <ol>
-     *   <li>longitudes in <strong>radians</strong> relative to the prime 
meridian (usually Greenwich),</li>
-     *   <li>latitudes in <strong>radians</strong>,</li>
-     *   <li>optionally heights above the ellipsoid, in same units than the 
source ellipsoid axes.</li>
-     * </ol>
-     *
-     * For converting geographic coordinates in degrees, {@code 
InterpolatedMolodenskyTransform} instances
-     * need to be concatenated with the following affine transforms:
-     *
-     * <ul>
-     *   <li><cite>Normalization</cite> before {@code 
InterpolatedMolodenskyTransform}:<ul>
-     *     <li>Conversion of (λ,φ) from degrees to radians.</li>
-     *   </ul></li>
-     *   <li><cite>Denormalization</cite> after {@code 
InterpolatedMolodenskyTransform}:<ul>
-     *     <li>Conversion of (λ,φ) from radians to degrees.</li>
-     *   </ul></li>
-     * </ul>
-     *
-     * After {@code InterpolatedMolodenskyTransform} construction,
-     * the full conversion chain including the above affine transforms can be 
created by
-     * <code>{@linkplain #getContextualParameters()}.{@linkplain 
ContextualParameters#completeTransform
-     * completeTransform}(factory, this)}</code>.
-     *
-     * @param source      the source ellipsoid.
-     * @param isSource3D  {@code true} if the source coordinates have a height.
-     * @param target      the target ellipsoid.
-     * @param isTarget3D  {@code true} if the target coordinates have a height.
-     * @param grid        the grid of datum shifts from source to target datum.
-     *                    The {@link DatumShiftGrid#interpolateInCell 
DatumShiftGrid.interpolateInCell(…)} method
-     *                    shall compute (ΔX, ΔY, ΔZ) translations from 
<em>source</em> to <em>target</em> in the
-     *                    unit of source ellipsoid axes.
-     *
-     * @see #createGeodeticTransformation(MathTransformFactory, Ellipsoid, 
boolean, Ellipsoid, boolean, DatumShiftGrid)
-     */
-    @SuppressWarnings("removal")
-    protected InterpolatedMolodenskyTransform(final Ellipsoid source, final 
boolean isSource3D,
-                                              final Ellipsoid target, final 
boolean isTarget3D,
-                                              final 
DatumShiftGrid<Angle,Length> grid)
-    {
-        super(source, isSource3D,
-              target, isTarget3D,
-              grid.getCellMean(0),
-              grid.getCellMean(1),
-              grid.getCellMean(2),
-              grid, false, DESCRIPTOR);
-
-        ensureGeocentricTranslation(grid, source.getAxisUnit());
-        if (isSource3D || isTarget3D) {
-            inverse = new Inverse(this, source, target);
-        } else {
-            inverse = new InterpolatedMolodenskyTransform2D.Inverse(this, 
source, target);
-        }
-    }
-
-    /**
-     * Creates a transformation between two geographic CRS. This factory 
method combines the
-     * {@code InterpolatedMolodenskyTransform} instance with the steps needed 
for converting values between
-     * degrees to radians. The transform works with input and output 
coordinates in the following units:
-     *
-     * <ol>
-     *   <li>longitudes in <strong>degrees</strong> relative to the prime 
meridian (usually Greenwich),</li>
-     *   <li>latitudes in <strong>degrees</strong>,</li>
-     *   <li>optionally heights above the ellipsoid, in same units than the 
source ellipsoids axes.</li>
-     * </ol>
-     *
-     * Note however that the given {@code grid} instance shall expect 
geographic coordinates (λ,φ)
-     * in <strong>radians</strong>.
-     *
-     * @param factory     the factory to use for creating the transform.
-     * @param source      the source ellipsoid.
-     * @param isSource3D  {@code true} if the source coordinates have a height.
-     * @param target      the target ellipsoid.
-     * @param isTarget3D  {@code true} if the target coordinates have a height.
-     * @param grid        the grid of datum shifts from source to target datum.
-     *                    The {@link DatumShiftGrid#interpolateInCell 
DatumShiftGrid.interpolateInCell(…)} method
-     *                    shall compute (ΔX, ΔY, ΔZ) translations from 
<em>source</em> to <em>target</em> in the
-     *                    unit of source ellipsoid axes.
-     * @return the transformation between geographic coordinates in degrees.
-     * @throws FactoryException if an error occurred while creating a 
transform.
-     */
-    @SuppressWarnings("removal")
-    public static MathTransform createGeodeticTransformation(final 
MathTransformFactory factory,
-            final Ellipsoid source, final boolean isSource3D,
-            final Ellipsoid target, final boolean isTarget3D,
-            final DatumShiftGrid<Angle,Length> grid) throws FactoryException
-    {
-        ArgumentChecks.ensureNonNull("grid", grid);
-        final InterpolatedMolodenskyTransform tr;
-        if (isSource3D || isTarget3D) {
-            tr = new InterpolatedMolodenskyTransform(source, isSource3D, 
target, isTarget3D, grid);
-        } else {
-            tr = new InterpolatedMolodenskyTransform2D(source, target, grid);
-        }
-        tr.inverse.context.completeTransform(factory, null);
-        return tr.context.completeTransform(factory, tr);
-    }
-
-    /**
-     * Invoked by constructor and by {@link #getParameterValues()} for setting 
all parameters other than axis lengths.
-     *
-     * @param  pg         where to set the parameters.
-     * @param  semiMinor  the semi minor axis length, in unit of {@code unit}.
-     * @param  unit       the unit of measurement to declare.
-     * @param  Δf         ignored.
-     */
-    @Override
-    final void completeParameters(final Parameters pg, final double semiMinor, 
final Unit<?> unit, double Δf) {
-        super.completeParameters(pg, semiMinor, unit, Δf);
-        if (pg != context) {
-            Δf = Δfmod / semiMinor;
-            pg.getOrCreate(Molodensky.AXIS_LENGTH_DIFFERENCE).setValue(Δa, 
unit);
-            pg.getOrCreate(Molodensky.FLATTENING_DIFFERENCE) .setValue(Δf, 
Units.UNITY);
-        }
-        grid.getParameterValues(pg);
-    }
-
-    /**
-     * Transforms the (λ,φ) or (λ,φ,<var>h</var>) coordinates between two 
geographic CRS,
-     * and optionally returns the derivative at that location.
-     *
-     * @return {@inheritDoc}
-     * @throws TransformException if the point cannot be transformed or
-     *         if a problem occurred while calculating the derivative.
-     */
-    @Override
-    public Matrix transform(final double[] srcPts, final int srcOff,
-                            final double[] dstPts, final int dstOff,
-                            final boolean derivate) throws TransformException
-    {
-        final double[] vector = new double[3];
-        final double λ = srcPts[srcOff];
-        final double φ = srcPts[srcOff+1];
-        grid.interpolateInCell(normalizedToGridX(λ),
-                               normalizedToGridY(φ), vector);
-        return transform(λ, φ, isSource3D ? srcPts[srcOff+2] : 0,
-                dstPts, dstOff, vector[0], vector[1], vector[2], null, 
derivate);
-    }
-
-    /**
-     * Transforms the (λ,φ) or (λ,φ,<var>h</var>) coordinates between two 
geographic CRS.
-     * This method performs the same work than the above
-     * {@link #transform(double[], int, double[], int, boolean) transform(…)} 
method,
-     * but on an arbitrary number of coordinate tuples and without computing 
derivative.
-     *
-     * @throws TransformException if a point cannot be transformed.
-     */
-    @Override
-    public void transform(double[] srcPts, int srcOff, double[] dstPts, int 
dstOff, int numPts) throws TransformException {
-        int srcInc = isSource3D ? 3 : 2;
-        int dstInc = isTarget3D ? 3 : 2;
-        int offFinal = 0;
-        double[] dstFinal  = null;
-        if (srcPts == dstPts) {
-            switch (IterationStrategy.suggest(srcOff, srcInc, dstOff, dstInc, 
numPts)) {
-                case ASCENDING: {
-                    break;
-                }
-                case DESCENDING: {
-                    srcOff += (numPts-1) * srcInc;  srcInc = -srcInc;
-                    dstOff += (numPts-1) * dstInc;  dstInc = -dstInc;
-                    break;
-                }
-                default: {  // BUFFER_SOURCE, but also a reasonable default 
for any case.
-                    srcPts = Arrays.copyOfRange(srcPts, srcOff, srcOff + 
numPts*srcInc);
-                    srcOff = 0;
-                    break;
-                }
-                case BUFFER_TARGET: {
-                    dstFinal = dstPts;
-                    offFinal = dstOff;
-                    dstPts = new double[numPts * dstInc];
-                    dstOff = 0;
-                    break;
-                }
-            }
-        }
-        final double[] offset = new double[3];
-        while (--numPts >= 0) {
-            final double λ = srcPts[srcOff  ];
-            final double φ = srcPts[srcOff+1];
-            grid.interpolateInCell(normalizedToGridX(λ),
-                                   normalizedToGridY(φ), offset);
-            transform(λ, φ, isSource3D ? srcPts[srcOff+2] : 0,
-                      dstPts, dstOff, offset[0], offset[1], offset[2], null, 
false);
-            srcOff += srcInc;
-            dstOff += dstInc;
-        }
-        if (dstFinal != null) {
-            System.arraycopy(dstPts, 0, dstFinal, offFinal, dstPts.length);
-        }
-    }
-
-    /*
-     * 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 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).
-     */
-
-    /**
-     * Returns the inverse of this interpolated Molodensky transform.
-     * The source ellipsoid of the returned transform will be the target 
ellipsoid of this transform, and conversely.
-     *
-     * @return a transform from the target ellipsoid to the source ellipsoid 
of this transform.
-     */
-    @Override
-    public MathTransform inverse() {
-        return inverse;
-    }
-
-
-
-
-
-    /**
-     * The inverse of the enclosing {@link InterpolatedMolodenskyTransform}.
-     * This transform applies an algorithm similar to the one documented in 
the enclosing class,
-     * with the following differences:
-     *
-     * <ol>
-     *   <li>First, target coordinates are estimated using the ({@link #tX}, 
{@link #tY}, {@link #tZ}) translation.</li>
-     *   <li>A new ({@code ΔX}, {@code ΔY}, {@code ΔZ}) translation is 
interpolated at the geographic coordinates found
-     *       in above step, and target coordinates are recomputed again using 
that new translation.</li>
-     * </ol>
-     *
-     * @author  Martin Desruisseaux (Geomatys)
-     */
-    static class Inverse extends InterpolatedMolodenskyTransform {
-        /**
-         * Serial number for inter-operability with different versions.
-         */
-        private static final long serialVersionUID = -3520896803296425651L;
-
-        /**
-         * Constructs the inverse of an interpolated Molodensky transform.
-         *
-         * @param inverse  the transform for which to create the inverse.
-         * @param source   the source ellipsoid of the given {@code inverse} 
transform.
-         * @param target   the target ellipsoid of the given {@code inverse} 
transform.
-         */
-        Inverse(final InterpolatedMolodenskyTransform inverse, final Ellipsoid 
source, final Ellipsoid target) {
-           super(inverse, source, target);
-        }
-
-        /**
-         * Transforms the (λ,φ) or (λ,φ,<var>h</var>) coordinates between two 
geographic CRS,
-         * and optionally returns the derivative at that location.
-         *
-         * @return {@inheritDoc}
-         * @throws TransformException if the point cannot be transformed or
-         *         if a problem occurred while calculating the derivative.
-         */
-        @Override
-        public Matrix transform(final double[] srcPts, final int srcOff,
-                                final double[] dstPts, final int dstOff,
-                                final boolean derivate) throws 
TransformException
-        {
-            return transform(srcPts[srcOff], srcPts[srcOff+1], isSource3D ? 
srcPts[srcOff+2] : 0,
-                             dstPts, dstOff, tX, tY, tZ, new double[3], 
derivate);
-        }
-
-        /**
-         * Transforms the (λ,φ) or (λ,φ,<var>h</var>) coordinates between two 
geographic CRS.
-         * This method performs the same work than the above
-         * {@link #transform(double[], int, double[], int, boolean) 
transform(…)} method,
-         * but on an arbitrary number of coordinate tuples and without 
computing derivative.
-         *
-         * @throws TransformException if a point cannot be transformed.
-         */
-        @Override
-        public void transform(double[] srcPts, int srcOff, double[] dstPts, 
int dstOff, int numPts) throws TransformException {
-            int srcInc = isSource3D ? 3 : 2;
-            int dstInc = isTarget3D ? 3 : 2;
-            int offFinal = 0;
-            double[] dstFinal  = null;
-            if (srcPts == dstPts) {
-                switch (IterationStrategy.suggest(srcOff, srcInc, dstOff, 
dstInc, numPts)) {
-                    case ASCENDING: {
-                        break;
-                    }
-                    case DESCENDING: {
-                        srcOff += (numPts-1) * srcInc;  srcInc = -srcInc;
-                        dstOff += (numPts-1) * dstInc;  dstInc = -dstInc;
-                        break;
-                    }
-                    default: {  // BUFFER_SOURCE, but also a reasonable 
default for any case.
-                        srcPts = Arrays.copyOfRange(srcPts, srcOff, srcOff + 
numPts*srcInc);
-                        srcOff = 0;
-                        break;
-                    }
-                    case BUFFER_TARGET: {
-                        dstFinal = dstPts;
-                        offFinal = dstOff;
-                        dstPts = new double[numPts * dstInc];
-                        dstOff = 0;
-                        break;
-                    }
-                }
-            }
-            final double[] offset = new double[3];
-            while (--numPts >= 0) {
-                transform(srcPts[srcOff], srcPts[srcOff+1], isSource3D ? 
srcPts[srcOff+2] : 0,
-                          dstPts, dstOff, tX, tY, tZ, offset, false);
-                srcOff += srcInc;
-                dstOff += dstInc;
-            }
-            if (dstFinal != null) {
-                System.arraycopy(dstPts, 0, dstFinal, offFinal, dstPts.length);
-            }
-        }
-    }
-
-    /**
-     * Returns a description of the internal parameters of this {@code 
InterpolatedMolodenskyTransform} transform.
-     * The returned group contains parameters for the source ellipsoid 
semi-axis lengths and the differences between
-     * source and target ellipsoid parameters.
-     *
-     * <h4>Usage note</h4>
-     * This method is mostly for {@linkplain 
org.apache.sis.io.wkt.Convention#INTERNAL debugging purposes}
-     * since the isolation of non-linear parameters in this class is highly 
implementation dependent.
-     * Most GIS applications will instead be interested in the {@linkplain 
#getContextualParameters()
-     * contextual parameters}.
-     *
-     * @return a description of the internal parameters.
-     */
-    @Debug
-    @Override
-    public ParameterDescriptorGroup getParameterDescriptors() {
-        final ParameterDescriptor<?>[] param = new ParameterDescriptor<?>[] {
-                Molodensky.DIMENSION,
-                Molodensky.SRC_SEMI_MAJOR,
-                Molodensky.SRC_SEMI_MINOR,
-                Molodensky.AXIS_LENGTH_DIFFERENCE,
-                Molodensky.FLATTENING_DIFFERENCE,
-                FranceGeocentricInterpolation.FILE
-        };
-        return new ParameterBuilder().setRequired(true)
-                .setCodeSpace(Citations.SIS, Constants.SIS)
-                .addName(context.getDescriptor().getName().getCode() + " 
(radians domain)").createGroup(param);
-    }
-}
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/InterpolatedMolodenskyTransform2D.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/InterpolatedMolodenskyTransform2D.java
deleted file mode 100644
index 8bd3785d52..0000000000
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/InterpolatedMolodenskyTransform2D.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.sis.referencing.operation.transform;
-
-import java.awt.Shape;
-import java.awt.geom.Point2D;
-import javax.measure.quantity.Angle;
-import javax.measure.quantity.Length;
-import org.opengis.referencing.datum.Ellipsoid;
-import org.opengis.referencing.operation.Matrix;
-import org.opengis.referencing.operation.MathTransform2D;
-import org.opengis.referencing.operation.TransformException;
-import org.apache.sis.referencing.datum.DatumShiftGrid;
-
-
-/**
- * An interpolated Molodensky transform for two-dimensional input and output 
coordinates.
- *
- * @author  Martin Desruisseaux (Geomatys)
- *
- * @see <a href="https://issues.apache.org/jira/browse/SIS-500";>Deprecate (for 
removal) InterpolatedMolodenskyTransform</a>
- */
-@SuppressWarnings("removal")
-@Deprecated(since="1.4", forRemoval=true)
-final class InterpolatedMolodenskyTransform2D extends 
InterpolatedMolodenskyTransform implements MathTransform2D {
-    /**
-     * Serial number for compatibility with different versions.
-     */
-    private static final long serialVersionUID = 3050077982181110135L;
-
-    /**
-     * Constructs a 2D transform.
-     */
-    InterpolatedMolodenskyTransform2D(final Ellipsoid source, final Ellipsoid 
target, final DatumShiftGrid<Angle,Length> grid) {
-        super(source, false, target, false, grid);
-    }
-
-    /**
-     * Computes the derivative at the given position.
-     */
-    @Override
-    public Matrix derivative(Point2D point) throws TransformException {
-        return AbstractMathTransform2D.derivative(this, point);
-    }
-
-    /**
-     * Transforms a single point.
-     */
-    @Override
-    public Point2D transform(Point2D ptSrc, Point2D ptDst) throws 
TransformException {
-        return AbstractMathTransform2D.transform(this, ptSrc, ptDst);
-    }
-
-    /**
-     * Transforms the given shape.
-     */
-    @Override
-    public Shape createTransformedShape(Shape shape) throws TransformException 
{
-        return AbstractMathTransform2D.createTransformedShape(this, shape, 
null, null, false);
-    }
-
-    /**
-     * Returns the inverse transform of this transform.
-     */
-    @Override
-    public MathTransform2D inverse() {
-        return (MathTransform2D) super.inverse();
-    }
-
-    /**
-     * The inverse of the enclosing {@link InterpolatedMolodenskyTransform2D}.
-     *
-     * @author  Martin Desruisseaux (Geomatys)
-     */
-    @SuppressWarnings("removal")
-    static final class Inverse extends InterpolatedMolodenskyTransform.Inverse 
implements MathTransform2D {
-        /**
-         * Serial number for inter-operability with different versions.
-         */
-        private static final long serialVersionUID = 3175846640786132902L;
-
-        /**
-         * Constructs the inverse of an interpolated Molodensky transform.
-         *
-         * @param inverse  the transform for which to create the inverse.
-         * @param source   the source ellipsoid of the given {@code inverse} 
transform.
-         * @param target   the target ellipsoid of the given {@code inverse} 
transform.
-         */
-        Inverse(final InterpolatedMolodenskyTransform inverse, final Ellipsoid 
source, final Ellipsoid target) {
-           super(inverse, source, target);
-        }
-
-        /**
-         * Computes the derivative at the given position.
-         */
-        @Override
-        public Matrix derivative(Point2D point) throws TransformException {
-            return AbstractMathTransform2D.derivative(this, point);
-        }
-
-        /**
-         * Transforms a single point.
-         */
-        @Override
-        public Point2D transform(Point2D ptSrc, Point2D ptDst) throws 
TransformException {
-            return AbstractMathTransform2D.transform(this, ptSrc, ptDst);
-        }
-
-        /**
-         * Transforms the given shape.
-         */
-        @Override
-        public Shape createTransformedShape(Shape shape) throws 
TransformException {
-            return AbstractMathTransform2D.createTransformedShape(this, shape, 
null, null, false);
-        }
-
-        /**
-         * Returns the inverse transform of this transform.
-         */
-        @Override
-        public MathTransform2D inverse() {
-            return (MathTransform2D) super.inverse();
-        }
-    }
-}
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/MolodenskyFormula.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/MolodenskyFormula.java
index b9ef61ccfe..63c0a9f3e9 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/MolodenskyFormula.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/MolodenskyFormula.java
@@ -37,14 +37,7 @@ import static java.lang.Math.*;
 
 
 /**
- * Implementation of Molodensky formulas. This class is used by:
- *
- * <ul>
- *   <li>The "real" {@link MolodenskyTransform} (see that class for 
documentation about Molodensky transform).</li>
- *   <li>{@link InterpolatedMolodenskyTransform}, which conceptually works on 
geocentric coordinates but
- *       is implemented in Apache SIS using Molodensky (never abridged) 
formulas for performance reasons.
- *       However, this implementation choice should be hidden to users (except 
by mention in javadoc).</li>
- * </ul>
+ * Implementation of Molodensky formulas.
  *
  * @author  Martin Desruisseaux (Geomatys)
  */
@@ -295,13 +288,7 @@ abstract class MolodenskyFormula extends 
DatumShiftTransform {
     /**
      * Implementation of {@link #transform(double[], int, double[], int, 
boolean)} with possibility
      * to override some field values. In this method signature, parameters 
having the same name than
-     * fields have the same value, except in some special circumstances:
-     *
-     * <ul>
-     *   <li>{@code tX}, {@code tY} and {@code tZ} parameters always have the 
values of {@link #tX}, {@link #tY}
-     *       and {@link #tZ} fields when this method is invoked by {@link 
MolodenskyTransform}. But those values
-     *       may be slightly different when this method is invoked by {@link 
InterpolatedMolodenskyTransform}.</li>
-     * </ul>
+     * fields have the same value.
      *
      * @param  λ           longitude (radians).
      * @param  φ           latitude (radians).
@@ -311,12 +298,11 @@ abstract class MolodenskyFormula extends 
DatumShiftTransform {
      * @param  tX          the {@link #tX} field value (or a slightly 
different value during geocentric interpolation).
      * @param  tY          the {@link #tY} field value (or a slightly 
different value during geocentric interpolation).
      * @param  tZ          the {@link #tZ} field value (or a slightly 
different value during geocentric interpolation).
-     * @param  offset      an array of length 3 if this method should use the 
interpolation grid, or {@code null} otherwise.
      * @param  derivate    {@code true} for computing the derivative, or 
{@code false} if not needed.
      * @throws TransformException if a point cannot be transformed.
      */
     final Matrix transform(final double λ, final double φ, final double h, 
final double[] dstPts, int dstOff,
-                           double tX, double tY, double tZ, double[] offset, 
final boolean derivate)
+                           double tX, double tY, double tZ, final boolean 
derivate)
             throws TransformException
     {
         /*
@@ -350,26 +336,13 @@ abstract class MolodenskyFormula extends 
DatumShiftTransform {
             t = t*(0.5/νden + 0.5/ρden)                 // = Δf⋅[ν⋅(b/a) + 
ρ⋅(a/b)]     (without the +h in ν and ρ)
                     + Δa*eccentricitySquared/νden;      // = Δa⋅[ℯ²⋅ν/a]
         }
-        double spcλ, cmsλ, cmsφ, scaleX, scaleY;        // Intermediate terms 
to be reused by the derivative
-        double λt, φt;                                  // The target 
geographic coordinates
-        do {
-            spcλ = tY*sinλ + tX*cosλ;                   // "spc" stands for 
"sin plus cos"
-            cmsλ = tY*cosλ - tX*sinλ;                   // "cms" stands for 
"cos minus sin"
-            cmsφ = (tZ + t*sinφ)*cosφ - spcλ*sinφ;
-            scaleX = ANGULAR_SCALE / (ν*cosφ);
-            scaleY = ANGULAR_SCALE / ρ;
-            λt = λ + (cmsλ * scaleX);
-            φt = φ + (cmsφ * scaleY);
-            if (offset == null) break;
-            /*
-             * Following is executed only in InterpolatedMolodenskyTransform 
case.
-             */
-            grid.interpolateInCell(normalizedToGridX(λt), 
normalizedToGridY(φt), offset);
-            tX = -offset[0];
-            tY = -offset[1];
-            tZ = -offset[2];
-            offset = null;
-        } while (true);
+        final double spcλ = tY*sinλ + tX*cosλ;                  // "spc" 
stands for "sin plus cos"
+        final double cmsλ = tY*cosλ - tX*sinλ;                  // "cms" 
stands for "cos minus sin"
+        final double cmsφ = (tZ + t*sinφ)*cosφ - spcλ*sinφ;
+        final double scaleX = ANGULAR_SCALE / (ν*cosφ);
+        final double scaleY = ANGULAR_SCALE / ρ;
+        final double λt = λ + (cmsλ * scaleX);          // The target 
geographic coordinates
+        final double φt = φ + (cmsφ * scaleY);
         if (dstPts != null) {
             dstPts[dstOff++] = λt;
             dstPts[dstOff++] = φt;
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/MolodenskyTransform.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/MolodenskyTransform.java
index 4d5f1ac4d2..f8039f182b 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/MolodenskyTransform.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/MolodenskyTransform.java
@@ -272,7 +272,7 @@ public class MolodenskyTransform extends MolodenskyFormula {
                             final boolean derivate) throws TransformException
     {
         return transform(srcPts[srcOff], srcPts[srcOff+1], isSource3D ? 
srcPts[srcOff+2] : 0,
-                         dstPts, dstOff, tX, tY, tZ, null, derivate);
+                         dstPts, dstOff, tX, tY, tZ, derivate);
     }
 
     /**
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/package-info.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/package-info.java
index 23dc01ce24..a04776ec81 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/package-info.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/package-info.java
@@ -61,7 +61,7 @@
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @author  Adrian Custer (Geomatys)
- * @version 1.4
+ * @version 1.5
  * @since   0.5
  */
 package org.apache.sis.referencing.operation.transform;
diff --git 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/provider/ProvidersTest.java
 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/provider/ProvidersTest.java
index e143efddc0..f1365ba0e9 100644
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/provider/ProvidersTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/provider/ProvidersTest.java
@@ -125,7 +125,6 @@ public final class ProvidersTest extends TestCase {
             NTv1.class,
             NADCON.class,
             FranceGeocentricInterpolation.class,
-            MolodenskyInterpolation.class,
             Interpolation1D.class,
             Wraparound.class
         };
diff --git 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/transform/InterpolatedMolodenskyTransformTest.java
 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/transform/InterpolatedMolodenskyTransformTest.java
deleted file mode 100644
index 5558f43830..0000000000
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/transform/InterpolatedMolodenskyTransformTest.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.sis.referencing.operation.transform;
-
-import org.opengis.util.FactoryException;
-import org.opengis.referencing.operation.TransformException;
-import org.apache.sis.referencing.operation.provider.MolodenskyInterpolation;
-import 
org.apache.sis.referencing.operation.provider.FranceGeocentricInterpolationTest;
-import org.apache.sis.referencing.operation.provider.GeocentricTranslationTest;
-import org.apache.sis.referencing.util.Formulas;
-
-// Test dependencies
-import org.junit.Test;
-import org.apache.sis.test.DependsOn;
-
-
-/**
- * Tests {@link InterpolatedMolodenskyTransform}. The accuracy of using the 
Molodensky approximation
- * instead of the real geocentric translation is verified by the following 
tests:
- *
- * <ul>
- *   <li>{@link 
GeocentricTranslationTest#testFranceGeocentricInterpolationPoint()}</li>
- *   <li>{@link 
MolodenskyTransformTest#testFranceGeocentricInterpolationPoint()}</li>
- * </ul>
- *
- * @author  Martin Desruisseaux (Geomatys)
- */
-@DependsOn({
-    MolodenskyTransformTest.class,
-    GeocentricTranslationTest.class,
-    InterpolatedGeocentricTransformTest.class
-})
-public final class InterpolatedMolodenskyTransformTest extends 
InterpolatedGeocentricTransformTest {
-    /**
-     * Creates a new test case.
-     */
-    public InterpolatedMolodenskyTransformTest() {
-    }
-
-    /**
-     * Creates an approximation of the <cite>"France geocentric 
interpolation"</cite> transform
-     * using the Molodensky transform. This method relax slightly the 
tolerance threshold since
-     * Molodensky transformations are approximation of translations in 
geocentric domain.
-     *
-     * @throws FactoryException if an error occurred while loading the grid.
-     */
-    @Override
-    final void createGeodeticTransformation() throws FactoryException {
-        createGeodeticTransformation(new MolodenskyInterpolation());
-        tolerance = Formulas.ANGULAR_TOLERANCE;     // Relax tolerance 
threshold.
-    }
-
-    /**
-     * Tests the Well Known Text (version 1) formatting.
-     * The result is what we show to users, but may quite different than what 
SIS has in memory.
-     *
-     * @throws FactoryException if an error occurred while creating a 
transform.
-     * @throws TransformException should never happen.
-     */
-    @Test
-    @Override
-    public void testWKT() throws FactoryException, TransformException {
-        createGeodeticTransformation();
-        transform = transform.inverse();
-        assertWktEqualsRegex("(?m)\\Q" +
-                "PARAM_MT[“Molodensky interpolation”,\n" +
-                "  PARAMETER[“dim”, 2],\n" +
-                "  PARAMETER[“src_semi_major”, 6378137.0],\n" +
-                "  PARAMETER[“src_semi_minor”, 6356752.314140356],\n" +
-                "  PARAMETER[“tgt_semi_major”, 6378249.2],\n" +
-                "  PARAMETER[“tgt_semi_minor”, 6356515.0],\n" +
-                "  PARAMETER[“Geocentric translation file”, “\\E.*\\W\\Q" +
-                             FranceGeocentricInterpolationTest.TEST_FILE + 
"”]]\\E");
-
-        transform = transform.inverse();
-        assertWktEqualsRegex("(?m)\\Q" +
-                "PARAM_MT[“Molodensky inverse interpolation”,\n" +
-                "  PARAMETER[“dim”, 2],\n" +
-                "  PARAMETER[“src_semi_major”, 6378249.2],\n" +
-                "  PARAMETER[“src_semi_minor”, 6356515.0],\n" +
-                "  PARAMETER[“tgt_semi_major”, 6378137.0],\n" +
-                "  PARAMETER[“tgt_semi_minor”, 6356752.314140356],\n" +
-                "  PARAMETER[“Geocentric translation file”, “\\E.*\\W\\Q" +
-                             FranceGeocentricInterpolationTest.TEST_FILE + 
"”]]\\E");
-    }
-
-    /**
-     * Tests the internal Well Known Text formatting.
-     * This WKT shows what SIS has in memory for debugging purpose.
-     * This is normally not what we show to users.
-     *
-     * @throws FactoryException if an error occurred while creating a 
transform.
-     * @throws TransformException should never happen.
-     */
-    @Test
-    @Override
-    public void testInternalWKT() throws FactoryException, TransformException {
-        createGeodeticTransformation();
-        assertInternalWktEqualsRegex("(?m)\\Q" +
-                "Concat_MT[\n" +
-                "  Param_MT[“Affine parametric transformation”,\n" +
-                "    Parameter[“A0”, 0.017453292519943295, Id[“EPSG”, 
8623]],\n" +   // Degrees to radians conversion
-                "    Parameter[“B1”, 0.017453292519943295, Id[“EPSG”, 
8640]]],\n" +
-                "  Param_MT[“Molodensky inverse interpolation (radians 
domain)”,\n" +
-                "    Parameter[“src_semi_major”, 6378249.2],\n" +
-                "    Parameter[“src_semi_minor”, 6356515.0],\n" +
-                "    Parameter[“Semi-major axis length difference”, -112.2, 
Id[“EPSG”, 8654]],\n" +
-                "    Parameter[“Flattening difference”, 
-5.4738838833299144E-5, Id[“EPSG”, 8655]],\n" +
-                "    ParameterFile[“Geocentric translation file”, 
“\\E.*\\W\\Q" +
-                                   FranceGeocentricInterpolationTest.TEST_FILE 
+ "”, Id[“EPSG”, 8727]],\n" +
-                "    Parameter[“dim”, 2]],\n" +
-                "  Param_MT[“Affine parametric transformation”,\n" +
-                "    Parameter[“A0”, 57.29577951308232, Id[“EPSG”, 8623]],\n" 
+      // Radians to degrees conversion
-                "    Parameter[“B1”, 57.29577951308232, Id[“EPSG”, 
8640]]]]\\E");
-    }
-}

Reply via email to