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());
+    }
 }

Reply via email to