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);