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 5617967a85673b3e5b77986a3163d2e4d93788f8 Author: Alexis Manin <[email protected]> AuthorDate: Wed Apr 3 19:49:06 2019 +0200 fix(raster): Ensure wrap-around trick is applied on grid geometry slicing. --- .../apache/sis/coverage/grid/GridDerivation.java | 47 +++++++++++++++------- .../internal/referencing/WraparoundAdjustment.java | 6 ++- 2 files changed, 36 insertions(+), 17 deletions(-) diff --git a/core/sis-raster/src/main/java/org/apache/sis/coverage/grid/GridDerivation.java b/core/sis-raster/src/main/java/org/apache/sis/coverage/grid/GridDerivation.java index f43c008..a0172e5 100644 --- a/core/sis-raster/src/main/java/org/apache/sis/coverage/grid/GridDerivation.java +++ b/core/sis-raster/src/main/java/org/apache/sis/coverage/grid/GridDerivation.java @@ -504,9 +504,9 @@ public class GridDerivation { dimension = baseExtent.getDimension(); // Non-null since 'base.requireGridToCRS()' succeed. GeneralEnvelope indices = null; if (areaOfInterest != null) { - final WraparoundAdjustment adj = new WraparoundAdjustment(areaOfInterest); - adj.shiftInto(base.envelope, (baseToAOI != null) ? baseToAOI.getMathTransform() : null); - indices = adj.result(cornerToCRS.inverse()); + indices = new WraparoundAdjustment(areaOfInterest) + .shiftInto(base.envelope, (baseToAOI != null) ? baseToAOI.getMathTransform() : null) + .result(cornerToCRS.inverse()); clipExtent(indices); } if (indices == null || indices.getDimension() != dimension) { @@ -723,9 +723,13 @@ public class GridDerivation { * For dimensionality reduction, see {@link GridGeometry#reduce(int...)}.</li> * </ul> * - * @param slicePoint the coordinates where to get a slice. + * @param slicePoint the coordinates where to get a slice. If no coordinate reference system is attached to it, + * we consider it's the same as base grid geometry. * @return {@code this} for method call chaining. - * @throws IncompleteGridGeometryException if the base grid geometry has no extent or no "grid to CRS" transform. + * @throws IncompleteGridGeometryException if the base grid geometry has no extent, no "grid to CRS" transform, or + * if its coordinate reference system is unknown while input point one is (in which case we're unable to find a + * transform between base CRS and input point CRS). Note that if you're sure that your point is expressed in base + * CRS, you can give a point without any CRS, to avoid this check. * @throws IllegalGridGeometryException if an error occurred while converting the point coordinates to grid coordinates. * @throws PointOutsideCoverageException if the given point is outside the grid extent. */ @@ -737,23 +741,36 @@ public class GridDerivation { if (toBase != null) { gridToCRS = MathTransforms.concatenate(toBase, gridToCRS); } - if (base.envelope != null) { - final CoordinateReferenceSystem sourceCRS = base.envelope.getCoordinateReferenceSystem(); - if (sourceCRS != null) { - final CoordinateReferenceSystem targetCRS = slicePoint.getCoordinateReferenceSystem(); - if (targetCRS != null) { - final CoordinateOperation operation = CRS.findOperation(sourceCRS, targetCRS, null); - gridToCRS = MathTransforms.concatenate(gridToCRS, operation.getMathTransform()); - } - } + + /* We'll try to find a link between base coordinate system and input point one. Note that we allow unknown + * CRS on slice point, in which case we consider it to be expressed in base geometry system. However, if the + * point CRS is known, but base geometry one is not, too much ambiguity resides, and we'll throw an error. + */ + final MathTransform baseToSlice; + final CoordinateReferenceSystem targetCRS = slicePoint.getCoordinateReferenceSystem(); + if (targetCRS != null) { + final CoordinateReferenceSystem sourceCRS = base.getCoordinateReferenceSystem(); + baseToSlice = CRS.findOperation(sourceCRS, targetCRS, null) + .getMathTransform(); + gridToCRS = MathTransforms.concatenate(gridToCRS, baseToSlice); + } else { + baseToSlice = null; } + final int dimension = gridToCRS.getTargetDimensions(); ArgumentChecks.ensureDimensionMatches("slicePoint", dimension, slicePoint); gridToCRS = dropUnusedDimensions(gridToCRS, dimension); - DirectPosition gridPoint = gridToCRS.inverse().transform(slicePoint, null); + + GeneralEnvelope sliceEnvelope = new GeneralEnvelope(slicePoint, slicePoint); + sliceEnvelope = new WraparoundAdjustment(sliceEnvelope) + .shiftInto(base.envelope, baseToSlice) + .result(gridToCRS.inverse()); + DirectPosition gridPoint = sliceEnvelope.getMedian(); if (scaledExtent != null) { scaledExtent = scaledExtent.slice(gridPoint, modifiedDimensions); } + + // Rebuild the extent without scaling if (toBase != null) { gridPoint = toBase.transform(gridPoint, gridPoint); } diff --git a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/WraparoundAdjustment.java b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/WraparoundAdjustment.java index 96568f2..fb66213 100644 --- a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/WraparoundAdjustment.java +++ b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/WraparoundAdjustment.java @@ -117,16 +117,17 @@ public final class WraparoundAdjustment { * @param validToAOI if the envelopes do not use the same CRS, the transformation from {@code domainOfValidity} * to {@code areaOfInterest}. Otherwise {@code null}. This method does not check by itself if * a coordinate operation is needed; it must be supplied. + * @return this object, allowing to chain {@link #result(MathTransform)} operation. * @throws TransformException if an envelope transformation was required but failed. * * @see GeneralEnvelope#simplify() */ - public void shiftInto(Envelope domainOfValidity, MathTransform validToAOI) throws TransformException { + public WraparoundAdjustment shiftInto(Envelope domainOfValidity, MathTransform validToAOI) throws TransformException { CoordinateReferenceSystem crs = areaOfInterest.getCoordinateReferenceSystem(); if (crs == null) { crs = domainOfValidity.getCoordinateReferenceSystem(); // Assumed to apply to AOI too. if (crs == null) { - return; + return this; } } /* @@ -301,6 +302,7 @@ public final class WraparoundAdjustment { } } } + return this; } /**
