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 <[email protected]>
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.