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


The following commit(s) were added to refs/heads/geoapi-4.0 by this push:
     new 2a8655e255 Change of axis order in GeoTIFF writer should accept 
directions such as "North along 90°E".
2a8655e255 is described below

commit 2a8655e25570d766064ff700455e14b9f77b035c
Author: Martin Desruisseaux <martin.desruisse...@geomatys.com>
AuthorDate: Wed Jan 22 16:50:59 2025 +0100

    Change of axis order in GeoTIFF writer should accept directions such as 
"North along 90°E".
---
 .../org/apache/sis/referencing/cs/AxisName.java    |  2 +-
 .../main/org/apache/sis/referencing/cs/Codes.java  |  6 ++--
 .../sis/referencing/cs/CoordinateSystems.java      | 33 +++++++++++++++++++++-
 .../cs/DefaultCoordinateSystemAxis.java            |  4 +--
 .../sis/referencing/cs/DirectionAlongMeridian.java |  4 +--
 .../org/apache/sis/referencing/cs/Normalizer.java  | 12 ++++----
 .../sis/referencing/privy/AxisDirections.java      |  2 +-
 .../sis/referencing/cs/CoordinateSystemsTest.java  | 22 ++++++++++++++-
 .../sis/storage/geotiff/writer/GeoEncoder.java     |  2 +-
 .../main/org/apache/sis/gui/map/MapCanvas.java     |  2 +-
 10 files changed, 70 insertions(+), 19 deletions(-)

diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/AxisName.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/AxisName.java
index 94c086a1a6..45e5f19a73 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/AxisName.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/AxisName.java
@@ -24,7 +24,7 @@ import org.apache.sis.util.resources.Vocabulary;
 
 
 /**
- * Pattern of {@link CoordinateSystemAxis} together with resource to use for 
localized axis name.
+ * Pattern of a {@link CoordinateSystemAxis} together with the resource to use 
for localized axis name.
  *
  * @author  Martin Desruisseaux (Geomatys)
  */
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/Codes.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/Codes.java
index c85db0b272..2e8f370670 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/Codes.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/Codes.java
@@ -21,6 +21,7 @@ import java.util.HashMap;
 import java.util.OptionalInt;
 import javax.measure.Unit;
 import org.opengis.referencing.cs.AxisDirection;
+import org.opengis.referencing.cs.CoordinateSystem;
 import org.apache.sis.measure.Units;
 import org.apache.sis.util.ArraysExt;
 import static org.apache.sis.util.privy.Constants.EPSG_METRE;
@@ -28,8 +29,7 @@ import static 
org.apache.sis.util.privy.Constants.EPSG_AXIS_DEGREES;
 
 
 /**
- * Map units of measurement and axis directions to {@link 
org.opengis.referencing.cs.CoordinateSystem}
- * objects defined in the EPSG database.
+ * Map units of measurement and axis directions to {@link CoordinateSystem} 
objects defined in the EPSG database.
  * Current version uses hard-coded mapping.
  *
  * @author  Rémi Maréchal (Geomatys)
@@ -132,7 +132,7 @@ final class Codes {
      */
     private static final Map<Codes,Codes> EPSG = new HashMap<>(31);
     static {
-        final AxisDirection[] directions = new AxisDirection[] 
{AxisDirection.EAST, AxisDirection.NORTH};
+        final var directions = new AxisDirection[] {AxisDirection.EAST, 
AxisDirection.NORTH};
         final int addVertical = AxisDirection.UP.ordinal() << (2 * Byte.SIZE);
         OptionalInt packed = pack(directions);
         short unit = EPSG_METRE;
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/CoordinateSystems.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/CoordinateSystems.java
index 80de0f4a98..8a5743bd7e 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/CoordinateSystems.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/CoordinateSystems.java
@@ -563,7 +563,7 @@ next:   for (final CoordinateSystem cs : targets) {
      * @since 0.8
      */
     public static AxisDirection[] getAxisDirections(final CoordinateSystem cs) 
{
-        final AxisDirection[] directions = new 
AxisDirection[cs.getDimension()];
+        final var directions = new AxisDirection[cs.getDimension()];
         for (int i=0; i<directions.length; i++) {
             final CoordinateSystemAxis axis = cs.getAxis(i);
             ArgumentChecks.ensureNonNullElement("cs", i, cs);
@@ -572,6 +572,37 @@ next:   for (final CoordinateSystem cs : targets) {
         return directions;
     }
 
+    /**
+     * Returns the axis directions, replacing "North/South along meridian" by 
a cardinal direction.
+     * When a {@linkplain #isAlongMeridian direction along a meridian} is 
detected,
+     * this method uses the axis abbreviation for the direction by East or 
North.
+     *
+     * <h4>Example</h4>
+     * The <q>WGS 84 / UPS South (E,N)</q> coordinate reference system has two 
axis
+     * oriented toward North: <q>North along 90°E</q> and <q>North along 
0°E</q>.
+     * Those axes are conventionally named <q>Easting (E)</q> and <q>Northing 
(N)</q>.
+     * This method uses those conventional names for returning (east, north) 
directions.
+     *
+     * @param  cs  the coordinate system.
+     * @return the simple axis directions for the specified coordinate system.
+     * @throws NullPointerException if {@code cs} is null, or one of its axes 
or directions is null.
+     *
+     * @since 1.5
+     */
+    public static AxisDirection[] getSimpleAxisDirections(final 
CoordinateSystem cs) {
+        final var directions = getAxisDirections(cs);
+        for (int i=0; i<directions.length; i++) {
+            if (isAlongMeridian(directions[i])) {
+                final String abbreviation = cs.getAxis(i).getAbbreviation();
+                if (abbreviation != null && abbreviation.length() == 1) {
+                    AxisDirection r = 
AxisDirections.fromAbbreviation(abbreviation.charAt(0));
+                    if (r != null) directions[i] = r;
+                }
+            }
+        }
+        return directions;
+    }
+
     /**
      * Returns a short (if possible) localized name for the given axis. This 
method replaces
      * names such as "Geodetic latitude" or "Geocentric latitude" by a simple 
"Latitude" word.
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultCoordinateSystemAxis.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultCoordinateSystemAxis.java
index 068af8f232..120198b4a5 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultCoordinateSystemAxis.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultCoordinateSystemAxis.java
@@ -622,7 +622,7 @@ public class DefaultCoordinateSystemAxis extends 
AbstractIdentifiedObject implem
          * only if the range meaning is "wraparound" for both axes, because 
only in such case a
          * coordinate operation may shift some coordinate values (typically 
±360° on longitudes).
          */
-        final CoordinateSystemAxis that = (CoordinateSystemAxis) object;
+        final var that = (CoordinateSystemAxis) object;
         if (!equalsIgnoreMetadata(that, mode, this.getRangeMeaning() == 
RangeMeaning.WRAPAROUND &&
                                               that.getRangeMeaning() == 
RangeMeaning.WRAPAROUND))
         {
@@ -754,7 +754,7 @@ public class DefaultCoordinateSystemAxis extends 
AbstractIdentifiedObject implem
         if (!isWKT1) {
             final String a = 
formatter.getTransliterator().toLatinAbbreviation(cs, dir, getAbbreviation());
             if (a != null && !a.equals(name)) {
-                final StringBuilder buffer = new StringBuilder();
+                final var buffer = new StringBuilder();
                 if (name != null) {
                     buffer.append(name).append(' ');
                 }
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DirectionAlongMeridian.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DirectionAlongMeridian.java
index af9a8a86bc..b3144991cb 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DirectionAlongMeridian.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DirectionAlongMeridian.java
@@ -236,7 +236,7 @@ final class DirectionAlongMeridian extends 
FormattableObject implements Comparab
     @Override
     public boolean equals(final Object object) {
         if (object instanceof DirectionAlongMeridian) {
-            final DirectionAlongMeridian that = (DirectionAlongMeridian) 
object;
+            final var that = (DirectionAlongMeridian) object;
             return baseDirection.equals(that.baseDirection) &&
                    Numerics.equals(meridian, that.meridian);
         }
@@ -263,7 +263,7 @@ final class DirectionAlongMeridian extends 
FormattableObject implements Comparab
     public String toString() {
         String name = baseDirection.name();
         final int length = name.length();
-        final StringBuilder buffer = new StringBuilder(length);
+        final var buffer = new StringBuilder(length);
         for (int i=0; i<length;) {
             final int c = name.codePointAt(i);
             buffer.appendCodePoint(i == 0 ? Character.toUpperCase(c) : 
Character.toLowerCase(c));
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/Normalizer.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/Normalizer.java
index 0f64309fdd..0d29e27cb3 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/Normalizer.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/Normalizer.java
@@ -51,7 +51,7 @@ import static 
org.apache.sis.referencing.privy.NilReferencingObject.UNNAMED;
 
 
 /**
- * Derives an coordinate system from an existing one for {@link 
AxesConvention}.
+ * Derives a coordinate system from an existing one for a given {@link 
AxesConvention}.
  * The main usage for this class is to reorder the axes in some fixed order 
like
  * (<var>x</var>, <var>y</var>, <var>z</var>) or (<var>longitude</var>, 
<var>latitude</var>).
  *
@@ -203,7 +203,7 @@ final class Normalizer implements Comparable<Normalizer> {
      * @param angularUnitOrder  -1 for sorting angular units first, +1 for 
sorting them last, or 0 if neutral.
      */
     static boolean sort(final CoordinateSystemAxis[] axes, final int 
angularUnitOrder) {
-        final Normalizer[] wrappers = new Normalizer[axes.length];
+        final var wrappers = new Normalizer[axes.length];
         for (int i=0; i<axes.length; i++) {
             wrappers[i] = new Normalizer(axes[i], angularUnitOrder);
         }
@@ -243,7 +243,7 @@ final class Normalizer implements Comparable<Normalizer> {
         final String abbreviation = axis.getAbbreviation();
         final String newAbbr = sameDirection ? abbreviation :
                 AxisDirections.suggestAbbreviation(axis.getName().getCode(), 
newDir, newUnit);
-        final Map<String,Object> properties = new HashMap<>(8);
+        final var properties = new HashMap<String,Object>(8);
         if (newAbbr.equals(abbreviation)) {
             properties.putAll(IdentifiedObjects.getProperties(axis, EXCLUDES));
         } else {
@@ -293,7 +293,7 @@ final class Normalizer implements Comparable<Normalizer> {
          * axes before normalization in order to detect which axes have been 
reused
          * and whether reused axes are in the same order as before.
          */
-        final CoordinateSystemAxis[] oldAxes = new 
CoordinateSystemAxis[dimension];
+        final var oldAxes = new CoordinateSystemAxis[dimension];
         int n = 0;
         for (int i=0; i<dimension; i++) {
             final CoordinateSystemAxis axis = cs.getAxis(i);
@@ -394,7 +394,7 @@ final class Normalizer implements Comparable<Normalizer> {
      */
     private static AbstractCS shiftAxisRange(final CoordinateSystem cs) {
         boolean changed = false;
-        final CoordinateSystemAxis[] axes = new 
CoordinateSystemAxis[cs.getDimension()];
+        final var axes = new CoordinateSystemAxis[cs.getDimension()];
         for (int i=0; i<axes.length; i++) {
             CoordinateSystemAxis axis = cs.getAxis(i);
             if (axis.getRangeMeaning() == RangeMeaning.WRAPAROUND) {
@@ -424,7 +424,7 @@ final class Normalizer implements Comparable<Normalizer> {
      * and the minimum and maximum values which are set to the given values.
      */
     private static CoordinateSystemAxis forRange(final CoordinateSystemAxis 
axis, final double min, final double max) {
-        final Map<String,Object> properties = new HashMap<>(8);
+        final var properties = new HashMap<String,Object>(8);
         properties.putAll(IdentifiedObjects.getProperties(axis, EXCLUDES));
         properties.put(DefaultCoordinateSystemAxis.MINIMUM_VALUE_KEY, min);
         properties.put(DefaultCoordinateSystemAxis.MAXIMUM_VALUE_KEY, max);
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/AxisDirections.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/AxisDirections.java
index af51464b71..178de792bb 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/AxisDirections.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/AxisDirections.java
@@ -262,7 +262,7 @@ public final class AxisDirections extends Static {
     }
 
     /**
-     * Returns {@code true} if the given direction is a user-defined direction 
(i.e. is not defined by GeoAPI).
+     * Returns {@code true} if the given direction is a user-defined direction 
(i.e., is not defined by GeoAPI).
      *
      * @param  dir  the direction to test, or {@code null}.
      * @return {@code true} if the given direction is user-defined.
diff --git 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/cs/CoordinateSystemsTest.java
 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/cs/CoordinateSystemsTest.java
index 626e9a4a9d..fd9296c1b3 100644
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/cs/CoordinateSystemsTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/cs/CoordinateSystemsTest.java
@@ -161,12 +161,32 @@ public final class CoordinateSystemsTest extends TestCase 
{
         assertEquals(-expected, (inverse != null) ? inverse.degrees() : 
Double.NaN, 0);     // Δ=0 for ignoring the sign of ±0.
     }
 
+    /**
+     * Tests {@link 
CoordinateSystems#getSimpleAxisDirections(CoordinateSystem)}.
+     */
+    @Test
+    public void testGetSimpleAxisDirections() {
+        final AxisDirection n90 = parseAxisDirection("North along 90°E");
+        final AxisDirection n00 = parseAxisDirection("North along 0°E");
+        final var cs = new AbstractCS(Map.of(NAME_KEY, "Polar"),
+                new DefaultCoordinateSystemAxis(Map.of(NAME_KEY, "Easting"),  
"E", n90, Units.METRE),
+                new DefaultCoordinateSystemAxis(Map.of(NAME_KEY, "Northing"), 
"N", n00, Units.METRE),
+                HardCodedAxes.DEPTH);
+
+        final var expected = new AxisDirection[] {n90, n00, 
AxisDirection.DOWN};
+        assertArrayEquals(expected, getAxisDirections(cs));
+
+        expected[0] = AxisDirection.EAST;
+        expected[1] = AxisDirection.NORTH;
+        assertArrayEquals(expected, getSimpleAxisDirections(cs));
+    }
+
     /**
      * Tests {@link CoordinateSystems#hasAllTargetTypes(CoordinateSystem, 
CoordinateSystem)}.
      */
     @Test
     public void testHasAllTargetTypes() {
-        final DefaultCompoundCS cs = new 
DefaultCompoundCS(HardCodedCS.GEODETIC_2D, HardCodedCS.GRAVITY_RELATED_HEIGHT);
+        final var cs = new DefaultCompoundCS(HardCodedCS.GEODETIC_2D, 
HardCodedCS.GRAVITY_RELATED_HEIGHT);
         assertTrue (CoordinateSystems.hasAllTargetTypes(cs, 
HardCodedCS.GRAVITY_RELATED_HEIGHT));
         assertFalse(CoordinateSystems.hasAllTargetTypes(cs, HardCodedCS.DAYS));
         assertTrue (CoordinateSystems.hasAllTargetTypes(cs, 
HardCodedCS.GEODETIC_2D));
diff --git 
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/writer/GeoEncoder.java
 
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/writer/GeoEncoder.java
index 1ce9787fc4..82370219a2 100644
--- 
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/writer/GeoEncoder.java
+++ 
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/writer/GeoEncoder.java
@@ -259,7 +259,7 @@ public final class GeoEncoder {
             return;
         }
         final CoordinateReferenceSystem crs = 
horizontal.getCoordinateReferenceSystem();
-        axisDirections = 
CoordinateSystems.getAxisDirections(crs.getCoordinateSystem());
+        axisDirections = 
CoordinateSystems.getSimpleAxisDirections(crs.getCoordinateSystem());
         if (crs instanceof ProjectedCRS) {
             writeCRS((ProjectedCRS) crs);
         } else if (crs instanceof GeodeticCRS) {
diff --git 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/map/MapCanvas.java 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/map/MapCanvas.java
index 4174e8036b..2ee421ddc0 100644
--- a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/map/MapCanvas.java
+++ b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/map/MapCanvas.java
@@ -1223,7 +1223,7 @@ public abstract class MapCanvas extends PlanarCanvas {
                         final MatrixSIS m;
                         objectiveCRS = 
objectiveBounds.getCoordinateReferenceSystem();
                         if (objectiveCRS != null) {
-                            AxisDirection[] srcAxes = 
CoordinateSystems.getAxisDirections(objectiveCRS.getCoordinateSystem());
+                            AxisDirection[] srcAxes = 
CoordinateSystems.getSimpleAxisDirections(objectiveCRS.getCoordinateSystem());
                             m = Matrices.createTransform(objectiveBounds, 
srcAxes, target, toDisplayDirections(srcAxes));
                         } else {
                             m = Matrices.createTransform(objectiveBounds, 
target);

Reply via email to