sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject [sis] branch geoapi-4.0 updated: Add a GridGeometry.slice(DirectPosition) method.
Date Wed, 02 Jan 2019 12:58:08 GMT
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 <martin.desruisseaux@geomatys.com>
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());
+    }
 }


Mime
View raw message