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 d9b0d29 Replace GridGeometry.reduce(lower, upper) by
reduce(dimensions) and add test.
d9b0d29 is described below
commit d9b0d2911f7ee70fc30789f4a7e4addbec8c65dc
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Fri Jan 4 11:31:40 2019 +0100
Replace GridGeometry.reduce(lower, upper) by reduce(dimensions) and add
test.
---
.../org/apache/sis/coverage/grid/GridExtent.java | 74 ++++++++++++++++------
.../org/apache/sis/coverage/grid/GridGeometry.java | 61 ++++++++++--------
.../org/apache/sis/internal/raster/Resources.java | 5 ++
.../sis/internal/raster/Resources.properties | 1 +
.../sis/internal/raster/Resources_fr.properties | 1 +
.../apache/sis/coverage/grid/GridExtentTest.java | 21 +++---
.../apache/sis/coverage/grid/GridGeometryTest.java | 43 ++++++++++++-
.../main/java/org/apache/sis/referencing/CRS.java | 10 ++-
8 files changed, 157 insertions(+), 59 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 5b278dd..89b89d1 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
@@ -47,6 +47,7 @@ import org.apache.sis.geometry.Envelopes;
import org.apache.sis.referencing.operation.transform.MathTransforms;
import org.apache.sis.referencing.operation.transform.TransformSeparator;
import org.apache.sis.io.TableAppender;
+import org.apache.sis.util.ArraysExt;
import org.apache.sis.util.iso.Types;
// Branch-dependent imports
@@ -753,35 +754,66 @@ public class GridExtent implements Serializable {
}
/**
+ * Verifies the validity of a given {@code dimensions} argument.
+ *
+ * @param dimensions the user-supplied argument to validate.
+ * @param limit maximal number of dimensions, exclusive.
+ * @return {@code true} if the caller can return {@code this}.
+ */
+ static boolean verifyDimensions(final int[] dimensions, final int limit) {
+ ArgumentChecks.ensureNonNull("dimensions", dimensions);
+ final int n = dimensions.length;
+ if (n == 0) {
+ throw new
IllegalArgumentException(Errors.format(Errors.Keys.EmptyArgument_1,
"dimensions"));
+ }
+ if (!ArraysExt.isSorted(dimensions, true)) {
+ throw new
IllegalArgumentException(Resources.format(Resources.Keys.NotStrictlyOrderedDimensions));
+ }
+ int d = dimensions[0];
+ if (d >= 0) {
+ d = dimensions[n - 1];
+ if (d < limit) {
+ return n == limit;
+ }
+ }
+ throw new
IndexOutOfBoundsException(Errors.format(Errors.Keys.IndexOutOfBounds_1, d));
+ }
+
+ /**
* Returns a grid envelope that encompass only some dimensions of this
grid envelope.
- * This method copies this grid envelope into a new grid envelope,
beginning at dimension
- * {@code lower} and extending to dimension {@code upper-1} inclusive.
Thus the dimension
- * of the sub grid envelope is {@code upper - lower}.
+ * This method copies the specified dimensions of this grid envelope into
a new grid envelope.
+ * The given dimensions must be in strictly ascending order without
duplicated values.
+ * The dimension of the sub grid envelope will be {@code
dimensions.length}.
*
* <p>This method performs a <cite>dimensionality reduction</cite> and can
be used as the
- * converse of {@link #append(DimensionNameType, long, long, boolean)}.</p>
+ * converse of {@link #append(DimensionNameType, long, long, boolean)}.
+ * This method can not be used for changing dimension order.</p>
*
- * @param lower the first dimension to copy, inclusive.
- * @param upper the last dimension to copy, exclusive.
- * @return the sub-envelope, or {@code this} if [{@code lower} … {@code
upper}] is [0 … {@link #getDimension() dimension}].
+ * @param dimensions the dimensions to select, in strictly increasing
order.
+ * @return the sub-envelope, or {@code this} if the given array contains
all dimensions of this grid extent.
* @throws IndexOutOfBoundsException if an index is out of bounds.
*
- * @see GridGeometry#reduce(int, int)
+ * @see GridGeometry#reduce(int...)
*/
- public GridExtent reduce(final int lower, final int upper) {
- final int dimension = getDimension();
- ArgumentChecks.ensureValidIndexRange(dimension, lower, upper);
- final int newDim = upper - lower;
- if (newDim == dimension) {
+ public GridExtent reduce(final int... dimensions) {
+ final int sd = getDimension();
+ if (verifyDimensions(dimensions, sd)) {
return this;
}
- DimensionNameType[] axisTypes = types;
- if (axisTypes != null) {
- axisTypes = Arrays.copyOfRange(axisTypes, lower, upper);
+ final int td = dimensions.length;
+ DimensionNameType[] tt = null;
+ if (types != null) {
+ tt = new DimensionNameType[td];
+ for (int i=0; i<td; i++) {
+ tt[i] = types[dimensions[i]];
+ }
+ }
+ final GridExtent sub = new GridExtent(td, tt);
+ for (int i=0; i<td; i++) {
+ final int j = dimensions[i];
+ sub.coordinates[i] = coordinates[j];
+ sub.coordinates[i+td] = coordinates[j+sd];
}
- final GridExtent sub = new GridExtent(newDim, axisTypes);
- System.arraycopy(coordinates, lower, sub.coordinates, 0,
newDim);
- System.arraycopy(coordinates, lower+dimension, sub.coordinates,
newDim, newDim);
return sub;
}
@@ -799,7 +831,7 @@ public class GridExtent implements Serializable {
* grid borders.</div>
*
* This method does not reduce the number of dimensions of the grid extent.
- * For dimensionality reduction, see {@link #reduce(int, int)}.
+ * For dimensionality reduction, see {@link #reduce(int...)}.
*
* @param strides the strides. Length shall be equal to the number of
dimension and all values shall be greater than zero.
* @return the sub-sampled extent, or {@code this} is sub-sampling results
in the same extent.
@@ -838,7 +870,7 @@ public class GridExtent implements Serializable {
* the number of dimensions of the grid extent.
*
* <p>This method does not reduce the number of dimensions of the grid
extent.
- * For dimensionality reduction, see {@link #reduce(int, int)}.</p>
+ * For dimensionality reduction, see {@link #reduce(int...)}.</p>
*
* @param slicePoint where to take a slice. NaN values are
handled as if their dimensions were absent.
* @param modifiedDimensions mapping from {@code slicePoint} dimensions
to this {@code GridExtent} dimensions,
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 4001abb..9a66bc0 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
@@ -482,35 +482,39 @@ public class GridGeometry implements Serializable {
}
/**
- * Creates a new grid geometry over the specified range of dimensions of
the given grid geometry.
+ * Creates a new grid geometry over the specified dimensions of the given
grid geometry.
*
- * @param other the grid geometry to copy.
- * @param lower the first dimension to copy, inclusive.
- * @param upper the last dimension to copy, exclusive.
+ * @param other the grid geometry to copy.
+ * @param dimensions the dimensions to select, in strictly increasing
order (this may not be verified).
* @throws FactoryException if an error occurred while separating the
"grid to CRS" transform.
*
- * @see #reduce(int, int)
+ * @see #reduce(int...)
*/
- private GridGeometry(final GridGeometry other, final int lower, final int
upper) throws FactoryException {
- extent = (other.extent != null) ? other.extent.reduce(lower, upper) :
null;
- final int n = upper - lower;
- final int[] dimensions;
+ private GridGeometry(final GridGeometry other, int[] dimensions) throws
FactoryException {
+ extent = (other.extent != null) ? other.extent.reduce(dimensions) :
null;
+ final int n = dimensions.length;
if (other.gridToCRS != null) {
+ final int[] sources = dimensions;
TransformSeparator sep = new TransformSeparator(other.gridToCRS);
- sep.addSourceDimensionRange(lower, upper);
+ sep.addSourceDimensions(sources);
gridToCRS = sep.separate();
dimensions = sep.getTargetDimensions();
assert dimensions.length == n : Arrays.toString(dimensions);
-
+ if (!ArraysExt.isSorted(dimensions, true)) {
+ throw new
IllegalGridGeometryException(Resources.format(Resources.Keys.IllegalGridGeometryComponent_1,
"dimensions"));
+ }
+ /*
+ * We redo a separation for 'cornerToCRS' instead than applying a
translation of the 'gridToCRS'
+ * computed above because we don't know which of 'gridToCRS' and
'cornerToCRS' has less NaN values.
+ */
sep = new TransformSeparator(other.cornerToCRS);
- sep.addSourceDimensionRange(lower, upper);
+ sep.addSourceDimensions(sources);
sep.addTargetDimensions(dimensions);
cornerToCRS = sep.separate();
assert Arrays.equals(sep.getSourceDimensions(), dimensions) :
Arrays.toString(dimensions);
} else {
gridToCRS = null;
cornerToCRS = null;
- dimensions = ArraysExt.sequence(lower, upper);
}
final ImmutableEnvelope env = other.envelope;
if (env != null) {
@@ -653,7 +657,7 @@ public class GridGeometry implements Serializable {
* In such case the envelope needs to contain all dimensions.</p>
*
* <p>This method does not reduce the number of dimensions of this grid
geometry.
- * For dimensionality reduction, see {@link #reduce(int, int)}.</p>
+ * For dimensionality reduction, see {@link #reduce(int...)}.</p>
*
* @param areaOfInterest the desired spatiotemporal region in any CRS
(transformations will be applied as needed).
* @return a grid extent of the same dimension than the grid geometry
which intersects the given area of interest.
@@ -681,7 +685,7 @@ public class GridGeometry implements Serializable {
* See {@link #slice(DirectPosition)} for examples.
*
* <p>This method does not reduce the number of dimensions of this grid
geometry.
- * For dimensionality reduction, see {@link #reduce(int, int)}.</p>
+ * For dimensionality reduction, see {@link #reduce(int...)}.</p>
*
* @param slicePoint the coordinates where to get a slice.
* @return a slice of the grid extent at the given slice point.
@@ -1024,7 +1028,7 @@ public class GridGeometry implements Serializable {
* then no sub-sampling will be applied on the missing dimensions.
*
* <p>This method does not reduce the number of dimensions of this grid
geometry.
- * For dimensionality reduction, see {@link #reduce(int, int)}.</p>
+ * For dimensionality reduction, see {@link #reduce(int...)}.</p>
*
* @param areaOfInterest the desired spatiotemporal region in any CRS
(transformations will be applied as needed),
* or {@code null} for not restricting the
sub-grid to a sub-area.
@@ -1069,7 +1073,7 @@ public class GridGeometry implements Serializable {
* </ul></div>
*
* This method does not reduce the number of dimensions of this grid
geometry.
- * For dimensionality reduction, see {@link #reduce(int, int)}.
+ * For dimensionality reduction, see {@link #reduce(int...)}.
*
* @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}.
@@ -1094,24 +1098,25 @@ public class GridGeometry implements Serializable {
/**
* Returns a grid geometry that encompass only some dimensions of this
grid geometry.
- * This method copies this grid geometry into a new grid geometry,
beginning at dimension
- * {@code lower} and extending to dimension {@code upper-1} inclusive.
Thus the dimension
- * of the sub grid geometry is {@code upper - lower}.
+ * This method copies the specified dimensions of this grid geometry into
a new grid geometry.
+ * The given dimensions must be in strictly ascending order without
duplicated values.
+ * The dimension of the sub grid grid geometry will be {@code
dimensions.length}.
*
- * <p>This method performs a <cite>dimensionality reduction</cite>.</p>
+ * <p>This method performs a <cite>dimensionality reduction</cite>.
+ * This method can not be used for changing dimension order.</p>
*
- * @param lower the first grid dimension to copy, inclusive.
- * @param upper the last grid dimension to copy, exclusive.
- * @return the sub grid geometry, or {@code this} if [{@code lower} …
{@code upper}] is [0 … {@link #getDimension() dimension}].
+ * @param dimensions the dimensions to select, in strictly increasing
order.
+ * @return the sub grid geometry, or {@code this} if the given array
contains all dimensions of this grid grid geometry.
* @throws IndexOutOfBoundsException if an index is out of bounds.
*
- * @see GridExtent#reduce(int, int)
+ * @see GridExtent#reduce(int...)
+ * @see org.apache.sis.referencing.CRS#reduce(CoordinateReferenceSystem,
int...)
*/
- public GridGeometry reduce(final int lower, final int upper) {
- if (lower == 0 && upper == getDimension()) {
+ public GridGeometry reduce(final int... dimensions) {
+ if (GridExtent.verifyDimensions(dimensions, getDimension())) {
return this;
} else try {
- return new GridGeometry(this, lower, upper);
+ return new GridGeometry(this, dimensions);
} catch (FactoryException e) {
throw new IllegalGridGeometryException(e, "dimensions");
}
diff --git
a/core/sis-raster/src/main/java/org/apache/sis/internal/raster/Resources.java
b/core/sis-raster/src/main/java/org/apache/sis/internal/raster/Resources.java
index 51ef8eb..865cd1d 100644
---
a/core/sis-raster/src/main/java/org/apache/sis/internal/raster/Resources.java
+++
b/core/sis-raster/src/main/java/org/apache/sis/internal/raster/Resources.java
@@ -145,6 +145,11 @@ public final class Resources extends IndexedResourceBundle
{
public static final short NonLinearInDimensions_1 = 20;
/**
+ * The specified dimensions are not in strictly ascending order.
+ */
+ public static final short NotStrictlyOrderedDimensions = 24;
+
+ /**
* The ({0}, {1}) pixel coordinate is outside iterator domain.
*/
public static final short OutOfIteratorDomain_2 = 1;
diff --git
a/core/sis-raster/src/main/java/org/apache/sis/internal/raster/Resources.properties
b/core/sis-raster/src/main/java/org/apache/sis/internal/raster/Resources.properties
index 0f5531c..fd2bd6f 100644
---
a/core/sis-raster/src/main/java/org/apache/sis/internal/raster/Resources.properties
+++
b/core/sis-raster/src/main/java/org/apache/sis/internal/raster/Resources.properties
@@ -36,6 +36,7 @@ MismatchedSampleModel = The two images use
different sample models.
MismatchedTileGrid = The two images have different tile grid.
NoCategoryForValue_1 = No category for value {0}.
NonLinearInDimensions_1 = non-linear in {0}
dimension{0,choice,1#|2#s}:
+NotStrictlyOrderedDimensions = The specified dimensions are not in
strictly ascending order.
OutOfIteratorDomain_2 = The ({0}, {1}) pixel coordinate is outside
iterator domain.
PointOutsideCoverageDomain_1 = Point ({0}) is outside the coverage domain.
TooManyQualitatives = Too many qualitative categories.
diff --git
a/core/sis-raster/src/main/java/org/apache/sis/internal/raster/Resources_fr.properties
b/core/sis-raster/src/main/java/org/apache/sis/internal/raster/Resources_fr.properties
index 0dc3acb..4dcd1d7 100644
---
a/core/sis-raster/src/main/java/org/apache/sis/internal/raster/Resources_fr.properties
+++
b/core/sis-raster/src/main/java/org/apache/sis/internal/raster/Resources_fr.properties
@@ -41,6 +41,7 @@ MismatchedSampleModel = Les deux images disposent
les pixels diff\u0
MismatchedTileGrid = Les deux images utilisent des grilles de
tuiles diff\u00e9rentes.
NoCategoryForValue_1 = Aucune cat\u00e9gorie n\u2019est
d\u00e9finie pour la valeur {0}.
NonLinearInDimensions_1 = non-lin\u00e9aire dans {0}
dimension{0,choice,1#|2#s}\u2008:
+NotStrictlyOrderedDimensions = Les dimensions sp\u00e9cifi\u00e9es ne
sont pas en ordre strictement croissant.
OutOfIteratorDomain_2 = La coordonn\u00e9e pixel ({0}, {1}) est en
dehors du domaine de l\u2019it\u00e9rateur.
PointOutsideCoverageDomain_1 = Le point ({0}) est en dehors du domaine de
la couverture de donn\u00e9es.
TooManyQualitatives = Trop de cat\u00e9gories qualitatives.
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 01bfeff..c6ca296 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
@@ -122,17 +122,22 @@ public final strictfp class GridExtentTest extends
TestCase {
}
/**
- * Tests {@link GridExtent#reduce(int, int)}.
+ * Tests {@link GridExtent#reduce(int...)}.
*/
@Test
public void testReduce() {
- GridExtent extent = create3D();
- extent = extent.reduce(0, 2);
- assertEquals("dimension", 2, extent.getDimension());
- assertExtentEquals(extent, 0, 100, 499);
- assertExtentEquals(extent, 1, 200, 799);
- assertEquals(DimensionNameType.COLUMN, extent.getAxisType(0).get());
- assertEquals(DimensionNameType.ROW, extent.getAxisType(1).get());
+ final GridExtent extent = create3D();
+ GridExtent reduced = extent.reduce(0, 1);
+ assertEquals("dimension", 2, reduced.getDimension());
+ assertExtentEquals(reduced, 0, 100, 499);
+ assertExtentEquals(reduced, 1, 200, 799);
+ assertEquals(DimensionNameType.COLUMN, reduced.getAxisType(0).get());
+ assertEquals(DimensionNameType.ROW, reduced.getAxisType(1).get());
+
+ reduced = extent.reduce(2);
+ assertEquals("dimension", 1, reduced.getDimension());
+ assertExtentEquals(reduced, 0, 40, 49);
+ assertEquals(DimensionNameType.TIME, reduced.getAxisType(0).get());
}
/**
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 b692e2f..0533f1b 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
@@ -20,6 +20,7 @@ import org.opengis.metadata.spatial.DimensionNameType;
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.Matrix2;
import org.apache.sis.referencing.operation.matrix.Matrix3;
import org.apache.sis.referencing.operation.matrix.Matrix4;
import org.apache.sis.referencing.operation.matrix.Matrices;
@@ -368,10 +369,13 @@ public final strictfp class GridGeometryTest extends
TestCase {
0.5, 0, 0, -180,
0, 0, 2, 3,
0, 0, 0, 1)), HardCodedCRS.WGS84_3D);
+ /*
+ * There is two ways to ask for a slice. The first way is to set some
coordinates to NaN.
+ */
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[] expectedLow = {336, 20, 6};
final long[] expectedHigh = {401, 419, 6};
assertExtentEquals(expectedLow, expectedHigh, slice.getExtent());
/*
@@ -385,4 +389,41 @@ public final strictfp class GridGeometryTest extends
TestCase {
assertSame("gridToCRS", grid.gridToCRS, slice.gridToCRS);
assertExtentEquals(expectedLow, expectedHigh, slice.getExtent());
}
+
+ /**
+ * Tests {@link GridGeometry#reduce(int...)}.
+ */
+ @Test
+ public void testReduce() {
+ 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.GEOID_3D);
+ /*
+ * Tests on the two first dimensions.
+ */
+ GridGeometry reduced = grid.reduce(0, 1);
+ assertNotSame(grid, reduced);
+ assertExtentEquals(new long[] {336, 20}, new long[] {401, 419},
reduced.getExtent());
+ assertSame("CRS", HardCodedCRS.WGS84,
reduced.getCoordinateReferenceSystem());
+ assertArrayEquals("resolution", new double[] {0.5, 0.5},
reduced.getResolution(false), STRICT);
+ assertMatrixEquals("gridToCRS", new Matrix3(
+ 0, 0.5, -90,
+ 0.5, 0, -180,
+ 0, 0, 1),
MathTransforms.getMatrix(reduced.getGridToCRS(PixelInCell.CELL_CORNER)),
STRICT);
+ /*
+ * Tests on the last dimension.
+ */
+ reduced = grid.reduce(2);
+ assertNotSame(grid, reduced);
+ assertExtentEquals(new long[] {4}, new long[] {10},
reduced.getExtent());
+ assertSame("CRS", HardCodedCRS.GRAVITY_RELATED_HEIGHT,
reduced.getCoordinateReferenceSystem());
+ assertArrayEquals("resolution", new double[] {2},
reduced.getResolution(false), STRICT);
+ assertMatrixEquals("gridToCRS", new Matrix2(
+ 2, 3,
+ 0, 1),
MathTransforms.getMatrix(reduced.getGridToCRS(PixelInCell.CELL_CORNER)),
STRICT);
+ }
}
diff --git
a/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
b/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
index e91666d..f1e837d 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
@@ -933,7 +933,15 @@ public final class CRS extends Static {
/**
* Gets or creates a coordinate reference system with a subset of the
dimensions of the given CRS.
- * This method can be used for dimensionality reduction.
+ * This method can be used for dimensionality reduction, but not for
changing axis order.
+ * The specified dimensions are used as if they were in strictly
increasing order without duplicated values.
+ *
+ * <div class="section">Ellipsoidal height</div>
+ * This method can transform a three-dimensional geographic CRS into a
two-dimensional geographic CRS.
+ * In this aspect, this method is the converse of {@link
#compound(CoordinateReferenceSystem...)}.
+ * This method can also extract the {@linkplain
CommonCRS.Vertical#ELLIPSOIDAL ellipsoidal height}
+ * from a three-dimensional geographic CRS, but this is generally not
recommended since ellipsoidal
+ * heights make little sense without their (<var>latitude</var>,
<var>longitude</var>) locations.
*
* @param crs the CRS to reduce the dimensionality, or {@code
null} if none.
* @param dimensions the dimensions to retain. The dimensions will be
taken in increasing order, ignoring duplicated values.