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 abd5100711 If the original CRS used the [0 … 360]° longitude range, convert to the [−180 … +180]° range. abd5100711 is described below commit abd5100711f4c7d111117db883c3f9ee415dc1e9 Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Fri Feb 28 15:16:14 2025 +0100 If the original CRS used the [0 … 360]° longitude range, convert to the [−180 … +180]° range. --- .../sis/storage/geotiff/writer/GeoEncoder.java | 27 ++++++++++++++++++++++ 1 file changed, 27 insertions(+) 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 7bdd7ef79d..c6ade06582 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 @@ -38,6 +38,7 @@ import org.opengis.referencing.crs.VerticalCRS; import org.opengis.referencing.crs.EngineeringCRS; import org.opengis.referencing.cs.AxisDirection; import org.opengis.referencing.cs.CoordinateSystem; +import org.opengis.referencing.cs.CoordinateSystemAxis; import org.opengis.referencing.cs.CartesianCS; import org.opengis.referencing.cs.EllipsoidalCS; import org.opengis.referencing.cs.VerticalCS; @@ -79,6 +80,7 @@ import org.apache.sis.storage.geotiff.base.Resources; import org.apache.sis.storage.event.StoreListeners; import org.apache.sis.metadata.iso.citation.Citations; import org.apache.sis.math.MathFunctions; +import org.apache.sis.measure.Longitude; import org.apache.sis.pending.jdk.JDK15; @@ -135,6 +137,12 @@ public final class GeoEncoder { */ private AxisDirection[] axisDirections; + /** + * The longitude axis if the <abbr>CRS</abbr> is geodetic, + * or {@code null} if the <abbr>CRS</abbr> is projected or unknown. + */ + private CoordinateSystemAxis longitudeAxis; + /** * The conversion from grid coordinates to full CRS, which determines the model transformation. * This conversion may operate on more dimensions than the three dimensions mandated by GeoTIFF. @@ -412,6 +420,7 @@ public final class GeoEncoder { { final short type; final CoordinateSystem cs = crs.getCoordinateSystem(); + longitudeAxis = cs.getAxis(AxisDirections.indexOfColinear(cs, AxisDirection.EAST)); addUnits(UnitKey.ANGULAR, cs); if (cs instanceof EllipsoidalCS) { type = GeoCodes.ModelTypeGeographic; @@ -873,6 +882,24 @@ public final class GeoEncoder { gridToCRS = Matrices.createTransform(axisDirections, target).multiply(gridToCRS); axisDirections = null; // For avoiding to do the multiplication again. } + /* + * If the first axis is a longitude axis, ensure that the longitude is in the [−180 … +180]° range. + * We need this shift because the source CRS may be using the [0 … 360]° range (for example, when + * the data come from a netCDF file), but CRS in GeoTIFF are implicitly in [−180 … +180]°. + */ + if (longitudeAxis != null) try { + final double max = Units.DEGREE.getConverterToAny(longitudeAxis.getUnit()).convert(Longitude.MAX_VALUE); + if (Math.abs(longitudeAxis.getMaximumValue() - max) > max / Longitude.MAX_VALUE) { // Arbitrary tolerance. + final int translationColumn = gridToCRS.getNumCol() - 1; + double translation = gridToCRS.getElement(0, translationColumn); + translation = Math.IEEEremainder(translation, 2*max); + if (translation == max) translation = -translation; + gridToCRS.setElement(0, translationColumn, translation); + } + } catch (IncommensurableException e) { + // Should never happen. If happen anyway, we will simply not shift the longitude coordinate. + listeners.warning(e); + } /* * Copy matrix coefficients. This matrix size is always 4×4, no matter the size of the `gridToCRS` matrix. * So we cannot invoke `MatrixSIS.getElements()`.