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 f943c9d02e48ded272c2fa2e592b1f6d6eea7305 Author: Martin Desruisseaux <[email protected]> AuthorDate: Tue Mar 19 20:39:33 2019 +0100 Bug fix: when the 'areaOfInterest' has been converted to geographic coordinates, a conversion needs to be applied on 'domainOfValidity' too. --- .../apache/sis/coverage/grid/GridDerivation.java | 2 +- .../internal/referencing/WraparoundAdjustment.java | 42 ++++++++++++++-------- .../referencing/WraparoundAdjustmentTest.java | 33 +++++++++++++---- 3 files changed, 55 insertions(+), 22 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 67d5186..3633e3d 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 @@ -503,7 +503,7 @@ public class GridDerivation { GeneralEnvelope indices = null; if (areaOfInterest != null) { final WraparoundAdjustment adj = new WraparoundAdjustment(areaOfInterest); - adj.shiftInto(base.envelope, baseToAOI); + adj.shiftInto(base.envelope, (baseToAOI != null) ? baseToAOI.getMathTransform() : null); indices = adj.result(cornerToCRS.inverse()); clipExtent(indices); } 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 2641126..4e0d107 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 @@ -27,7 +27,6 @@ import org.opengis.referencing.cs.RangeMeaning; import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.referencing.crs.ProjectedCRS; import org.opengis.referencing.operation.MathTransform; -import org.opengis.referencing.operation.CoordinateOperation; import org.opengis.referencing.operation.TransformException; import org.apache.sis.referencing.operation.transform.MathTransforms; import org.apache.sis.internal.metadata.AxisDirections; @@ -122,7 +121,7 @@ public final class WraparoundAdjustment { * * @see GeneralEnvelope#simplify() */ - public void shiftInto(Envelope domainOfValidity, CoordinateOperation validToAOI) throws TransformException { + public void shiftInto(Envelope domainOfValidity, MathTransform validToAOI) throws TransformException { CoordinateReferenceSystem crs = areaOfInterest.getCoordinateReferenceSystem(); if (crs == null) { crs = domainOfValidity.getCoordinateReferenceSystem(); // Assumed to apply to AOI too. @@ -135,19 +134,29 @@ public final class WraparoundAdjustment { * We need to perform the verification in its base geographic CRS instead, and remember that we * may need to transform the result later. */ + final MathTransform projection; + final DirectPosition lowerCorner; + final DirectPosition upperCorner; GeneralEnvelope shifted = null; // To be initialized to a copy of 'areaOfInterest' when first needed. if (crs instanceof ProjectedCRS) { final ProjectedCRS p = (ProjectedCRS) crs; crs = p.getBaseCRS(); - geographicToAOI = p.getConversionFromBase().getMathTransform(); - areaOfInterest = shifted = Envelopes.transform(geographicToAOI.inverse(), areaOfInterest); + projection = p.getConversionFromBase().getMathTransform(); + shifted = Envelopes.transform(projection.inverse(), areaOfInterest); + lowerCorner = shifted.getLowerCorner(); + upperCorner = shifted.getUpperCorner(); + if (validToAOI == null) { + validToAOI = MathTransforms.identity(projection.getTargetDimensions()); + } + } else { + projection = null; + lowerCorner = areaOfInterest.getLowerCorner(); + upperCorner = areaOfInterest.getUpperCorner(); } /* - * We will not reference 'areaOfInterest' anymore after we got its two corner points. + * We will not read 'areaOfInterest' anymore after we got its two corner points. * The following loop search for "wraparound" axis. */ - final DirectPosition lowerCorner = areaOfInterest.getLowerCorner(); - final DirectPosition upperCorner = areaOfInterest.getUpperCorner(); final CoordinateSystem cs = crs.getCoordinateSystem(); for (int i=cs.getDimension(); --i >= 0;) { final double period = range(cs, i); @@ -158,14 +167,13 @@ public final class WraparoundAdjustment { * Transform that envelope when first needed. */ if (validToAOI != null) { - MathTransform mt = validToAOI.getMathTransform(); - if (geographicToAOI != null) { - mt = MathTransforms.concatenate(mt, geographicToAOI.inverse()); + if (projection != null) { + validToAOI = MathTransforms.concatenate(validToAOI, projection.inverse()); } - validToAOI = null; - if (!mt.isIdentity()) { - domainOfValidity = Envelopes.transform(mt, domainOfValidity); + if (!validToAOI.isIdentity()) { + domainOfValidity = Envelopes.transform(validToAOI, domainOfValidity); } + validToAOI = null; } /* * "Unroll" the range. For example if we have [+160 … -170]° of longitude, we can replace by [160 … 190]°. @@ -268,12 +276,16 @@ public final class WraparoundAdjustment { } } /* - * If there is change to apply, copy the envelope when first needed. + * If there is change to apply, copy the envelope when first needed and set the fields. + * If we never enter in this block, then 'areaOfInterest' will stay the envelope given + * at construction time. */ if (lowerCycles != 0 || upperCycles != 0) { if (shifted == null) { - areaOfInterest = shifted = new GeneralEnvelope(areaOfInterest); + shifted = new GeneralEnvelope(areaOfInterest); } + areaOfInterest = shifted; // 'shifted' may have been set before the loop. + geographicToAOI = projection; shifted.setRange(i, lower + lowerCycles * period, // TODO: use Math.fma in JDK9. upper + upperCycles * period); } diff --git a/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/WraparoundAdjustmentTest.java b/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/WraparoundAdjustmentTest.java index e6634ed..6feaf28 100644 --- a/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/WraparoundAdjustmentTest.java +++ b/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/WraparoundAdjustmentTest.java @@ -16,14 +16,16 @@ */ package org.apache.sis.internal.referencing; -import org.apache.sis.geometry.GeneralEnvelope; import org.opengis.geometry.Envelope; import org.opengis.referencing.cs.*; -import org.opengis.referencing.operation.CoordinateOperation; +import org.opengis.referencing.operation.MathTransform; import org.opengis.referencing.operation.TransformException; +import org.apache.sis.referencing.crs.DefaultProjectedCRS; import org.apache.sis.referencing.crs.HardCodedCRS; import org.apache.sis.referencing.cs.HardCodedCS; +import org.apache.sis.referencing.operation.HardCodedConversions; import org.apache.sis.referencing.operation.transform.MathTransforms; +import org.apache.sis.geometry.GeneralEnvelope; import org.apache.sis.test.DependsOnMethod; import org.apache.sis.test.TestCase; import org.junit.Test; @@ -53,7 +55,7 @@ public final strictfp class WraparoundAdjustmentTest extends TestCase { /** * Convenience method for the tests. */ - private static Envelope adjustWraparoundAxes(Envelope areaOfInterest, Envelope domainOfValidity, CoordinateOperation validToAOI) + private static Envelope adjustWraparoundAxes(Envelope areaOfInterest, Envelope domainOfValidity, MathTransform validToAOI) throws TransformException { WraparoundAdjustment adj = new WraparoundAdjustment(areaOfInterest); @@ -62,7 +64,7 @@ public final strictfp class WraparoundAdjustmentTest extends TestCase { } /** - * Tests {@link WraparoundAdjustment#shiftInto(Envelope, CoordinateOperation)} + * Tests {@link WraparoundAdjustment#shiftInto(Envelope, MathTransform)} * with an envelope crossing the anti-meridian. * * @throws TransformException should never happen since this test does not transform coordinates. @@ -86,7 +88,7 @@ public final strictfp class WraparoundAdjustmentTest extends TestCase { } /** - * Tests {@link WraparoundAdjustment#shiftInto(Envelope, CoordinateOperation)} + * Tests {@link WraparoundAdjustment#shiftInto(Envelope, MathTransform)} * with an envelope shifted by 360° before or after the grid valid area. * * @throws TransformException should never happen since this test does not transform coordinates. @@ -117,7 +119,7 @@ public final strictfp class WraparoundAdjustmentTest extends TestCase { } /** - * Tests {@link WraparoundAdjustment#shiftInto(Envelope, CoordinateOperation)} + * Tests {@link WraparoundAdjustment#shiftInto(Envelope, MathTransform)} * with an envelope that cause the method to expand the area of interest. Illustration: * * {@preformat text @@ -149,4 +151,23 @@ public final strictfp class WraparoundAdjustmentTest extends TestCase { final Envelope actual = adjustWraparoundAxes(areaOfInterest, domainOfValidity, null); assertEnvelopeEquals(expected, actual); } + + /** + * Tests {@link WraparoundAdjustment#shiftInto(Envelope, MathTransform)} with a projected envelope. + * + * @throws TransformException if an error occurred while projecting a coordinate. + */ + @Test + public void testWithProjection() throws TransformException { + final GeneralEnvelope domainOfValidity = new GeneralEnvelope(HardCodedCRS.WGS84); + domainOfValidity.setRange(0, 80, 100); + domainOfValidity.setRange(1, -70, +70); + + final DefaultProjectedCRS mercator = HardCodedConversions.mercator(); + final GeneralEnvelope areaOfInterest = new GeneralEnvelope(mercator); + areaOfInterest.setRange(0, 5000000, 7000000); // About 45°E to 63°E + areaOfInterest.setRange(1, -10000000, 10000000); // About 66.6°S to 66.6°N + + // TODO: complete test. + } }
