sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject [sis] 17/35: Add tests for GridGeometry.
Date Wed, 20 Jun 2018 13:48:12 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

commit 308e8b44febb15c18b462b9dac1845142cbf2731
Author: Martin Desruisseaux <desruisseaux@apache.org>
AuthorDate: Thu May 31 14:04:57 2018 +0000

    Add tests for GridGeometry.
    
    
    git-svn-id: https://svn.apache.org/repos/asf/sis/branches/JDK8@1832616 13f79535-47bb-0310-9956-ffa450edef68
---
 core/sis-raster/pom.xml                            |  14 ++
 .../org/apache/sis/coverage/grid/GridGeometry.java |  38 +++--
 .../apache/sis/coverage/grid/GridGeometryTest.java | 165 +++++++++++++++++++++
 .../org/apache/sis/test/suite/RasterTestSuite.java |   3 +-
 4 files changed, 204 insertions(+), 16 deletions(-)

diff --git a/core/sis-raster/pom.xml b/core/sis-raster/pom.xml
index 124ecb8..c336974 100644
--- a/core/sis-raster/pom.xml
+++ b/core/sis-raster/pom.xml
@@ -113,6 +113,20 @@
       <type>test-jar</type>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.apache.sis.core</groupId>
+      <artifactId>sis-metadata</artifactId>
+      <version>${project.version}</version>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.sis.core</groupId>
+      <artifactId>sis-referencing</artifactId>
+      <version>${project.version}</version>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
 </project>
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 246a71c..6bf983d 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
@@ -19,6 +19,7 @@ package org.apache.sis.coverage.grid;
 import java.util.Objects;
 import java.io.Serializable;
 import java.awt.image.RenderedImage;            // For javadoc only.
+import org.opengis.geometry.Envelope;
 import org.opengis.geometry.MismatchedDimensionException;
 import org.opengis.referencing.datum.PixelInCell;
 import org.opengis.referencing.operation.Matrix;
@@ -54,12 +55,12 @@ import org.opengis.coverage.grid.GridEnvelope;
  *       This CRS is the target of the <cite>grid to CRS</cite> transform.</li>
  *   <li>An <em>estimation</em> of {@linkplain #resolution(boolean) grid
resolution} along each CRS axes,
  *       computed from the <cite>grid to CRS</cite> transform and eventually
from the grid extent.</li>
- *   <li>An {@linkplain #isConversionLinear indication of whether conversion for an
axis is linear or not}.</li>
+ *   <li>An {@linkplain #isConversionLinear indication of whether conversion for some
axes is linear or not}.</li>
  * </ul>
  *
- * All above properties except the CRS should be mandatory, but are allowed to be temporarily
absent during
- * grid coverage construction. Temporarily absent properties are allowed because they may
be inferred from
- * a wider context. For example a grid geometry know nothing about {@link RenderedImage},
+ * The first three properties should be mandatory, but are allowed to be temporarily absent
during
+ * grid coverage construction. Temporarily absent properties are allowed because they may
be inferred
+ * from a wider context. For example a grid geometry know nothing about {@link RenderedImage},
  * but {@code GridCoverage2D} does and may use that information for providing a missing grid
envelope.
  * By default, any request for an undefined property will throw an {@link IncompleteGridGeometryException}.
  * In order to check if a property is defined, use {@link #isDefined(int)}.
@@ -344,7 +345,7 @@ public class GridGeometry implements Serializable {
      * @throws IncompleteGridGeometryException if this grid geometry has no envelope —
      *         i.e. <code>{@linkplain #isDefined(int) isDefined}({@linkplain #ENVELOPE})</code>
returned {@code false}.
      */
-    public ImmutableEnvelope getEnvelope() throws IncompleteGridGeometryException {
+    public Envelope getEnvelope() throws IncompleteGridGeometryException {
         if (envelope != null && !envelope.isAllNaN()) {
             return envelope;
         }
@@ -356,7 +357,7 @@ public class GridGeometry implements Serializable {
      * for {@link java.awt.image.BufferedImage}, but may be non-zero for arbitrary {@link
RenderedImage}.
      * A grid with 512 cells can have a minimum coordinate of 0 and maximum of 511.
      *
-     * @return the grid envelope (never {@code null}).
+     * @return the valid extent of grid coordinates (never {@code null}).
      * @throws IncompleteGridGeometryException if this grid geometry has no extent —
      *         i.e. <code>{@linkplain #isDefined(int) isDefined}({@linkplain #EXTENT})</code>
returned {@code false}.
      */
@@ -395,7 +396,7 @@ public class GridGeometry implements Serializable {
      * </ul>
      *
      * @param  anchor  the pixel part to map.
-     * @return the transform (never {@code null}).
+     * @return the conversion from grid coordinates to "real world" coordinates (never {@code
null}).
      * @throws IllegalArgumentException if the given {@code anchor} is not a known code list
value.
      * @throws IncompleteGridGeometryException if this grid geometry has no transform —
      *         i.e. <code>{@linkplain #isDefined(int) isDefined}({@linkplain #GRID_TO_CRS})</code>
returned {@code false}.
@@ -418,10 +419,10 @@ public class GridGeometry implements Serializable {
     /**
      * Indicates whether the <cite>grid to CRS</cite> conversion is linear for
all the specified CRS axes.
      * The conversion from grid coordinates to real world coordinates is often linear for
some dimensions,
-     * typically the horizontal ones at indices 0 and 1. But the vertical dimension (usually
at index 3)
+     * typically the horizontal ones at indices 0 and 1. But the vertical dimension (usually
at index 2)
      * is often non-linear, for example with data at 0, 5, 10, 100 and 1000 metres.
      *
-     * @param  targets  indices of the CRS axes. This is not necessarily the same than indices
of grid axes.
+     * @param  targets  indices of CRS axes. This is not necessarily the same than indices
of grid axes.
      * @return {@code true} if the conversion from grid coordinates to "real world" coordinates
is linear
      *         for all the given CRS dimension.
      */
@@ -437,12 +438,13 @@ public class GridGeometry implements Serializable {
 
     /**
      * Returns an <em>estimation</em> of the grid resolution, in units of the
coordinate reference system axes.
-     * If non-null, the length of the returned array is the number of CRS dimensions, with
{@code resolution[0]}
+     * The length of the returned array is the number of CRS dimensions, with {@code resolution[0]}
      * being the resolution along the first CRS axis, {@code resolution[1]} the resolution
along the second CRS
      * axis, <i>etc</i>. Note that this axis order is not necessarily the same
than grid axis order.
      *
-     * <p>If some resolutions are not constant factors (i.e. the {@code gridToCRS}
transform for the corresponding
-     * dimension is non-linear), then the resolution is set to one of the following values:</p>
+     * <p>If the resolution at CRS dimension <var>i</var> is not a constant
factor
+     * (i.e. the <code>{@linkplain #isConversionLinear(int...) isConversionLinear}(i)</code>
returns {@code false}),
+     * then {@code resolution[i]} is set to one of the following values:</p>
      *
      * <ul>
      *   <li>{@link Double#NaN} if {@code allowEstimates} is {@code false}.</li>
@@ -455,7 +457,7 @@ public class GridGeometry implements Serializable {
      * The resolution is computed and may be representative of only a part of the grid.</div>
      *
      * @param  allowEstimates  whether to provide some values even for resolutions that are
not constant factors.
-     * @return an <em>estimation</em> of the grid resolution.
+     * @return an <em>estimation</em> of the grid resolution (never {@code null}).
      * @throws IncompleteGridGeometryException if this grid geometry has no resolution —
      *         i.e. <code>{@linkplain #isDefined(int) isDefined}({@linkplain #RESOLUTION})</code>
returned {@code false}.
      */
@@ -503,6 +505,9 @@ public class GridGeometry implements Serializable {
      * <p>We keep trace of non-linear dimensions in a bitmask, with bits of non-linear
dimensions set to 1.
      * This limit us to 64 dimensions, which is assumed more than enough. Note that {@code
GridGeometry} can
      * contain more dimensions provided that index of the last non-linear dimension is not
greater than 64.</p>
+     *
+     * @param  gridToCRS  the transform to "real world" coordinates, or {@code null} if unknown.
+     * @return a bitmask of dimensions, or 0 (i.e. conversion assumed fully linear) if the
given transform was null.
      */
     private static long findNonLinearTargets(final MathTransform gridToCRS) {
         long nonLinearDimensions = 0;
@@ -611,14 +616,17 @@ public class GridGeometry implements Serializable {
 
     /**
      * Returns {@code true} if all the parameters specified by the argument are set.
+     * If this method returns {@code true}, then invoking the corresponding getter
+     * methods will not throw {@link IncompleteGridGeometryException}.
      *
-     * @param  bitmask any combination of {@link #CRS}, {@link #ENVELOPE}, {@link #EXTENT}
and {@link #GRID_TO_CRS}.
+     * @param  bitmask  any combination of {@link #CRS}, {@link #ENVELOPE}, {@link #EXTENT},
+     *         {@link #GRID_TO_CRS} and {@link #RESOLUTION}.
      * @return {@code true} if all specified attributes are defined (i.e. invoking the
      *         corresponding method will not thrown an {@link IncompleteGridGeometryException}).
      * @throws IllegalArgumentException if the specified bitmask is not a combination of
known masks.
      */
     public boolean isDefined(final int bitmask) throws IllegalArgumentException {
-        if ((bitmask & ~(CRS | ENVELOPE | EXTENT | GRID_TO_CRS)) != 0) {
+        if ((bitmask & ~(CRS | ENVELOPE | EXTENT | GRID_TO_CRS | RESOLUTION)) != 0) {
             throw new IllegalArgumentException(Errors.format(
                     Errors.Keys.IllegalArgumentValue_2, "bitmask", bitmask));
         }
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
new file mode 100644
index 0000000..35787c6
--- /dev/null
+++ b/core/sis-raster/src/test/java/org/apache/sis/coverage/grid/GridGeometryTest.java
@@ -0,0 +1,165 @@
+/*
+ * 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 org.opengis.referencing.datum.PixelInCell;
+import org.opengis.referencing.operation.MathTransform;
+import org.opengis.referencing.operation.TransformException;
+import org.apache.sis.referencing.operation.matrix.Matrix4;
+import org.apache.sis.referencing.operation.matrix.Matrices;
+import org.apache.sis.referencing.operation.transform.MathTransforms;
+import org.apache.sis.geometry.GeneralEnvelope;
+import org.apache.sis.test.TestCase;
+import org.junit.Test;
+
+import static org.apache.sis.test.ReferencingAssert.*;
+
+// Branch-dependent imports
+import org.opengis.coverage.grid.GridEnvelope;
+
+
+/**
+ * Tests the {@link GridGeometry} implementation.
+ *
+ * @author  Martin Desruisseaux (IRD, Geomatys)
+ * @version 1.0
+ * @since   1.0
+ * @module
+ */
+public final strictfp class GridGeometryTest extends TestCase {
+    /**
+     * Verifies grid extent coordinates.
+     */
+    private static void assertExtentEquals(final GridEnvelope extent, final int[] low, final
int[] high) {
+        assertArrayEquals("extent.low",  low,  extent.getLow() .getCoordinateValues());
+        assertArrayEquals("extent.high", high, extent.getHigh().getCoordinateValues());
+    }
+
+    /**
+     * Tests construction with an identity transform mapping pixel corner.
+     *
+     * @throws TransformException if an error occurred while using the "grid to CRS" transform.
+     */
+    @Test
+    public void testSimple() throws TransformException {
+        final int[]         low      = new int[] {100, 300, 3, 6};
+        final int[]         high     = new int[] {200, 400, 4, 7};
+        final GridExtent    extent   = new GridExtent(low, high, true);
+        final MathTransform identity = MathTransforms.identity(4);
+        final GridGeometry  grid     = new GridGeometry(extent, PixelInCell.CELL_CORNER,
identity, null);
+        /*
+         * Verify properties that should be stored "as-is".
+         */
+        final MathTransform trCorner = grid.getGridToCRS(PixelInCell.CELL_CORNER);
+        assertSame("gridToCRS", identity, trCorner);
+        assertExtentEquals(grid.getExtent(), low, high);
+        /*
+         * Verify computed math transform.
+         */
+        final MathTransform trCenter = grid.getGridToCRS(PixelInCell.CELL_CENTER);
+        assertNotSame(trCenter, trCorner);
+        assertFalse ("gridToCRS.isIdentity",          trCenter.isIdentity());
+        assertEquals("gridToCRS.sourceDimensions", 4, trCenter.getSourceDimensions());
+        assertEquals("gridToCRS.targetDimensions", 4, trCenter.getTargetDimensions());
+        assertMatrixEquals("gridToCRS", Matrices.create(5, 5, new double[] {
+                1, 0, 0, 0, 0.5,
+                0, 1, 0, 0, 0.5,
+                0, 0, 1, 0, 0.5,
+                0, 0, 0, 1, 0.5,
+                0, 0, 0, 0, 1}), MathTransforms.getMatrix(trCenter), STRICT);
+        /*
+         * Verify the envelope, which should have been computed using the given math transform
as-is.
+         */
+        assertEnvelopeEquals(new GeneralEnvelope(
+                new double[] {100, 300, 3, 6},
+                new double[] {201, 401, 5, 8}), grid.getEnvelope(), STRICT);
+        /*
+         * Verify other computed properties.
+         */
+        assertArrayEquals("resolution", new double[] {1, 1, 1, 1}, grid.resolution(false),
STRICT);
+        assertTrue("isConversionLinear", grid.isConversionLinear(0, 1, 2, 3));
+    }
+
+    /**
+     * Tests construction with an identity transform mapping pixel center.
+     * This results a 0.5 pixel shifts in the "real world" envelope.
+     *
+     * @throws TransformException if an error occurred while using the "grid to CRS" transform.
+     */
+    @Test
+    public void testShifted() throws TransformException {
+        final int[]         low      = new int[] { 0,   0, 2};
+        final int[]         high     = new int[] {99, 199, 4};
+        final GridExtent    extent   = new GridExtent(low, high, true);
+        final MathTransform identity = MathTransforms.identity(3);
+        final GridGeometry  grid     = new GridGeometry(extent, PixelInCell.CELL_CENTER,
identity, null);
+        /*
+         * Verify properties that should be stored "as-is".
+         */
+        final MathTransform trCenter = grid.getGridToCRS(PixelInCell.CELL_CENTER);
+        assertSame("gridToCRS", identity, trCenter);
+        assertExtentEquals(grid.getExtent(), low, high);
+        /*
+         * Verify computed math transform.
+         */
+        final MathTransform trCorner = grid.getGridToCRS(PixelInCell.CELL_CORNER);
+        assertNotSame(trCenter, trCorner);
+        assertFalse ("gridToCRS.isIdentity",          trCorner.isIdentity());
+        assertEquals("gridToCRS.sourceDimensions", 3, trCorner.getSourceDimensions());
+        assertEquals("gridToCRS.targetDimensions", 3, trCorner.getTargetDimensions());
+        assertMatrixEquals("gridToCRS", new Matrix4(
+                1, 0, 0, -0.5,
+                0, 1, 0, -0.5,
+                0, 0, 1, -0.5,
+                0, 0, 0,  1), MathTransforms.getMatrix(trCorner), STRICT);
+        /*
+         * Verify the envelope, which should have been computed using the math transform
shifted by 0.5.
+         */
+        assertEnvelopeEquals(new GeneralEnvelope(
+                new double[] {-0.5,  -0.5, 1.5},
+                new double[] {99.5, 199.5, 4.5}), grid.getEnvelope(), STRICT);
+        /*
+         * Verify other computed properties.
+         */
+        assertArrayEquals("resolution", new double[] {1, 1, 1}, grid.resolution(false), STRICT);
+        assertTrue("isConversionLinear", grid.isConversionLinear(0, 1, 2));
+    }
+
+    /**
+     * Tests construction with a non-linear component in the transform.
+     *
+     * @throws TransformException if an error occurred while using the "grid to CRS" transform.
+     */
+    @Test
+    public void testNonLinear() throws TransformException {
+        final GridExtent extent = new GridExtent(
+                new int[] {0,     0, 2, 6},
+                new int[] {100, 200, 3, 9}, false);
+        final MathTransform horizontal = MathTransforms.linear(Matrices.create(3, 3, new
double[] {
+                0.5, 0,    12,
+                0,   0.25, -2,
+                0,   0,     1}));
+        final MathTransform vertical  = MathTransforms.interpolate(null, new double[] {1,
2, 4, 10});
+        final MathTransform temporal  = MathTransforms.linear(3600, 60);
+        final MathTransform gridToCRS = MathTransforms.compound(horizontal, vertical, temporal);
+        final GridGeometry  grid      = new GridGeometry(extent, PixelInCell.CELL_CENTER,
gridToCRS, null);
+        assertArrayEquals("resolution", new double[] {0.5, 0.25,        6.0, 3600}, grid.resolution(true),
 STRICT);
+        assertArrayEquals("resolution", new double[] {0.5, 0.25, Double.NaN, 3600}, grid.resolution(false),
STRICT);
+        assertFalse("isConversionLinear", grid.isConversionLinear(0, 1, 2, 3));
+        assertTrue ("isConversionLinear", grid.isConversionLinear(0, 1,    3));
+    }
+}
diff --git a/core/sis-raster/src/test/java/org/apache/sis/test/suite/RasterTestSuite.java
b/core/sis-raster/src/test/java/org/apache/sis/test/suite/RasterTestSuite.java
index 24c99c4..1817827 100644
--- a/core/sis-raster/src/test/java/org/apache/sis/test/suite/RasterTestSuite.java
+++ b/core/sis-raster/src/test/java/org/apache/sis/test/suite/RasterTestSuite.java
@@ -31,7 +31,8 @@ import org.junit.BeforeClass;
  */
 @Suite.SuiteClasses({
     org.apache.sis.image.DefaultIteratorTest.class,
-    org.apache.sis.coverage.grid.PixelTranslationTest.class
+    org.apache.sis.coverage.grid.PixelTranslationTest.class,
+    org.apache.sis.coverage.grid.GridGeometryTest.class
 })
 public final strictfp class RasterTestSuite extends TestSuite {
     /**


Mime
View raw message