You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sis.apache.org by de...@apache.org on 2018/06/20 13:48:12 UTC
[sis] 17/35: Add tests for GridGeometry.
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 <de...@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 {
/**