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 ca8241da59f6885fc6d5446ee9589890c2d3cebb Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Fri Nov 24 16:28:54 2023 +0100 Add a `GridGeometry` constructor doing the concatenation of two grid geometries. Opportunistic migration of JUnit 4 to JUnit 5 for the relevant tests. --- .../org/apache/sis/coverage/grid/GridExtent.java | 29 ++++- .../org/apache/sis/coverage/grid/GridGeometry.java | 63 +++++++++- .../apache/sis/coverage/grid/GridExtentTest.java | 113 +++++++++-------- .../apache/sis/coverage/grid/GridGeometryTest.java | 140 +++++++++++++-------- .../main/org/apache/sis/util/ArraysExt.java | 20 ++- 5 files changed, 260 insertions(+), 105 deletions(-) diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridExtent.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridExtent.java index 352247f403..62d68bb38b 100644 --- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridExtent.java +++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridExtent.java @@ -91,7 +91,7 @@ import org.opengis.coverage.grid.GridCoordinates; * @author Martin Desruisseaux (IRD, Geomatys) * @author Alexis Manin (Geomatys) * @author Johann Sorel (Geomatys) - * @version 1.4 + * @version 1.5 * @since 1.0 */ public class GridExtent implements GridEnvelope, LenientComparable, Serializable { @@ -354,6 +354,33 @@ public class GridExtent implements GridEnvelope, LenientComparable, Serializable validateCoordinates(); } + /** + * Creates a new grid extent as the concatenation of the two specified grid extent. + * The number of dimensions of the new extent is the sum of the number of dimensions + * of the two specified extents. The dimensions of the lower extent are first, + * followed by the dimensions of the upper extent. + * + * @param lower the grid extent providing the lowest dimensions. + * @param upper the grid extent providing the highest dimensions. + * @throws IllegalArgumentException if the concatenation results in duplicated {@linkplain #getAxisType(int) axis types}. + * + * @since 1.5 + */ + public GridExtent(final GridExtent lower, final GridExtent upper) { + final int d1 = lower.getDimension(); + final int d2 = upper.getDimension(); + final int dim = d1 + d2; + final var axisTypes = new DimensionNameType[dim]; + if (lower.types != null) System.arraycopy(lower.types, 0, axisTypes, 0, d1); + if (upper.types != null) System.arraycopy(upper.types, 0, axisTypes, d1, d2); + types = validateAxisTypes(axisTypes); + coordinates = allocate(dim); + System.arraycopy(lower.coordinates, 0, coordinates, 0, d1); + System.arraycopy(upper.coordinates, 0, coordinates, d1, d2); + System.arraycopy(lower.coordinates, d1, coordinates, dim, d1); + System.arraycopy(upper.coordinates, d2, coordinates, dim+d1, d2); + } + /** * Infers the axis types from the given coordinate reference system. * This method is the converse of {@link GridExtentCRS}. diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridGeometry.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridGeometry.java index 3389b1a534..464b9644bd 100644 --- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridGeometry.java +++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridGeometry.java @@ -747,6 +747,66 @@ public class GridGeometry implements LenientComparable, Serializable { } } + /** + * Creates a new grid geometry as the concatenation of the two specified grid geometries. + * The number of dimensions of the new grid geometry is the sum of the number of dimensions + * of the two specified grid geometries. The dimensions of the lower grid geometry are first, + * followed by the dimensions of the upper grid geometry. + * + * @param lower the grid geometry providing the lowest dimensions. + * @param upper the grid geometry providing the highest dimensions. + * @throws IncompleteGridGeometryException if a property presents in one grid geometry is absent in the other. + * @throws IllegalArgumentException if the concatenation results in duplicated + * {@linkplain GridExtent#getAxisType(int) grid axis types}. + * @throws FactoryException if the geodetic factory failed to create the compound CRS. + * + * @see #selectDimensions(int...) + * + * @since 1.5 + */ + public GridGeometry(final GridGeometry lower, final GridGeometry upper) throws FactoryException { + /* + * Concatenate the extents first because they perform a check for axis duplication. + * We set the extent to null only if both `lower` and `upper` have a null extent. + * Otherwise, invoke `getExtent()` for causing an `IncompleteGridGeometryException` + * to be thrown if only one grid geometry has an extent. + */ + extent = (lower.extent == null && upper.extent == null) ? null + : new GridExtent(lower.getExtent(), upper.getExtent()); + /* + * Concatenate the "grid to CRS" transforms and derived information + * (resolutions and non-linearity). + */ + if (lower.gridToCRS == null && upper.gridToCRS == null) { + gridToCRS = null; + cornerToCRS = null; + } else { + gridToCRS = compound(lower, upper, PixelInCell.CELL_CENTER); + cornerToCRS = compound(lower, upper, PixelInCell.CELL_CORNER); + } + nonLinears = lower.nonLinears | (upper.nonLinears << lower.getDimension()); + resolution = (lower.resolution == null && upper.resolution == null) ? null + : ArraysExt.concatenate(lower.getResolution(true), upper.getResolution(true)); + /* + * The check for presence/absence of envelope is more complex because an envelope + * may be considered missing, but still be non-null in order to store the CRS. + */ + if (lower.envelope == null && upper.envelope == null) { + envelope = null; + } else { + Envelope e1 = lower.envelope; if (e1 == null) e1 = lower.getEnvelope(); + Envelope e2 = upper.envelope; if (e2 == null) e2 = upper.getEnvelope(); + envelope = ImmutableEnvelope.castOrCopy(Envelopes.compound(e1, e2)); + } + } + + /** + * Aggregates the dimensions of the "grid to CRS" transforms of the given grid geometries. + */ + private static MathTransform compound(final GridGeometry lower, final GridGeometry upper, final PixelInCell anchor) { + return MathTransforms.compound(lower.getGridToCRS(anchor), upper.getGridToCRS(anchor)); + } + /** * Converts a "grid to CRS" transform from "cell corner" convention to "cell center" convention. * This is a helper method for use of {@link #GridGeometry(GridExtent, MathTransform, MathTransform, @@ -1542,7 +1602,8 @@ public class GridGeometry implements LenientComparable, Serializable { * The number of dimensions of the sub grid geometry will be {@code dimensions.length}. * * <p>This method performs a <cite>dimensionality reduction</cite>. - * This method cannot be used for changing dimension order.</p> + * This method cannot be used for changing dimension order. + * The converse operation is the {@linkplain #GridGeometry(GridGeometry, GridGeometry) concatenation}.</p> * * @param indices the grid (not CRS) 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 geometry. diff --git a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/coverage/grid/GridExtentTest.java b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/coverage/grid/GridExtentTest.java index b9f3646dae..c9afd55f9b 100644 --- a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/coverage/grid/GridExtentTest.java +++ b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/coverage/grid/GridExtentTest.java @@ -37,7 +37,8 @@ import org.apache.sis.util.internal.Numerics; // Test dependencies import org.junit.Test; -import static org.junit.Assert.*; +import org.junit.jupiter.api.DisplayName; +import static org.junit.jupiter.api.Assertions.*; import org.apache.sis.test.TestCase; import org.apache.sis.referencing.crs.HardCodedCRS; import static org.apache.sis.test.Assertions.assertMapEquals; @@ -77,10 +78,10 @@ public final class GridExtentTest extends TestCase { * Verifies the low and high values in the specified dimension of the given extent */ static void assertExtentEquals(final GridExtent extent, final int dimension, final int low, final int high) { - assertEquals("low", low, extent.getLow (dimension)); - assertEquals("high", high, extent.getHigh(dimension)); - assertEquals("size", high - low + 1, extent.getSize(dimension)); - assertEquals("median", Numerics.ceilDiv(high + low, 2), extent.getMedian(dimension)); + assertEquals(low, extent.getLow (dimension), "low"); + assertEquals(high, extent.getHigh(dimension), "high"); + assertEquals(high - low + 1, extent.getSize(dimension), "size"); + assertEquals(Numerics.ceilDiv(high + low, 2), extent.getMedian(dimension), "median"); } /** @@ -185,7 +186,7 @@ public final class GridExtentTest extends TestCase { GridExtent extent = new GridExtent(new DimensionNameType[] {DimensionNameType.COLUMN, DimensionNameType.ROW}, new long[] {100, 200}, new long[] {500, 800}, true); extent = extent.insertDimension(offset, DimensionNameType.TIME, 40, 50, false); - assertEquals("dimension", 3, extent.getDimension()); + assertEquals(3, extent.getDimension(), "dimension"); assertExtentEquals(extent, 0, 100, 500); assertExtentEquals(extent, rowIndex, 200, 800); assertExtentEquals(extent, offset, 40, 49); @@ -201,14 +202,14 @@ public final class GridExtentTest extends TestCase { public void testSelectDimensions() { final GridExtent extent = create3D(); GridExtent reduced = extent.selectDimensions(0, 1); - assertEquals("dimension", 2, reduced.getDimension()); + assertEquals(2, reduced.getDimension(), "dimension"); 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.selectDimensions(2); - assertEquals("dimension", 1, reduced.getDimension()); + assertEquals(1, reduced.getDimension(), "dimension"); assertExtentEquals(reduced, 0, 40, 49); assertEquals(DimensionNameType.TIME, reduced.getAxisType(0).get()); } @@ -294,12 +295,8 @@ public final class GridExtentTest extends TestCase { assertExtentEquals(extent, 2, 40, 46); assertSame(extent.intersect(domain), extent); final GridExtent disjoint = domain.translate(0, 1000); - try { - extent.intersect(disjoint); - fail("Expected DisjointExtentException."); - } catch (DisjointExtentException e) { - assertNotNull(e.getMessage()); - } + String message = assertThrows(DisjointExtentException.class, () -> extent.intersect(disjoint)).getMessage(); + assertNotNull(message); } /** @@ -325,12 +322,30 @@ public final class GridExtentTest extends TestCase { final GridExtent other = new GridExtent( new DimensionNameType[] {DimensionNameType.COLUMN, DimensionNameType.TRACK, DimensionNameType.TIME}, new long[] {100, 200, 40}, new long[] {500, 800, 50}, false); - try { - domain.intersect(other); - fail("Should not be allowed"); - } catch (IllegalArgumentException e) { - assertNotNull(e.getMessage()); - } + + String message = assertThrows(IllegalArgumentException.class, () -> domain.intersect(other)).getMessage(); + assertNotNull(message); + } + + /** + * Tests {@link GridExtent#GridExtent(GridExtent, GridExtent)}. + */ + @Test + public void testConcatenate() { + final GridExtent domain = create3D(); + final GridExtent other = new GridExtent( + new DimensionNameType[] {DimensionNameType.VERTICAL}, + new long[] {-4}, new long[] {17}, true); + final GridExtent extent = new GridExtent(domain, other); + + assertArrayEquals(new DimensionNameType[] { + DimensionNameType.COLUMN, DimensionNameType.ROW, DimensionNameType.TIME, DimensionNameType.VERTICAL + }, extent.getAxisTypes()); + + assertArrayEquals(new long[] { + 100, 200, 40, -4, + 499, 799, 49, 17 + }, extent.getCoordinates()); } /** @@ -341,7 +356,7 @@ public final class GridExtentTest extends TestCase { 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()); + assertEquals(3, slice.getDimension(), "dimension"); assertExtentEquals(slice, 0, 100, 499); assertExtentEquals(slice, 1, 227, 227); assertExtentEquals(slice, 2, 47, 47); @@ -352,13 +367,8 @@ public final class GridExtentTest extends TestCase { * 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. - } + String message = assertThrows(PointOutsideCoverageException.class, () -> extent.slice(slicePoint, new int[] {1, 2})).getLocalizedMessage(); + assertTrue(message.contains("(900, 47)"), message); // See above comment. } /** @@ -372,12 +382,8 @@ public final class GridExtentTest extends TestCase { assertSubspaceEquals(extent, 0, 2 ); assertSubspaceEquals(extent, 0,1,2 ); assertSubspaceEquals(extent, 0,1,2,3); - try { - extent.getSubspaceDimensions(1); - fail("Should not reduce to 1 dimension."); - } catch (SubspaceNotSpecifiedException e) { - assertNotNull(e.getMessage()); - } + String message = assertThrows(SubspaceNotSpecifiedException.class, () -> extent.getSubspaceDimensions(1)).getMessage(); + assertNotNull(message); } /** @@ -508,11 +514,12 @@ public final class GridExtentTest extends TestCase { * Verifies that a translation of zero cell results in the same {@link GridExtent} instance. */ @Test - public void empty_translation_returns_same_extent_instance() { + @DisplayName("Empty translation returns same extent instance") + public void testZeroTranslation() { final GridExtent extent = new GridExtent(10, 10); - assertSame("Same instance returned in case of no-op", extent, extent.translate()); - assertSame("Same instance returned in case of no-op", extent, extent.translate(0)); - assertSame("Same instance returned in case of no-op", extent, extent.translate(0, 0)); + assertSame(extent, extent.translate()); + assertSame(extent, extent.translate(0)); + assertSame(extent, extent.translate(0, 0)); } /** @@ -520,26 +527,27 @@ public final class GridExtentTest extends TestCase { * than the extent number of dimensions. No translation shall be applied in missing dimensions. */ @Test - public void translating_only_first_dimensions_leave_others_untouched() { + @DisplayName("Translating only first dimensions leave others untouched") + public void testTranslateOneDimension() { final GridExtent base = new GridExtent(null, new long[] { 0, 0, 0, 2, 2, 2 }); final GridExtent translatedByX = base.translate(1); - assertArrayEquals("Lower corner", new long[] {1, 0, 0}, translatedByX.getLow() .getCoordinateValues()); - assertArrayEquals("Upper corner", new long[] {3, 2, 2}, translatedByX.getHigh().getCoordinateValues()); + assertArrayEquals(new long[] {1, 0, 0}, translatedByX.getLow() .getCoordinateValues(), "Lower corner"); + assertArrayEquals(new long[] {3, 2, 2}, translatedByX.getHigh().getCoordinateValues(), "Upper corner"); final GridExtent translatedByY = base.translate(0, -1); - assertArrayEquals("Lower corner", new long[] {0, -1, 0}, translatedByY.getLow() .getCoordinateValues()); - assertArrayEquals("Upper corner", new long[] {2, 1, 2}, translatedByY.getHigh().getCoordinateValues()); + assertArrayEquals(new long[] {0, -1, 0}, translatedByY.getLow() .getCoordinateValues(), "Lower corner"); + assertArrayEquals(new long[] {2, 1, 2}, translatedByY.getHigh().getCoordinateValues(), "Upper corner"); final GridExtent translatedByXAndY = base.translate(-1, 4); - assertArrayEquals("Lower corner", new long[] {-1, 4, 0}, translatedByXAndY.getLow() .getCoordinateValues()); - assertArrayEquals("Upper corner", new long[] { 1, 6, 2}, translatedByXAndY.getHigh().getCoordinateValues()); + assertArrayEquals(new long[] {-1, 4, 0}, translatedByXAndY.getLow() .getCoordinateValues(), "Lower corner"); + assertArrayEquals(new long[] { 1, 6, 2}, translatedByXAndY.getHigh().getCoordinateValues(), "Upper corner"); // Paranoiac check: ensure that base extent has been left untouched. - assertArrayEquals("Base lower corner", new long[] {0, 0, 0}, base.getLow() .getCoordinateValues()); - assertArrayEquals("Base lower corner", new long[] {2, 2, 2}, base.getHigh().getCoordinateValues()); + assertArrayEquals(new long[] {0, 0, 0}, base.getLow() .getCoordinateValues(), "Base lower corner"); + assertArrayEquals(new long[] {2, 2, 2}, base.getHigh().getCoordinateValues(), "Base lower corner"); } /** @@ -547,17 +555,18 @@ public final class GridExtentTest extends TestCase { * when the given vector is long enough. */ @Test - public void translating_all_dimensions() { + @DisplayName("Translating all dimensions") + public void testTranslateAllDimensions() { final GridExtent base = new GridExtent(null, new long[] { -1, -1, -2, 10, 2, 2, 2, 20 }); final GridExtent translated = base.translate(-2, 1, 1, 100); - assertArrayEquals("Lower corner", new long[] {-3, 0, -1, 110}, translated.getLow() .getCoordinateValues()); - assertArrayEquals("Upper corner", new long[] { 0, 3, 3, 120}, translated.getHigh().getCoordinateValues()); + assertArrayEquals(new long[] {-3, 0, -1, 110}, translated.getLow() .getCoordinateValues(), "Lower corner"); + assertArrayEquals(new long[] { 0, 3, 3, 120}, translated.getHigh().getCoordinateValues(), "Upper corner"); // Paranoiac check: ensure that base extent has been left untouched. - assertArrayEquals("Base lower corner", new long[] {-1, -1, -2, 10}, base.getLow() .getCoordinateValues()); - assertArrayEquals("Base lower corner", new long[] { 2, 2, 2, 20}, base.getHigh().getCoordinateValues()); + assertArrayEquals(new long[] {-1, -1, -2, 10}, base.getLow() .getCoordinateValues(), "Base lower corner"); + assertArrayEquals(new long[] { 2, 2, 2, 20}, base.getHigh().getCoordinateValues(), "Base lower corner"); } } diff --git a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/coverage/grid/GridGeometryTest.java b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/coverage/grid/GridGeometryTest.java index e0823cdc82..5c2d342226 100644 --- a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/coverage/grid/GridGeometryTest.java +++ b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/coverage/grid/GridGeometryTest.java @@ -16,6 +16,7 @@ */ package org.apache.sis.coverage.grid; +import org.opengis.util.FactoryException; import org.opengis.geometry.Envelope; import org.opengis.metadata.spatial.DimensionNameType; import org.opengis.referencing.crs.DerivedCRS; @@ -32,10 +33,11 @@ import org.apache.sis.referencing.operation.matrix.Matrices; import org.apache.sis.referencing.operation.matrix.MatrixSIS; import org.apache.sis.referencing.operation.transform.MathTransforms; import org.apache.sis.referencing.util.ExtendedPrecisionMatrix; +import org.apache.sis.util.ComparisonMode; // Test dependencies import org.junit.Test; -import static org.junit.Assert.*; +import static org.junit.jupiter.api.Assertions.*; import org.apache.sis.test.TestCase; import org.apache.sis.test.DependsOn; import org.apache.sis.referencing.crs.HardCodedCRS; @@ -64,8 +66,8 @@ public final class GridGeometryTest extends TestCase { * Verifies grid extent coordinates. */ static void assertExtentEquals(final long[] low, final long[] high, final GridExtent extent) { - assertArrayEquals("extent.low", low, extent.getLow() .getCoordinateValues()); - assertArrayEquals("extent.high", high, extent.getHigh().getCoordinateValues()); + assertArrayEquals(low, extent.getLow() .getCoordinateValues(), "extent.low"); + assertArrayEquals(high, extent.getHigh().getCoordinateValues(), "extent.high"); } /** @@ -123,16 +125,16 @@ public final class GridGeometryTest extends TestCase { * Verify properties that should be stored "as-is". */ final MathTransform trCorner = grid.getGridToCRS(PixelInCell.CELL_CORNER); - assertSame("gridToCRS", identity, trCorner); + assertSame(identity, trCorner, "gridToCRS"); assertExtentEquals(low, high, grid.getExtent()); /* * 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()); + assertFalse (trCenter.isIdentity(), "gridToCRS.isIdentity"); + assertEquals(4, trCenter.getSourceDimensions(), "gridToCRS.sourceDimensions"); + assertEquals(4, trCenter.getTargetDimensions(), "gridToCRS.targetDimensions"); assertMatrixEquals("gridToCRS", Matrices.create(5, 5, new double[] { 1, 0, 0, 0, 0.5, 0, 1, 0, 0, 0.5, @@ -148,8 +150,8 @@ public final class GridGeometryTest extends TestCase { /* * Verify other computed properties. */ - assertArrayEquals("resolution", new double[] {1, 1, 1, 1}, grid.getResolution(false), STRICT); - assertTrue("isConversionLinear", grid.isConversionLinear(0, 1, 2, 3)); + assertArrayEquals(new double[] {1, 1, 1, 1}, grid.getResolution(false), "resolution"); + assertTrue(grid.isConversionLinear(0, 1, 2, 3), "isConversionLinear"); verifyGridToCRS(grid); } @@ -168,16 +170,16 @@ public final class GridGeometryTest extends TestCase { * Verify properties that should be stored "as-is". */ final MathTransform trCenter = grid.getGridToCRS(PixelInCell.CELL_CENTER); - assertSame("gridToCRS", identity, trCenter); + assertSame(identity, trCenter, "gridToCRS"); assertExtentEquals(low, high, grid.getExtent()); /* * 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()); + assertFalse (trCorner.isIdentity(), "gridToCRS.isIdentity"); + assertEquals(3, trCorner.getSourceDimensions(), "gridToCRS.sourceDimensions"); + assertEquals(3, trCorner.getTargetDimensions(), "gridToCRS.targetDimensions"); assertMatrixEquals("gridToCRS", new Matrix4( 1, 0, 0, -0.5, 0, 1, 0, -0.5, @@ -192,8 +194,8 @@ public final class GridGeometryTest extends TestCase { /* * Verify other computed properties. */ - assertArrayEquals("resolution", new double[] {1, 1, 1}, grid.getResolution(false), STRICT); - assertTrue("isConversionLinear", grid.isConversionLinear(0, 1, 2)); + assertArrayEquals(new double[] {1, 1, 1}, grid.getResolution(false), "resolution"); + assertTrue(grid.isConversionLinear(0, 1, 2), "isConversionLinear"); verifyGridToCRS(grid); } @@ -224,8 +226,8 @@ public final class GridGeometryTest extends TestCase { /* * Verify other computed properties. */ - assertArrayEquals("resolution", new double[] {2, 1, 3}, grid.getResolution(false), STRICT); - assertTrue("isConversionLinear", grid.isConversionLinear(0, 1, 2)); + assertArrayEquals(new double[] {2, 1, 3}, grid.getResolution(false), "resolution"); + assertTrue(grid.isConversionLinear(0, 1, 2), "isConversionLinear"); verifyGridToCRS(grid); } @@ -275,7 +277,7 @@ public final class GridGeometryTest extends TestCase { 0, 1, 0.5, 0, 0, 1)); final GridGeometry grid = new GridGeometry(extent, PixelInCell.CELL_CENTER, gridToCRS, null); - assertTrue("gridToCRS.isIdentity", grid.getGridToCRS(PixelInCell.CELL_CORNER).isIdentity()); + assertTrue(grid.getGridToCRS(PixelInCell.CELL_CORNER).isIdentity(), "gridToCRS.isIdentity"); verifyGridToCRS(grid); } @@ -301,10 +303,10 @@ public final class GridGeometryTest extends TestCase { 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.getResolution(true), STRICT); - assertArrayEquals("resolution", new double[] {0.5, 0.25, Double.NaN, 3600}, grid.getResolution(false), STRICT); - assertFalse("isConversionLinear", grid.isConversionLinear(0, 1, 2, 3)); - assertTrue ("isConversionLinear", grid.isConversionLinear(0, 1, 3)); + assertArrayEquals(new double[] {0.5, 0.25, 6.0, 3600}, grid.getResolution(true), "resolution"); + assertArrayEquals(new double[] {0.5, 0.25, Double.NaN, 3600}, grid.getResolution(false), "resolution"); + assertFalse(grid.isConversionLinear(0, 1, 2, 3), "isConversionLinear"); + assertTrue (grid.isConversionLinear(0, 1, 3), "isConversionLinear"); } /** @@ -327,7 +329,7 @@ public final class GridGeometryTest extends TestCase { assertEnvelopeEquals(new GeneralEnvelope( new double[] {-70, 5}, new double[] {+80, 15}), grid.getEnvelope(), STRICT); - assertArrayEquals("resolution", new double[] {0.5, 0.5}, grid.getResolution(false), STRICT); + assertArrayEquals(new double[] {0.5, 0.5}, grid.getResolution(false), "resolution"); assertMatrixEquals("gridToCRS", new Matrix3( 0, 0.5, -89.75, 0.5, 0, -179.75, @@ -335,8 +337,8 @@ public final class GridGeometryTest extends TestCase { /* * Verify other computed properties. */ - assertArrayEquals("resolution", new double[] {0.5, 0.5}, grid.getResolution(false), STRICT); - assertTrue("isConversionLinear", grid.isConversionLinear(0, 1)); + assertArrayEquals(new double[] {0.5, 0.5}, grid.getResolution(false), "resolution"); + assertTrue(grid.isConversionLinear(0, 1), "isConversionLinear"); verifyGridToCRS(grid); } @@ -366,9 +368,9 @@ public final class GridGeometryTest extends TestCase { 0, 0, 1), matrix, STRICT); // Verify other computed properties. - assertArrayEquals("resolution", new double[] {0.5, 2}, grid.getResolution(false), STRICT); - assertTrue("isConversionLinear", grid.isConversionLinear(0, 1)); - assertSame("extent", extent, grid.getExtent()); + assertArrayEquals(new double[] {0.5, 2}, grid.getResolution(false), "resolution"); + assertTrue(grid.isConversionLinear(0, 1), "isConversionLinear"); + assertSame(extent, grid.getExtent(), "extent"); verifyGridToCRS(grid); /* * Same envelope and extent, but flip Y axis. @@ -382,9 +384,9 @@ public final class GridGeometryTest extends TestCase { 0, 0, 1), matrix, STRICT); // Verify other computed properties. - assertArrayEquals("resolution", new double[] {0.5, 2}, grid.getResolution(false), STRICT); - assertTrue("isConversionLinear", grid.isConversionLinear(0, 1)); - assertSame("extent", extent, grid.getExtent()); + assertArrayEquals(new double[] {0.5, 2}, grid.getResolution(false), "resolution"); + assertTrue(grid.isConversionLinear(0, 1), "isConversionLinear"); + assertSame(extent, grid.getExtent(), "extent"); verifyGridToCRS(grid); /* * The use of `DISPLAY` mode in this particular case should be equivalent ro `REFLECTION_Y`. @@ -423,9 +425,9 @@ public final class GridGeometryTest extends TestCase { 0, 0, 1), matrix, STRICT); // Verify other computed properties. - assertArrayEquals("resolution", new double[] {0.5, 2}, grid.getResolution(false), STRICT); - assertTrue("isConversionLinear", grid.isConversionLinear(0, 1)); - assertSame("extent", extent, grid.getExtent()); + assertArrayEquals(new double[] {0.5, 2}, grid.getResolution(false), "resolution"); + assertTrue(grid.isConversionLinear(0, 1), "isConversionLinear"); + assertSame(extent, grid.getExtent(), "extent"); verifyGridToCRS(grid); /* * Same extent and envelope, but reordering extend dimensions @@ -443,9 +445,9 @@ public final class GridGeometryTest extends TestCase { new long[] { 9, 14}, grid.getExtent()); // Verify other computed properties. - assertArrayEquals("resolution", new double[] {0.5, 2}, grid.getResolution(false), STRICT); - assertTrue("isConversionLinear", grid.isConversionLinear(0, 1)); - assertNotSame("extent", extent, grid.getExtent()); + assertArrayEquals(new double[] {0.5, 2}, grid.getResolution(false), "resolution"); + assertTrue(grid.isConversionLinear(0, 1), "isConversionLinear"); + assertNotSame(extent, grid.getExtent(), "extent"); verifyGridToCRS(grid); } @@ -467,7 +469,7 @@ public final class GridGeometryTest extends TestCase { final Matrix gridToCRS = MathTransforms.getMatrix(grid.getGridToCRS(PixelInCell.CELL_CORNER)); final Number[] numbers = ((ExtendedPrecisionMatrix) gridToCRS).getElementAsNumbers(false); final double[] elements = MatrixSIS.castOrCopy(gridToCRS).getElements(); - assertArrayEquals(new double[] {360, 0, 0, -180, 0, 180, 0, -90, 0, 0, 3000, -1000, 0, 0, 0, 1}, elements, STRICT); + assertArrayEquals(new double[] {360, 0, 0, -180, 0, 180, 0, -90, 0, 0, 3000, -1000, 0, 0, 0, 1}, elements); assertEquals(elements.length, numbers.length); for (int i=0; i<elements.length; i++) { final double expected = elements[i]; @@ -475,7 +477,7 @@ public final class GridGeometryTest extends TestCase { if (expected == 0) { assertNull(actual); } else { - assertEquals(expected, actual.doubleValue(), STRICT); + assertEquals(expected, actual.doubleValue()); } } } @@ -539,9 +541,9 @@ public final class GridGeometryTest extends TestCase { final MathTransform gridToCRS = MathTransforms.linear(mat); expected = new GridGeometry(extent, PixelInCell.CELL_CENTER, gridToCRS, HardCodedCRS.CARTESIAN_2D); } - assertSame("envelope", grid.getEnvelope(), upsampled.getEnvelope()); - assertEquals("GridGeometry", expected, upsampled); - assertArrayEquals("resolution", new double[] {0.25, 0.5}, expected.getResolution(false), STRICT); + assertSame(grid.getEnvelope(), upsampled.getEnvelope(), "envelope"); + assertEquals(expected, upsampled, "GridGeometry"); + assertArrayEquals(new double[] {0.25, 0.5}, expected.getResolution(false), "resolution"); } /** @@ -613,8 +615,8 @@ public final class GridGeometryTest extends TestCase { GridGeometry reduced = grid.selectDimensions(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); + assertSame(HardCodedCRS.WGS84, reduced.getCoordinateReferenceSystem(), "CRS"); + assertArrayEquals(new double[] {0.5, 0.5}, reduced.getResolution(false), "resolution"); assertMatrixEquals("gridToCRS", new Matrix3( 0, 0.5, -90, 0.5, 0, -180, @@ -625,16 +627,16 @@ public final class GridGeometryTest extends TestCase { reduced = grid.selectDimensions(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); + assertSame(HardCodedCRS.GRAVITY_RELATED_HEIGHT, reduced.getCoordinateReferenceSystem(), "CRS"); + assertArrayEquals(new double[] {2}, reduced.getResolution(false), "resolution"); assertMatrixEquals("gridToCRS", new Matrix2( 2, 3, 0, 1), MathTransforms.getMatrix(reduced.getGridToCRS(PixelInCell.CELL_CORNER)), STRICT); /* * Verify other computed properties. */ - assertArrayEquals("resolution", new double[] {0.5, 0.5, 2}, grid.getResolution(false), STRICT); - assertTrue("isConversionLinear", grid.isConversionLinear(0, 1, 2)); + assertArrayEquals(new double[] {0.5, 0.5, 2}, grid.getResolution(false), "resolution"); + assertTrue(grid.isConversionLinear(0, 1, 2), "isConversionLinear"); verifyGridToCRS(grid); } @@ -668,8 +670,8 @@ public final class GridGeometryTest extends TestCase { /* * Verify other computed properties. */ - assertArrayEquals("resolution", new double[] {0.5, 0.5}, reduced.getResolution(false), STRICT); - assertTrue("isConversionLinear", reduced.isConversionLinear(0, 1)); + assertArrayEquals(new double[] {0.5, 0.5}, reduced.getResolution(false), "resolution"); + assertTrue(reduced.isConversionLinear(0, 1), "isConversionLinear"); verifyGridToCRS(reduced); /* * Test again by keeping the dimension without scale instead of discarding it. @@ -680,6 +682,44 @@ public final class GridGeometryTest extends TestCase { assertMatrixEquals("gridToCRS", new Matrix2(0, 3, 0, 1), MathTransforms.getMatrix(tr), STRICT); } + /** + * Tests {@link GridGeometry#GridGeometry(GridGeometry, GridGeometry)}. + * + * @throws FactoryException if the constructor could not combine the CRS. + */ + @Test + public void testConcatenate() throws FactoryException { + final GridGeometry lower = new GridGeometry( + new GridExtent(null, null, new long[] {17, 10}, true), + PixelInCell.CELL_CENTER, + MathTransforms.linear(new Matrix3( + 1, 0, -7, + 0, -1, 50, + 0, 0, 1)), + HardCodedCRS.WGS84); + + final GridGeometry upper = new GridGeometry( + new GridExtent(null, null, new long[] {4}, true), + PixelInCell.CELL_CENTER, + MathTransforms.linear(new Matrix2( + 8, 20, + 0, 1)), + HardCodedCRS.TIME); + + final GridGeometry expected = new GridGeometry( + new GridExtent(null, null, new long[] {17, 10, 4}, true), + PixelInCell.CELL_CENTER, + MathTransforms.linear(new Matrix4( + 1, 0, 0, -7, + 0, -1, 0, 50, + 0, 0, 8, 20, + 0, 0, 0, 1)), + HardCodedCRS.WGS84_WITH_TIME); + + final GridGeometry actual = new GridGeometry(lower, upper); + assertTrue(actual.equals(expected, ComparisonMode.DEBUG)); + } + /** * Tests {@link GridGeometry#createImageCRS(String, PixelInCell)}. */ diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/ArraysExt.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/ArraysExt.java index e6baf24db0..87ccac229d 100644 --- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/ArraysExt.java +++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/ArraysExt.java @@ -67,7 +67,7 @@ import java.lang.reflect.Array; * objects. * * @author Martin Desruisseaux (IRD, Geomatys) - * @version 1.4 + * @version 1.5 * * @see Arrays * @@ -1219,6 +1219,24 @@ public final class ArraysExt extends Static { return copy; } + /** + * Returns the concatenation of the given arrays. + * If any of the supplied arrays is null or empty, then the other array is returned directly (not copied). + * + * @param a1 the first array to concatenate, or {@code null}. + * @param a2 the second array to concatenate, or {@code null}. + * @return the concatenation of given arrays. May be one of the given arrays returned without copying. + * + * @since 1.5 + */ + public static double[] concatenate(final double[] a1, final double[] a2) { + if (a1 == null || a1.length == 0) return a2; + if (a2 == null || a2.length == 0) return a1; + final double[] copy = Arrays.copyOf(a1, a1.length + a2.length); + System.arraycopy(a2, 0, copy, a1.length, a2.length); + return copy; + } + /** * Removes the duplicated elements in the given array. This method should be invoked only for small arrays, * typically less than 10 distinct elements. For larger arrays, use {@link java.util.LinkedHashSet} instead.