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);