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

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


The following commit(s) were added to refs/heads/geoapi-4.0 by this push:
     new 1150276b2e Consolidation of the way to transform a `GeometryWrapper`. 
The intend is to have a single place where additional checks such as transform 
domain of validity can be added.
1150276b2e is described below

commit 1150276b2e3d545807c2d84e544c3af22aa3d7d9
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Fri Oct 30 00:55:47 2026 +0100

    Consolidation of the way to transform a `GeometryWrapper`.
    The intend is to have a single place where additional checks
    such as transform domain of validity can be added.
---
 .../main/org/apache/sis/filter/package-info.java   |   2 +-
 .../sis/geometry/wrapper/GeometryWrapper.java      |  57 ++++++++---
 .../geometry/wrapper/SpatialOperationContext.java  |  29 +++---
 .../geometry/wrapper/jts/GeometryTransform.java    |   3 +-
 .../org/apache/sis/geometry/wrapper/jts/JTS.java   | 106 +--------------------
 .../apache/sis/geometry/wrapper/jts/Wrapper.java   |  42 +-------
 .../sis/filter/BinarySpatialFilterTestCase.java    |   1 +
 .../filter/BinarySpatialFilterUsingESRI_Test.java  |   1 +
 .../filter/BinarySpatialFilterUsingJTS_Test.java   |   1 +
 .../BinarySpatialFilterUsingJava2D_Test.java       |   1 +
 .../apache/sis/geometry/wrapper/jts/JTSTest.java   |  46 +++++----
 .../org/apache/sis/geometry/AbstractEnvelope.java  |   2 +
 .../operation/transform/AbstractMathTransform.java |  28 +++---
 .../operation/transform/DomainDefinition.java      |   8 +-
 .../transform/GeometryTransformException.java      |  67 +++++++++++++
 .../operation/transform/MathTransforms.java        |   8 +-
 .../org/apache/sis/geometries/adapter/Wrapper.java |  43 ++-------
 .../sis/storage/rs/internal/shared/s2/Wrapper.java |   7 --
 18 files changed, 191 insertions(+), 261 deletions(-)

diff --git 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/filter/package-info.java
 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/filter/package-info.java
index a90f5c7409..978e35bdc6 100644
--- 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/filter/package-info.java
+++ 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/filter/package-info.java
@@ -57,7 +57,7 @@
  *
  * @author  Johann Sorel (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.7
+ * @version 1.8
  *
  * @since 1.1
  */
diff --git 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/geometry/wrapper/GeometryWrapper.java
 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/geometry/wrapper/GeometryWrapper.java
index 1c02ea6a1b..fa9ab844a7 100644
--- 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/geometry/wrapper/GeometryWrapper.java
+++ 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/geometry/wrapper/GeometryWrapper.java
@@ -36,12 +36,14 @@ import org.apache.sis.referencing.CRS;
 import org.apache.sis.referencing.operation.transform.MathTransforms;
 import 
org.apache.sis.referencing.operation.transform.TransformFactoryException;
 import org.apache.sis.referencing.internal.shared.ReferencingUtilities;
+import org.apache.sis.metadata.iso.extent.DefaultGeographicBoundingBox;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.Classes;
 import org.apache.sis.util.Debug;
 import org.apache.sis.util.UnconvertibleObjectException;
 import org.apache.sis.util.collection.BackingStoreException;
 import org.apache.sis.util.resources.Errors;
+import org.apache.sis.util.logging.Logging;
 
 // Specific to the geoapi-3.1 and geoapi-4.0 branches:
 import java.util.Set;
@@ -68,6 +70,17 @@ import org.opengis.coordinate.MismatchedDimensionException;
  * @see Geometries#wrap(Object)
  */
 public abstract class GeometryWrapper extends AbstractGeometry implements 
Geometry {
+    /**
+     * Whether to compare the <abbr>CRS</abbr> of the geometry with the source 
<abbr>CRS</abbr>
+     * of the coordinate operation. For performance reasons, this flag should 
be {@code false}
+     * when the caller already knows that these <abbr>CRS</abbr>s are 
equivalent.
+     *
+     * <p>This is fixed to {@code false} for now because all callers made the 
above-cited check
+     * in the current version of Apache <abbr>SIS</abbr>. But this flag may 
become an option in
+     * the future if transforms become used in different contexts.</p>
+     */
+    protected static final boolean VERIFY_GEOMETRY_CRS_BEFORE_OPERATION = 
false;
+
     /**
      * The coordinate reference system, or {@code null} if unspecified.
      * The value of this field should be set by subclass constructors.
@@ -492,26 +505,24 @@ public abstract class GeometryWrapper extends 
AbstractGeometry implements Geomet
 
     /**
      * Transforms this geometry using the given coordinate operation.
-     * If the geometry uses a different <abbr>CRS</abbr> than the source 
<abbr>CRS</abbr>
-     * of the given {@code operation} and if the {@code validate} argument is 
{@code true},
-     * then a new operation to the target <abbr>CRS</abbr> will be 
automatically computed.
+     * The caller is responsible to ensure that the source <abbr>CRS</abbr> of 
the given {@code operation}
+     * is equivalent to {@link #getCoordinateReferenceSystem()}. This is not 
verified by this method.
      *
      * <p>This method is preferred to the {@link 
#transform(CoordinateReferenceSystem)} method
      * because not all geometry libraries store the <abbr>CRS</abbr> of their 
objects.</p>
      *
      * @param  operation  the coordinate operation to apply.
-     * @param  validate   whether to validate the operation source 
<abbr>CRS</abbr>.
      * @return the transformed geometry (may be the same geometry instance, 
but never {@code null}).
      * @throws UnsupportedOperationException if this operation is not 
supported for current implementation.
-     * @throws FactoryException if transformation to the target 
<abbr>CRS</abbr> cannot be found.
+     * @throws FactoryException if a problem happened while building a 
<abbr>CRS</abbr> from a <abbr>SRID</abbr>.
      * @throws TransformException if the geometry cannot be transformed.
      * @throws BackingStoreException if the operation failed because of 
another checked exception.
      */
-    public GeometryWrapper transform(final CoordinateOperation operation, 
boolean validate)
+    protected GeometryWrapper transform(final CoordinateOperation operation)
             throws FactoryException, TransformException
     {
         MathTransform transform = operation.getMathTransform();
-        if (validate && crs != null) {
+        if (VERIFY_GEOMETRY_CRS_BEFORE_OPERATION && crs != null) {
             CoordinateOperation step = CRS.findOperation(crs, 
operation.getSourceCRS(), null);
             transform = MathTransforms.concatenate(step.getMathTransform(), 
transform);
         }
@@ -529,10 +540,10 @@ public abstract class GeometryWrapper extends 
AbstractGeometry implements Geomet
      * @return the transformed geometry (may be the same geometry instance, 
but never {@code null}).
      * @throws UnsupportedOperationException if this operation is not 
supported for current implementation.
      * @throws TransformException if the geometry cannot be transformed.
-     * @throws FactoryException if a problem happened while setting the 
<abbr>CRS</abbr>.
+     * @throws FactoryException should never happen (declared because some 
constructors declare this exception).
      * @throws BackingStoreException if the operation failed because of 
another checked exception.
      */
-    public GeometryWrapper transform(final MathTransform transform)
+    protected GeometryWrapper transform(final MathTransform transform)
             throws FactoryException, TransformException
     {
         if (transform.isIdentity()) {
@@ -546,25 +557,37 @@ public abstract class GeometryWrapper extends 
AbstractGeometry implements Geomet
      * If the given <abbr>CRS</abbr> is {@code null} or the same as the 
current <abbr>CRS</abbr>,
      * or if the geometry has no <abbr>CRS</abbr>, then this wrapper is 
returned unchanged.
      *
-     * <p>Consider using {@link #transform(CoordinateOperation, boolean)} 
instead of this method,
-     * for performance reasons and because not all geometry libraries 
associate <abbr>CRS</abbr>
-     * with their geometric objects.</p>
+     * <p>Consider using {@link 
SpatialOperationContext#transform(GeometryWrapper)} instead of this method,
+     * for performance reasons, accuracy reasons (domain of validity) and 
because not all geometry libraries
+     * store information about the <abbr>CRS</abbr> in their geometric 
objects.</p>
      *
      * @param  targetCRS  the target coordinate reference system, or {@code 
null}.
      * @return the transformed geometry (may be the same geometry but never 
{@code null}).
      * @throws UnsupportedOperationException if this operation is not 
supported for current implementation.
-     * @throws TransformException if the given geometry has no CRS or cannot 
be transformed.
+     * @throws TransformException if the given geometry has no 
<abbr>CRS</abbr> or cannot be transformed.
      * @throws BackingStoreException if the operation failed because of 
another checked exception.
      *
      * @see #getCoordinateReferenceSystem()
+     * @see SpatialOperationContext#transform(GeometryWrapper)
      */
     @Override
-    public GeometryWrapper transform(final CoordinateReferenceSystem 
targetCRS) throws TransformException {
+    public final GeometryWrapper transform(final CoordinateReferenceSystem 
targetCRS) throws TransformException {
         if (targetCRS == null || targetCRS == crs || crs == null) {
             return this;
         }
+        DefaultGeographicBoundingBox bbox = null;
+        final GeneralEnvelope envelope = getEnvelope();
+        if (!envelope.isEmpty()) {
+            bbox = new DefaultGeographicBoundingBox();
+            try {
+                bbox.setBounds(envelope);
+            } catch (TransformException ex) {
+                bbox = null;
+                Logging.ignorableException(Geometries.LOGGER, 
GeometryWrapper.class, "transform", ex);
+            }
+        }
         try {
-            return transform(CRS.findOperation(crs, targetCRS, null), false);
+            return transform(CRS.findOperation(crs, targetCRS, bbox));
         } catch (FactoryException e) {
             throw new TransformFactoryException(e);
         }
@@ -637,6 +660,8 @@ public abstract class GeometryWrapper extends 
AbstractGeometry implements Geomet
 
     /**
      * Returns a hash code value based on the wrapped geometry.
+     *
+     * @return a hash code value based on the wrapped geometry.
      */
     @Override
     public final int hashCode() {
@@ -646,6 +671,8 @@ public abstract class GeometryWrapper extends 
AbstractGeometry implements Geomet
     /**
      * Returns the string representation of the wrapped geometry
      * (typically the class name and the bounds).
+     *
+     * @return a string representation of the wrapped geometry.
      */
     @Override
     public final String toString() {
diff --git 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/geometry/wrapper/SpatialOperationContext.java
 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/geometry/wrapper/SpatialOperationContext.java
index 7ca59c3f34..18d18c930d 100644
--- 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/geometry/wrapper/SpatialOperationContext.java
+++ 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/geometry/wrapper/SpatialOperationContext.java
@@ -56,11 +56,13 @@ import org.opengis.referencing.crs.DerivedCRS;
 
 
 /**
- * Context (such as desired CRS) in which a spatial operator will be executed.
+ * Context (such as desired <abbr>CRS</abbr>) in which a spatial operator will 
be executed.
  *
  * <p>Instances of this class are immutable and thread-safe.</p>
  *
- * <p>The serialization form is not a committed API and may change in any 
future version.</p>
+ * <p>This class is serializable because some filter implementations contain 
field of this
+ * type and are serializable (example: {@link 
org.apache.sis.filter.BinaryGeometryFilter}).
+ * But the serialization form is not a committed API and may change in any 
future version.</p>
  *
  * @author  Martin Desruisseaux (Geomatys)
  */
@@ -70,11 +72,6 @@ public final class SpatialOperationContext implements 
Serializable {
      */
     private static final long serialVersionUID = -6197547343970700471L;
 
-    /**
-     * The {@value} value, for identifying code that assume two-dimensional 
objects.
-     */
-    private static final int BIDIMENSIONAL = 2;
-
     /**
      * Approximate geographic area of geometries, or {@code null} if 
unspecified.
      */
@@ -82,7 +79,7 @@ public final class SpatialOperationContext implements 
Serializable {
     private final GeographicBoundingBox areaOfInterest;
 
     /**
-     * The target CRS in which to transform geometries, or {@code null} for 
inferring automatically.
+     * The target <abbr>CRS</abbr> in which to transform geometries, or {@code 
null} for inferring automatically.
      */
     @SuppressWarnings("serial")         // Most SIS implementations are 
serializable.
     private final CoordinateReferenceSystem computationCRS;
@@ -146,14 +143,14 @@ public final class SpatialOperationContext implements 
Serializable {
      * that {@link ReferencingUtilities#getUnit(CoordinateSystem)} returns 
{@code null}.
      */
     private static CoordinateReferenceSystem to2D(CoordinateReferenceSystem 
crs) {
-        if (CRS.getDimensionOrZero(crs) > BIDIMENSIONAL) {
-            crs = CRS.getComponentAt(crs, 0, BIDIMENSIONAL);
+        if (CRS.getDimensionOrZero(crs) > Geometries.BIDIMENSIONAL) {
+            crs = CRS.getComponentAt(crs, 0, Geometries.BIDIMENSIONAL);
         }
         return crs;
     }
 
     /**
-     * Transforms the specified geometry to the computation CRS.
+     * Transforms the specified geometry to the computation <abbr>CRS</abbr>.
      * Geometries with unspecified CRS will be used as-is, without 
transformation.
      * The common CRS is stored in the {@link #commonCRS} field.
      *
@@ -166,7 +163,7 @@ public final class SpatialOperationContext implements 
Serializable {
         if (computationCRS != null) {
             final CoordinateReferenceSystem sourceCRS = 
to2D(geometry.getCoordinateReferenceSystem());
             if (sourceCRS != null && !CRS.equivalent(computationCRS, 
sourceCRS)) {
-                geometry = geometry.transform(CRS.findOperation(sourceCRS, 
computationCRS, areaOfInterest), false);
+                geometry = geometry.transform(CRS.findOperation(sourceCRS, 
computationCRS, areaOfInterest));
             }
         }
         return geometry;
@@ -255,7 +252,7 @@ select: if (commonCRS == null) {
                 return false;                       // Geometries are in 
incompatible CRS.
             }
             if (systemUnit != null) {
-                for (int i=allCRS.length; --i >= 0;) {
+                for (int i = allCRS.length; --i >= 0;) {
                     final CoordinateReferenceSystem crs = allCRS[i];
                     if (crs != null) {
                         commonCRS = usingSystemUnit(geometries[i], crs, 
commonCRS, systemUnit);
@@ -269,11 +266,11 @@ select: if (commonCRS == null) {
          * At this point, `commonCRS` is the CRS to use for converting all 
geometries.
          * Perform the conversions in-place.
          */
-        for (int i=0; i<allCRS.length; i++) {
+        for (int i=0; i < allCRS.length; i++) {
             if (i != skipIndex) {
                 final CoordinateReferenceSystem sourceCRS = allCRS[i];
                 if (!CRS.equivalent(commonCRS, sourceCRS)) {
-                    geometries[i] = 
geometries[i].transform(CRS.findOperation(sourceCRS, commonCRS, 
areaOfInterest), false);
+                    geometries[i] = 
geometries[i].transform(CRS.findOperation(sourceCRS, commonCRS, 
areaOfInterest));
                 }
             }
         }
@@ -400,7 +397,7 @@ select: if (commonCRS == null) {
              */
             final CoordinateSystem cs = geometryCRS.getCoordinateSystem();
             double latitude = Double.NaN, longitude = Double.NaN;
-            for (int i=0; i<BIDIMENSIONAL; i++) {
+            for (int i = 0; i < Geometries.BIDIMENSIONAL; i++) {
                 final CoordinateSystemAxis axis = cs.getAxis(i);
                 double coordinate = centroid.getCoordinate(i);
                 coordinate = 
axis.getUnit().getConverterToAny(Units.DEGREE).convert(coordinate);
diff --git 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/geometry/wrapper/jts/GeometryTransform.java
 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/geometry/wrapper/jts/GeometryTransform.java
index 2cb88090ec..df0b24a0ee 100644
--- 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/geometry/wrapper/jts/GeometryTransform.java
+++ 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/geometry/wrapper/jts/GeometryTransform.java
@@ -31,6 +31,7 @@ import org.locationtech.jts.geom.Polygon;
 import org.opengis.referencing.operation.TransformException;
 import org.apache.sis.util.Classes;
 import org.apache.sis.util.resources.Errors;
+import 
org.apache.sis.referencing.operation.transform.GeometryTransformException;
 
 
 /**
@@ -79,7 +80,7 @@ public abstract class GeometryTransform {
         if (geom instanceof Polygon)            return transform((Polygon)     
       geom);
         if (geom instanceof MultiPolygon)       return 
transform((MultiPolygon)       geom);
         if (geom instanceof GeometryCollection) return 
transform((GeometryCollection) geom);
-        throw new 
IllegalArgumentException(Errors.format(Errors.Keys.UnsupportedType_1, 
Classes.getClass(geom)));
+        throw new 
GeometryTransformException(Errors.format(Errors.Keys.UnsupportedType_1, 
Classes.getClass(geom)));
     }
 
     /**
diff --git 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/geometry/wrapper/jts/JTS.java
 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/geometry/wrapper/jts/JTS.java
index 75521db2bd..487ee3ac60 100644
--- 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/geometry/wrapper/jts/JTS.java
+++ 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/geometry/wrapper/jts/JTS.java
@@ -22,7 +22,6 @@ import java.awt.Shape;
 import org.locationtech.jts.algorithm.Orientation;
 import org.locationtech.jts.geom.CoordinateSequence;
 import org.locationtech.jts.geom.CoordinateSequences;
-import org.locationtech.jts.geom.Envelope;
 import org.locationtech.jts.geom.Geometry;
 import org.locationtech.jts.geom.GeometryFactory;
 import org.locationtech.jts.geom.LinearRing;
@@ -32,19 +31,14 @@ import org.locationtech.jts.geom.GeometryCollection;
 import org.opengis.metadata.Identifier;
 import org.opengis.util.FactoryException;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
-import org.opengis.referencing.operation.CoordinateOperation;
 import org.opengis.referencing.operation.MathTransform;
 import org.opengis.referencing.operation.TransformException;
 import org.apache.sis.referencing.CRS;
 import org.apache.sis.referencing.IdentifiedObjects;
 import org.apache.sis.referencing.crs.AbstractCRS;
 import org.apache.sis.referencing.cs.AxesConvention;
-import org.apache.sis.util.logging.Logging;
-import org.apache.sis.metadata.iso.citation.Citations;
-import org.apache.sis.metadata.iso.extent.DefaultGeographicBoundingBox;
-import org.apache.sis.geometry.GeneralEnvelope;
 import org.apache.sis.util.internal.shared.Constants;
-import static org.apache.sis.geometry.wrapper.Geometries.LOGGER;
+import org.apache.sis.metadata.iso.citation.Citations;
 
 
 /**
@@ -161,104 +155,6 @@ public final class JTS {
         target.setUserData(crs);
     }
 
-    /**
-     * Finds an operation between the given CRS valid in the given area of 
interest.
-     * This method does not verify the <abbr>CRS</abbr> of the given geometry.
-     *
-     * @param  sourceCRS       the CRS of source coordinates.
-     * @param  targetCRS       the CRS of target coordinates.
-     * @param  areaOfInterest  the area of interest.
-     * @return the mathematical operation from {@code sourceCRS} to {@code 
targetCRS}.
-     * @throws FactoryException if the operation cannot be created.
-     */
-    private static CoordinateOperation findOperation(final 
CoordinateReferenceSystem sourceCRS,
-                                                     final 
CoordinateReferenceSystem targetCRS,
-                                                     final Geometry 
areaOfInterest)
-            throws FactoryException
-    {
-        DefaultGeographicBoundingBox bbox = null;
-        if (!areaOfInterest.isEmpty()) {
-            bbox = new DefaultGeographicBoundingBox();
-            try {
-                final Envelope e = areaOfInterest.getEnvelopeInternal();
-                final var env = new GeneralEnvelope(sourceCRS);     // May be 
3- or 4-dimensional.
-                env.setRange(0, e.getMinX(), e.getMaxX());
-                env.setRange(1, e.getMinY(), e.getMaxY());
-                bbox.setBounds(env);
-            } catch (TransformException ex) {
-                bbox = null;
-                Logging.ignorableException(LOGGER, JTS.class, "transform", ex);
-            }
-        }
-        return CRS.findOperation(sourceCRS, targetCRS, bbox);
-    }
-
-    /**
-     * Transforms the given geometry to the specified Coordinate Reference 
System (<abbr>CRS</abbr>).
-     * If the given geometry is {@code null}, or if the given <abbr>CRS</abbr> 
is {@code null} or the
-     * same as the current geometry <abbr>CRS</abbr>, then the given geometry 
is returned unchanged.
-     * If the geometry has no Coordinate Reference System, then the geometry 
is returned unchanged.
-     *
-     * <p><b>This operation may be slow!</b>
-     * If many geometries need to be transformed, it is better to fetch the 
{@link CoordinateOperation} only once,
-     * then invoke {@link #transform(Geometry, CoordinateOperation, boolean)} 
for each geometry.
-     * Alternatively, the geometries can be stored in a single geometry 
collection
-     * in order to invoke this method only once.</p>
-     *
-     * @param  geometry   the geometry to transform, or {@code null}.
-     * @param  targetCRS  the target coordinate reference system, or {@code 
null}.
-     * @return the transformed geometry, or the same geometry if it is already 
in target CRS.
-     * @throws FactoryException if transformation to the target CRS cannot be 
constructed.
-     * @throws TransformException if the given geometry cannot be transformed.
-     */
-    public static Geometry transform(Geometry geometry, final 
CoordinateReferenceSystem targetCRS)
-            throws FactoryException, TransformException
-    {
-        if (geometry != null && targetCRS != null) {
-            final CoordinateReferenceSystem sourceCRS = 
getCoordinateReferenceSystem(geometry);
-            if (sourceCRS != null) {
-                if (!CRS.equivalent(sourceCRS, targetCRS)) {
-                    geometry = transform(geometry, findOperation(sourceCRS, 
targetCRS, geometry), false);
-                }
-            }
-        }
-        return geometry;
-    }
-
-    /**
-     * Transforms the given geometry using the given coordinate operation.
-     * If the geometry or the operation is null, then the geometry is returned 
unchanged.
-     * If the source CRS is not equals to the geometry CRS and {@code 
validate} is {@code true},
-     * then a new operation is inferred.
-     *
-     * @todo Handle antimeridian case.
-     *
-     * @param  geometry   the geometry to transform, or {@code null}.
-     * @param  operation  the coordinate operation to apply, or {@code null}.
-     * @param  validate   whether to validate the operation source CRS.
-     * @return the transformed geometry, or the same geometry if it is already 
in target CRS.
-     * @throws FactoryException if transformation to the target CRS cannot be 
found.
-     * @throws TransformException if the given geometry cannot be transformed.
-     */
-    public static Geometry transform(Geometry geometry, CoordinateOperation 
operation, final boolean validate)
-            throws FactoryException, TransformException
-    {
-        if (geometry != null && operation != null) {
-            if (validate) {
-                final CoordinateReferenceSystem sourceCRS = 
operation.getSourceCRS();
-                if (sourceCRS != null) {
-                    final CoordinateReferenceSystem crs = 
getCoordinateReferenceSystem(geometry);
-                    if (crs != null && !CRS.equivalent(sourceCRS, crs)) {
-                        operation = findOperation(crs, 
operation.getTargetCRS(), geometry);
-                    }
-                }
-            }
-            geometry = transform(geometry, operation.getMathTransform());
-            geometry.setUserData(operation.getTargetCRS());
-        }
-        return geometry;
-    }
-
     /**
      * Transforms the given geometry using the given math transform.
      * If the geometry or the transform is null or identity, then the geometry 
is returned unchanged.
diff --git 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/geometry/wrapper/jts/Wrapper.java
 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/geometry/wrapper/jts/Wrapper.java
index bae9ca35f0..d18d28329b 100644
--- 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/geometry/wrapper/jts/Wrapper.java
+++ 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/geometry/wrapper/jts/Wrapper.java
@@ -43,11 +43,9 @@ import 
org.locationtech.jts.simplify.TopologyPreservingSimplifier;
 import org.opengis.util.FactoryException;
 import org.opengis.geometry.DirectPosition;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
-import org.opengis.referencing.operation.CoordinateOperation;
 import org.opengis.referencing.operation.MathTransform;
 import org.opengis.referencing.operation.TransformException;
 import org.apache.sis.referencing.CRS;
-import 
org.apache.sis.referencing.operation.transform.TransformFactoryException;
 import org.apache.sis.geometry.DirectPosition2D;
 import org.apache.sis.geometry.GeneralDirectPosition;
 import org.apache.sis.geometry.GeneralEnvelope;
@@ -701,43 +699,6 @@ add:    for (Geometry next = geometry;;) {
         return (geometry.getNumGeometries() >= 2) && !(geometry instanceof 
MultiPoint);
     }
 
-    /**
-     * Transforms this geometry using the given coordinate operation.
-     * If the operation is {@code null}, then the geometry is returned 
unchanged.
-     * If the geometry uses a different CRS than the source CRS of the given 
operation
-     * and {@code validate} is {@code true},
-     * then a new operation to the target CRS will be automatically computed.
-     *
-     * @param  operation  the coordinate operation to apply, or {@code null}.
-     * @param  validate   whether to validate the operation source CRS.
-     * @throws FactoryException if transformation to the target CRS cannot be 
found.
-     * @throws TransformException if the geometry cannot be transformed.
-     */
-    @Override
-    public GeometryWrapper transform(final CoordinateOperation operation, 
final boolean validate)
-            throws FactoryException, TransformException
-    {
-        return rewrap(JTS.transform(geometry, operation, validate));
-    }
-
-    /**
-     * Transforms this geometry to the specified Coordinate Reference System 
(CRS).
-     * If the given CRS is null or is the same CRS as current one, the 
geometry is returned unchanged.
-     * If the geometry has no Coordinate Reference System, then the geometry 
is returned unchanged.
-     *
-     * @param  targetCRS  the target coordinate reference system, or {@code 
null}.
-     * @return the transformed geometry (may be the same geometry instance), 
or {@code null}.
-     * @throws TransformException if this geometry cannot be transformed.
-     */
-    @Override
-    public GeometryWrapper transform(final CoordinateReferenceSystem 
targetCRS) throws TransformException {
-        try {
-            return rewrap(JTS.transform(geometry, targetCRS));
-        } catch (FactoryException e) {
-            throw new TransformFactoryException(e);
-        }
-    }
-
     /**
      * Transforms this geometry using the given transform.
      * If the transform is {@code null}, then the geometry is returned 
unchanged.
@@ -745,10 +706,11 @@ add:    for (Geometry next = geometry;;) {
      *
      * @param  transform  the math transform to apply, or {@code null}.
      * @return the transformed geometry (may be the same geometry instance, 
but never {@code null}).
+     * @throws FactoryException should never happen (declared because the 
constructor declares this exception).
      * @throws TransformException if the geometry cannot be transformed.
      */
     @Override
-    public GeometryWrapper transform(final MathTransform transform) throws 
FactoryException, TransformException {
+    protected GeometryWrapper transform(final MathTransform transform) throws 
FactoryException, TransformException {
         return rewrap(JTS.transform(geometry, transform));
     }
 
diff --git 
a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/filter/BinarySpatialFilterTestCase.java
 
b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/filter/BinarySpatialFilterTestCase.java
index 38fbe42ea0..65835be6a7 100644
--- 
a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/filter/BinarySpatialFilterTestCase.java
+++ 
b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/filter/BinarySpatialFilterTestCase.java
@@ -55,6 +55,7 @@ import org.opengis.filter.DistanceOperatorName;
  *
  * @param  <G> root class of geometry implementation.
  */
+@SuppressWarnings("exports")
 public abstract class BinarySpatialFilterTestCase<G> extends TestCase {
     /**
      * The factory to use for testing purpose.
diff --git 
a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/filter/BinarySpatialFilterUsingESRI_Test.java
 
b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/filter/BinarySpatialFilterUsingESRI_Test.java
index c4d5c39247..2c66c9d9a1 100644
--- 
a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/filter/BinarySpatialFilterUsingESRI_Test.java
+++ 
b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/filter/BinarySpatialFilterUsingESRI_Test.java
@@ -29,6 +29,7 @@ import org.junit.jupiter.api.Test;
  * @author  Johann Sorel (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
  */
+@SuppressWarnings("exports")
 public final class BinarySpatialFilterUsingESRI_Test extends 
BinarySpatialFilterTestCase<Geometry> {
     /**
      * Creates a new test.
diff --git 
a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/filter/BinarySpatialFilterUsingJTS_Test.java
 
b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/filter/BinarySpatialFilterUsingJTS_Test.java
index 6ee15261a5..47bedb62e5 100644
--- 
a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/filter/BinarySpatialFilterUsingJTS_Test.java
+++ 
b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/filter/BinarySpatialFilterUsingJTS_Test.java
@@ -25,6 +25,7 @@ import org.locationtech.jts.geom.Geometry;
  * @author  Johann Sorel (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
  */
+@SuppressWarnings("exports")
 public final class BinarySpatialFilterUsingJTS_Test extends 
BinarySpatialFilterTestCase<Geometry> {
     /**
      * Creates a new test.
diff --git 
a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/filter/BinarySpatialFilterUsingJava2D_Test.java
 
b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/filter/BinarySpatialFilterUsingJava2D_Test.java
index ff182e4036..8b4dd011d9 100644
--- 
a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/filter/BinarySpatialFilterUsingJava2D_Test.java
+++ 
b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/filter/BinarySpatialFilterUsingJava2D_Test.java
@@ -28,6 +28,7 @@ import org.junit.jupiter.api.Test;
  *
  * @author  Martin Desruisseaux (Geomatys)
  */
+@SuppressWarnings("exports")
 public final class BinarySpatialFilterUsingJava2D_Test extends 
BinarySpatialFilterTestCase<Shape> {
     /**
      * Creates a new test.
diff --git 
a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/geometry/wrapper/jts/JTSTest.java
 
b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/geometry/wrapper/jts/JTSTest.java
index 4c38c1cf32..3ea20b5a6b 100644
--- 
a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/geometry/wrapper/jts/JTSTest.java
+++ 
b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/geometry/wrapper/jts/JTSTest.java
@@ -24,7 +24,9 @@ import org.locationtech.jts.geom.Geometry;
 import org.locationtech.jts.geom.GeometryFactory;
 import org.opengis.util.FactoryException;
 import org.opengis.referencing.operation.TransformException;
+import org.opengis.referencing.operation.CoordinateOperation;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.apache.sis.referencing.CRS;
 import org.apache.sis.referencing.CommonCRS;
 import org.apache.sis.geometry.GeneralEnvelope;
 import org.apache.sis.geometry.wrapper.Geometries;
@@ -176,13 +178,7 @@ public final class JTSTest extends TestCase {
     }
 
     /**
-     * Tests various {@code transform} methods. This includes (sometimes 
indirectly):
-     *
-     * <ul>
-     *   <li>{@link JTS#transform(Geometry, CoordinateReferenceSystem)}</li>
-     *   <li>{@link JTS#transform(Geometry, CoordinateOperation)}</li>
-     *   <li>{@link JTS#transform(Geometry, MathTransform)}</li>
-     * </ul>
+     * Tests the {@code transform(…)} method.
      *
      * @throws FactoryException if an EPSG code cannot be resolved.
      * @throws TransformException if a coordinate cannot be transformed.
@@ -191,29 +187,25 @@ public final class JTSTest extends TestCase {
     public void testTransform() throws FactoryException, TransformException {
         final GeometryFactory factory = Factory.INSTANCE.factory(false);
         final Geometry in = factory.createPoint(new CoordinateXY(5, 6));
-        /*
-         * Test transforming geometry without CRS.
-         */
-        assertSame(in, JTS.transform(in, CommonCRS.WGS84.geographic()));
         /*
          * Test axes inversion transform.
          */
         in.setUserData(CommonCRS.WGS84.normalizedGeographic());
-        Point p = assertInstanceOf(Point.class, JTS.transform(in, 
CommonCRS.WGS84.geographic()));
+        Point p = assertInstanceOf(Point.class, transform(in, 
CommonCRS.WGS84.geographic()));
         assertEquals(6, p.getX());
         assertEquals(5, p.getY());
         assertEquals(CommonCRS.WGS84.geographic(), p.getUserData());
         /*
          * Test affine transform. User data must be preserved.
          */
-        final AffineTransform2D trs = new AffineTransform2D(1, 0, 0, 1, 10, 
20);
+        final var trs = new AffineTransform2D(1, 0, 0, 1, 10, 20);
         p = assertInstanceOf(Point.class, JTS.transform(in, trs));
         assertEquals(15, p.getX());
         assertEquals(26, p.getY());
     }
 
     /**
-     * Tests various {@code transform} method with a three-dimensional 
geometry.
+     * Tests the {@code transform(…)} method with a three-dimensional geometry.
      *
      * @throws FactoryException if an EPSG code cannot be resolved.
      * @throws TransformException if a coordinate cannot be transformed.
@@ -223,10 +215,9 @@ public final class JTSTest extends TestCase {
         final GeometryFactory factory = Factory.INSTANCE.factory(false);
         final Point in = factory.createPoint(new Coordinate(5, 6, 2));
         assertEquals(Factory.TRIDIMENSIONAL, 
in.getCoordinateSequence().getDimension());
-        assertSame(in, JTS.transform(in, CommonCRS.WGS84.geographic()));
 
         in.setUserData(CommonCRS.WGS84.geographic3D());
-        final Point p = assertInstanceOf(Point.class, JTS.transform(in, 
CommonCRS.WGS84.geographic()));
+        final Point p = assertInstanceOf(Point.class, transform(in, 
CommonCRS.WGS84.geographic()));
         assertEquals(5, p.getX());
         assertEquals(6, p.getY());
         assertEquals(CommonCRS.WGS84.geographic(), p.getUserData());
@@ -234,7 +225,7 @@ public final class JTSTest extends TestCase {
     }
 
     /**
-     * Test {@code transform} method on an empty geometry.
+     * Test {@code transform(…)} method on an empty geometry.
      *
      * @throws FactoryException if an EPSG code cannot be resolved.
      * @throws TransformException if a coordinate cannot be transformed.
@@ -244,8 +235,27 @@ public final class JTSTest extends TestCase {
         final GeometryFactory factory = Factory.INSTANCE.factory(false);
         final Point in = factory.createPoint();
         in.setUserData(CommonCRS.WGS84.geographic());
-        final Geometry r = JTS.transform(in, 
CommonCRS.WGS84.normalizedGeographic());
+        final Geometry r = transform(in, 
CommonCRS.WGS84.normalizedGeographic());
         assertEquals(CommonCRS.WGS84.normalizedGeographic(), r.getUserData());
         assertTrue(r.isEmpty());
     }
+
+    /**
+     * Transforms the given geometry to the specified Coordinate Reference 
System (<abbr>CRS</abbr>).
+     *
+     * @param  geometry   the geometry to transform.
+     * @param  targetCRS  the target coordinate reference system.
+     * @return the transformed geometry.
+     * @throws FactoryException if transformation to the target CRS cannot be 
constructed.
+     * @throws TransformException if the given geometry cannot be transformed.
+     */
+    private static Geometry transform(Geometry geometry, final 
CoordinateReferenceSystem targetCRS)
+            throws FactoryException, TransformException
+    {
+        final CoordinateReferenceSystem sourceCRS = 
JTS.getCoordinateReferenceSystem(geometry);
+        final CoordinateOperation operation = CRS.findOperation(sourceCRS, 
targetCRS, null);
+        geometry = org.apache.sis.geometry.wrapper.jts.JTS.transform(geometry, 
operation.getMathTransform());
+        geometry.setUserData(operation.getTargetCRS());
+        return geometry;
+    }
 }
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/geometry/AbstractEnvelope.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/geometry/AbstractEnvelope.java
index 67af590ef1..fdc2b9c697 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/geometry/AbstractEnvelope.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/geometry/AbstractEnvelope.java
@@ -1180,6 +1180,8 @@ public abstract class AbstractEnvelope extends 
FormattableObject implements Enve
 
     /**
      * Returns a hash value for this envelope.
+     *
+     * @return a hash value for this envelope.
      */
     @Override
     public int hashCode() {
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/AbstractMathTransform.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/AbstractMathTransform.java
index 4b67ce3c10..f96326aa89 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/AbstractMathTransform.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/AbstractMathTransform.java
@@ -162,30 +162,28 @@ public abstract class AbstractMathTransform extends 
FormattableObject
     public abstract int getTargetDimensions();
 
     /**
-     * Returns the ranges of coordinate values which can be used as inputs.
-     * They are limits where the transform is mathematically and numerically 
applicable.
+     * Returns the ranges of source coordinate values where this transform is 
mathematically applicable.
      * This is <em>not</em> the domain of validity for which a coordinate 
reference system has been defined,
-     * because this method ignores "real world" considerations such as datum 
and country boundaries.
-     *
-     * <p>This method is for allowing callers to crop their data for removing 
areas that may cause numerical problems.
-     * For example, results of Mercator projection tend to infinity when the 
latitude value approaches a pole.
-     * For avoiding data structures with unreasonably large values or {@link 
Double#NaN},
-     * we commonly crop data to some arbitrary maximal latitude value 
(typically 80 or 84°) before projection.
+     * because this method ignores real world considerations such as datum and 
country boundaries.
+     * This method can be used for cropping data in order to exclude areas 
that may cause numerical problems.
+     * For example, the results of a Mercator projection tend to infinity when 
the latitude values approach a pole.
+     * For avoiding data structures with unreasonably large values or {@link 
Double#NaN} values,
+     * an arbitrary maximal latitude value (typically 80° or 84°) can be 
enforced before projection.
      * Those limits are arbitrary, the transform does not become suddenly 
invalid after a limit.
-     * The {@link DomainDefinition} gives some controls on the criteria for 
choosing a limit.</p>
+     * But enforcing such limits can (for example) avoid chaotic viewer 
behavior when attempting
+     * to render a world-wide image.
      *
-     * <p>Many transforms, in particular all affine transforms, have no 
mathematical limits.
-     * Consequently, the default implementation returns an empty value.
-     * Again it does not mean that the {@linkplain 
org.apache.sis.referencing.operation.AbstractCoordinateOperation
-     * coordinate operation} has no geospatial domain of validity, but the 
latter is not the purpose of this method.
-     * This method is (for example) for preventing a viewer to crash when 
attempting to render a world-wide image.</p>
+     * <p>Many transforms, in particular affine transforms, have no 
mathematical limits.
+     * Therefore, the default implementation returns an empty value, but it 
does not mean that the associated
+     * {@linkplain 
org.apache.sis.referencing.operation.AbstractCoordinateOperation coordinate 
operation}
+     * has no geospatial domain of validity.</p>
      *
      * <p>Callers do not need to search through {@linkplain 
MathTransforms#getSteps(MathTransform) transform steps}.
      * The Apache <abbr>SIS</abbr> implementation of {@link 
MathTransforms#concatenate(MathTransform, MathTransform)
      * concatenated transforms} does that automatically.</p>
      *
      * @param  criteria  controls the definition of transform domain.
-     * @return estimation of a domain where this transform is considered 
numerically applicable.
+     * @return estimation of ranges of source coordinate values where the 
transform is numerically applicable.
      * @throws TransformException if the domain cannot be estimated.
      *
      * @see MathTransforms#getDomain(MathTransform)
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/DomainDefinition.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/DomainDefinition.java
index 948b2fac71..2996b1a548 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/DomainDefinition.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/DomainDefinition.java
@@ -28,11 +28,11 @@ import org.apache.sis.geometry.GeneralEnvelope;
 
 
 /**
- * Specification about how to estimate a domain of validity for transforms.
+ * Builder of the mathematical domain of validity of a {@code MathTransform}.
  * Contrary to {@linkplain CRS#getDomainOfValidity(CoordinateReferenceSystem) 
CRS domain of validity},
- * this class estimates a domain based on mathematical behavior only, not on 
"real world" considerations.
- * For example, the Mercator projection tends to infinity when approaching 
poles, so it is recommended to
- * not use it above some latitude threshold, typically 80° or 84°. The exact 
limit is arbitrary.
+ * this class estimates a domain based on mathematical behavior only, not on 
real world considerations.
+ * For example, the Mercator projection tends to infinity when approaching 
poles, so it is recommended
+ * to not use it above some latitude threshold, typically 80° or 84°. The 
exact limit is arbitrary.
  * This is different than the domain of validity of CRS, which is often 
limited to a particular country.
  * In general, the CRS domain of validity is much smaller than the domain 
computed by this class.
  *
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/GeometryTransformException.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/GeometryTransformException.java
new file mode 100644
index 0000000000..734853398d
--- /dev/null
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/GeometryTransformException.java
@@ -0,0 +1,67 @@
+/*
+ * 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.referencing.operation.TransformException;
+
+
+/**
+ * Thrown when a transform cannot be applied on a given geometry or envelope 
instance.
+ * This exception is usually thrown when a geometric prerequisite has not been 
met.
+ * The failed check may be before any attempt to actually transform a point.
+ * For example, the geometry may be an instance of an unrecognized type,
+ * or the geometry envelope may be outside the
+ * {@linkplain AbstractMathTransform#getDomain transform domain}.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 1.8
+ * @since   1.8
+ */
+public class GeometryTransformException extends TransformException {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = -9058827495784393813L;
+
+    /**
+     * Creates an exception with the specified detail message.
+     *
+     * @param message  the detail message, saved for later retrieval by the 
{@link #getMessage()} method.
+     */
+    public GeometryTransformException(String message) {
+        super(message);
+    }
+
+    /**
+     * Creates an exception with the specified cause.
+     *
+     * @param cause  the cause, saved for later retrieval by the {@link 
#getCause()} method.
+     */
+    public GeometryTransformException(Throwable cause) {
+        super(cause);
+    }
+
+    /**
+     * Creates an exception with the specified detail message and cause.
+     *
+     * @param message  the detail message, saved for later retrieval by the 
{@link #getMessage()} method.
+     * @param cause    the cause, saved for later retrieval by the {@link 
#getCause()} method.
+     */
+    public GeometryTransformException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/MathTransforms.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/MathTransforms.java
index 1a85580232..3880e732a9 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/MathTransforms.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/MathTransforms.java
@@ -786,17 +786,17 @@ public final class MathTransforms {
     }
 
     /**
-     * Returns source coordinate values where the transform is mathematically 
and numerically applicable.
+     * Returns the ranges of source coordinate values where the given 
transform is mathematically applicable.
      * This is <em>not</em> the domain of validity for which a coordinate 
reference system has been defined,
-     * because this method ignores "real world" considerations such as datum 
and country boundaries.
+     * because this method ignores real world considerations such as datum and 
country boundaries.
      * This method is for allowing callers to crop their data for removing 
areas that may cause numerical problems,
-     * for example latitudes too close to a pole before Mercator projection.
+     * for example latitudes too close to a pole used as inputs of a Mercator 
projection.
      *
      * <p>See {@link AbstractMathTransform#getDomain(DomainDefinition)} for 
more information.
      * This static method delegates to above-cited method if possible, or 
returns an empty value otherwise.</p>
      *
      * @param  evaluated  transform for which to evaluate a domain, or {@code 
null}.
-     * @return estimation of a domain where this transform is considered 
numerically applicable.
+     * @return estimation of ranges of source coordinate values where the 
transform is numerically applicable.
      * @throws TransformException if the domain cannot be estimated.
      *
      * @see AbstractMathTransform#getDomain(DomainDefinition)
diff --git 
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/adapter/Wrapper.java
 
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/adapter/Wrapper.java
index 40e7da88eb..617a40325e 100644
--- 
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/adapter/Wrapper.java
+++ 
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/adapter/Wrapper.java
@@ -62,7 +62,6 @@ import org.apache.sis.measure.Quantities;
 import org.apache.sis.measure.Units;
 import org.apache.sis.referencing.CRS;
 import org.apache.sis.referencing.operation.transform.MathTransforms;
-import 
org.apache.sis.referencing.operation.transform.TransformFactoryException;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.Debug;
 import org.apache.sis.util.UnconvertibleObjectException;
@@ -638,60 +637,34 @@ add:    for (Geometry next = geometry;;) {
     /**
      * Transforms this geometry using the given coordinate operation.
      * If the operation is {@code null}, then the geometry is returned 
unchanged.
-     * If the geometry uses a different CRS than the source CRS of the given 
operation
-     * and {@code validate} is {@code true},
-     * then a new operation to the target CRS will be automatically computed.
      *
-     * @param  operation  the coordinate operation to apply, or {@code null}.
-     * @param  validate   whether to validate the operation source CRS.
+     * @param  operation    the coordinate operation to apply.
      * @throws FactoryException if transformation to the target CRS cannot be 
found.
      * @throws TransformException if the geometry cannot be transformed.
      */
     @Override
-    public GeometryWrapper transform(final CoordinateOperation operation, 
final boolean validate)
-            throws FactoryException, TransformException {
-        if (operation == null) {
-            return this;
-        }
+    protected GeometryWrapper transform(final CoordinateOperation operation)
+            throws FactoryException, TransformException
+    {
         MathTransform mt = operation.getMathTransform();
-        if (validate && crs != null) {
+        if (VERIFY_GEOMETRY_CRS_BEFORE_OPERATION && crs != null) {
             final CoordinateOperation step = CRS.findOperation(crs, 
operation.getSourceCRS(), null);
             mt = MathTransforms.concatenate(step.getMathTransform(), mt);
         }
         return new Wrapper(new GeometryProcessor().transform(geometry, 
operation.getTargetCRS(), mt));
     }
 
-    /**
-     * Transforms this geometry to the specified Coordinate Reference System 
(CRS).
-     * If the given CRS is null or is the same CRS as current one, the 
geometry is returned unchanged.
-     *
-     * @param  targetCRS  the target coordinate reference system, or {@code 
null}.
-     * @return the transformed geometry (may be the same geometry instance), 
or {@code null}.
-     * @throws TransformException if this geometry cannot be transformed.
-     */
-    @Override
-    public GeometryWrapper transform(final CoordinateReferenceSystem 
targetCRS) throws TransformException {
-        if (targetCRS == null || targetCRS == crs || crs == null) {
-            return this;
-        }
-        try {
-            return transform(CRS.findOperation(crs, targetCRS, null), false);
-        } catch (FactoryException e) {
-            throw new TransformFactoryException(e);
-        }
-    }
-
     /**
      * Transforms this geometry using the given transform.
      * If the transform is {@code null}, then the geometry is returned 
unchanged.
      *
-     * @param  transform  the math transform to apply, or {@code null}.
+     * @param  transform  the math transform to apply.
      * @return the transformed geometry (may be the same geometry instance, 
but never {@code null}).
      * @throws TransformException if the geometry cannot be transformed.
      */
     @Override
-    public GeometryWrapper transform(final MathTransform transform) throws 
FactoryException, TransformException {
-        if (transform == null || transform.isIdentity()) {
+    protected GeometryWrapper transform(final MathTransform transform) throws 
TransformException {
+        if (transform.isIdentity()) {
             return this;
         }
         return new Wrapper(this, new GeometryProcessor().transform(geometry, 
null, transform));
diff --git 
a/incubator/src/org.apache.sis.referencing.dggs/main/org/apache/sis/storage/rs/internal/shared/s2/Wrapper.java
 
b/incubator/src/org.apache.sis.referencing.dggs/main/org/apache/sis/storage/rs/internal/shared/s2/Wrapper.java
index 1846ac90b2..e3c525ccd2 100644
--- 
a/incubator/src/org.apache.sis.referencing.dggs/main/org/apache/sis/storage/rs/internal/shared/s2/Wrapper.java
+++ 
b/incubator/src/org.apache.sis.referencing.dggs/main/org/apache/sis/storage/rs/internal/shared/s2/Wrapper.java
@@ -19,7 +19,6 @@ package org.apache.sis.storage.rs.internal.shared.s2;
 import java.util.Iterator;
 import com.google.common.geometry.S2Region;
 import org.opengis.geometry.DirectPosition;
-import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.apache.sis.geometry.GeneralEnvelope;
 import org.apache.sis.geometry.wrapper.Geometries;
 import org.apache.sis.geometry.wrapper.GeometryWrapper;
@@ -89,10 +88,4 @@ final class Wrapper extends GeometryWrapper {
     public String formatWKT(double flatness) {
         throw new UnsupportedOperationException("Unsupported operation");
     }
-
-    @Override
-    public void setCoordinateReferenceSystem(CoordinateReferenceSystem crs) {
-        throw new UnsupportedOperationException("Not supported yet."); // 
Generated from 
nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody
-    }
-
 }

Reply via email to