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 75167ab8a06956729f97436d81477bfbfa51042b Author: Martin Desruisseaux <[email protected]> AuthorDate: Wed Mar 17 15:02:32 2021 +0100 Omit extra dimensions such as time axis in `GridDerivation.substring(…)` if the base geometry does not have those dimensions. --- .../apache/sis/coverage/grid/DimensionReducer.java | 108 +++++++++++++++++++++ .../apache/sis/coverage/grid/GridDerivation.java | 4 +- .../sis/coverage/grid/GridDerivationTest.java | 26 +++++ 3 files changed, 137 insertions(+), 1 deletion(-) diff --git a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/DimensionReducer.java b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/DimensionReducer.java new file mode 100644 index 0000000..884380d --- /dev/null +++ b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/DimensionReducer.java @@ -0,0 +1,108 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.sis.coverage.grid; + +import java.util.Arrays; +import org.opengis.util.FactoryException; +import org.opengis.geometry.Envelope; +import org.opengis.geometry.DirectPosition; +import org.opengis.referencing.cs.CoordinateSystem; +import org.opengis.referencing.crs.CoordinateReferenceSystem; +import org.apache.sis.internal.referencing.AxisDirections; +import org.apache.sis.geometry.GeneralDirectPosition; +import org.apache.sis.geometry.GeneralEnvelope; +import org.apache.sis.referencing.CRS; + + +/** + * An helper class for reducing the number of dimensions in a grid geometry, an envelope or a position. + * This is used when the Area Of Interest has more dimensions than the grid geometry, in which case the + * transform from grid to AOI will fail if we do not discard the extra dimensions. + * + * @author Martin Desruisseaux (Geomatys) + * @version 1.1 + * @since 1.1 + * @module + */ +final class DimensionReducer { + /** + * The dimensions to keep, or {@code null} for keeping them all. + */ + private int[] dimensions; + + /** + * The CRS with only the {@linkplain #dimensions} to keep, or {@code null} if no reduction. + */ + private CoordinateReferenceSystem reducedCRS; + + /** + * Creates an helper which will retain only the {@code targetCRS} dimensions that are found the the base grid. + * This will be used by caller for creating a valid {@code sourceCRS} to {@code targetCRS} transform. + * + * @param base the grid geometry which will be derived. Can not be null. + * @param targetCRS CRS of the area or point of interest. Can not be null. + */ + DimensionReducer(final GridGeometry base, final CoordinateReferenceSystem targetCRS) throws FactoryException { + if (base != null && base.envelope != null) { + final CoordinateReferenceSystem sourceCRS = base.envelope.getCoordinateReferenceSystem(); + if (sourceCRS != null) { + final CoordinateSystem sourceCS = sourceCRS.getCoordinateSystem(); + final CoordinateSystem targetCS = targetCRS.getCoordinateSystem(); + if (sourceCS.getDimension() < targetCS.getDimension()) { + dimensions = AxisDirections.indicesOfColinear(targetCS, sourceCS); + if (dimensions != null) { + Arrays.sort(dimensions); + reducedCRS = CRS.reduce(targetCRS, dimensions); + } + } + } + } + } + + /** + * Applies reduction on the given position. + * If the position can not be reduced, then it is returned as-is. + */ + final DirectPosition apply(final DirectPosition target) { + if (dimensions == null) { + return target; + } + final GeneralDirectPosition position = new GeneralDirectPosition(reducedCRS); + for (int i=0; i < dimensions.length; i++) { + position.coordinates[i] = target.getOrdinate(dimensions[i]); + } + return position; + } + + /** + * Applies reduction on the given envelope. + * If the envelope can not be reduced, then it is returned as-is. + */ + final Envelope apply(final Envelope target) { + if (dimensions == null) { + return target; + } + final DirectPosition lowerCorner = target.getLowerCorner(); + final DirectPosition upperCorner = target.getUpperCorner(); + final GeneralEnvelope envelope = new GeneralEnvelope(reducedCRS); + for (int i=0; i < dimensions.length; i++) { + final int s = dimensions[i]; + envelope.setRange(i, lowerCorner.getOrdinate(s), upperCorner.getOrdinate(s)); + } + return envelope; + } +} 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 ea027ae..538f29e 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 @@ -509,6 +509,7 @@ public class GridDerivation { if (areaOfInterest != null) { final CoordinateReferenceSystem crs = areaOfInterest.getCoordinateReferenceSystem(); if (crs != null) { + areaOfInterest = new DimensionReducer(base, crs).apply(areaOfInterest); CoordinateOperation op = Envelopes.findOperation(base.envelope, areaOfInterest); if (op == null) { /* @@ -780,7 +781,7 @@ public class GridDerivation { * @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. */ - public GridDerivation slice(final DirectPosition slicePoint) { + public GridDerivation slice(DirectPosition slicePoint) { ArgumentChecks.ensureNonNull("slicePoint", slicePoint); MathTransform gridToCRS = base.requireGridToCRS(true); subGridSetter = "slice"; @@ -799,6 +800,7 @@ public class GridDerivation { if (sliceCRS == null) { baseToPOI = null; } else { + slicePoint = new DimensionReducer(base, sliceCRS).apply(slicePoint); final CoordinateReferenceSystem gridCRS = base.getCoordinateReferenceSystem(); // May throw exception. baseToPOI = CRS.findOperation(gridCRS, sliceCRS, null).getMathTransform(); gridToCRS = MathTransforms.concatenate(gridToCRS, baseToPOI); diff --git a/core/sis-feature/src/test/java/org/apache/sis/coverage/grid/GridDerivationTest.java b/core/sis-feature/src/test/java/org/apache/sis/coverage/grid/GridDerivationTest.java index b6e16bc..8b33e21 100644 --- a/core/sis-feature/src/test/java/org/apache/sis/coverage/grid/GridDerivationTest.java +++ b/core/sis-feature/src/test/java/org/apache/sis/coverage/grid/GridDerivationTest.java @@ -271,6 +271,32 @@ public final strictfp class GridDerivationTest extends TestCase { } /** + * Tests {@link GridDerivation#subgrid(Envelope, double...)} using an envelope with more dimensions + * than the source grid geometry. The additional dimensions should be ignored. + */ + @Test + @DependsOnMethod("testSubgridFromEnvelope") + public void testSubgridFromEnvelopeWithMoreDimensions() { + GeneralEnvelope envelope = new GeneralEnvelope(HardCodedCRS.WGS84); + envelope.setRange(0, -70, +80); + envelope.setRange(1, 5, 15); + GridGeometry grid = new GridGeometry(new GridExtent(300, 40), envelope, GridOrientation.HOMOTHETY); + /* + * Above grid has a resolution of 0.5° × 0.25° per pixel. Ask for a resolution of 2° × 1° × 3 meters + * per pixels. The resolution in meter should be ignored, together with the envelope vertical range. + */ + envelope = new GeneralEnvelope(HardCodedCRS.WGS84_WITH_TIME); + envelope.setRange(0, -40, +30); + envelope.setRange(1, 8, 18); + envelope.setRange(2, 20, 40); + grid = grid.derive().subgrid(envelope, 2, 1, 3).build(); + + assertExtentEquals(new long[] {15, 3}, new long[] {49, 9}, grid.getExtent()); + assertMatrixEquals("gridToCRS", new Matrix3(2, 0, -69, 0, 1, 5.5, 0, 0, 1), + MathTransforms.getMatrix(grid.getGridToCRS(PixelInCell.CELL_CENTER)), STRICT); + } + + /** * Tests {@link GridDerivation#slice(DirectPosition)}. */ @Test
