You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sis.apache.org by de...@apache.org on 2022/05/26 23:02:31 UTC
[sis] 02/03: Add a `PixelInCell` argument to the `GridExtent.getPointOfInterest()` method. It matter when we use that method for getting the coordinates of a slice.
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
commit 6dd5c5754d1b5b6a0c6bf611134a4cb24a57f87a
Author: Martin Desruisseaux <ma...@geomatys.com>
AuthorDate: Thu May 26 19:39:34 2022 +0200
Add a `PixelInCell` argument to the `GridExtent.getPointOfInterest()` method.
It matter when we use that method for getting the coordinates of a slice.
---
.../coverage/grid/CoordinateOperationFinder.java | 2 +-
.../sis/coverage/grid/GridCoverageProcessor.java | 2 +-
.../apache/sis/coverage/grid/GridDerivation.java | 7 ++++--
.../apache/sis/coverage/grid/GridEvaluator.java | 2 +-
.../org/apache/sis/coverage/grid/GridExtent.java | 29 ++++++++++++++++++++--
.../org/apache/sis/coverage/grid/GridGeometry.java | 17 +++++++------
.../sis/coverage/grid/ResampledGridCoverage.java | 9 ++++---
.../apache/sis/coverage/grid/SliceGeometry.java | 7 +++---
.../sis/internal/coverage/CoverageCombiner.java | 4 +--
.../main/java/org/apache/sis/portrayal/Canvas.java | 2 +-
.../org/apache/sis/portrayal/CanvasExtent.java | 10 +++++---
.../org/apache/sis/portrayal/package-info.java | 2 +-
.../sis/storage/geotiff/MultiResolutionImage.java | 6 ++---
13 files changed, 67 insertions(+), 32 deletions(-)
diff --git a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/CoordinateOperationFinder.java b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/CoordinateOperationFinder.java
index 11f1c65f34..2b2fefbc6d 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/CoordinateOperationFinder.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/CoordinateOperationFinder.java
@@ -645,7 +645,7 @@ apply: if (forwardChangeOfCRS == null) {
@SuppressWarnings("ReturnOfCollectionOrArrayField")
private double[] coordinates() {
if (coordinates == null) try {
- final double[] poi = grid.getExtent().getPointOfInterest();
+ final double[] poi = grid.getExtent().getPointOfInterest(PixelInCell.CELL_CENTER);
MathTransform tr = grid.getGridToCRS(PixelInCell.CELL_CENTER);
if (changeOfCRS != null) {
tr = MathTransforms.concatenate(tr, changeOfCRS);
diff --git a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridCoverageProcessor.java b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridCoverageProcessor.java
index 0e855321e1..d00e268bc1 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridCoverageProcessor.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridCoverageProcessor.java
@@ -273,7 +273,7 @@ public class GridCoverageProcessor implements Cloneable {
* </tr><tr>
* <td>{@linkplain GridGeometry#getExtent() Grid extent}</td>
* <td>A default size preserving resolution at source
- * {@linkplain GridExtent#getPointOfInterest() point of interest}.</td>
+ * {@linkplain GridExtent#getPointOfInterest(PixelInCell) point of interest}.</td>
* </tr><tr>
* <td>{@linkplain GridGeometry#getGridToCRS Grid to CRS transform}</td>
* <td>Whatever it takes for fitting data inside the supplied extent.</td>
diff --git a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridDerivation.java b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridDerivation.java
index cbf5981039..44772cba57 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridDerivation.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridDerivation.java
@@ -520,7 +520,7 @@ public class GridDerivation {
throw new IllegalGridGeometryException(e, "areaOfInterest");
}
// The `domain` extent must be the source of the `mapCenters` transform.
- scales = GridGeometry.resolution(mapCenters, domain);
+ scales = GridGeometry.resolution(mapCenters, domain, PixelInCell.CELL_CENTER);
}
/*
* The subsampling will determine the scale factors in the transform from the given desired grid geometry
@@ -771,9 +771,12 @@ public class GridDerivation {
* Returns the point of interest of current {@link #baseExtent}, keeping only the remaining
* dimensions after {@link #dropUnusedDimensions(MathTransform, int)} execution.
* The position is in units of {@link #base} grid coordinates.
+ *
+ * <p>This method assumes that the transform will be used with a "cell corner to CRS" transform
+ * instead of the usual "cell center to CRS".</p>
*/
private double[] getPointOfInterest() {
- final double[] pointOfInterest = baseExtent.getPointOfInterest();
+ final double[] pointOfInterest = baseExtent.getPointOfInterest(PixelInCell.CELL_CORNER);
if (modifiedDimensions == null) {
return pointOfInterest;
}
diff --git a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridEvaluator.java b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridEvaluator.java
index 4fd6641959..8feb79b4ef 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridEvaluator.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridEvaluator.java
@@ -187,7 +187,7 @@ public class GridEvaluator implements GridCoverage.Evaluator {
final GridExtent extent = gridGeometry.getExtent();
MathTransform gridToCRS = gridGeometry.getGridToCRS(PixelInCell.CELL_CENTER);
gridToWraparound = MathTransforms.concatenate(gridToCRS, f.preferredToSpecified.inverse());
- final Matrix m = gridToWraparound.derivative(new DirectPositionView.Double(extent.getPointOfInterest()));
+ final Matrix m = gridToWraparound.derivative(new DirectPositionView.Double(extent.getPointOfInterest(PixelInCell.CELL_CENTER)));
/*
* `gridToWraparound` is the transform from grid coordinates to a CRS where wraparound axes exist.
* It may be the coverage CRS or its base CRS. The wraparound axes are identified by `periods`.
diff --git a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridExtent.java b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridExtent.java
index 5ff27e6569..3376c00fe0 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridExtent.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridExtent.java
@@ -33,6 +33,7 @@ import org.opengis.metadata.spatial.DimensionNameType;
import org.opengis.referencing.cs.AxisDirection;
import org.opengis.referencing.cs.CoordinateSystem;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.referencing.datum.PixelInCell;
import org.opengis.referencing.operation.Matrix;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.TransformException;
@@ -785,23 +786,47 @@ public class GridExtent implements GridEnvelope, LenientComparable, Serializable
return Numerics.toUnsignedDouble(size);
}
+ /**
+ * @deprecated Replaced by {@link #getPointOfInterest(PixelInCell)}.
+ *
+ * @return the grid coordinates of a representative point.
+ */
+ @Deprecated
+ public double[] getPointOfInterest() {
+ return getPointOfInterest(PixelInCell.CELL_CORNER);
+ }
+
/**
* Returns the grid coordinates of a representative point.
* This point may be used for estimating a {@linkplain GridGeometry#getResolution(boolean) grid resolution}.
* The default implementation returns the median (or center) coordinates of this grid extent,
* but subclasses can override this method if another point is considered more representative.
*
+ * <p>The {@code anchpr} argument tells {@linkplain GridGeometry#getGridToCRS(PixelInCell) which transform}
+ * the caller intend to use for converting the grid coordinates to "real world" coordinates.
+ * With the default implementation, the coordinate values returned with {@code CELL_CORNER}
+ * are 0.5 cell units higher than the coordinate values returned with {@code CELL_CENTER}.
+ * Subclasses are free to ignore this argument.</p>
+ *
+ * @param anchor the convention to be used for conversion to "real world" coordinates.
* @return the grid coordinates of a representative point.
+ *
+ * @since 1.3
*/
- public double[] getPointOfInterest() {
+ public double[] getPointOfInterest(final PixelInCell anchor) {
final int dimension = getDimension();
final double[] center = new double[dimension];
+ final boolean isCorner = PixelInCell.CELL_CORNER.equals(anchor);
for (int i=0; i<dimension; i++) {
/*
* We want the average of (low + hi+1). However for the purpose of computing an average, it does
* not matter if we add 1 to `low` or `hi`. So we add 1 to `low` because it should not overflow.
*/
- center[i] = MathFunctions.average(Math.incrementExact(coordinates[i]), coordinates[i + dimension]);
+ long low = coordinates[i];
+ if (isCorner) {
+ low = Math.incrementExact(coordinates[i]);
+ }
+ center[i] = MathFunctions.average(low, coordinates[i + dimension]);
}
return center;
}
diff --git a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridGeometry.java b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridGeometry.java
index 7a9d5c481d..d7108e3167 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridGeometry.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridGeometry.java
@@ -129,7 +129,7 @@ import static org.apache.sis.referencing.CRS.findOperation;
* The same instance can be shared by different {@link GridCoverage} instances.
*
* @author Martin Desruisseaux (IRD, Geomatys)
- * @version 1.2
+ * @version 1.3
* @since 1.0
* @module
*/
@@ -367,12 +367,12 @@ public class GridGeometry implements LenientComparable, Serializable {
MathTransforms.uniformTranslation(dimension, -0.5));
cornerToCRS = MathTransforms.concatenate(toOther, other.cornerToCRS);
gridToCRS = MathTransforms.concatenate(centerShift, other.gridToCRS);
- resolution = resolution(gridToCRS, extent);
+ resolution = resolution(gridToCRS, extent, PixelInCell.CELL_CENTER);
nonLinears = findNonLinearTargets(gridToCRS);
} else {
cornerToCRS = null;
gridToCRS = null;
- resolution = resolution(toOther, extent); // Save resolution even if `gridToCRS` is null.
+ resolution = resolution(toOther, extent, PixelInCell.CELL_CENTER); // Save resolution even if `gridToCRS` is null.
nonLinears = findNonLinearTargets(toOther);
}
}
@@ -445,7 +445,7 @@ public class GridGeometry implements LenientComparable, Serializable {
this.gridToCRS = PixelTranslation.translate(gridToCRS, anchor, PixelInCell.CELL_CENTER);
this.cornerToCRS = PixelTranslation.translate(gridToCRS, anchor, PixelInCell.CELL_CORNER);
this.envelope = computeEnvelope(gridToCRS, crs, null); // `gridToCRS` specified by the user, not `this.gridToCRS`.
- this.resolution = resolution(gridToCRS, extent); // `gridToCRS` or `cornerToCRS` does not matter here.
+ this.resolution = resolution(gridToCRS, extent, anchor); // `gridToCRS` or `cornerToCRS` does not matter here.
this.nonLinears = findNonLinearTargets(gridToCRS);
} catch (TransformException e) {
throw new IllegalGridGeometryException(e, "gridToCRS");
@@ -541,7 +541,7 @@ public class GridGeometry implements LenientComparable, Serializable {
this.envelope = new ImmutableEnvelope(env);
if (scales == null) try {
// `gridToCRS` can not be null if `cornerToCRS` is non-null.
- scales = gridToCRS.derivative(new DirectPositionView.Double(extent.getPointOfInterest()));
+ scales = gridToCRS.derivative(new DirectPositionView.Double(extent.getPointOfInterest(anchor)));
numToIgnore = 0;
} catch (TransformException e) {
recoverableException("<init>", e);
@@ -1029,7 +1029,7 @@ public class GridGeometry implements LenientComparable, Serializable {
* <ul>
* <li>{@link Double#NaN} if {@code allowEstimates} is {@code false}.</li>
* <li>An arbitrary representative resolution otherwise.
- * Current implementation computes the resolution at {@link GridExtent#getPointOfInterest() grid center},
+ * Current implementation computes the resolution at {@link GridExtent#getPointOfInterest(PixelInCell) grid center},
* but different implementations may use alternative algorithms.</li>
* </ul>
*
@@ -1067,14 +1067,15 @@ public class GridGeometry implements LenientComparable, Serializable {
* @param gridToCRS a transform for which to compute the resolution, or {@code null} if none.
* @param domain the domain for which to get a resolution, or {@code null} if none.
* If non-null, must be the source of {@code gridToCRS}.
+ * @param anchor the pixel corner versus pixel center convention to use.
* @return the resolutions as positive numbers. May contain NaN values.
*/
- static double[] resolution(final MathTransform gridToCRS, final GridExtent domain) {
+ static double[] resolution(final MathTransform gridToCRS, final GridExtent domain, final PixelInCell anchor) {
final Matrix matrix = MathTransforms.getMatrix(gridToCRS);
if (matrix != null) {
return resolution(matrix, 1);
} else if (domain != null && gridToCRS != null) try {
- return resolution(gridToCRS.derivative(new DirectPositionView.Double(domain.getPointOfInterest())), 0);
+ return resolution(gridToCRS.derivative(new DirectPositionView.Double(domain.getPointOfInterest(anchor))), 0);
} catch (TransformException e) {
recoverableException("resolution", e);
}
diff --git a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/ResampledGridCoverage.java b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/ResampledGridCoverage.java
index d095047bd1..6df6d5d925 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/ResampledGridCoverage.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/ResampledGridCoverage.java
@@ -52,7 +52,7 @@ import org.apache.sis.util.Utilities;
*
* @author Martin Desruisseaux (Geomatys)
* @author Johann Sorel (Geomatys)
- * @version 1.2
+ * @version 1.3
* @since 1.1
* @module
*/
@@ -134,7 +134,7 @@ final class ResampledGridCoverage extends GridCoverage {
* For a source dimension <var>i</var>, {@code dependentDimensions[i]} is a bitmask with bits set to 1
* for each target dimension which require the source dimension <var>i</var> for its calculation.
*
- * @param mt the transform for which to determine dimension dependencies.
+ * @param mt the transform (mapping pixel centers) for which to determine dimension dependencies.
* @param domain domain of this {@code}.
* @return for each source dimension, a bitmask of target dependent dimensions.
* May be {@code null} if the mapping can not be computed or if it is not needed.
@@ -144,7 +144,8 @@ final class ResampledGridCoverage extends GridCoverage {
if (srcDim <= BIDIMENSIONAL) return null; // Dimension mapping not needed.
Matrix derivative = MathTransforms.getMatrix(mt);
if (derivative == null) try {
- derivative = mt.derivative(new DirectPositionView.Double(domain.getExtent().getPointOfInterest()));
+ derivative = mt.derivative(new DirectPositionView.Double(
+ domain.getExtent().getPointOfInterest(PixelInCell.CELL_CENTER)));
} catch (TransformException e) {
GridCoverageProcessor.recoverableException("resample", e); // Public caller of this method.
return null;
@@ -306,7 +307,7 @@ final class ResampledGridCoverage extends GridCoverage {
* `originToPOI` vector (the integer digits do not matter; they will be cancelled later).
*/
final GridExtent sourceExtent = sourceGG.getExtent();
- final double[] sourcePOI = sourceExtent.getPointOfInterest();
+ final double[] sourcePOI = sourceExtent.getPointOfInterest(PixelInCell.CELL_CENTER);
final double[] targetPOI = new double[sourceCenterToCRS.getTargetDimensions()];
final MatrixSIS vectors = MatrixSIS.castOrCopy(MathTransforms.derivativeAndTransform(
sourceCenterToCRS, sourcePOI, 0, targetPOI, 0));
diff --git a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/SliceGeometry.java b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/SliceGeometry.java
index 0279bacbe4..18e56c8b0e 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/SliceGeometry.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/SliceGeometry.java
@@ -20,6 +20,7 @@ import java.util.function.Function;
import java.awt.image.RenderedImage;
import java.awt.image.ImagingOpException;
import org.opengis.util.FactoryException;
+import org.opengis.referencing.datum.PixelInCell;
import org.opengis.referencing.operation.Matrix;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.MathTransformFactory;
@@ -47,7 +48,7 @@ import org.apache.sis.util.resources.Errors;
* That function is invoked (indirectly) by {@link org.apache.sis.internal.coverage.j2d.TiledImage#getProperty(String)}.</p>
*
* @author Martin Desruisseaux (Geomatys)
- * @version 1.1
+ * @version 1.3
* @since 1.1
* @module
*/
@@ -221,7 +222,7 @@ final class SliceGeometry implements Function<RenderedImage, GridGeometry> {
* from the original grid geometry.
*/
if (useSubExtent || resolution == null) {
- resolution = GridGeometry.resolution(gridToCRS, extent);
+ resolution = GridGeometry.resolution(gridToCRS, extent, PixelInCell.CELL_CENTER);
} else if (resolution.length != n) {
resolution = new double[n];
for (int i=0; i<n; i++) {
@@ -296,7 +297,7 @@ final class SliceGeometry implements Function<RenderedImage, GridGeometry> {
Matrix derivative = MathTransforms.getMatrix(gridToCRS);
if (derivative == null) {
if (extent != null) try {
- derivative = gridToCRS.derivative(new DirectPositionView.Double(extent.getPointOfInterest()));
+ derivative = gridToCRS.derivative(new DirectPositionView.Double(extent.getPointOfInterest(PixelInCell.CELL_CENTER)));
} catch (TransformException e) {
// GridGeometry.reduce(…) is the public method invoking indirectly this method.
GridGeometry.recoverableException("reduce", e);
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/CoverageCombiner.java b/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/CoverageCombiner.java
index e8c4b09818..e47aa35218 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/CoverageCombiner.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/CoverageCombiner.java
@@ -65,7 +65,7 @@ import static org.apache.sis.internal.util.Numerics.saturatingSubtract;
* be outside the bounds of destination coverage.</p>
*
* @author Martin Desruisseaux (Geomatys)
- * @version 1.2
+ * @version 1.3
*
* @see ImageCombiner
*
@@ -233,7 +233,7 @@ next: for (int j=0; j<sources.length; j++) {
*/
final long[] minSliceIndices = minIndices.clone();
final long[] maxSliceIndices = maxIndices.clone();
- final double[] centerIndices = targetEx.getPointOfInterest();
+ final double[] centerIndices = targetEx.getPointOfInterest(PixelInCell.CELL_CENTER);
final Dimension margin = processor.getInterpolation().getSupportSize();
margin.width = ((margin.width + 1) >> 1) + 1;
margin.height = ((margin.height + 1) >> 1) + 1;
diff --git a/core/sis-portrayal/src/main/java/org/apache/sis/portrayal/Canvas.java b/core/sis-portrayal/src/main/java/org/apache/sis/portrayal/Canvas.java
index 26b29e0cc0..20f03709a0 100644
--- a/core/sis-portrayal/src/main/java/org/apache/sis/portrayal/Canvas.java
+++ b/core/sis-portrayal/src/main/java/org/apache/sis/portrayal/Canvas.java
@@ -1079,7 +1079,7 @@ public class Canvas extends Observable implements Localized {
crs = null;
newPOI = new GeneralDirectPosition(gridToCRS.getTargetDimensions());
}
- gridToCRS.transform(extent.getPointOfInterest(), 0, newPOI.coordinates, 0, 1);
+ gridToCRS.transform(extent.getPointOfInterest(PixelInCell.CELL_CORNER), 0, newPOI.coordinates, 0, 1);
/*
* Get the CRS component in the dimensions shown by this canvas.
*
diff --git a/core/sis-portrayal/src/main/java/org/apache/sis/portrayal/CanvasExtent.java b/core/sis-portrayal/src/main/java/org/apache/sis/portrayal/CanvasExtent.java
index 8ef655ce5f..2f0ba14db3 100644
--- a/core/sis-portrayal/src/main/java/org/apache/sis/portrayal/CanvasExtent.java
+++ b/core/sis-portrayal/src/main/java/org/apache/sis/portrayal/CanvasExtent.java
@@ -18,6 +18,7 @@ package org.apache.sis.portrayal;
import java.util.List;
import org.opengis.geometry.DirectPosition;
+import org.opengis.referencing.datum.PixelInCell;
import org.opengis.referencing.operation.Matrix;
import org.opengis.referencing.cs.AxisDirection;
import org.opengis.referencing.cs.CoordinateSystem;
@@ -40,7 +41,7 @@ import org.apache.sis.internal.util.Numerics;
* This class contains also static help functions for the construction of {@link GridGeometry}.
*
* @author Martin Desruisseaux (Geomatys)
- * @version 1.1
+ * @version 1.3
* @since 1.1
* @module
*/
@@ -54,7 +55,7 @@ final class CanvasExtent extends GridExtent {
* The grid coordinates of a representative point. The {@code CanvasExtent} point of interest
* is the {@code Canvas} point of interest converted to (typically) pixel coordinates.
*
- * @see #getPointOfInterest()
+ * @see #getPointOfInterest(PixelInCell)
*/
private final double[] pointOfInterest;
@@ -75,10 +76,13 @@ final class CanvasExtent extends GridExtent {
* Returns the grid coordinates of a representative point.
* This is the canvas point of interest converted to (typically) pixel coordinates.
*
+ * @param anchor the convention to be used for conversion to "real world" coordinates.
+ * @return the grid coordinates of a representative point.
+ *
* @see Canvas#getPointOfInterest(boolean)
*/
@Override
- public double[] getPointOfInterest() {
+ public double[] getPointOfInterest(final PixelInCell anchor) {
return pointOfInterest.clone();
}
diff --git a/core/sis-portrayal/src/main/java/org/apache/sis/portrayal/package-info.java b/core/sis-portrayal/src/main/java/org/apache/sis/portrayal/package-info.java
index 2b8bbb237f..18b7fc3e2e 100644
--- a/core/sis-portrayal/src/main/java/org/apache/sis/portrayal/package-info.java
+++ b/core/sis-portrayal/src/main/java/org/apache/sis/portrayal/package-info.java
@@ -25,7 +25,7 @@
* Synchronization, if desired, must be done by the caller.
*
* @author Johann Sorel (Geomatys)
- * @version 1.1
+ * @version 1.3
* @since 1.1
* @module
*/
diff --git a/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/MultiResolutionImage.java b/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/MultiResolutionImage.java
index 8ca1b4d1ba..d5cf951dbe 100644
--- a/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/MultiResolutionImage.java
+++ b/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/MultiResolutionImage.java
@@ -152,8 +152,8 @@ final class MultiResolutionImage extends GridResourceWrapper {
}
image.initReducedResolution(base, scales);
if (geometry.isDefined(GridGeometry.GRID_TO_CRS)) {
- final MatrixSIS gridToCRS = MatrixSIS.castOrCopy(geometry.getGridToCRS(PixelInCell.CELL_CENTER)
- .derivative(new DirectPositionView.Double(fullExtent.getPointOfInterest())));
+ DirectPosition poi = new DirectPositionView.Double(fullExtent.getPointOfInterest(PixelInCell.CELL_CENTER));
+ MatrixSIS gridToCRS = MatrixSIS.castOrCopy(geometry.getGridToCRS(PixelInCell.CELL_CENTER).derivative(poi));
resolution = gridToCRS.multiply(scales);
} else {
// Assume an identity transform for the `gridToCRS` of full resolution image.
@@ -211,7 +211,7 @@ final class MultiResolutionImage extends GridResourceWrapper {
* If the `domain` grid geometry has a resolution and an envelope, then it should have
* an extent and a "grid to CRS" transform (otherwise it may be a `GridGeometry` bug)
*/
- DirectPosition poi = new DirectPositionView.Double(domain.getExtent().getPointOfInterest());
+ DirectPosition poi = new DirectPositionView.Double(domain.getExtent().getPointOfInterest(PixelInCell.CELL_CENTER));
poi = domain.getGridToCRS(PixelInCell.CELL_CENTER).transform(poi, null);
final MatrixSIS derivative = MatrixSIS.castOrCopy(sourceToCoverage.derivative(poi));
resolution = derivative.multiply(resolution);