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 f797799d32 Missing translation when writing a GeoTIFF file with grid 
coordinates that do not start at zero.
f797799d32 is described below

commit f797799d320ac7249520fdfb822c685343ae9bd4
Author: Martin Desruisseaux <martin.desruisse...@geomatys.com>
AuthorDate: Fri Jan 24 16:53:29 2025 +0100

    Missing translation when writing a GeoTIFF file with grid coordinates that 
do not start at zero.
---
 .../org/apache/sis/coverage/grid/GridGeometry.java    | 19 +++++++++++++++++++
 .../apache/sis/coverage/grid/GridGeometryTest.java    | 14 +++++++++++---
 .../apache/sis/storage/geotiff/writer/GeoEncoder.java |  9 +++++----
 3 files changed, 35 insertions(+), 7 deletions(-)

diff --git 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridGeometry.java
 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridGeometry.java
index b8e60e5817..d70c086fac 100644
--- 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridGeometry.java
+++ 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridGeometry.java
@@ -1669,6 +1669,25 @@ public class GridGeometry implements LenientComparable, 
Serializable {
         return new GridGeometry(newExtent, t1, t2, envelope, resolution, 
nonLinears);
     }
 
+    /**
+     * Translates the grid to lower coordinate values of zero without changing 
the "real world" coordinates.
+     * The returned grid has the same {@linkplain GridExtent#getSize(int) 
size} than this grid,
+     * i.e. both low and high grid coordinates are displaced by the same 
number of cells.
+     * The "grid to CRS" transforms are adjusted accordingly in order to map 
to the same
+     * "real world" coordinates.
+     *
+     * @return a grid geometry whose lower coordinates are zeros.
+     * @throws ArithmeticException if the translation results in upper 
coordinates that overflow 64-bits integer.
+     *
+     * @since 1.5
+     */
+    public GridGeometry shiftGridToZeros() {
+        if (extent == null || extent.startsAtZero()) {
+            return this;
+        }
+        return shiftGrid(extent.getLow().getCoordinateValues(), true);
+    }
+
     /**
      * Returns a grid geometry with the given grid extent, which implies a new 
"real world" computation.
      * The "grid to CRS" transforms and the resolution stay the same as this 
{@code GridGeometry}.
diff --git 
a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/coverage/grid/GridGeometryTest.java
 
b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/coverage/grid/GridGeometryTest.java
index 7798fd1487..603e8c6259 100644
--- 
a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/coverage/grid/GridGeometryTest.java
+++ 
b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/coverage/grid/GridGeometryTest.java
@@ -555,6 +555,7 @@ public final class GridGeometryTest extends TestCase {
 
     /**
      * Tests {@link GridGeometry#shiftGrid(long[])}.
+     * Also opportunistically tests the closely-related {@link 
GridGeometry#shiftGridToZeros()} method.
      */
     @Test
     public void testShiftGrid() {
@@ -569,10 +570,17 @@ public final class GridGeometryTest extends TestCase {
         /*
          * The "real world" envelope should be unchanged by grid translation.
          */
+        assertSame(grid, grid.shiftGridToZeros());
         final Envelope envelope = grid.getEnvelope();
-        grid = grid.shiftGrid(12, 15);
-        assertExtentEquals(new long[] {12, 15}, new long[] {12 + 16, 15 + 9}, 
grid.getExtent());
-        assertEquals(envelope, grid.getEnvelope());
+        GridGeometry shifted = grid.shiftGrid(12, 15);
+        assertExtentEquals(new long[] {12, 15}, new long[] {12 + 16, 15 + 9}, 
shifted.getExtent());
+        assertEquals(envelope, shifted.getEnvelope());
+        /*
+         * Shift back to zero.
+         */
+        assertNotEquals(grid, shifted);
+        shifted = shifted.shiftGridToZeros();
+        assertEquals(grid, shifted);
     }
 
     /**
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 3f9f551ae3..fc61bfaef5 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
@@ -243,9 +243,10 @@ public final class GeoEncoder {
      * @throws IncompleteGridGeometryException if the grid geometry is 
incomplete.
      * @throws IncompatibleResourceException if the grid geometry cannot be 
encoded.
      */
-    public void write(final GridGeometry grid, final MetadataFetcher<?> 
metadata)
+    public void write(GridGeometry grid, final MetadataFetcher<?> metadata)
             throws FactoryException, TransformException, 
IncommensurableException, IncompatibleResourceException
     {
+        grid = grid.shiftGridToZeros();
         citation = CollectionsExt.first(metadata.transformationDimension);
         isPoint  = CollectionsExt.first(metadata.cellGeometry) == 
CellGeometry.POINT;
         final var anchor = isPoint ? PixelInCell.CELL_CENTER : 
PixelInCell.CELL_CORNER;
@@ -290,8 +291,8 @@ public final class GeoEncoder {
         final VerticalCRS vertical = CRS.getVerticalComponent(fullCRS, true);
         if (vertical != null) {
             final CoordinateSystem cs = vertical.getCoordinateSystem();
-            final int vi = 
AxisDirections.indexOfColinear(fullCRS.getCoordinateSystem(), cs);
-            if (vi >= 0 && Arrays.binarySearch(dimensions, vi) < 0) {
+            final int verticalDimension = 
AxisDirections.indexOfColinear(fullCRS.getCoordinateSystem(), cs);
+            if (verticalDimension >= 0 && Arrays.binarySearch(dimensions, 
verticalDimension) < 0) {
                 writeCRS(vertical);
                 axisDirections = Arrays.copyOf(axisDirections, 
BIDIMENSIONAL+1);
                 axisDirections[BIDIMENSIONAL] = cs.getAxis(0).getDirection();
@@ -302,7 +303,7 @@ public final class GeoEncoder {
                         final int s;
                         switch (i) {
                             default:            s = dimensions[i];        
break;    // Shear from horizontal dimensions.
-                            case BIDIMENSIONAL: s = vi;                   
break;    // Scale from vertical dimension.
+                            case BIDIMENSIONAL: s = verticalDimension;    
break;    // Scale from vertical dimension.
                             case MATRIX_SIZE-1: s = more.getNumCol() - 1; 
break;    // Translation.
                         }
                         // Copy the rows of the third dimension.

Reply via email to