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 23f2e78a1acf9d898c9b8a44be3698e0c939d2bb
Merge: f975967824 a1e3ecb82c
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Fri Sep 5 14:54:35 2025 +0200

    Merge branch 'geoapi-3.1'.

 NOTICE                                             |   2 +-
 README.md                                          |   2 +-
 .../apache/sis/console/MetadataCommandTest.java    |   3 +-
 .../iso/extent/DefaultGeographicDescription.java   |   2 +-
 .../sis/openoffice/ReferencingFunctions.java       |   7 +-
 .../sis/referencing/AbstractIdentifiedObject.java  |  13 +-
 .../sis/referencing/StandardDefinitions.java       |  21 +-
 .../sis/referencing/cs/CoordinateSystems.java      |   3 +
 .../sis/referencing/datum/DatumOrEnsemble.java     |  17 +-
 .../referencing/datum/DefaultGeodeticDatum.java    |   2 +
 .../referencing/factory/GeodeticObjectFactory.java |   5 +-
 .../internal/PositionalAccuracyConstant.java       |  11 -
 .../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  |   2 +-
 .../operation/CoordinateOperationFinder.java       | 244 +++++++++++++++------
 .../operation/CoordinateOperationRegistry.java     | 108 +++++----
 .../sis/referencing/operation/matrix/Matrix1.java  |  17 +-
 .../sis/referencing/operation/matrix/Matrix2.java  |  16 +-
 .../CoordinateSystemTransformBuilder.java          |   3 +-
 .../org/apache/sis/referencing/CommonCRSTest.java  |  24 +-
 .../operation/CoordinateOperationFinderTest.java   |  10 +-
 .../DefaultCoordinateOperationFactoryTest.java     |   2 +-
 .../sis/test/integration/ConsistencyTest.java      |   1 -
 .../apache/sis/setup/OptionalInstallations.java    |   4 +-
 .../org/apache/sis/util/resources/Vocabulary.java  |  15 +-
 .../sis/util/resources/Vocabulary.properties       |   3 +-
 .../sis/util/resources/Vocabulary_fr.properties    |   3 +-
 netbeans-project/ivy-settings.xml                  |   2 +-
 optional/build.gradle.kts                          |   3 +
 optional/src/org.apache.sis.gui/bundle/README      |   8 +-
 .../sis/referencing/factory/sql/epsg/README.md     |   4 +-
 parent/pom.xml                                     |   2 +-
 settings.gradle.kts                                |   4 +-
 35 files changed, 373 insertions(+), 204 deletions(-)

diff --cc 
endorsed/src/org.apache.sis.openoffice/main/org/apache/sis/openoffice/ReferencingFunctions.java
index c6a2624b8e,f94b1178b6..88ca0e81a1
--- 
a/endorsed/src/org.apache.sis.openoffice/main/org/apache/sis/openoffice/ReferencingFunctions.java
+++ 
b/endorsed/src/org.apache.sis.openoffice/main/org/apache/sis/openoffice/ReferencingFunctions.java
@@@ -42,9 -42,8 +42,10 @@@ import org.apache.sis.storage.DataStore
  import org.apache.sis.storage.DataStoreException;
  import org.apache.sis.storage.base.CodeType;
  
 -// Specific to the geoapi-3.1 and geoapi-4.0 branches:
 -import org.opengis.referencing.ObjectDomain;
 +// Specific to the main branch:
 +import org.apache.sis.referencing.DefaultObjectDomain;
++import org.apache.sis.referencing.datum.DefaultDatumEnsemble;
 +import org.apache.sis.referencing.internal.Legacy;
  
  
  /**
@@@ -306,8 -306,8 +307,10 @@@ public class ReferencingFunctions exten
                          } else if (object instanceof CoordinateSystem) {
                              cs = (CoordinateSystem) object;
                          } else {
--                            final Class<?> actual;
--                            if (object instanceof AbstractIdentifiedObject) {
++                            final Object actual;
++                            if (object instanceof DefaultDatumEnsemble) {
++                                actual = "DatumEnsemble";
++                            } else if (object instanceof 
AbstractIdentifiedObject) {
                                  actual = ((AbstractIdentifiedObject) 
object).getInterface();
                              } else {
                                  actual = Classes.getClass(object);
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/AbstractIdentifiedObject.java
index 27dc8e2409,15739e97e9..985c33a045
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/AbstractIdentifiedObject.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/AbstractIdentifiedObject.java
@@@ -76,11 -76,11 +76,13 @@@ import static org.apache.sis.util.privy
  
  // Specific to the main and geoapi-3.1 branches:
  import org.opengis.referencing.ReferenceIdentifier;
+ import org.opengis.referencing.operation.Conversion;
+ import org.opengis.referencing.operation.Projection;
  
 -// Specific to the geoapi-3.1 and geoapi-4.0 branches:
 -import org.opengis.referencing.ObjectDomain;
 +// Specific to the main branch:
 +import org.opengis.referencing.ReferenceSystem;
 +import org.apache.sis.metadata.iso.DefaultIdentifier;
 +import org.apache.sis.referencing.internal.Legacy;
  
  
  /**
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/StandardDefinitions.java
index fc062eace9,5ce8ea62fc..a67a8e3916
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/StandardDefinitions.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/StandardDefinitions.java
@@@ -376,12 -376,23 +376,23 @@@ final class StandardDefinitions 
      static VerticalDatum createVerticalDatum(final short code) {
          final String name;
          final String alias;
 -        final RealizationMethod method;
++        final VerticalDatumType method;
          switch (code) {
-             case 5100: name = "Mean Sea Level";                     alias = 
"MSL";    break;
-             case 5103: name = "North American Vertical Datum 1988"; alias = 
"NAVD88"; break;
-             default:   throw new AssertionError(code);
+             case 5100: {
+                 name   = "Mean Sea Level";
+                 alias  = "MSL";
 -                method = RealizationMethod.TIDAL;
++                method = VerticalDatumType.DEPTH;       // Actually 
`RealizationMethod.TIDAL`
+                 break;
+             }
+             case 5103: {
+                 name   = "North American Vertical Datum 1988";
+                 alias  = "NAVD88";
 -                method = RealizationMethod.LEVELLING;
++                method = VerticalDatumType.GEOIDAL;     // Actually 
`RealizationMethod.LEVELLING`;
+                 break;
+             }
+             default: throw new AssertionError(code);
          }
-         return new DefaultVerticalDatum(properties(code, name, alias, true), 
VerticalDatumType.GEOIDAL);
+         return new DefaultVerticalDatum(properties(code, name, alias, true), 
method);
      }
  
      /**
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DatumOrEnsemble.java
index 5243d12f90,89ab1e4124..c527fac71b
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DatumOrEnsemble.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DatumOrEnsemble.java
@@@ -315,11 -325,12 +315,12 @@@ public final class DatumOrEnsemble exte
          if (sourceDatum != null && 
Utilities.equalsIgnoreMetadata(sourceDatum, targetDatum)) {
              return Optional.of(targetDatum);
          }
 -        DatumEnsemble<D> sourceEnsemble;
 -        DatumEnsemble<D> targetEnsemble;
 -        DatumEnsemble<D> selected;
 -        if ((isMember(selected = targetEnsemble = (DatumEnsemble<D>) 
targetCRS.getDatumEnsemble(), sourceDatum)) ||
 -            (isMember(selected = sourceEnsemble = (DatumEnsemble<D>) 
sourceCRS.getDatumEnsemble(), targetDatum)) ||
 +        DefaultDatumEnsemble<D> sourceEnsemble;
 +        DefaultDatumEnsemble<D> targetEnsemble;
 +        DefaultDatumEnsemble<D> selected;
 +        if ((isMember(selected = targetEnsemble = (DefaultDatumEnsemble<D>) 
getDatumEnsemble(targetCRS), sourceDatum)) ||
-             (isMember(selected = sourceEnsemble = (DefaultDatumEnsemble<D>) 
getDatumEnsemble(sourceCRS), targetDatum)))
++            (isMember(selected = sourceEnsemble = (DefaultDatumEnsemble<D>) 
getDatumEnsemble(sourceCRS), targetDatum)) ||
+             (sourceEnsemble != null && sourceEnsemble == targetEnsemble))     
// Optimization for a common case.
          {
              return Optional.of(constructor.apply(selected));
          }
@@@ -361,8 -372,8 +362,8 @@@
       * @param  ensemble  the ensemble to test, or {@code null}.
       * @return whether the ensemble contains the given datum.
       */
 -    private static boolean isMember(final DatumEnsemble<?> ensemble, final 
IdentifiedObject datum) {
 +    private static boolean isMember(final DefaultDatumEnsemble<?> ensemble, 
final IdentifiedObject datum) {
-         if (ensemble != null) {
+         if (ensemble != null && datum != null) {
              for (final Datum member : ensemble.getMembers()) {
                  if (Utilities.equalsIgnoreMetadata(datum, member)) {
                      return true;
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/GeodeticObjectFactory.java
index c647333610,245afd1036..040dd2259e
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/GeodeticObjectFactory.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/GeodeticObjectFactory.java
@@@ -1380,14 -1435,14 +1380,13 @@@ public class GeodeticObjectFactory exte
      }
  
      /**
 -     * Creates a parametric <abbr>CRS</abbr> with a datum that may be a datum 
ensemble.
 -     * If the given {@code datum} argument is a {@linkplain 
DefaultDatumEnsemble datum ensemble
 -     * viewed as a pseudo-datum}, then it is used as the {@code ensemble} 
argument of the above
 -     * constructor.
 +     * Creates a parametric <abbr>CRS</abbr> from a datum.
 +     * This is a shortcut for the {@linkplain #createParametricCRS(Map, 
ParametricDatum, DefaultDatumEnsemble, ParametricCS)
 +     * more generic method} without datum ensemble.
       *
       * @param  properties  name and other properties to give to the new 
object.
-      *         Available properties are {@linkplain ObjectFactory listed 
there}.
-      * @param  datum  temporal datum to use in created CRS.
-      * @param  cs  the temporal coordinate system for the created CRS.
+      * @param  datum       the parametric datum or datum ensemble viewed as a 
pseudo-datum.
+      * @param  cs          the parametric coordinate system for the created 
<abbr>CRS</abbr>.
       * @return the coordinate reference system for the given properties.
       * @throws FactoryException if the object creation failed.
       */
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationFinder.java
index 611d3b2e35,8378f742fb..3aa4b827fe
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationFinder.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationFinder.java
@@@ -527,12 -531,9 +527,9 @@@ public class CoordinateOperationFinder 
               * Coordinate system change (including change in the number of 
dimensions) without datum shift.
               * May contain the addition of ellipsoidal height or spherical 
radius, which need an ellipsoid.
               */
-             final boolean isGeographic = (sourceCS instanceof EllipsoidalCS);
-             identifier = isGeographic != (targetCS instanceof EllipsoidalCS) 
? GEOCENTRIC_CONVERSION : AXIS_CHANGES;
 -            final var builder = 
factorySIS.getMathTransformFactory().builder(Constants.COORDINATE_SYSTEM_CONVERSION);
 +            final var builder = 
CoordinateOperations.builder(factorySIS.getMathTransformFactory(), 
Constants.COORDINATE_SYSTEM_CONVERSION);
-             final var ellipsoid = (isGeographic ? sourceDatum : 
targetDatum).getEllipsoid();
-             builder.setSourceAxes(sourceCS, ellipsoid);
-             builder.setTargetAxes(targetCS, ellipsoid);
+             builder.setSourceAxes(sourceCS, sourceDatum.getEllipsoid());
+             builder.setTargetAxes(targetCS, targetDatum.getEllipsoid());
              transform  = builder.create();
              method     = builder.getMethod();
              parameters = builder.parameters();
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/CoordinateSystemTransformBuilder.java
index 225b068543,b102444f2f..77e7477225
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/CoordinateSystemTransformBuilder.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/CoordinateSystemTransformBuilder.java
@@@ -43,11 -43,9 +43,12 @@@ import org.apache.sis.referencing.opera
  import org.apache.sis.referencing.operation.provider.GeocentricToGeographic;
  import org.apache.sis.referencing.operation.provider.GeographicToGeocentric;
  import org.apache.sis.referencing.privy.WKTUtilities;
+ import org.apache.sis.util.Utilities;
  import org.apache.sis.util.resources.Errors;
  
 +// Specific to the main branch:
 +import org.apache.sis.referencing.privy.CoordinateOperations;
 +
  
  /**
   * Builder of transforms between coordinate systems.
diff --cc 
endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/CommonCRSTest.java
index 3ffc248bff,bdfcb1cf3f..0257d6f35f
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/CommonCRSTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/CommonCRSTest.java
@@@ -45,7 -45,7 +45,6 @@@ import static org.apache.sis.util.privy
  // Test dependencies
  import org.junit.jupiter.api.Test;
  import static org.junit.jupiter.api.Assertions.*;
--import org.opengis.test.Validators;
  import static org.apache.sis.test.Assertions.assertEqualsIgnoreMetadata;
  import static org.apache.sis.test.Assertions.assertMessageContains;
  import static org.apache.sis.test.TestUtilities.*;
@@@ -130,7 -130,7 +129,6 @@@ public final class CommonCRSTest extend
      @Test
      public void testGeographic() {
          final GeographicCRS geographic = CommonCRS.WGS84.geographic();
--        Validators.validate(geographic);
          GeodeticObjectVerifier.assertIsWGS84(geographic, true, true);
          assertSame(geographic, CommonCRS.WGS84.geographic(), "Cached value");
      }
@@@ -142,7 -142,7 +140,6 @@@
      public void testNormalizedGeographic() {
          final GeographicCRS geographic = CommonCRS.WGS84.geographic();
          final GeographicCRS normalized = 
CommonCRS.WGS84.normalizedGeographic();
--        Validators.validate(normalized);
          assertSame(geographic.getDatum(), normalized.getDatum());
          /*
           * Compare axes. Note that axes in different order have different 
EPSG codes.
@@@ -160,7 -160,7 +157,6 @@@
      @Test
      public void testGeographic3D() {
          final GeographicCRS crs = CommonCRS.WGS72.geographic3D();
--        Validators.validate(crs);
          assertEquals ("WGS 72", crs.getName().getCode());
          assertSame   (CommonCRS.WGS72.geographic().getDatum(), 
crs.getDatum());
          assertNotSame(CommonCRS.WGS84.geographic().getDatum(), 
crs.getDatum());
@@@ -179,7 -179,7 +175,6 @@@
      @Test
      public void testGeocentric() {
          final GeodeticCRS crs = CommonCRS.WGS72.geocentric();
--        Validators.validate(crs);
          assertEquals ("WGS 72", crs.getName().getCode());
          assertSame   (CommonCRS.WGS72.geographic().getDatum(), 
crs.getDatum());
          assertNotSame(CommonCRS.WGS84.geographic().getDatum(), 
crs.getDatum());
@@@ -198,7 -198,7 +193,6 @@@
      @Test
      public void testSpherical() {
          final GeodeticCRS crs = CommonCRS.ETRS89.spherical();
--        Validators.validate(crs);
          assertEquals ("ETRS89", crs.getName().getCode());
          assertSame   (CommonCRS.ETRS89.geographic().getDatum(), 
crs.getDatum());
          assertNotSame(CommonCRS.WGS84 .datum(true), crs.getDatum());
@@@ -215,34 -215,37 +209,29 @@@
       * Verifies the vertical datum enumeration.
       */
      @Test
 -    @SuppressWarnings("deprecation")
      public void testVertical() {
          for (final CommonCRS.Vertical e : CommonCRS.Vertical.values()) {
 -            final RealizationMethod method;
 +            final VerticalDatumType method;
              final String axisName, datumName;
              switch (e) {
-                 case NAVD88:         axisName = 
AxisNames.GRAVITY_RELATED_HEIGHT; datumName = "North American Vertical Datum 
1988"; method = VerticalDatumType. GEOIDAL;       break;
 -                case NAVD88:         axisName = 
AxisNames.GRAVITY_RELATED_HEIGHT; datumName = "North American Vertical Datum 
1988"; method = RealizationMethod. GEOID; break;
 -                case BAROMETRIC:     axisName = "Barometric altitude";        
    datumName = "Constant pressure surface";          method = 
RealizationMethod.valueOf("BAROMETRIC"); break;
 -                case MEAN_SEA_LEVEL: axisName = 
AxisNames.GRAVITY_RELATED_HEIGHT; datumName = "Mean Sea Level";                 
    method = RealizationMethod. TIDAL; break;
 -                case DEPTH:          axisName = AxisNames.DEPTH;              
    datumName = "Mean Sea Level";                     method = 
RealizationMethod. TIDAL; break;
++                case NAVD88:         axisName = 
AxisNames.GRAVITY_RELATED_HEIGHT; datumName = "North American Vertical Datum 
1988"; method = null; break;
 +                case BAROMETRIC:     axisName = "Barometric altitude";        
    datumName = "Constant pressure surface";          method = 
VerticalDatumType. BAROMETRIC;    break;
-                 case MEAN_SEA_LEVEL: axisName = 
AxisNames.GRAVITY_RELATED_HEIGHT; datumName = "Mean Sea Level";                 
    method = VerticalDatumType. GEOIDAL;       break;
-                 case DEPTH:          axisName = AxisNames.DEPTH;              
    datumName = "Mean Sea Level";                     method = 
VerticalDatumType. GEOIDAL;       break;
++                case MEAN_SEA_LEVEL: axisName = 
AxisNames.GRAVITY_RELATED_HEIGHT; datumName = "Mean Sea Level";                 
    method = VerticalDatumType. DEPTH;         break;
++                case DEPTH:          axisName = AxisNames.DEPTH;              
    datumName = "Mean Sea Level";                     method = 
VerticalDatumType. DEPTH;         break;
                  case ELLIPSOIDAL:    axisName = AxisNames.ELLIPSOIDAL_HEIGHT; 
    datumName = "Ellipsoid";                          method = 
VerticalDatumTypes.ellipsoidal(); break;
 -                case OTHER_SURFACE:  axisName = "Height";                     
    datumName = "Other surface";                      method = null; break;
 +                case OTHER_SURFACE:  axisName = "Height";                     
    datumName = "Other surface";                      method = 
VerticalDatumType. OTHER_SURFACE; break;
                  default: throw new AssertionError(e);
              }
              final String        name  = e.name();
              final VerticalDatum datum = e.datum();
              final VerticalCRS   crs   = e.crs();
-             if (e.isEPSG && !name.startsWith("NAV")) {
 -            if (e.isEPSG) {
--                /*
--                 * BAROMETRIC and ELLIPSOIDAL uses an axis named "Height", 
which is not a valid
--                 * axis name according ISO 19111. We skip the validation test 
for those enums.
--                 */
--                Validators.validate(crs);
--            }
              assertSame(datum, e.datum(), name);                         // 
Datum before CRS creation.
              assertSame(crs.getDatum(), e.datum(), name);                // 
Datum after CRS creation.
              assertEquals(datumName, datum.getName().getCode(), name);
-             assertEquals(method, datum.getVerticalDatumType(), name);
 -            assertEquals(axisName,  
crs.getCoordinateSystem().getAxis(0).getName().getCode(), name);
 -            if (!e.isEPSG) {  // Because the information is not in EPSG 
database 9.x.
 -                assertEquals(method, 
datum.getRealizationMethod().orElse(null), name);
++            if (method != null) {
++                assertEquals(method, datum.getVerticalDatumType(), name);
+             }
 +            assertEquals(axisName,  
crs.getCoordinateSystem().getAxis(0).getName().getCode(), name);
          }
      }
  
@@@ -284,7 -287,7 +273,6 @@@
              final TemporalDatum datum  = e.datum();
              final TemporalCRS   crs    = e.crs();
              final Date          origin = datum.getOrigin();
--            Validators.validate(crs);
              assertSame(datum, e.datum(), name);             // Datum before 
CRS creation.
              assertSame(crs.getDatum(), e.datum(), name);    // Datum after 
CRS creation.
              assertEquals(epoch, dateFormat.format(origin), name);
diff --cc 
endorsed/src/org.apache.sis.referencing/test/org/apache/sis/test/integration/ConsistencyTest.java
index b62308cb44,e111d7bd47..03d9b0cfc8
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/test/integration/ConsistencyTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/test/integration/ConsistencyTest.java
@@@ -22,7 -22,7 +22,6 @@@ import javax.measure.Quantity
  import javax.measure.Unit;
  import javax.measure.UnitConverter;
  import org.opengis.metadata.Identifier;
--import org.opengis.util.CodeList;
  import org.opengis.util.FactoryException;
  import org.opengis.util.NoSuchIdentifierException;
  import org.opengis.referencing.crs.CoordinateReferenceSystem;

Reply via email to