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 c41d719 Add a GridGeometry.slice(DirectPosition) method.
c41d719 is described below
commit c41d7191a5bb339a98ba526f636dafa6b5ae30a0
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Wed Jan 2 13:52:52 2019 +0100
Add a GridGeometry.slice(DirectPosition) method.
---
.../org/apache/sis/coverage/grid/GridExtent.java | 8 ++--
.../org/apache/sis/coverage/grid/GridGeometry.java | 45 +++++++++++++++++++---
.../sis/coverage/grid/SubgridCalculator.java | 2 +-
.../apache/sis/coverage/grid/GridExtentTest.java | 31 +++++++++++++++
.../apache/sis/coverage/grid/GridGeometryTest.java | 33 ++++++++++++++++
5 files changed, 108 insertions(+), 11 deletions(-)
diff --git
a/core/sis-raster/src/main/java/org/apache/sis/coverage/grid/GridExtent.java
b/core/sis-raster/src/main/java/org/apache/sis/coverage/grid/GridExtent.java
index 25fa0f2..49cc364 100644
--- a/core/sis-raster/src/main/java/org/apache/sis/coverage/grid/GridExtent.java
+++ b/core/sis-raster/src/main/java/org/apache/sis/coverage/grid/GridExtent.java
@@ -846,13 +846,11 @@ public class GridExtent implements Serializable {
slice.coordinates[i + m] = slice.coordinates[i] = c;
} else {
final StringBuilder b = new StringBuilder();
- String separator = "";
for (int j=0; j<n; j++) {
+ if (j != 0) b.append(", ");
p = slicePoint.getOrdinate(j);
- if (!Double.isNaN(p)) {
- b.append(separator).append(Math.round(p));
- separator = ", ";
- }
+ if (Double.isNaN(p)) b.append("NaN");
+ else b.append(Math.round(p));
}
throw new
PointOutsideCoverageException(Resources.format(Resources.Keys.GridCoordinateOutsideCoverage_4,
getAxisIdentification(i,k), low, high,
b.toString()));
diff --git
a/core/sis-raster/src/main/java/org/apache/sis/coverage/grid/GridGeometry.java
b/core/sis-raster/src/main/java/org/apache/sis/coverage/grid/GridGeometry.java
index a76ca6e..a376d04 100644
---
a/core/sis-raster/src/main/java/org/apache/sis/coverage/grid/GridGeometry.java
+++
b/core/sis-raster/src/main/java/org/apache/sis/coverage/grid/GridGeometry.java
@@ -25,6 +25,7 @@ import java.io.UncheckedIOException;
import java.awt.image.RenderedImage; // For javadoc only.
import org.opengis.metadata.Identifier;
import org.opengis.geometry.Envelope;
+import org.opengis.geometry.DirectPosition;
import org.opengis.geometry.MismatchedDimensionException;
import org.opengis.referencing.datum.PixelInCell;
import org.opengis.referencing.operation.Matrix;
@@ -56,6 +57,9 @@ import org.apache.sis.util.Classes;
import org.apache.sis.util.Debug;
import org.apache.sis.io.TableAppender;
+// Branch-dependent imports
+import org.opengis.coverage.PointOutsideCoverageException;
+
/**
* Valid extent of grid coordinates together with the transform from those
grid coordinates
@@ -223,7 +227,7 @@ public class GridGeometry implements Serializable {
*
* The new {@linkplain #getEnvelope() grid geometry envelope} will be
{@linkplain GeneralEnvelope#intersect(Envelope)
* clipped} to the envelope of the other grid geometry. This is for
preventing the envelope to become larger under the
- * effect of sub-sampling (because {@linkplain
GridExtent#subsample(int...) each cell become larger}).
+ * effect of sub-sampling (because {@link GridExtent#subsample(int[]) each
cell become larger}).
*
* @param other the other grid geometry to copy.
* @param extent the new extent for the grid geometry to construct, or
{@code null} if none.
@@ -898,10 +902,12 @@ public class GridGeometry implements Serializable {
/**
* Returns a grid geometry over a sub-region of this grid geometry and
optionally with sub-sampling.
- * The given envelope does not need to be expressed in the same coordinate
reference system
- * (CRS) than {@linkplain #getCoordinateReferenceSystem() the one of this
grid geometry};
+ * The given envelope does not need to be expressed in the same coordinate
reference system (CRS)
+ * than {@linkplain #getCoordinateReferenceSystem() the CRS of this grid
geometry};
* coordinate conversions or transformations will be applied as needed.
- * The target resolution, if provided, shall be in same units than the
given envelope with axes in the same order.
+ * That envelope CRS may have fewer dimensions than this grid geometry CRS,
+ * in which case grid dimensions not mapped to envelope dimensions will be
returned unchanged.
+ * The target resolution, if provided, shall be in same units and same
order than the given envelope axes.
* If the length of {@code targetResolution} array is less than the number
of dimensions of {@code areaOfInterest},
* then no sub-sampling will be applied on the missing dimensions.
*
@@ -914,7 +920,7 @@ public class GridGeometry implements Serializable {
* @throws TransformException if an error occurred while converting the
envelope coordinates to grid coordinates.
*
* @see #getExtent(Envelope)
- * @see GridExtent#subsample(int...)
+ * @see GridExtent#subsample(int[])
*/
public GridGeometry subgrid(final Envelope areaOfInterest, double...
targetResolution) throws TransformException {
if (extent == null) {
@@ -931,6 +937,35 @@ public class GridGeometry implements Serializable {
}
/**
+ * Returns a grid geometry for a slice at the given point.
+ * The given position can be expressed in any coordinate reference system
(CRS).
+ * The position should not define a coordinate for all dimensions,
otherwise the sub-grid would degenerate
+ * to a single point. Dimensions can be left unspecified either by
assigning to {@code slicePoint} a CRS
+ * without those dimensions, or by assigning the NaN value to some
coordinates.
+ *
+ * <div class="note"><b>Example:</b>
+ * if the {@linkplain #getCoordinateReferenceSystem() coordinate reference
system} of this grid geometry has
+ * (<var>longitude</var>, <var>latitude</var>, <var>time</var>) axes, then
a (<var>longitude</var>, <var>latitude</var>)
+ * slice at time <var>t</var> can be created with one of the following two
positions:
+ * <ul>
+ * <li>A three-dimensional position with ({@link Double#NaN}, {@link
Double#NaN}, <var>t</var>) coordinates.</li>
+ * <li>A one-dimensional position with (<var>t</var>) coordinate and the
coordinate reference system set to
+ * {@linkplain
org.apache.sis.referencing.CRS#getTemporalComponent(CoordinateReferenceSystem)
the temporal component}
+ * of the grid geometry CRS.</li>
+ * </ul></div>
+ *
+ * @param slicePoint the coordinates where to get a slice.
+ * @return a slice of this grid geometry at the given slice point. May be
{@code this}.
+ * @throws TransformException if an error occurred while converting the
point coordinates to grid coordinates.
+ * @throws PointOutsideCoverageException if the given point is outside the
grid extent.
+ */
+ public GridGeometry slice(final DirectPosition slicePoint) throws
TransformException {
+ ArgumentChecks.ensureNonNull("slicePoint", slicePoint);
+ final GridExtent slice = new SubgridCalculator(this, cornerToCRS,
slicePoint).extent;
+ return (slice != extent) ? new GridGeometry(this, slice, null) : this;
+ }
+
+ /**
* Returns a hash value for this grid geometry. This value need not remain
* consistent between different implementations of the same class.
*/
diff --git
a/core/sis-raster/src/main/java/org/apache/sis/coverage/grid/SubgridCalculator.java
b/core/sis-raster/src/main/java/org/apache/sis/coverage/grid/SubgridCalculator.java
index 302f4dc..8f307ae 100644
---
a/core/sis-raster/src/main/java/org/apache/sis/coverage/grid/SubgridCalculator.java
+++
b/core/sis-raster/src/main/java/org/apache/sis/coverage/grid/SubgridCalculator.java
@@ -100,7 +100,7 @@ final class SubgridCalculator {
} catch (FactoryException e) {
throw new
TransformException(Resources.format(Resources.Keys.CanNotMapToGridDimensions),
e);
}
- extent = grid.extent.slice(cornerToCRS.transform(slicePoint, null),
modifiedDimensions);
+ extent = grid.extent.slice(cornerToCRS.inverse().transform(slicePoint,
null), modifiedDimensions);
}
/**
diff --git
a/core/sis-raster/src/test/java/org/apache/sis/coverage/grid/GridExtentTest.java
b/core/sis-raster/src/test/java/org/apache/sis/coverage/grid/GridExtentTest.java
index 6588e80..b1ad427 100644
---
a/core/sis-raster/src/test/java/org/apache/sis/coverage/grid/GridExtentTest.java
+++
b/core/sis-raster/src/test/java/org/apache/sis/coverage/grid/GridExtentTest.java
@@ -17,9 +17,12 @@
package org.apache.sis.coverage.grid;
import java.util.Locale;
+import org.opengis.geometry.DirectPosition;
import org.opengis.metadata.spatial.DimensionNameType;
+import org.opengis.coverage.PointOutsideCoverageException;
import org.apache.sis.geometry.AbstractEnvelope;
import org.apache.sis.geometry.GeneralEnvelope;
+import org.apache.sis.geometry.GeneralDirectPosition;
import org.apache.sis.referencing.crs.HardCodedCRS;
import org.apache.sis.util.resources.Vocabulary;
import org.apache.sis.test.TestCase;
@@ -133,6 +136,34 @@ public final strictfp class GridExtentTest extends
TestCase {
}
/**
+ * Tests {@link GridExtent#slice(DirectPosition, int[])}.
+ */
+ @Test
+ public void testSlice() {
+ final GeneralDirectPosition slicePoint = new
GeneralDirectPosition(226.7, 47.2);
+ final GridExtent extent = create3D();
+ final GridExtent slice = extent.slice(slicePoint, new int[] {1, 2});
+ assertEquals("dimension", 3, slice.getDimension());
+ assertExtentEquals(slice, 0, 100, 499);
+ assertExtentEquals(slice, 1, 227, 227);
+ assertExtentEquals(slice, 2, 47, 47);
+ /*
+ * Verify that point outside the GridExtent causes an exception to be
thrown.
+ * The message is localized but the grid coordinates "(900, 47)" are
currently
+ * unlocalized, so the check below should work in any locale (note
that it may
+ * change in future SIS version).
+ */
+ slicePoint.setOrdinate(0, 900);
+ try {
+ extent.slice(slicePoint, new int[] {1, 2});
+ fail("Expected PointOutsideCoverageException");
+ } catch (PointOutsideCoverageException e) {
+ final String message = e.getLocalizedMessage();
+ assertTrue(message, message.contains("(900, 47)")); // See
above comment.
+ }
+ }
+
+ /**
* Tests {@link GridExtent#toString()}.
* Note that the string representation may change in any future SIS
version.
*/
diff --git
a/core/sis-raster/src/test/java/org/apache/sis/coverage/grid/GridGeometryTest.java
b/core/sis-raster/src/test/java/org/apache/sis/coverage/grid/GridGeometryTest.java
index fd592b6..3c503bc 100644
---
a/core/sis-raster/src/test/java/org/apache/sis/coverage/grid/GridGeometryTest.java
+++
b/core/sis-raster/src/test/java/org/apache/sis/coverage/grid/GridGeometryTest.java
@@ -26,6 +26,7 @@ import org.apache.sis.referencing.operation.matrix.Matrices;
import org.apache.sis.referencing.operation.transform.MathTransforms;
import org.apache.sis.referencing.crs.HardCodedCRS;
import org.apache.sis.geometry.DirectPosition2D;
+import org.apache.sis.geometry.GeneralDirectPosition;
import org.apache.sis.geometry.GeneralEnvelope;
import org.apache.sis.test.DependsOnMethod;
import org.apache.sis.test.DependsOn;
@@ -368,4 +369,36 @@ public final strictfp class GridGeometryTest extends
TestCase {
src.x = 94; src.y = 13; exp.x = -50; exp.y = 8; assertEquals("Lower
corner", exp, cornerToCRS.transform(src, tgt));
src.x = 96; src.y = 40; exp.x = +31; exp.y = 12; assertEquals("Upper
corner", exp, cornerToCRS.transform(src, tgt));
}
+
+ /**
+ * Tests {@link GridGeometry#slice(DirectPosition)}.
+ *
+ * @throws TransformException if an error occurred during computation.
+ */
+ @Test
+ public void testSlice() throws TransformException {
+ final GridGeometry grid = new GridGeometry(
+ new GridExtent(null, new long[] {336, 20, 4}, new long[] {401,
419, 10}, true),
+ PixelInCell.CELL_CORNER, MathTransforms.linear(new Matrix4(
+ 0, 0.5, 0, -90,
+ 0.5, 0, 0, -180,
+ 0, 0, 2, 3,
+ 0, 0, 0, 1)), HardCodedCRS.WGS84_3D);
+ GridGeometry slice = grid.slice(new GeneralDirectPosition(Double.NaN,
Double.NaN, 15));
+ assertNotSame(grid, slice);
+ assertSame("gridToCRS", grid.gridToCRS, slice.gridToCRS);
+ final long[] expectedLow = {336, 20, 6};
+ final long[] expectedHigh = {401, 419, 6};
+ assertExtentEquals(expectedLow, expectedHigh, slice.getExtent());
+ /*
+ * Same test, but using a one-dimensional slice point instead than NaN
values.
+ * Opportunistically use different units for testing conversions.
+ */
+ GeneralDirectPosition p = new
GeneralDirectPosition(HardCodedCRS.ELLIPSOIDAL_HEIGHT_cm);
+ p.setOrdinate(0, 1500);
+ slice = grid.slice(p);
+ assertNotSame(grid, slice);
+ assertSame("gridToCRS", grid.gridToCRS, slice.gridToCRS);
+ assertExtentEquals(expectedLow, expectedHigh, slice.getExtent());
+ }
}