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 6a5584c4867a595b524a5b42a5f1f9e83a5acd04 Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Tue Aug 9 13:04:30 2022 +0200 Replace `Context.setSource(EllipsoidalCS, Ellipsoid)` method by `setSource(GeodeticCRS)`. The rational which was in previous method is actually inexact: we may need the ellipsoid even with non-ellipsoidal CS, if the CRS is geocentric. --- .../internal/referencing/ReferencingUtilities.java | 39 +++++------ .../operation/CoordinateOperationFinder.java | 5 +- .../operation/CoordinateOperationRegistry.java | 4 +- .../referencing/operation/DefaultConversion.java | 4 +- .../transform/DefaultMathTransformFactory.java | 76 +++++++++++++++++++--- 5 files changed, 90 insertions(+), 38 deletions(-) diff --git a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingUtilities.java b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingUtilities.java index 3df50b8c34..c3825e8b0d 100644 --- a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingUtilities.java +++ b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingUtilities.java @@ -509,38 +509,33 @@ public final class ReferencingUtilities extends Static { } /** - * Sets the source and target ellipsoids and coordinate systems to values inferred from the given CRS. - * The ellipsoids will be non-null only if the given CRS is geographic (not geocentric). + * Creates a context with source and target ellipsoids and coordinate systems inferred from the given CRS. + * The ellipsoids will be non-null only if the given CRS is geodetic (geographic or geocentric). * - * @param sourceCRS the CRS from which to get the source coordinate system and ellipsoid. - * @param targetCRS the CRS from which to get the target coordinate system and ellipsoid. - * @param context a pre-allocated context, or {@code null} for creating a new one. - * @return the given context if it was non-null, or a new context otherwise. + * @param sourceCRS the CRS from which to get the source coordinate system and ellipsoid, or {@code null}. + * @param targetCRS the CRS from which to get the target coordinate system and ellipsoid, or {@code null}. + * @return the context to provides to math transform factory. */ public static Context createTransformContext(final CoordinateReferenceSystem sourceCRS, - final CoordinateReferenceSystem targetCRS, Context context) + final CoordinateReferenceSystem targetCRS) { - if (context == null) { - context = new Context(); + final Context context = new Context(); + if (sourceCRS instanceof GeodeticCRS) { + context.setSource((GeodeticCRS) sourceCRS); + } else if (sourceCRS != null) { + context.setSource(sourceCRS.getCoordinateSystem()); } - final CoordinateSystem sourceCS = (sourceCRS != null) ? sourceCRS.getCoordinateSystem() : null; - final CoordinateSystem targetCS = (targetCRS != null) ? targetCRS.getCoordinateSystem() : null; - if (sourceCRS instanceof GeodeticCRS && sourceCS instanceof EllipsoidalCS) { - context.setSource((EllipsoidalCS) sourceCS, ((GeodeticCRS) sourceCRS).getDatum().getEllipsoid()); - } else { - context.setSource(sourceCS); - } - if (targetCRS instanceof GeodeticCRS && targetCS instanceof EllipsoidalCS) { - context.setTarget((EllipsoidalCS) targetCS, ((GeodeticCRS) targetCRS).getDatum().getEllipsoid()); - } else { - context.setTarget(targetCS); + if (targetCRS instanceof GeodeticCRS) { + context.setTarget((GeodeticCRS) targetCRS); + } else if (targetCRS != null) { + context.setTarget(targetCRS.getCoordinateSystem()); } return context; } /** * Substitute for the deprecated {@link MathTransformFactory#createBaseToDerived createBaseToDerived(…)} method. - * This substitute use the full {@code targetCRS} instead of only the coordinate system of the target. + * This substitute uses the full {@code targetCRS} instead of only the coordinate system of the target. * This is needed for setting the {@code "tgt_semi_minor"} and {@code "tgt_semi_major"} parameters of * Molodensky transformation for example. * @@ -561,7 +556,7 @@ public final class ReferencingUtilities extends Static { { if (factory instanceof DefaultMathTransformFactory) { return ((DefaultMathTransformFactory) factory).createParameterizedTransform( - parameters, createTransformContext(sourceCRS, targetCRS, null)); + parameters, createTransformContext(sourceCRS, targetCRS)); } else { // Fallback for non-SIS implementations. Work for map projections but not for Molodensky. return factory.createBaseToDerived(sourceCRS, parameters, targetCRS.getCoordinateSystem()); diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationFinder.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationFinder.java index 94f949561e..f61f85df2b 100644 --- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationFinder.java +++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationFinder.java @@ -524,8 +524,9 @@ public class CoordinateOperationFinder extends CoordinateOperationRegistry { * set to Greenwich in EPSG dataset 8.9. For safety, the SIS's DefaultGeodeticDatum class ensures that if the * prime meridians are not the same, then the target meridian must be Greenwich. */ - final DefaultMathTransformFactory.Context context = ReferencingUtilities.createTransformContext( - sourceCRS, targetCRS, new MathTransformContext(sourceDatum, targetDatum)); + final DefaultMathTransformFactory.Context context = new MathTransformContext(sourceDatum, targetDatum); + context.setSource(sourceCRS); + context.setTarget(targetCRS); /* * If both CRS use the same datum and the same prime meridian, then the coordinate operation is only axis * swapping, unit conversion or change of coordinate system type (Ellipsoidal ↔ Cartesian ↔ Spherical). diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java index 3991cc6240..52a76c2844 100644 --- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java +++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java @@ -982,7 +982,7 @@ class CoordinateOperationRegistry { final MathTransformFactory mtFactory = factorySIS.getMathTransformFactory(); if (mtFactory instanceof DefaultMathTransformFactory) { MathTransform mt = ((DefaultMathTransformFactory) mtFactory).createParameterizedTransform( - parameters, ReferencingUtilities.createTransformContext(sourceCRS, targetCRS, null)); + parameters, ReferencingUtilities.createTransformContext(sourceCRS, targetCRS)); return factorySIS.createSingleOperation(IdentifiedObjects.getProperties(operation), sourceCRS, targetCRS, null, operation.getMethod(), mt); } @@ -1104,7 +1104,7 @@ class CoordinateOperationRegistry { try { mt = ((DefaultMathTransformFactory) mtFactory).createParameterizedTransform( ((SingleOperation) op).getParameterValues(), - ReferencingUtilities.createTransformContext(sourceCRS, targetCRS, null)); + ReferencingUtilities.createTransformContext(sourceCRS, targetCRS)); } catch (InvalidGeodeticParameterException e) { log(null, e); break; diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConversion.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConversion.java index 92ac8c9899..8cec2a3414 100644 --- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConversion.java +++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConversion.java @@ -256,10 +256,10 @@ public class DefaultConversion extends AbstractSingleOperation implements Conver */ final DefaultMathTransformFactory.Context context; if (target instanceof GeneralDerivedCRS) { - context = ReferencingUtilities.createTransformContext(source, null, null); + context = ReferencingUtilities.createTransformContext(source, null); context.setTarget(target.getCoordinateSystem()); // Using `target` would be unsafe here. } else { - context = ReferencingUtilities.createTransformContext(source, target, null); + context = ReferencingUtilities.createTransformContext(source, target); } transform = ((DefaultMathTransformFactory) factory).createParameterizedTransform(parameters, context); parameters = Parameters.unmodifiable(context.getCompletedParameters()); diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java index ff5ce4ac11..b863524fa5 100644 --- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java +++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java @@ -38,6 +38,7 @@ import org.opengis.parameter.ParameterNotFoundException; import org.opengis.parameter.InvalidParameterNameException; import org.opengis.parameter.InvalidParameterValueException; import org.opengis.referencing.crs.CoordinateReferenceSystem; +import org.opengis.referencing.crs.GeodeticCRS; import org.opengis.referencing.cs.CoordinateSystem; import org.opengis.referencing.cs.EllipsoidalCS; import org.opengis.referencing.cs.CartesianCS; @@ -165,7 +166,7 @@ import static java.util.logging.Logger.getLogger; * There is typically only one {@code MathTransformFactory} instance for the whole application. * * @author Martin Desruisseaux (Geomatys, IRD) - * @version 1.1 + * @version 1.3 * * @see MathTransformProvider * @see AbstractMathTransform @@ -541,16 +542,17 @@ public class DefaultMathTransformFactory extends AbstractFactory implements Math * coordinate systems are not {@linkplain AxesConvention#NORMALIZED normalized}.</li> * </ul> * - * By default this class does <strong>not</strong> handle change of + * This class does <strong>not</strong> handle change of * {@linkplain org.apache.sis.referencing.datum.DefaultGeodeticDatum#getPrimeMeridian() prime meridian} * or anything else related to datum. Datum changes have dedicated {@link OperationMethod}, * for example <cite>"Longitude rotation"</cite> (EPSG:9601) for changing the prime meridian. * * @author Martin Desruisseaux (Geomatys) - * @version 0.7 + * @version 1.3 * @since 0.7 * @module */ + @SuppressWarnings("serial") // Fields are not statically typed as Serializable. public static class Context implements Serializable { /** * For cross-version compatibility. @@ -575,14 +577,14 @@ public class DefaultMathTransformFactory extends AbstractFactory implements Math * * @todo We could make this information public as a replacement of {@link #getLastMethodUsed()}. */ - OperationMethod provider; + private OperationMethod provider; /** * The parameters actually used. * * @see #getCompletedParameters() */ - ParameterValueGroup parameters; + private ParameterValueGroup parameters; /** * Creates a new context with all properties initialized to {@code null}. @@ -615,12 +617,38 @@ public class DefaultMathTransformFactory extends AbstractFactory implements Math * * @param cs the coordinate system to set as the source, or {@code null}. * @param ellipsoid the ellipsoid associated to the given coordinate system, or {@code null}. + * + * @deprecated Replaced by {@link #setSource(GeodeticCRS)}. */ + @Deprecated public void setSource(final EllipsoidalCS cs, final Ellipsoid ellipsoid) { sourceCS = cs; sourceEllipsoid = ellipsoid; } + /** + * Sets the source coordinate system and related ellipsoid to the components of given CRS. + * The {@link Ellipsoid}, fetched from the geodetic datum, is often used together with an {@link EllipsoidalCS}, + * but not necessarily. The geodetic CRS may also be associated with a spherical or Cartesian coordinate system, + * and the ellipsoid information may still be needed even with those non-ellipsoidal coordinate systems. + * + * <p><strong>This method is not for datum shifts.</strong> + * All datum information other than the ellipsoid are ignored.</p> + * + * @param crs the coordinate system and ellipsoid to set as the source, or {@code null}. + * + * @since 1.3 + */ + public void setSource(final GeodeticCRS crs) { + if (crs != null) { + sourceCS = crs.getCoordinateSystem(); + sourceEllipsoid = crs.getDatum().getEllipsoid(); + } else { + sourceCS = null; + sourceEllipsoid = null; + } + } + /** * Sets the target coordinate system to the given value. * The target ellipsoid is unconditionally set to {@code null}. @@ -640,12 +668,38 @@ public class DefaultMathTransformFactory extends AbstractFactory implements Math * * @param cs the coordinate system to set as the source, or {@code null}. * @param ellipsoid the ellipsoid associated to the given coordinate system, or {@code null}. + * + * @deprecated Replaced by {@link #setTarget(GeodeticCRS)}. */ + @Deprecated public void setTarget(final EllipsoidalCS cs, final Ellipsoid ellipsoid) { targetCS = cs; targetEllipsoid = ellipsoid; } + /** + * Sets the target coordinate system and related ellipsoid to the components of given CRS. + * The {@link Ellipsoid}, fetched from the geodetic datum, is often used together with an {@link EllipsoidalCS}, + * but not necessarily. The geodetic CRS may also be associated with a spherical or Cartesian coordinate system, + * and the ellipsoid information may still be needed even with those non-ellipsoidal coordinate systems. + * + * <p><strong>This method is not for datum shifts.</strong> + * All datum information other than the ellipsoid are ignored.</p> + * + * @param crs the coordinate system and ellipsoid to set as the target, or {@code null}. + * + * @since 1.3 + */ + public void setTarget(final GeodeticCRS crs) { + if (crs != null) { + targetCS = crs.getCoordinateSystem(); + targetEllipsoid = crs.getDatum().getEllipsoid(); + } else { + targetCS = null; + targetEllipsoid = null; + } + } + /** * Returns the source coordinate system, or {@code null} if unspecified. * @@ -986,8 +1040,8 @@ public class DefaultMathTransformFactory extends AbstractFactory implements Math n = ((AbstractProvider) provider).getEllipsoidsMask(); } else { n = 0; - if (sourceEllipsoid != null) n = 1; - if (targetEllipsoid != null) n |= 2; + if (getSourceEllipsoid() != null) n = 1; + if (getTargetEllipsoid() != null) n |= 2; } /* * Set the ellipsoid axis-length parameter values. Those parameters may appear in the source ellipsoid, @@ -1356,7 +1410,7 @@ public class DefaultMathTransformFactory extends AbstractFactory implements Math ArgumentChecks.ensureNonNull("baseCRS", baseCRS); ArgumentChecks.ensureNonNull("parameters", parameters); ArgumentChecks.ensureNonNull("derivedCS", derivedCS); - final Context context = ReferencingUtilities.createTransformContext(baseCRS, null, null); + final Context context = ReferencingUtilities.createTransformContext(baseCRS, null); context.setTarget(derivedCS); return createParameterizedTransform(parameters, context); } @@ -1403,12 +1457,14 @@ public class DefaultMathTransformFactory extends AbstractFactory implements Math final String operation; if (isEllipsoidalSource) { operation = GeographicToGeocentric.NAME; - context.setSource(cs = (EllipsoidalCS) source, ellipsoid); + context.setSource(cs = (EllipsoidalCS) source); context.setTarget(target); + context.sourceEllipsoid = ellipsoid; } else { operation = GeocentricToGeographic.NAME; context.setSource(source); - context.setTarget(cs = (EllipsoidalCS) target, ellipsoid); + context.setTarget(cs = (EllipsoidalCS) target); + context.targetEllipsoid = ellipsoid; } final ParameterValueGroup pg = getDefaultParameters(operation); if (cs.getDimension() < 3) pg.parameter("dim").setValue(2); // Apache SIS specific parameter.