This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits 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 6988814b79 Avoid an `IllegalGridGeometryException` when a pyramid
contains no "grid to CRS" transform.
6988814b79 is described below
commit 6988814b79345969c34cd2681d5d59a9565035c8
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Wed Jun 24 18:57:23 2026 +0200
Avoid an `IllegalGridGeometryException` when a pyramid contains no "grid to
CRS" transform.
---
.../apache/sis/coverage/grid/GridDerivation.java | 61 ++++++++++++++++------
.../org/apache/sis/coverage/grid/GridGeometry.java | 16 ++----
.../sis/coverage/grid/ResampledGridCoverage.java | 2 +-
.../sis/coverage/grid/GridDerivationTest.java | 19 +++++++
4 files changed, 70 insertions(+), 28 deletions(-)
diff --git
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridDerivation.java
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridDerivation.java
index 2f1f394eda..d330971eff 100644
---
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridDerivation.java
+++
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridDerivation.java
@@ -87,7 +87,7 @@ import org.opengis.coverage.PointOutsideCoverageException;
*
* @author Martin Desruisseaux (Geomatys)
* @author Alexis Manin (Geomatys)
- * @version 1.6
+ * @version 1.7
*
* @see GridGeometry#derive()
* @see GridGeometry#selectDimensions(int[])
@@ -543,27 +543,58 @@ public class GridDerivation {
if (base.equals(areaOfInterest, ComparisonMode.BY_CONTRACT)) {
return this;
}
- if (areaOfInterest.isEnvelopeOnly()) {
- return subgrid(areaOfInterest.envelope, (double[]) null);
- }
final double[] scales;
- if (areaOfInterest.isExtentOnly()) {
+ if (areaOfInterest.extent == null && areaOfInterest.envelope == null
&& base.gridToCRS == null) {
+ /*
+ * Case when `areaOfInterest` specifies only a resolution
(typically in a pyramid)
+ * and we cannot use that resolution by a concatenation of "grid
to CRS" transforms.
+ * The given resolution is relative to the base grid which was
used for deriving `areaOfInterest`.
+ * We don't really know if it was the same base as `this.base`,
but there is good chances that the
+ * fact that `base.gridToCRS` is null is the reason why
`areaOfInterest` has no information other
+ * than resolution. On the assumption that both bases are the
same, we need to divide the specified
+ * resolution by `base.resolution` in order to get subsampling
factors.
+ */
+ scales = areaOfInterest.getResolution(true);
+ final double[] resolution = base.resolution;
+ if (resolution != null) {
+ for (int i = scales.length; --i >= 0;) {
+ scales[i] /= resolution[i];
+ }
+ }
+ } else if (areaOfInterest.gridToCRS == null && (areaOfInterest.extent
== null) != (areaOfInterest.envelope == null)) {
+ /*
+ * Case of some kind of bounding box (in grid units or CRS units)
without "grid to CRS" transform.
+ * In principle, `areaOfInterest.resolution` should be null since
`areaOfInterest.gridToCRS` is null.
+ * Nevertheless, it may be non-null if the given `areaOfInterest`
has been derived from another grid,
+ * in which case the resolution requested by the user was saved
even if no `gridToCRS` was available.
+ */
+ if (areaOfInterest.extent == null) {
+ double[] resolution = areaOfInterest.resolution;
+ if (resolution != null) {
+ resolution = resolution.clone();
+ }
+ return subgrid(areaOfInterest.envelope, resolution);
+ }
if (baseExtent != null) {
baseExtent = baseExtent.intersect(areaOfInterest.extent);
subGridSetter = "subgrid";
}
- scales = areaOfInterest.resolution;
/*
- * In principle, the above `resolution` should be null because it
could not be derived from `gridToCRS`,
- * because the latter is null (otherwise `isExtentOnly()` would
have been false). However, an exception
- * to this rule happens if the given `areaOfInterest` has been
computed by another `GridDerivation`,
- * in which case the resolution requested by the user was saved
even if no `gridToCRS` was available.
- * That resolution is relative to the base grid of the other
`GridDerivation` instead of this one,
- * but we ignore that details because the `resolution` field is
only indicative, especially since
- * the subsampling offsets are lost. If the exact resolution and
subsampling offsets where known,
- * they would have been stored in `gridToCRS`.
+ * The resolution is relative to the base grid which was used for
deriving `areaOfInterest`.
+ * We don't really know if it was the same base as `this.base`,
but it is surely not the case if
+ * `base.gridToCRS` is non-null, otherwise `areaOfInterest` would
have inherited that transform.
+ * Conservatively do NOT divide the specified resolution by
`base.resolution`.
+ *
+ * This approach is quite approximate. But the `resolution` field
is only indicative anyway,
+ * especially since the subsampling offsets are lost. If the exact
resolution and subsampling
+ * offsets where known, they should have been stored in
`gridToCRS`.
*/
+ scales = areaOfInterest.resolution;
} else try {
+ /*
+ * Case of grid geometries for which we require the presence of a
"grid to CRS" transform.
+ * An `IllegalGridGeometryException` will be thrown if a transform
is missing.
+ */
final MathTransform nowraparound;
final var finder = new CoordinateOperationFinder(areaOfInterest,
base);
finder.verifyPresenceOfCRS(false);
@@ -697,7 +728,7 @@ public class GridDerivation {
* @param resolution the desired resolution in the same units and
order than the axes of the given envelope,
* or {@code null} or an empty array if no
subsampling is desired. The array length should
* be equal to the {@code areaOfInterest}
dimension, but this is not mandatory
- * (zero or missing values mean no sub-sampling,
extraneous values are ignored).
+ * (zero or NaN values mean no sub-sampling,
extraneous values are ignored).
* @return {@code this} for method call chaining.
* @throws DisjointExtentException if the given area of interest does not
intersect the grid extent.
* @throws IncompleteGridGeometryException if the base grid geometry has
no extent, no "grid to CRS" transform,
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 2dbea346be..10a3778369 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
@@ -1604,18 +1604,10 @@ public class GridGeometry implements LenientComparable,
Serializable {
}
/**
- * Returns {@code true} if this grid geometry contains only a grid extent
and no other information.
- * Note: if {@link #gridToCRS} is {@code null}, then {@link #cornerToCRS}
and {@link #resolution}
- * should be null as well.
- */
- final boolean isExtentOnly() {
- return gridToCRS == null && envelope == null && extent != null;
- }
-
- /**
- * Returns {@code true} if this grid geometry contains only an envelope
and no other information.
- * Note: if {@link #gridToCRS} is {@code null}, then {@link #cornerToCRS}
and {@link #resolution}
- * should be null as well.
+ * Returns {@code true} if this grid geometry contains only an envelope
with no extent or transform.
+ * Note: if {@link #gridToCRS} is {@code null}, then {@link #cornerToCRS}
shall also be {@code null}.
+ * The {@link #resolution} array is usually also null, but may be non-null
if this grid geometry was
+ * {@linkplain #GridGeometry(GridGeometry, GridExtent, MathTransform)
derived from another grid}.
*/
final boolean isEnvelopeOnly() {
return gridToCRS == null && extent == null && envelope != null;
diff --git
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/ResampledGridCoverage.java
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/ResampledGridCoverage.java
index 67a4710758..237401e492 100644
---
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/ResampledGridCoverage.java
+++
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/ResampledGridCoverage.java
@@ -292,7 +292,7 @@ final class ResampledGridCoverage extends
DerivedGridCoverage {
throws FactoryException, TransformException
{
final GridGeometry sourceGG = source.getGridGeometry();
- final CoordinateOperationFinder changeOfCRS = new
CoordinateOperationFinder(sourceGG, target);
+ final var changeOfCRS = new CoordinateOperationFinder(sourceGG,
target);
changeOfCRS.verifyPresenceOfCRS(true);
/*
* Compute the transform from source pixels to target CRS (to be
completed to target pixels later).
diff --git
a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/coverage/grid/GridDerivationTest.java
b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/coverage/grid/GridDerivationTest.java
index 6abb65f224..3e3405a4ed 100644
---
a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/coverage/grid/GridDerivationTest.java
+++
b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/coverage/grid/GridDerivationTest.java
@@ -617,6 +617,25 @@ public final class GridDerivationTest extends TestCase {
assertArrayEquals(new double[] {3, 5}, result.getResolution(false));
}
+ /**
+ * Tests {@link GridDerivation#subgrid(GridExtent, long...)} with a null
"grid to CRS" transform
+ * but a non-null resolution.
+ */
+ @Test
+ public void testSubgridWithoutTransformButWithResolution() {
+ GridGeometry aoi = new GridGeometry(null, PixelInCell.CELL_CORNER,
MathTransforms.scale(128, 128), null);
+ GridGeometry base = new GridGeometry(new GridExtent(2048, 798), null,
null, null, aoi.resolution, 0);
+ assertArrayEquals(new double[] {128, 128}, base.getResolution(false));
+ assertSame(base, base.derive().subgrid(aoi).build());
+
+ aoi = new GridGeometry(null, PixelInCell.CELL_CORNER,
MathTransforms.scale(256, 256), null);
+ GridGeometry derived = base.derive().subgrid(aoi).build();
+ assertArrayEquals(new double[] {256, 256},
derived.getResolution(false));
+ assertExtentEquals(new long[2], new long[] {1023, 398},
derived.getExtent());
+ assertNull(derived.gridToCRS);
+ assertNull(derived.envelope);
+ }
+
/**
* Tests {@link GridDerivation#slice(DirectPosition)}.
*/