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

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

commit 42a3d15915c33d0395e0620117b64b5e13b7ba63
Merge: 95d808c404 cb32b1b2f0
Author: Martin Desruisseaux <martin.desruisse...@geomatys.com>
AuthorDate: Tue Jun 24 18:21:42 2025 +0200

    Merge branch 'geoapi-3.1', excluding the `org.apache.sis.geometry` module 
(incubator).
    That geometry module depends on GeoAPI interfaces that are not released 
(and may not).
    A review of the geometry module is necessary before it can be merged to the 
main branch.

 buildSrc/build.gradle.kts                          |   2 +-
 .../main/org/apache/sis/console/AboutCommand.java  |   2 +-
 .../main/org/apache/sis/coverage/CategoryList.java |  10 +-
 .../coverage/grid/CoordinateOperationFinder.java   | 116 ++-
 .../sis/coverage/internal/CompoundTransform.java   |   8 +-
 .../sis/geometry/wrapper/GeometryFactories.java    |   2 +-
 .../org/apache/sis/geometry/wrapper/jts/JTS.java   |  96 +++
 .../main/org/apache/sis/image/AnnotatedImage.java  |   2 +-
 .../main/org/apache/sis/image/ErrorHandler.java    |   2 +-
 .../org/apache/sis/image/privy/TileOpExecutor.java |   2 +-
 .../sis/coverage/grid/GridDerivationTest.java      |  28 +
 .../apache/sis/coverage/grid/GridGeometryTest.java |  61 +-
 .../apache/sis/metadata/sql/CachedStatement.java   |   2 +-
 .../apache/sis/metadata/sql/MetadataSource.java    |   4 +-
 .../apache/sis/metadata/sql/MetadataWriter.java    |   2 +-
 .../apache/sis/metadata/sql/privy/Initializer.java |   6 +-
 .../main/org/apache/sis/util/iso/Types.java        |   2 +-
 .../main/org/apache/sis/xml/bind/Context.java      |   2 +-
 .../apache/sis/xml/privy/ExceptionSimplifier.java  |   2 +-
 .../org/apache/sis/metadata/sql/TestDatabase.java  |   3 +-
 .../main/org/apache/sis/io/wkt/Warnings.java       |   4 +-
 .../factory/AuthorityFactoryIdentifier.java        |   4 +-
 .../factory/ConcurrentAuthorityFactory.java        |   4 +-
 .../referencing/factory/GeodeticObjectFactory.java |   2 +-
 .../referencing/factory/IdentifiedObjectSet.java   |   2 +-
 .../factory/MultiAuthoritiesFactory.java           |   4 +-
 .../referencing/factory/sql/EPSGDataAccess.java    |  14 +-
 .../sis/referencing/factory/sql/EPSGInstaller.java |  13 +-
 .../factory/sql/InstallationScriptProvider.java    |   4 +-
 .../internal/ParameterizedTransformBuilder.java    |   9 +-
 .../apache/sis/referencing/internal/Resources.java |  10 +
 .../sis/referencing/internal/Resources.properties  |   2 +
 .../referencing/internal/Resources_fr.properties   |   2 +
 .../apache/sis/referencing/operation/CRSPair.java  |   4 +-
 .../operation/CoordinateOperationFinder.java       |  33 +-
 .../operation/CoordinateOperationRegistry.java     |   2 +-
 .../referencing/operation/SubOperationInfo.java    | 174 ++--
 .../referencing/operation/gridded/GridFile.java    |   5 +-
 .../referencing/operation/gridded/LoadedGrid.java  |   2 +-
 .../projection/EquidistantCylindrical.java         |  25 +
 .../referencing/operation/projection/Mercator.java |  41 +-
 .../operation/projection/NormalizedProjection.java |   7 +-
 .../provider/FranceGeocentricInterpolation.java    |   2 +-
 .../operation/provider/Interpolation1D.java        |  10 +-
 .../sis/referencing/operation/provider/NTv2.java   |   4 +-
 .../operation/transform/AbstractMathTransform.java | 379 +--------
 .../transform/AbstractMathTransform1D.java         |  24 +-
 .../transform/AbstractMathTransform2D.java         |   6 +-
 .../operation/transform/ConcatenatedTransform.java | 428 +++++-----
 .../transform/ConcatenatedTransformDirect.java     |   4 +-
 .../operation/transform/ConstantTransform1D.java   |   8 +-
 .../transform/CoordinateSystemTransform.java       |  23 +-
 .../operation/transform/CopyTransform.java         |   2 +-
 .../operation/transform/DatumShiftTransform.java   |  22 +-
 .../transform/DefaultMathTransformFactory.java     |   3 +-
 .../transform/EllipsoidToCentricTransform.java     |  18 +-
 .../transform/EllipsoidToRadiusTransform.java      |  10 +-
 .../transform/ExponentialTransform1D.java          |  15 +-
 .../operation/transform/IdentityTransform.java     |  16 +-
 .../operation/transform/IdentityTransform1D.java   |   8 +-
 .../operation/transform/InterpolatedTransform.java |   2 +-
 .../operation/transform/LinearInterpolator1D.java  |   7 +-
 .../operation/transform/LinearTransform1D.java     |  10 +-
 .../transform/LogarithmicTransform1D.java          |  33 +-
 .../operation/transform/MathTransforms.java        |  77 +-
 .../operation/transform/MolodenskyTransform.java   |  48 +-
 .../operation/transform/PassThroughTransform.java  |  94 +-
 .../operation/transform/PowerTransform1D.java      |  17 +-
 .../operation/transform/ProjectiveTransform.java   |   2 +-
 .../operation/transform/ScaleTransform.java        |   2 +-
 .../operation/transform/TransformJoiner.java       | 945 +++++++++++++++++++++
 .../operation/transform/TransformSeparator.java    |   2 +-
 .../operation/transform/TranslationTransform.java  |   2 +-
 .../operation/transform/UnitConversion.java        |  10 +-
 .../operation/transform/WraparoundTransform.java   | 321 +++----
 .../sis/referencing/privy/DefinitionVerifier.java  |   2 +-
 .../apache/sis/geometry/EnvelopeReducerTest.java   |   7 +-
 .../referencing/crs/DefaultProjectedCRSTest.java   |   5 +-
 .../DefaultCoordinateOperationFactoryTest.java     |   4 +-
 .../operation/projection/ObliqueMercatorTest.java  |   4 +-
 .../transform/ConcatenatedTransformTest.java       |  69 +-
 .../transform/EllipsoidToCentricTransformTest.java |   4 +-
 .../transform/EllipsoidToRadiusTransformTest.java  |  22 +
 .../operation/transform/MathTransformWrapper.java  |   8 +-
 .../transform/MolodenskyTransformTest.java         |  56 +-
 .../transform/PassThroughTransformTest.java        |  36 +-
 .../transform/TransformResultComparator.java       |   9 +-
 .../transform/TransformSeparatorTest.java          |   4 +-
 .../transform/WraparoundTransformTest.java         |   2 +-
 .../sis/storage/geotiff/ImageFileDirectory.java    |   2 +-
 .../sis/storage/geotiff/reader/CRSBuilder.java     |   2 +-
 .../sis/storage/netcdf/NetcdfStoreProvider.java    |   2 +-
 .../apache/sis/storage/netcdf/base/Decoder.java    |   2 +-
 .../org/apache/sis/storage/netcdf/base/Grid.java   |   3 +-
 .../sis/storage/netcdf/base/NamedElement.java      |   2 +-
 .../apache/sis/storage/sql/feature/Database.java   |   2 +-
 .../sis/storage/sql/feature/SelectionClause.java   |   2 +-
 .../apache/sis/storage/sql/postgis/Postgres.java   |   6 +-
 .../sis/storage/AbstractGridCoverageResource.java  |   2 +-
 .../main/org/apache/sis/storage/URLDataSource.java |   9 +-
 .../sis/storage/base/DocumentedStoreProvider.java  |   2 +-
 .../org/apache/sis/storage/base/URIDataStore.java  |   6 +-
 .../sis/storage/csv/MovingFeatureBuilder.java      |   9 +-
 .../main/org/apache/sis/storage/csv/Store.java     |   2 +-
 .../org/apache/sis/storage/wkt/StoreFormat.java    |   2 +-
 .../main/org/apache/sis/system/DataDirectory.java  |   2 +-
 .../org/apache/sis/system/OptionalDependency.java  |   6 +-
 .../main/org/apache/sis/system/Supervisor.java     |   2 +-
 .../org/apache/sis/util/collection/WeakEntry.java  |   2 +-
 .../main/org/apache/sis/util/resources/Errors.java |   2 +-
 .../apache/sis/util/resources/Errors.properties    |   2 +-
 .../apache/sis/util/resources/Errors_fr.properties |   2 +-
 .../sis/util/resources/IndexedResourceBundle.java  |  55 +-
 .../resources/ResourceInternationalString.java     |   2 +-
 .../util/resources/IndexedResourceBundleTest.java  |   8 +-
 incubator/build.gradle.kts                         |   6 +-
 .../apache/sis/storage/geoheif/GeoHeifStore.java   |   2 +-
 .../org/apache/sis/storage/isobmff/Reader.java     |   2 +-
 netbeans-project/ivy.xml                           |  16 +-
 netbeans-project/nbproject/project.xml             |   1 +
 .../main/org/apache/sis/storage/gdal/GDAL.java     |   2 +-
 .../apache/sis/storage/panama/LibraryLoader.java   |   2 +-
 settings.gradle.kts                                |  12 +-
 123 files changed, 2399 insertions(+), 1289 deletions(-)

diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/SubOperationInfo.java
index e845b6e2a5,b6ab6e89f7..f58a9eaaf7
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/SubOperationInfo.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/SubOperationInfo.java
@@@ -18,16 -18,17 +18,20 @@@ package org.apache.sis.referencing.oper
  
  import java.util.List;
  import org.opengis.referencing.crs.*;
+ import org.opengis.referencing.operation.Matrix;
  import org.opengis.referencing.operation.CoordinateOperation;
  import org.opengis.referencing.operation.OperationNotFoundException;
+ import org.opengis.referencing.operation.NoninvertibleTransformException;
  import org.opengis.referencing.operation.TransformException;
  import org.opengis.util.FactoryException;
+ import org.apache.sis.referencing.internal.Resources;
  import org.apache.sis.referencing.operation.matrix.Matrices;
  import org.apache.sis.referencing.operation.matrix.MatrixSIS;
+ import org.apache.sis.referencing.operation.transform.MathTransforms;
  
 +// Specific to the main branch:
 +import org.apache.sis.referencing.crs.DefaultParametricCRS;
 +
  
  /**
   * Information about the operation from a source component to a target 
component in {@code CompoundCRS} instances.
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/AbstractMathTransform.java
index 28d98f6fc6,8e7f6cf19f..aa73abba1f
--- 
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
@@@ -49,12 -46,10 +46,10 @@@ import org.apache.sis.util.Utilities
  import org.apache.sis.util.ComparisonMode;
  import org.apache.sis.util.LenientComparable;
  import org.apache.sis.util.OptionalCandidate;
- 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 org.opengis.coordinate.MismatchedDimensionException;
 +// Specific to the main branch:
 +import org.opengis.geometry.MismatchedDimensionException;
  
  
  /**
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/AbstractMathTransform1D.java
index 4551bcdfb2,fef35f5bcb..e0f30cac58
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/AbstractMathTransform1D.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/AbstractMathTransform1D.java
@@@ -135,8 -147,8 +147,8 @@@ public abstract class AbstractMathTrans
          if (point == null) {
              coordinate = Double.NaN;
          } else {
-             ensureDimensionMatches("point", 1, point);
+             ensureDimensionMatches("point", DIMENSION, point);
 -            coordinate = point.getCoordinate(0);
 +            coordinate = point.getOrdinate(0);
          }
          return new Matrix1(derivative(coordinate));
      }
@@@ -214,8 -226,8 +226,8 @@@
              if (point == null) {
                  coordinate = Double.NaN;
              } else {
-                 ensureDimensionMatches("point", 1, point);
+                 ensureDimensionMatches("point", DIMENSION, point);
 -                coordinate = point.getCoordinate(0);
 +                coordinate = point.getOrdinate(0);
              }
              return new Matrix1(derivative(coordinate));
          }
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/MathTransforms.java
index 7c776b623a,26b85b0af3..0564d0c7a9
--- 
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
@@@ -294,8 -294,11 +294,9 @@@ public final class MathTransforms exten
       *
       * @param  preimage  the input values (<var>x</var>) in the function 
domain, or {@code null}.
       * @param  values    the output values (<var>y</var>) in the function 
range, or {@code null}.
+      * @throws IllegalArgumentException if {@code preimage} is non-null and 
the sequence of values is not monotonic.
       * @return the <i>y=f(x)</i> function.
       *
 -     * @see org.opengis.coverage.InterpolationMethod
 -     *
       * @since 0.7
       */
      public static MathTransform1D interpolate(final double[] preimage, final 
double[] values) {
diff --cc 
endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/projection/ObliqueMercatorTest.java
index 517c8fadde,bbae27f48e..a77cb57d68
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/projection/ObliqueMercatorTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/projection/ObliqueMercatorTest.java
@@@ -26,7 -25,12 +25,8 @@@ import org.apache.sis.parameter.Paramet
  
  // Test dependencies
  import org.junit.jupiter.api.Test;
+ import org.apache.sis.referencing.datum.HardCodedDatum;
  
 -// Specific to the geoapi-3.1 and geoapi-4.0 branches:
 -import org.opengis.util.FactoryException;
 -import org.opengis.test.ToleranceModifier;
 -
  
  /**
   * Tests the {@link ObliqueMercator} class.
diff --cc 
endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/transform/ConcatenatedTransformTest.java
index 9b15e1d5cf,8315b68eef..d118a1f2b8
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/transform/ConcatenatedTransformTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/transform/ConcatenatedTransformTest.java
@@@ -158,6 -161,48 +161,48 @@@ public final class ConcatenatedTransfor
          assertEquals(4, transform.getTargetDimensions());
      }
  
+     /**
+      * Test pass-through which is build-in the transform.
+      *
+      * @throws FactoryException if an error occurred while creating the math 
transform to test.
+      */
+     @Test
+     public void testBuildinPassthrough() throws FactoryException {
+         final var kernel = new PseudoTransform(2, 2) {
+             /** Whether the pass-through optimization has been applied. */
+             private boolean done;
+ 
+             /** Tries to apply the pass-through optimization. */
+             @Override protected void tryConcatenate(final TransformJoiner 
context) throws FactoryException {
+                 if (context.replacePassThrough(Map.of(1, 1))) {
+                     assertFalse(done);
+                     done = true;
+                 }
+             }
+         };
+         final Matrix3 before, after;
+         before = new Matrix3(0.25,  0,    -45,
+                              0,    -0.25,  90,
+                              0,     0,      1);
+ 
+         after  = new Matrix3(1,     0,     45,
+                              0,    -1,     90,
+                              0,     0,      1);
+ 
+         transform = MathTransforms.concatenate(MathTransforms.linear(before), 
kernel, MathTransforms.linear(after));
+         final List<MathTransform> steps = MathTransforms.getSteps(transform);
+         assertEquals(3, steps.size());
+         assertSame(kernel, steps.get(1));
+         /*
+          * The optimization should have moved the -1 factor from `after` to 
`before`
+          * in order to simplify `after` to a matrix doing only a translation.
+          */
+         after .m11 = -after .m11;    after .m12 = 0;
+         before.m11 = -before.m11;    before.m12 = 0;
 -        assertMatrixEquals(before, MathTransforms.getMatrix(steps.get(0)), 
null, "before");
 -        assertMatrixEquals(after,  MathTransforms.getMatrix(steps.get(2)), 
null, "after");
++        assertMatrixEquals(before, MathTransforms.getMatrix(steps.get(0)), 
STRICT, "before");
++        assertMatrixEquals(after,  MathTransforms.getMatrix(steps.get(2)), 
STRICT, "after");
+     }
+ 
      /**
       * Tests concatenation of transforms built from non-square matrices. The 
transforms are invertible
       * when taken separately, but the transform resulting from concatenation 
cannot be inverted unless
diff --cc 
endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/transform/EllipsoidToRadiusTransformTest.java
index 09513a4b3f,d4c6831e94..4530cfd75a
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/transform/EllipsoidToRadiusTransformTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/transform/EllipsoidToRadiusTransformTest.java
@@@ -24,8 -26,9 +26,10 @@@ import org.apache.sis.referencing.opera
  
  // Test dependencies
  import org.junit.jupiter.api.Test;
+ import static org.junit.jupiter.api.Assertions.*;
  import org.apache.sis.referencing.datum.HardCodedDatum;
  import static org.apache.sis.test.Assertions.assertSerializedEquals;
++import static org.apache.sis.test.GeoapiAssert.assertMatrixEquals;
  
  
  /**
@@@ -103,6 -106,24 +107,24 @@@ public final class EllipsoidToRadiusTra
          });
      }
  
+     /**
+      * Tests a concatenation of transform that can be simplified by moving an 
offset of the longitude value.
+      */
+     @Test
+     public void testPassThrough() {
+         transform = new 
EllipsoidToRadiusTransform(HardCodedDatum.WGS84.getEllipsoid());
+         transform = MathTransforms.concatenate(MathTransforms.scale(2, 3), 
transform, MathTransforms.translation(-5, 0, 0));
+         final ConcatenatedTransform c = 
assertInstanceOf(ConcatenatedTransform.class, transform);
+         final EllipsoidToRadiusTransform tr2 = 
assertInstanceOf(EllipsoidToRadiusTransform.class, c.transform2);
+         assertEquals(0.006694379990141317, tr2.eccentricitySquared, 1E-17);
+         final Matrix tr1 = MathTransforms.getMatrix(c.transform1);
+         assertNotNull(tr1);
+         assertMatrixEquals(new Matrix3(
+                 2, 0, -5,
+                 0, 3,  0,
 -                0, 0,  1), tr1, null, null);
++                0, 0,  1), tr1, 0, null);
+     }
+ 
      /**
       * Tests serialization.
       *
diff --cc 
endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/transform/MolodenskyTransformTest.java
index 04255fa62c,699e340af0..72ee28d56f
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/transform/MolodenskyTransformTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/transform/MolodenskyTransformTest.java
@@@ -31,13 -33,24 +33,14 @@@ import org.apache.sis.referencing.privy
  // Test dependencies
  import org.junit.jupiter.api.Test;
  import static org.junit.jupiter.api.Assertions.*;
- import 
org.apache.sis.referencing.operation.provider.FranceGeocentricInterpolationTest;
- import 
org.apache.sis.referencing.operation.provider.GeocentricTranslationTest;
  import org.apache.sis.test.TestUtilities;
+ import org.apache.sis.referencing.datum.GeodeticDatumMock;
  import org.apache.sis.referencing.datum.HardCodedDatum;
+ import 
org.apache.sis.referencing.operation.provider.FranceGeocentricInterpolationTest;
+ import 
org.apache.sis.referencing.operation.provider.GeocentricTranslationTest;
  
 -// Specific to the geoapi-3.1 and geoapi-4.0 branches:
 -import java.io.IOException;
 -import org.opengis.referencing.operation.MathTransform;
 -import org.apache.sis.referencing.operation.provider.AbridgedMolodensky;
 -import org.apache.sis.math.StatisticsFormat;
 -import org.apache.sis.math.Statistics;
 -import static org.apache.sis.metadata.privy.ReferencingServices.NAUTICAL_MILE;
 -import org.opengis.test.CalculationType;
 -import org.opengis.test.ToleranceModifier;
 -import org.opengis.test.ToleranceModifiers;
 -import org.opengis.test.referencing.ParameterizedTransformTest;
 -import org.apache.sis.test.TestCase;
 +// Specific to the main branch:
 +import static org.apache.sis.referencing.privy.CoordinateOperations.builder;
  
  
  /**
@@@ -63,8 -76,69 +66,8 @@@ public final class MolodenskyTransformT
          tolerance          = Formulas.ANGULAR_TOLERANCE;        // Tolerance 
for longitude and latitude in degrees
      }
  
 -    /**
 -     * Compares the Molodensky (non-abridged) transform with a geocentric 
translation.
 -     * Molodensky is an approximation of geocentric translation, so we test 
here how good this approximation is.
 -     * If {@link TestCase#VERBOSE} is {@code true}, then this method will 
print error statistics.
 -     *
 -     * @throws FactoryException if an error occurred while creating a 
transform step.
 -     * @throws TransformException if a transformation failed.
 -     * @throws IOException should never happen.
 -     *
 -     * @see #compareWithGeocentricTranslation()
 -     */
 -    @SuppressWarnings("fallthrough")
 -    private void compareWithGeocentricTranslation(
 -            final Ellipsoid source, final Ellipsoid target,
 -            final double tX,   final double tY,   final double tZ,
 -            final double xmin, final double ymin, final double zmin,
 -            final double xmax, final double ymax, final double zmax)
 -            throws FactoryException, TransformException, IOException
 -    {
 -        final MathTransform reference;
 -        final MathTransformFactory factory = 
DefaultMathTransformFactory.provider();
 -        transform = MolodenskyTransform.createGeodeticTransformation(factory, 
source, true, target, true, tX, tY, tZ, false);
 -        reference = 
GeocentricTranslationTest.createDatumShiftForGeographic3D(factory, source, 
target, tX, tY, tZ);
 -        final float[] srcPts = verifyInDomain(
 -                new double[] {xmin, ymin, zmin},
 -                new double[] {xmax, ymax, zmax},
 -                new int[]    {  10,   10,   10},
 -                
TestUtilities.createRandomNumberGenerator(103627524044558476L));
 -        /*
 -         * Transform the same input coordinates using Molodensky transform 
(actual) and using the reference
 -         * implementation (expected). If we were asked to print statistics, 
compute them before to test the
 -         * values since the statistics may be a useful information in case of 
problem.
 -         */
 -        final double[] actual   = new double[srcPts.length];
 -        final double[] expected = new double[srcPts.length];
 -        transform.transform(srcPts, 0, actual,   0, srcPts.length / 3);
 -        reference.transform(srcPts, 0, expected, 0, srcPts.length / 3);
 -        if (TestCase.VERBOSE) {
 -            final Statistics[] stats = {
 -                new Statistics("|Δλ| (~cm)"),
 -                new Statistics("|Δφ| (~cm)"),
 -                new Statistics("|Δh| (cm)")
 -            };
 -            for (int i=0; i<srcPts.length; i++) {
 -                double Δ = actual[i] - expected[i];
 -                final int j = i % stats.length;
 -                switch (j) {
 -                    case 0: Δ *= cos(toRadians(expected[i+1]));     // Fall 
through
 -                    case 1: Δ *= 60 * NAUTICAL_MILE; break;         // 
Approximate conversion to metres
 -                }
 -                Δ *= 100;   // Conversion to centimetres.
 -                stats[j].accept(abs(Δ));
 -            }
 -            StatisticsFormat.getInstance().format(stats, TestCase.out);
 -        }
 -        assertCoordinatesEqual(3, expected, 0,
 -                actual, 0, expected.length / 3,
 -                CalculationType.DIRECT_TRANSFORM,
 -                "Comparison of Molodensky and geocentric translation");
 -    }
 -
      /**
-      * Creates a Molodensky transform for a datum shift from WGS84 to ED50.
+      * Creates a three-dimensional Molodensky transform for a datum shift 
from WGS84 to ED50.
       * Tolerance thresholds are also initialized.
       *
       * @throws FactoryException if an error occurred while creating a 
transform step.
@@@ -266,6 -391,49 +269,49 @@@
          validate();
      }
  
+     /**
+      * Tests the concatenation of a 3-dimensional transform with a "3D to 2D" 
transform.
+      *
+      * @throws FactoryException if an error occurred while creating a 
transform step.
+      * @throws TransformException if an error occurred while requesting the 
inverse transform.
+      */
+     @Test
+     public void testRedimension3Dto2D() throws FactoryException, 
TransformException {
 -        final MathTransformFactory factory = 
DefaultMathTransformFactory.provider();
++        final DefaultMathTransformFactory factory = 
DefaultMathTransformFactory.provider();
+         transform = new MolodenskyTransform(
+                 HardCodedDatum.WGS84.getEllipsoid(), true,
+                 GeodeticDatumMock.ED50.getEllipsoid(), true,
+                 GeocentricTranslationTest.TX,
+                 GeocentricTranslationTest.TY,
+                 GeocentricTranslationTest.TZ,
+                 false);
+         validate();
+         MolodenskyTransform forward, inverse;
+ 
+         // Verify initial conditions.
+         forward = assertInstanceOf(MolodenskyTransform.class, transform);
+         inverse = assertInstanceOf(MolodenskyTransform.class, 
transform.inverse());
+         assertSame(forward, inverse.inverse());
+         assertEquals(3, forward.getSourceDimensions());
+         assertEquals(3, forward.getTargetDimensions());
+ 
+         // Drop target dimension.
+         transform = MathTransforms.concatenate(transform, 
factory.builder(Geographic3Dto2D.NAME).create());
+         forward = assertInstanceOf(MolodenskyTransform.class, transform);
+         inverse = assertInstanceOf(MolodenskyTransform.class, 
transform.inverse());
+         assertSame(forward, inverse.inverse());
+         assertEquals(3, forward.getSourceDimensions());
+         assertEquals(2, forward.getTargetDimensions());
+ 
+         // Drop source dimension.
+         transform = 
MathTransforms.concatenate(factory.builder(Geographic2Dto3D.NAME).create(), 
transform);
+         forward = assertInstanceOf(MolodenskyTransform.class, transform);
+         inverse = assertInstanceOf(MolodenskyTransform.class, 
transform.inverse());
+         assertSame(forward, inverse.inverse());
+         assertEquals(2, forward.getSourceDimensions());
+         assertEquals(2, forward.getTargetDimensions());
+     }
+ 
      /**
       * Tests the standard Well Known Text (version 1) formatting.
       * The result is what we show to users, but may quite different than what 
SIS has in memory.
diff --cc 
endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/transform/PassThroughTransformTest.java
index 6af766cdab,132e1aa42e..be6207c87c
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/transform/PassThroughTransformTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/transform/PassThroughTransformTest.java
@@@ -335,4 -349,35 +336,35 @@@ public final class PassThroughTransform
              new double[] {2, 1, -1,    0.2,    0.1, 9,  2, 8, 4, -1},
              new double[] {2, 4, -1, 1600.6, 2700.7, 9, 10, 8, 4,  6});
      }
+ 
+     /**
+      * Tests a concatenation that delegates the work to {@link 
TransformJoiner#replacePassThrough(Map)}.
+      *
+      * @see <a 
href="https://issues.apache.org/jira/browse/SIS-384";>SIS-384</a>
+      */
+     @Test
+     public void testTransformJoiner() {
+         final Matrix before   = Matrices.createIdentity(5);
+         final Matrix after    = Matrices.createIdentity(5);
+         final Matrix expected = Matrices.createIdentity(5);
+         List.of(before, expected).forEach((m) -> {
+             m.setElement(0, 0,  0.025);
+             m.setElement(1, 1, -0.025);
+             m.setElement(0, 4,  3.0125);
+             m.setElement(1, 4, 44.9875);
+         });
+         List.of(after, expected).forEach((m) -> {
+             m.setElement(3, 3, 3600000.0);
+             m.setElement(3, 4, 1.5127128E12);
+         });
+         final var interpolate = MathTransforms.interpolate(null, new double[] 
{2.0, 10.0, 20.0, 35.0, 50.0, 75.0, 100.0});
+         final var passThrough = PassThroughTransform.create(2, interpolate, 
1);
+         transform = MathTransforms.concatenate(MathTransforms.linear(before), 
passThrough, MathTransforms.linear(after));
+ 
+         final var c = assertInstanceOf(ConcatenatedTransform.class, 
transform);
+         final Matrix m = MathTransforms.getMatrix(c.transform1);
+         assertNotNull(m);
+         assertSame(passThrough, c.transform2);
 -        assertMatrixEquals(expected, m, null, null);
++        assertMatrixEquals(expected, m, 0, null);
+     }
  }
diff --cc 
endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/SelectionClause.java
index 4f29d64996,c456c25856..ff31e233f0
--- 
a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/SelectionClause.java
+++ 
b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/SelectionClause.java
@@@ -354,10 -355,10 +354,10 @@@ public final class SelectionClause exte
       */
      @Override
      public void accept(final WarningEvent event) {
-         final LogRecord record = resources().getLogRecord(
+         final LogRecord record = resources().createLogRecord(
                  Level.WARNING,
                  Resources.Keys.IncompatibleLiteralCRS_2,
 -                event.getOperatorType().map(CodeList::identifier).orElse("?"),
 +                event.getOperatorType().map(Enum::name).orElse("?"),
                  
event.getParameter(ValueReference.class).map(ValueReference<?,?>::getXPath).orElse("?"));
          record.setThrown(event.exception);
          log(record);
diff --cc netbeans-project/ivy.xml
index bfee97924e,84d86ca69e..6d7cb0ccdf
--- a/netbeans-project/ivy.xml
+++ b/netbeans-project/ivy.xml
@@@ -11,14 -11,12 +11,14 @@@
  <ivy-module version="2.0">
      <info organisation="org.apache" module="sis"/>
      <dependencies defaultconf="default">
 +        <dependency org="org.opengis"            name="geoapi"                
  rev="3.0.2"/>
 +        <dependency org="org.opengis"            name="geoapi-conformance"    
  rev="3.0.2"/>
          <dependency org="javax.measure"          name="unit-api"              
  rev="2.1.3"/>
          <dependency org="org.glassfish.jaxb"     name="jaxb-runtime"          
  rev="4.0.5"/>
-         <dependency org="org.eclipse"            name="yasson"                
  rev="3.0.3"/>
+         <dependency org="org.eclipse"            name="yasson"                
  rev="3.0.4"/>
          <dependency org="com.esri.geometry"      name="esri-geometry-api"     
  rev="2.2.4"/>
          <dependency org="org.locationtech.jts"   name="jts-core"              
  rev="1.20.0"/>
-         <dependency org="org.postgresql"         name="postgresql"            
  rev="42.7.3"/>
+         <dependency org="org.postgresql"         name="postgresql"            
  rev="42.7.7"/>
          <dependency org="edu.ucar"               name="cdm-core"              
  rev="5.5.3"/>
          <dependency org="edu.ucar"               name="udunits"               
  rev="5.5.3"/>
          <dependency org="org.jdom"               name="jdom2"                 
  rev="2.0.6"/>

Reply via email to