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 9cb97c64c3e89899bef6299568ad5f1b2a33ec5f Author: Martin Desruisseaux <[email protected]> AuthorDate: Wed Feb 11 18:33:20 2026 +0100 Add a `GridExtent.reshape(long[])` method and use that for simplifying some code. Minor opportunistic reformating. --- .../org/apache/sis/coverage/grid/GridExtent.java | 61 ++++++++++++++++------ .../apache/sis/coverage/grid/GridExtentTest.java | 10 +++- .../sis/storage/geotiff/ImageFileDirectory.java | 5 +- .../sis/storage/UnsupportedQueryException.java | 1 + .../sis/storage/aggregate/GridSliceLocator.java | 5 +- .../apache/sis/storage/base/TiledGridCoverage.java | 5 +- .../org/apache/sis/storage/CoverageQueryTest.java | 8 ++- .../storage/MemoryGridCoverageResourceTest.java | 6 ++- .../sis/storage/test/CoverageReadConsistency.java | 2 +- .../main/org/apache/sis/util/ArgumentChecks.java | 26 ++++++++- .../main/org/apache/sis/gui/map/MapCanvas.java | 6 ++- 11 files changed, 98 insertions(+), 37 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 07d68fc690..e7c887de45 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 @@ -92,7 +92,7 @@ import org.opengis.coverage.grid.GridCoordinates; * @author Martin Desruisseaux (IRD, Geomatys) * @author Alexis Manin (Geomatys) * @author Johann Sorel (Geomatys) - * @version 1.5 + * @version 1.7 * @since 1.0 */ public class GridExtent implements GridEnvelope, LenientComparable, Serializable { @@ -355,28 +355,33 @@ public class GridExtent implements GridEnvelope, LenientComparable, Serializable * * @see #getLow() * @see #getHigh() - * @see #insertDimension(int, DimensionNameType, long, long, boolean) + * @see #reshape(long[], long[], boolean) */ public GridExtent(final DimensionNameType[] axisTypes, final long[] low, final long[] high, final boolean isHighIncluded) { - final int dimension = high.length; - if (low != null && low.length != dimension) { - throw new IllegalArgumentException(Errors.format(Errors.Keys.MismatchedDimension_2, low.length, dimension)); - } - if (axisTypes != null && axisTypes.length != dimension) { - throw new IllegalArgumentException(Errors.format(Errors.Keys.MismatchedArrayLengths)); - } - coordinates = allocate(dimension); + ArgumentChecks.ensureNonNull("high", high); + coordinates = pack(axisTypes != null ? axisTypes.length : high.length, low, high, isHighIncluded); + types = validateAxisTypes(axisTypes); + validateCoordinates(); + } + + /** + * Returns the given coordinates packed in a single array. + * This method verifies that the array lengths match the expected number of dimensions. + */ + private static long[] pack(final int dimension, final long[] low, final long[] high, final boolean isHighIncluded) { + ArgumentChecks.ensureDimensionMatches("low", dimension, low); + ArgumentChecks.ensureDimensionMatches("high", dimension, high); + final long[] coordinates = allocate(dimension); if (low != null) { System.arraycopy(low, 0, coordinates, 0, dimension); } System.arraycopy(high, 0, coordinates, dimension, dimension); if (!isHighIncluded) { - for (int i=dimension; i < coordinates.length; i++) { + for (int i = dimension; i < coordinates.length; i++) { coordinates[i] = Math.decrementExact(coordinates[i]); } } - types = validateAxisTypes(axisTypes); - validateCoordinates(); + return coordinates; } /** @@ -644,8 +649,8 @@ public class GridExtent implements GridEnvelope, LenientComparable, Serializable /** * Creates a new grid extent with the same axes as the given extent, but different coordinates. - * This constructor does not invoke {@link #validateCoordinates()}; we presume that the caller's - * computation is correct. + * This constructor does not invoke {@link #validateCoordinates()}, instead it presumes that the + * caller's computation is correct. * * @param enclosing the extent from which to copy axes, or {@code null} if none. * @param coordinates the coordinates. This array is not cloned. @@ -1644,6 +1649,32 @@ public class GridExtent implements GridEnvelope, LenientComparable, Serializable return Arrays.equals(c, coordinates) ? this : resize; } + /** + * Returns an extent with the same number of dimensions and the same axes than this extent, + * but different coordinate values. + * + * @param low the valid minimum grid coordinates (always inclusive), or {@code null} for all zeros. + * @param high the valid maximum grid coordinates, inclusive or exclusive depending on the next argument. + * @param isHighIncluded {@code true} if the {@code high} values are inclusive, or {@code false} if they are exclusive. + * @throws IllegalArgumentException if a coordinate value in the low part is + * greater than the corresponding coordinate value in the high part. + * @return a grid extent with the same axes but the given coordinates. + * + * @see #GridExtent(DimensionNameType[], long[], long[], boolean) + * + * @since 1.7 + */ + public GridExtent reshape(final long[] low, final long[] high, final boolean isHighIncluded) { + ArgumentChecks.ensureNonNull("high", high); + final long[] copy = pack(getDimension(), low, high, isHighIncluded); + if (Arrays.equals(copy, coordinates)) { + return this; + } + final var extent = new GridExtent(this, copy); + extent.validateCoordinates(); + return extent; + } + /** * Creates a new grid extent subsampled by the given number of cells along each grid dimensions. * This method divides {@linkplain #getLow(int) low coordinates} and {@linkplain #getSize(int) grid sizes} 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 f8d5785caf..d80f1bab6a 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 @@ -71,8 +71,14 @@ public final class GridExtentTest extends TestCase { */ private static GridExtent create3D() { return new GridExtent( - new DimensionNameType[] {DimensionNameType.COLUMN, DimensionNameType.ROW, DimensionNameType.TIME}, - new long[] {100, 200, 40}, new long[] {500, 800, 50}, false); + new DimensionNameType[] { + DimensionNameType.COLUMN, + DimensionNameType.ROW, + DimensionNameType.TIME + }, + new long[] {100, 200, 40}, + new long[] {500, 800, 50}, + false); } /** diff --git a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/ImageFileDirectory.java b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/ImageFileDirectory.java index f7005e7c37..25570a7b9c 100644 --- a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/ImageFileDirectory.java +++ b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/ImageFileDirectory.java @@ -35,7 +35,6 @@ import static javax.imageio.plugins.tiff.GeoTIFFTagSet.*; import static javax.imageio.plugins.tiff.BaselineTIFFTagSet.*; import org.opengis.metadata.Metadata; import org.opengis.metadata.citation.DateType; -import org.opengis.metadata.spatial.DimensionNameType; import org.opengis.util.GenericName; import org.opengis.util.NameSpace; import org.opengis.util.FactoryException; @@ -1486,11 +1485,9 @@ final class ImageFileDirectory extends DataCube { final GridGeometry geometry = fullResolution.getGridGeometry(); final GridExtent fullExtent = geometry.getExtent(); final int dimension = fullExtent.getDimension(); - final var axisTypes = new DimensionNameType[dimension]; final var scales = new double[dimension]; final var high = new long[dimension]; for (int i=0; i<dimension; i++) { - axisTypes[i] = fullExtent.getAxisType(i).orElse(null); final long size; switch (i) { case 0: size = imageWidth; break; @@ -1503,7 +1500,7 @@ final class ImageFileDirectory extends DataCube { if (referencing == null) { gridGeometry = new GridGeometry( geometry, - new GridExtent(axisTypes, null, high, true), + fullExtent.reshape(null, high, true), MathTransforms.scale(scales)); } if (samplesPerPixel == fullResolution.samplesPerPixel) { diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/UnsupportedQueryException.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/UnsupportedQueryException.java index b0a5d879ac..1b61b1b438 100644 --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/UnsupportedQueryException.java +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/UnsupportedQueryException.java @@ -27,6 +27,7 @@ package org.apache.sis.storage; * <li>The query is requesting a property that does not exist in the {@link Resource}.</li> * <li>The values in the {@link DataStore} are unconvertible to some characteristics * (e.g., type or name) requested by the query.</li> + * <li>The query is too large (e.g., overflows the capability of some integer type).</li> * </ul> * * This exception may be thrown when {@link FeatureSet#subset(Query)} is executed, diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/aggregate/GridSliceLocator.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/aggregate/GridSliceLocator.java index 5af99db062..6333116a62 100644 --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/aggregate/GridSliceLocator.java +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/aggregate/GridSliceLocator.java @@ -18,7 +18,6 @@ package org.apache.sis.storage.aggregate; import java.util.Arrays; import org.opengis.util.InternationalString; -import org.opengis.metadata.spatial.DimensionNameType; import org.apache.sis.coverage.grid.GridExtent; import org.apache.sis.coverage.grid.GridGeometry; import org.apache.sis.util.ArraysExt; @@ -96,11 +95,9 @@ final class GridSliceLocator { this.sliceHighs = new long[selected.length]; GridExtent aoi = domain.getExtent(); final int dimension = aoi.getDimension(); - final var axes = new DimensionNameType[dimension]; final var low = new long[dimension]; final var high = new long[dimension]; for (int i=0; i<dimension; i++) { - axes[i] = aoi.getAxisType(i).orElse(null); low [i] = Long.MAX_VALUE; high[i] = Long.MIN_VALUE; } @@ -114,7 +111,7 @@ final class GridSliceLocator { high[j] = Math.max(high[j], extent.getHigh(j)); } } - if (!aoi.equals(aoi = new GridExtent(axes, low, high, true))) { + if (!aoi.equals(aoi = aoi.reshape(low, high, true))) { var crs = domain.isDefined(GridGeometry.CRS) ? domain.getCoordinateReferenceSystem() : null; domain = new GridGeometry(aoi, GridSlice.CELL_ANCHOR, domain.getGridToCRS(GridSlice.CELL_ANCHOR), crs); } diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/TiledGridCoverage.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/TiledGridCoverage.java index 332778096c..b921826c94 100644 --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/TiledGridCoverage.java +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/TiledGridCoverage.java @@ -36,7 +36,6 @@ import static java.lang.Math.decrementExact; import static java.lang.Math.toIntExact; import static java.lang.Math.floorDiv; import org.opengis.util.GenericName; -import org.opengis.metadata.spatial.DimensionNameType; import org.apache.sis.coverage.grid.GridCoverage; import org.apache.sis.coverage.grid.GridExtent; import org.apache.sis.coverage.grid.DisjointExtentException; @@ -1076,15 +1075,13 @@ public abstract class TiledGridCoverage extends GridCoverage { */ public GridExtent getFullRegionInResourceCoordinates() { final int dimension = tileLower.length; - final var axes = new DimensionNameType[dimension]; final long[] lower = new long[dimension]; final long[] upper = new long[dimension]; for (int i=0; i<dimension; i++) { - axes [i] = readExtent.getAxisType(i).orElse(null); lower[i] = Math.max(coverageTileToResourceCell(tileLower[i], i), readExtent.getLow(i)); upper[i] = Math.min(coverageTileToResourceCell(tileUpper[i], i)-1, readExtent.getHigh(i)); } - return new GridExtent(axes, lower, upper, true); + return readExtent.reshape(lower, upper, true); } /** diff --git a/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/CoverageQueryTest.java b/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/CoverageQueryTest.java index 3202f5e829..11ea0815e6 100644 --- a/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/CoverageQueryTest.java +++ b/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/CoverageQueryTest.java @@ -37,6 +37,7 @@ import org.apache.sis.referencing.crs.HardCodedCRS; * * @author Johann Sorel (Geomatys) */ +@SuppressWarnings("exports") public final class CoverageQueryTest extends TestCase { /** * The coordinate reference system used by the tests. @@ -82,8 +83,11 @@ public final class CoverageQueryTest extends TestCase { * Creates an arbitrary grid geometry included inside the {@linkplain #resource} extent. */ private GridGeometry createSubGrid(final int expansion) { - final GridExtent extent = new GridExtent( - new DimensionNameType[] {DimensionNameType.COLUMN, DimensionNameType.ROW}, + final var extent = new GridExtent( + new DimensionNameType[] { + DimensionNameType.COLUMN, + DimensionNameType.ROW + }, new long[] { 7 - expansion, 19 - expansion}, new long[] {21 + expansion, 27 + expansion}, true); diff --git a/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/MemoryGridCoverageResourceTest.java b/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/MemoryGridCoverageResourceTest.java index e900922d2f..e80ff9878d 100644 --- a/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/MemoryGridCoverageResourceTest.java +++ b/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/MemoryGridCoverageResourceTest.java @@ -75,9 +75,11 @@ public final class MemoryGridCoverageResourceTest extends TestCase { * Creates an arbitrary grid geometry included inside the {@linkplain #resource} extent. */ private GridGeometry createSubGrid() { - final var extent = new GridExtent(null, + final var extent = new GridExtent( + null, new long[] {7, 4}, - new long[] {WIDTH - 9, HEIGHT - 11}, true); + new long[] {WIDTH - 9, HEIGHT - 11}, + true); return new GridGeometry(extent, PixelInCell.CELL_CENTER, gridToCRS, crs); } diff --git a/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/test/CoverageReadConsistency.java b/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/test/CoverageReadConsistency.java index f44e47ccdf..ae7a4460bd 100644 --- a/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/test/CoverageReadConsistency.java +++ b/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/test/CoverageReadConsistency.java @@ -319,7 +319,7 @@ public abstract class CoverageReadConsistency<S extends DataStore> extends TestC subsampling[d] += random.nextInt(StrictMath.max(rs / 16, 1)); } } - return gg.derive().subgrid(new GridExtent(null, low, high, true), subsampling).build(); + return gg.derive().subgrid(fullExtent.reshape(low, high, true), subsampling).build(); } /** diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/ArgumentChecks.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/ArgumentChecks.java index d842f5a165..ca28d60e38 100644 --- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/ArgumentChecks.java +++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/ArgumentChecks.java @@ -83,7 +83,7 @@ import org.opengis.coverage.grid.GridEnvelope; * * @author Martin Desruisseaux (Geomatys) * @author Alexis Manin (Geomatys) - * @version 1.6 + * @version 1.7 * @since 0.3 */ public final class ArgumentChecks { @@ -779,6 +779,30 @@ public final class ArgumentChecks { } } + /** + * Ensures that the given array of indices, if non-null, has the expected number of dimensions + * (taken as its length). This method does nothing if the given array is null. + * + * @param name the name of the argument to be checked. Used only if an exception is thrown. + * @param expected the expected number of dimensions. + * @param indices the array of indices to check for its number of dimensions, or {@code null}. + * @throws MismatchedDimensionException if the given array of indices is non-null and does not have + * the expected number of dimensions (taken as its length). + * + * @since 1.7 + */ + public static void ensureDimensionMatches(final String name, final int expected, final long[] indices) + throws MismatchedDimensionException + { + if (indices != null) { + final int dimension = indices.length; + if (dimension != expected) { + throw new MismatchedDimensionException(Errors.format( + Errors.Keys.MismatchedDimension_3, name, expected, dimension)); + } + } + } + /** * Ensures that the given vector, if non-null, has the expected number of dimensions * (taken as its length). This method does nothing if the given vector is null. diff --git a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/map/MapCanvas.java b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/map/MapCanvas.java index 10c3de3a84..4f3c69678b 100644 --- a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/map/MapCanvas.java +++ b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/map/MapCanvas.java @@ -1195,9 +1195,11 @@ public abstract class MapCanvas extends PlanarCanvas { return; } invalidObjectiveToDisplay = false; - final var extent = new GridExtent(null, + final var extent = new GridExtent( + null, new long[] {Math.round(target.getMinX()), Math.round(target.getMinY())}, - new long[] {Math.round(target.getMaxX()), Math.round(target.getMaxY())}, false); + new long[] {Math.round(target.getMaxX()), Math.round(target.getMaxY())}, + false); /* * The main purpose of this block is to find the initial value of the `objectiveToDisplay` transform * (named `crsToDisplay` here). If that value was explicitly specified by a call to `initialize(…)`,
