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 d58bf3769ea80723c2b24802da01a4933bea847d Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Mon Nov 29 23:01:23 2021 +0100 Subsampling computed by `GridDerivation.subgrid(GridGeometry)` must be integer (it was not when the given grid geometry has only a "grid to CRS" transform). Better determination of which grid between source and target must have a CRS. --- .../coverage/grid/CoordinateOperationFinder.java | 65 ++++++++++------------ .../apache/sis/coverage/grid/GridDerivation.java | 22 ++++---- .../org/apache/sis/coverage/grid/GridGeometry.java | 1 + .../sis/coverage/grid/ResampledGridCoverage.java | 1 + 4 files changed, 43 insertions(+), 46 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 1608b6c..df88dbb 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 @@ -17,6 +17,7 @@ package org.apache.sis.coverage.grid; import java.util.Arrays; +import java.util.Objects; import java.util.function.Supplier; import javax.measure.Quantity; import javax.measure.quantity.Length; @@ -74,7 +75,7 @@ import org.apache.sis.internal.util.Numerics; * * @author Alexis Manin (Geomatys) * @author Martin Desruisseaux (Geomatys) - * @version 1.1 + * @version 1.2 * @since 1.1 * @module */ @@ -234,6 +235,18 @@ final class CoordinateOperationFinder implements Supplier<double[]> { } /** + * Verifies whether the presence of a CRS considered mandatory, unless the CRS of opposite grid + * is also missing. + * + * @param rs {@code true} is source CRS is mandatory, {@code false} if target CRS is mandatory. + */ + final void verifyPresenceOfCRS(final boolean rs) { + if ((rs ? target : source).isDefined(GridGeometry.CRS)) { + Objects.requireNonNull((rs ? source : target).getCoordinateReferenceSystem()); + } + } + + /** * Sets whether operations will be between cell centers or cell corners. * This method must be invoked before any other method in this class. * The {@link PixelInCell#CELL_CORNER} value should be used first @@ -277,28 +290,12 @@ final class CoordinateOperationFinder implements Supplier<double[]> { } /** - * Returns the CRS of the source grid geometry. If neither the source and target grid geometry - * define a CRS, then this method returns {@code null}. - * - * @throws IncompleteGridGeometryException if the target grid geometry has a CRS but the source - * grid geometry has none. Note that the converse is allowed, in which case the target - * CRS is assumed the same than the source. - */ - private CoordinateReferenceSystem getSourceCRS() { - return source.isDefined(GridGeometry.CRS) || - target.isDefined(GridGeometry.CRS) ? source.getCoordinateReferenceSystem() : null; - } - - /** * Returns the target of the "corner to CRS" transform. * May be {@code null} if the neither the source and target grid geometry define a CRS. - * - * @throws IncompleteGridGeometryException if the target grid geometry has a CRS but the source - * grid geometry has none. Note that the converse is allowed, in which case the target - * CRS is assumed the same than the source. */ final CoordinateReferenceSystem getTargetCRS() { - return (changeOfCRS != null) ? changeOfCRS.getTargetCRS() : getSourceCRS(); + return (changeOfCRS != null) ? changeOfCRS.getTargetCRS() : + source.isDefined(GridGeometry.CRS) ? source.getCoordinateReferenceSystem() : null; } /** @@ -322,23 +319,21 @@ final class CoordinateOperationFinder implements Supplier<double[]> { if (sourceEnvelope != null && targetEnvelope != null) { changeOfCRS = Envelopes.findOperation(sourceEnvelope, targetEnvelope); } - if (changeOfCRS == null && target.isDefined(GridGeometry.CRS)) { - final CoordinateReferenceSystem sourceCRS = getSourceCRS(); - if (sourceCRS != null) { - /* - * Unconditionally create operation even if CRS are the same. A non-null operation trig - * the check for wraparound axes, which is necessary even if the transform is identity. - */ - DefaultGeographicBoundingBox areaOfInterest = null; - if (sourceEnvelope != null || targetEnvelope != null) try { - areaOfInterest = new DefaultGeographicBoundingBox(); - areaOfInterest.setBounds(targetEnvelope != null ? targetEnvelope : sourceEnvelope); - } catch (TransformException e) { - areaOfInterest = null; - recoverableException("changeOfCRS", e); - } - changeOfCRS = CRS.findOperation(sourceCRS, target.getCoordinateReferenceSystem(), areaOfInterest); + if (changeOfCRS == null && source.isDefined(GridGeometry.CRS) && target.isDefined(GridGeometry.CRS)) { + final CoordinateReferenceSystem sourceCRS = source.getCoordinateReferenceSystem(); + /* + * Unconditionally create operation even if CRS are the same. A non-null operation trig + * the check for wraparound axes, which is necessary even if the transform is identity. + */ + DefaultGeographicBoundingBox areaOfInterest = null; + if (sourceEnvelope != null || targetEnvelope != null) try { + areaOfInterest = new DefaultGeographicBoundingBox(); + areaOfInterest.setBounds(targetEnvelope != null ? targetEnvelope : sourceEnvelope); + } catch (TransformException e) { + areaOfInterest = null; + recoverableException("changeOfCRS", e); } + changeOfCRS = CRS.findOperation(sourceCRS, target.getCoordinateReferenceSystem(), areaOfInterest); } } catch (BackingStoreException e) { // May be thrown by getConstantCoordinates(). throw e.unwrapOrRethrow(TransformException.class); 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 9041ca6..0822d14 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 @@ -500,25 +500,25 @@ public class GridDerivation { if (base.equals(areaOfInterest)) { return this; } - if (areaOfInterest.extent == null && areaOfInterest.resolution != null) { - return subgrid(areaOfInterest.envelope, areaOfInterest.resolution); - } final MathTransform mapCenters; - final GridExtent domain = areaOfInterest.getExtent(); // May throw IncompleteGridGeometryException. + final GridExtent domain = areaOfInterest.extent; + final CoordinateOperationFinder finder = new CoordinateOperationFinder(areaOfInterest, base); + finder.verifyPresenceOfCRS(false); try { - final CoordinateOperationFinder finder = new CoordinateOperationFinder(areaOfInterest, base); - final MathTransform mapCorners = finder.gridToGrid(); + final MathTransform mapCorners = (domain != null) ? finder.gridToGrid() : null; finder.setAnchor(PixelInCell.CELL_CENTER); finder.nowraparound(); mapCenters = finder.gridToGrid(); // We will use only the scale factors. - setBaseExtentClipped(domain.toCRS(mapCorners, mapCenters, null)); + if (domain != null) { + setBaseExtentClipped(domain.toCRS(mapCorners, mapCenters, null)); + if (baseExtent != base.extent && baseExtent.equals(domain)) { + baseExtent = domain; // Share common instance. + } + } subGridSetter = "subgrid"; } catch (FactoryException | TransformException e) { throw new IllegalGridGeometryException(e, "areaOfInterest"); } - if (baseExtent != base.extent && baseExtent.equals(areaOfInterest.extent)) { - baseExtent = areaOfInterest.extent; // Share common instance. - } // The `domain` extent must be the source of the `mapCenters` transform. scales = GridGeometry.resolution(mapCenters, domain); } @@ -540,7 +540,7 @@ public class GridDerivation { } /** - * Requests a grid geometry over a sub-envelope and optionally with a different a coarser resolution. + * Requests a grid geometry over a sub-envelope and optionally with a coarser resolution. * The given envelope does not need to be expressed in the same coordinate reference system (CRS) * than {@linkplain GridGeometry#getCoordinateReferenceSystem() the CRS of the base grid geometry}; * coordinate conversions or transformations will be applied as needed. 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 720fd8d..25eddfd 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 @@ -1365,6 +1365,7 @@ public class GridGeometry implements LenientComparable, Serializable { * effort for using `WraparoundTransform` only if needed (contrarily to `gridToCRS(…)`). */ final CoordinateOperationFinder finder = new CoordinateOperationFinder(target, this); + finder.verifyPresenceOfCRS(false); finder.setAnchor(anchor); final MathTransform tr; try { 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 dc01606..758678b 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 @@ -282,6 +282,7 @@ final class ResampledGridCoverage extends GridCoverage { { final GridGeometry sourceGG = source.getGridGeometry(); final CoordinateOperationFinder changeOfCRS = new CoordinateOperationFinder(sourceGG, target); + changeOfCRS.verifyPresenceOfCRS(true); /* * Compute the transform from source pixels to target CRS (to be completed to target pixels later). * The following lines may throw IncompleteGridGeometryException, which is desired because if that