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

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

commit 8fc9815c594c47d497d5fabd5faaf320a45a49f1
Author: Martin Desruisseaux <martin.desruisse...@geomatys.com>
AuthorDate: Thu May 25 15:49:09 2023 +0200

    Add support for two-dimensional `SphericalCS` as submitted in ISO 19111 
amendment 2.
---
 .../apache/sis/io/wkt/GeodeticObjectParser.java    | 14 +++++----
 .../sis/referencing/cs/CoordinateSystems.java      |  4 +--
 .../sis/referencing/cs/DefaultSphericalCS.java     | 32 ++++++++++++++++++--
 .../referencing/factory/GeodeticObjectFactory.java | 35 ++++++++++++++++++++++
 .../referencing/factory/sql/EPSGDataAccess.java    |  1 +
 .../org/apache/sis/storage/geotiff/CRSBuilder.java |  4 +--
 .../org/apache/sis/internal/netcdf/CRSBuilder.java | 10 +++++--
 7 files changed, 86 insertions(+), 14 deletions(-)

diff --git 
a/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/GeodeticObjectParser.java
 
b/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/GeodeticObjectParser.java
index 5bae69b55b..701a429280 100644
--- 
a/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/GeodeticObjectParser.java
+++ 
b/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/GeodeticObjectParser.java
@@ -99,7 +99,7 @@ import static java.util.Collections.singletonMap;
  * @author  Rémi Eve (IRD)
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @author  Johann Sorel (Geomatys)
- * @version 1.3
+ * @version 1.4
  * @since   0.6
  */
 class GeodeticObjectParser extends MathTransformParser implements 
Comparator<CoordinateSystemAxis> {
@@ -927,6 +927,14 @@ class GeodeticObjectParser extends MathTransformParser 
implements Comparator<Coo
                 dimension = (axes.length < 2) ? 2 : 3;                      // 
For error message.
                 break;
             }
+            case WKTKeywords.spherical: {
+                switch (axes.length) {
+                    case 2: return csFactory.createSphericalCS(csProperties, 
axes[0], axes[1]);
+                    case 3: return csFactory.createSphericalCS(csProperties, 
axes[0], axes[1], axes[2]);
+                }
+                dimension = (axes.length < 2) ? 2 : 3;                      // 
For error message.
+                break;
+            }
             case WKTKeywords.Cartesian: {
                 switch (axes.length) {
                     case 2: return csFactory.createCartesianCS(csProperties, 
axes[0], axes[1]);
@@ -963,10 +971,6 @@ class GeodeticObjectParser extends MathTransformParser 
implements Comparator<Coo
                 if (axes.length != (dimension = 3)) break;
                 return csFactory.createCylindricalCS(csProperties, axes[0], 
axes[1], axes[2]);
             }
-            case WKTKeywords.spherical: {
-                if (axes.length != (dimension = 3)) break;
-                return csFactory.createSphericalCS(csProperties, axes[0], 
axes[1], axes[2]);
-            }
             case WKTKeywords.parametric: {
                 if (axes.length != (dimension = 1)) break;
                 return csFactory.createParametricCS(csProperties, axes[0]);
diff --git 
a/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/CoordinateSystems.java
 
b/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/CoordinateSystems.java
index 722da90e42..09debdf369 100644
--- 
a/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/CoordinateSystems.java
+++ 
b/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/CoordinateSystems.java
@@ -520,7 +520,7 @@ next:   for (final CoordinateSystem cs : targets) {
      */
     public static CoordinateSystem replaceLinearUnit(final CoordinateSystem 
cs, final Unit<Length> newUnit) {
         ArgumentChecks.ensureNonNull("newUnit", newUnit);
-        return CoordinateSystems.replaceAxes(cs, new AxisFilter() {
+        return replaceAxes(cs, new AxisFilter() {
             @Override public Unit<?> getUnitReplacement(CoordinateSystemAxis 
axis, Unit<?> unit) {
                 return Units.isLinear(unit) ? newUnit : unit;
             }
@@ -551,7 +551,7 @@ next:   for (final CoordinateSystem cs : targets) {
      */
     public static CoordinateSystem replaceAngularUnit(final CoordinateSystem 
cs, final Unit<javax.measure.quantity.Angle> newUnit) {
         ArgumentChecks.ensureNonNull("newUnit", newUnit);
-        return CoordinateSystems.replaceAxes(cs, new AxisFilter() {
+        return replaceAxes(cs, new AxisFilter() {
             @Override public Unit<?> getUnitReplacement(CoordinateSystemAxis 
axis, Unit<?> unit) {
                 return Units.isAngular(unit) ? newUnit : unit;
             }
diff --git 
a/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/DefaultSphericalCS.java
 
b/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/DefaultSphericalCS.java
index d9a14ba01d..f82fc34bce 100644
--- 
a/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/DefaultSphericalCS.java
+++ 
b/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/DefaultSphericalCS.java
@@ -28,7 +28,8 @@ import org.apache.sis.measure.Units;
 
 
 /**
- * A 3-dimensional coordinate system with one distance measured from the 
origin and two angular coordinates.
+ * A 2- or 3-dimensional coordinate system with one distance measured from the 
origin and two angular coordinates.
+ * In the two-dimensional case, the radius is omitted and may be implicitly an 
ellipsoid surface.
  * Not to be confused with an {@linkplain DefaultEllipsoidalCS ellipsoidal 
coordinate system}
  * based on an ellipsoid "degenerated" into a sphere.
  *
@@ -125,6 +126,27 @@ public class DefaultSphericalCS extends AbstractCS 
implements SphericalCS {
         super(properties, axis0, axis1, axis2);
     }
 
+    /**
+     * Constructs a two-dimensional coordinate system from a set of properties.
+     * The given axes shall be angular measurements, without radius.
+     * The properties map is given unchanged to the
+     * {@linkplain AbstractCS#AbstractCS(Map,CoordinateSystemAxis[]) 
super-class constructor}.
+     *
+     * @param  properties  the properties to be given to the identified object.
+     * @param  axis0       the first  axis (e.g. “Spherical latitude”).
+     * @param  axis1       the second axis (e.g. “Spherical longitude”).
+     *
+     * @see 
org.apache.sis.referencing.factory.GeodeticObjectFactory#createSphericalCS(Map, 
CoordinateSystemAxis, CoordinateSystemAxis)
+     *
+     * @since 1.4
+     */
+    public DefaultSphericalCS(final Map<String,?>   properties,
+                              final CoordinateSystemAxis axis0,
+                              final CoordinateSystemAxis axis1)
+    {
+        super(properties, axis0, axis1);
+    }
+
     /**
      * Creates a new coordinate system with the same values than the specified 
one.
      * This copy constructor provides a way to convert an arbitrary 
implementation into a SIS one
@@ -202,9 +224,15 @@ public class DefaultSphericalCS extends AbstractCS 
implements SphericalCS {
      * Returns a coordinate system with different axes.
      */
     @Override
+    @SuppressWarnings("fallthrough")
     final AbstractCS createForAxes(final Map<String,?> properties, final 
CoordinateSystemAxis[] axes) {
         switch (axes.length) {
-            case 2: return new DefaultPolarCS(properties, axes);
+            case 2: {
+                if (Units.isLinear(axes[0].getUnit()) || 
Units.isLinear(axes[1].getUnit())) {
+                    return new DefaultPolarCS(properties, axes);
+                }
+                // Fall through
+            }
             case 3: return new DefaultSphericalCS(properties, axes);
             default: throw unexpectedDimension(properties, axes, 2);
         }
diff --git 
a/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticObjectFactory.java
 
b/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticObjectFactory.java
index 5d721fdbc5..f53cf7812e 100644
--- 
a/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticObjectFactory.java
+++ 
b/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticObjectFactory.java
@@ -479,6 +479,41 @@ public class GeodeticObjectFactory extends AbstractFactory 
implements CRSFactory
         return unique("createSphericalCS", cs);
     }
 
+    /**
+     * Creates a spherical coordinate system without radius.
+     * This coordinate system can be used with geocentric, engineering and 
derived CRS.
+     *
+     * <h4>Dependencies</h4>
+     * The components needed by this method can be created by the following 
methods:
+     * <ol>
+     *   <li>{@link #createCoordinateSystemAxis(Map, String, AxisDirection, 
Unit)}</li>
+     * </ol>
+     *
+     * The default implementation creates a {@link DefaultSphericalCS} 
instance.
+     *
+     * @param  properties  name and other properties to give to the new object.
+     * @param  axis0       the first  axis (e.g. “Spherical latitude”).
+     * @param  axis1       the second axis (e.g. “Spherical longitude”).
+     * @throws FactoryException if the object creation failed.
+     *
+     * @see DefaultSphericalCS#DefaultSphericalCS(Map, CoordinateSystemAxis, 
CoordinateSystemAxis)
+     *
+     * @since 1.4
+     */
+    @Override
+    public SphericalCS createSphericalCS(final Map<String,?> properties,
+            final CoordinateSystemAxis axis0,
+            final CoordinateSystemAxis axis1) throws FactoryException
+    {
+        final DefaultSphericalCS cs;
+        try {
+            cs = new DefaultSphericalCS(complete(properties), axis0, axis1);
+        } catch (IllegalArgumentException exception) {
+            throw new InvalidGeodeticParameterException(exception);
+        }
+        return unique("createSphericalCS", cs);
+    }
+
     /**
      * Creates a geographic coordinate reference system. It can be 
(<var>latitude</var>, <var>longitude</var>)
      * or (<var>longitude</var>, <var>latitude</var>), optionally with an 
ellipsoidal height.
diff --git 
a/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java
 
b/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java
index 79894aaf20..5f0eb61e0e 100644
--- 
a/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java
+++ 
b/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java
@@ -2197,6 +2197,7 @@ codes:  for (int i=0; i<codes.length; i++) {
                     }
                     case WKTKeywords.spherical: {
                         switch (dimension) {
+                            case 2: cs = 
csFactory.createSphericalCS(properties, axes[0], axes[1]); break;
                             case 3: cs = 
csFactory.createSphericalCS(properties, axes[0], axes[1], axes[2]); break;
                         }
                         break;
diff --git 
a/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/CRSBuilder.java
 
b/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/CRSBuilder.java
index 2a700e0c6d..f19ab41b14 100644
--- 
a/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/CRSBuilder.java
+++ 
b/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/CRSBuilder.java
@@ -1067,7 +1067,7 @@ final class CRSBuilder extends 
ReferencingFactoryContainer {
     private void verify(final GeographicCRS crs, final Unit<Angle> 
angularUnit) throws FactoryException {
         /*
          * Note: current createUnit(…) implementation does not allow us to 
distinguish whether METRE ou DEGREE units
-         * were specified in the GeoTIFF file or if we got the default values. 
We do not compare units of that reason.
+         * were specified in the GeoTIFF file or if we got the default values. 
We do not compare units for that reason.
          */
         final Unit<Length> linearUnit = createUnit(GeoKeys.GeogLinearUnits, 
GeoKeys.GeogLinearUnitSize, Length.class, Units.METRE);
         final GeodeticDatum datum = crs.getDatum();
@@ -1134,7 +1134,7 @@ final class CRSBuilder extends 
ReferencingFactoryContainer {
     private void verify(final GeocentricCRS crs) throws FactoryException {
         /*
          * Note: current createUnit(…) implementation does not allow us to 
distinguish whether METRE ou DEGREE units
-         * were specified in the GeoTIFF file or if we got the default values. 
We do not compare units of that reason.
+         * were specified in the GeoTIFF file or if we got the default values. 
We do not compare units for that reason.
          */
         final Unit<Length> linearUnit = createUnit(GeoKeys.GeogLinearUnits, 
GeoKeys.GeogLinearUnitSize, Length.class, Units.METRE);
         final Unit<Angle> angularUnit = createUnit(GeoKeys.AngularUnits, 
GeoKeys.AngularUnitSize, Angle.class, Units.DEGREE);
diff --git 
a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/CRSBuilder.java
 
b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/CRSBuilder.java
index d62c4b041b..97d0ca7164 100644
--- 
a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/CRSBuilder.java
+++ 
b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/CRSBuilder.java
@@ -84,7 +84,7 @@ import org.apache.sis.measure.Units;
  * while {@link DataStoreException} is handled as a fatal error. Warnings are 
stored in {@link #warnings} field.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.2
+ * @version 1.4
  * @since   1.0
  */
 abstract class CRSBuilder<D extends Datum, CS extends CoordinateSystem> {
@@ -677,12 +677,16 @@ previous:   for (int i=components.size(); --i >= 0;) {
         }
 
         /**
-         * Creates the three-dimensional {@link SphericalCS} from given axes. 
This method is invoked only
+         * Creates the two- or three-dimensional {@link SphericalCS} from 
given axes. This method is invoked only
          * if {@link #setPredefinedComponents(Decoder)} failed to assign a CS 
or if {@link #build(Decoder, boolean)}
          * found that the {@link #coordinateSystem} does not have compatible 
axes.
          */
         @Override void createCS(CSFactory factory, Map<String,?> properties, 
CoordinateSystemAxis[] axes) throws FactoryException {
-            coordinateSystem = factory.createSphericalCS(properties, axes[0], 
axes[1], axes[2]);
+            if (axes.length > 2) {
+                coordinateSystem = factory.createSphericalCS(properties, 
axes[0], axes[1], axes[2]);
+            } else {
+                coordinateSystem = factory.createSphericalCS(properties, 
axes[0], axes[1]);
+            }
         }
 
         /**

Reply via email to