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 e1d1015  Requested resolution needs to be converted to coverage 
resolution in a multi-resolution grid resource.
e1d1015 is described below

commit e1d10154dd29d87140c5372083884a2625733483
Author: Martin Desruisseaux <martin.desruisse...@geomatys.com>
AuthorDate: Thu Feb 24 16:36:02 2022 +0100

    Requested resolution needs to be converted to coverage resolution in a 
multi-resolution grid resource.
---
 .../org/apache/sis/coverage/grid/GridGeometry.java |  2 +-
 .../sis/storage/geotiff/MultiResolutionImage.java  | 62 ++++++++++++++++++----
 2 files changed, 54 insertions(+), 10 deletions(-)

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 0ef45e2..1987d8a 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
@@ -1260,7 +1260,7 @@ public class GridGeometry implements LenientComparable, 
Serializable {
     }
 
     /**
-     * Returns {@code true} if all the parameters specified by the argument 
are set.
+     * Returns {@code true} if all the properties specified by the argument 
are set.
      * If this method returns {@code true}, then invoking the corresponding 
getter
      * methods will not throw {@link IncompleteGridGeometryException}.
      *
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 2c35a2d..6247dec 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
@@ -19,8 +19,13 @@ package org.apache.sis.storage.geotiff;
 import java.util.List;
 import java.util.Arrays;
 import java.io.IOException;
+import org.opengis.util.FactoryException;
+import org.opengis.geometry.DirectPosition;
 import org.opengis.referencing.datum.PixelInCell;
+import org.opengis.referencing.operation.MathTransform;
 import org.opengis.referencing.operation.TransformException;
+import org.opengis.referencing.operation.CoordinateOperation;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.apache.sis.coverage.grid.GridExtent;
 import org.apache.sis.coverage.grid.GridGeometry;
 import org.apache.sis.coverage.grid.GridCoverage;
@@ -30,6 +35,7 @@ import org.apache.sis.storage.DataStoreReferencingException;
 import org.apache.sis.internal.storage.GridResourceWrapper;
 import org.apache.sis.internal.referencing.DirectPositionView;
 import org.apache.sis.referencing.operation.matrix.MatrixSIS;
+import org.apache.sis.referencing.CRS;
 
 
 /**
@@ -57,6 +63,12 @@ final class MultiResolutionImage extends GridResourceWrapper 
{
     private final double[][] resolutions;
 
     /**
+     * The last coordinate operation returned by {@link 
#getTransformFrom(CoordinateReferenceSystem)}.
+     * Used as an optimization in the common case where the same CRS is used 
for many requests.
+     */
+    private volatile CoordinateOperation lastOperation;
+
+    /**
      * Creates a multi-resolution images with all the given reduced-resolution 
(overview) images,
      * from finest resolution to coarsest resolution. The full-resolution 
image shall be at index 0.
      */
@@ -155,6 +167,45 @@ final class MultiResolutionImage extends 
GridResourceWrapper {
     }
 
     /**
+     * Converts a resolution from units in the given CRS to units of this 
coverage CRS.
+     *
+     * @param  domain  the geometry from which to get the resolution.
+     * @return resolution from the given grid geometry in units of this 
coverage CRS, or {@code null}.
+     */
+    private double[] getResolution(final GridGeometry domain) throws 
DataStoreException {
+        if (domain == null || !domain.isDefined(GridGeometry.RESOLUTION)) {
+            return null;
+        }
+        double[] resolution = domain.getResolution(true);
+        if (domain.isDefined(GridGeometry.CRS | GridGeometry.ENVELOPE)) try {
+            final CoordinateReferenceSystem crs = 
domain.getCoordinateReferenceSystem();
+            CoordinateOperation op = lastOperation;
+            if (op == null || !crs.equals(op.getTargetCRS())) {
+                final GridGeometry gg = getGridGeometry();
+                op = CRS.findOperation(crs, gg.getCoordinateReferenceSystem(), 
gg.getGeographicExtent().orElse(null));
+                lastOperation = op;
+            }
+            final MathTransform sourceToCoverage = op.getMathTransform();
+            if (!sourceToCoverage.isIdentity()) {
+                /*
+                 * 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());
+                poi = 
domain.getGridToCRS(PixelInCell.CELL_CENTER).transform(poi, null);
+                final MatrixSIS derivative = 
MatrixSIS.castOrCopy(sourceToCoverage.derivative(poi));
+                resolution = derivative.multiply(resolution);
+                for (int i=0; i<resolution.length; i++) {
+                    resolution[i] = Math.abs(resolution[i]);
+                }
+            }
+        } catch (FactoryException | TransformException e) {
+            throw new DataStoreReferencingException(e);
+        }
+        return resolution;
+    }
+
+    /**
      * Loads a subset of the grid coverage represented by this resource.
      *
      * @param  domain  desired grid extent and resolution, or {@code null} for 
reading the whole domain.
@@ -164,15 +215,8 @@ final class MultiResolutionImage extends 
GridResourceWrapper {
      */
     @Override
     public GridCoverage read(final GridGeometry domain, final int... range) 
throws DataStoreException {
-        final double[] request;
-        int level;
-        if (domain != null && domain.isDefined(GridGeometry.RESOLUTION)) {
-            request = domain.getResolution(true);
-            level   = resolutions.length;
-        } else {
-            request = null;
-            level   = 1;
-        }
+        final double[] request = getResolution(domain);
+        int level = (request != null) ? resolutions.length : 1;
         synchronized (getSynchronizationLock()) {
 finer:      while (--level > 0) {
                 final double[] resolution = resolution(level);

Reply via email to