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 2358b982a043579d645ca8f6fce4fbd17b8bffd4
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Thu Feb 12 15:27:12 2026 +0100

    Replace `X_DIMENSION` and `Y_DIMENSION` constant by configurable fields.
    The intend it to reduce the risk of breaking API compatibility in future 
evolutions.
---
 .../sis/storage/geotiff/CompressedSubset.java      |  12 +-
 .../org/apache/sis/storage/geotiff/DataCube.java   |   2 +-
 .../org/apache/sis/storage/geotiff/DataSubset.java |  12 +-
 .../sis/storage/tiling/TiledDeferredImage.java     |  12 +-
 .../sis/storage/tiling/TiledGridCoverage.java      | 138 +++++++++++++--------
 .../sis/storage/tiling/TiledGridResource.java      |  74 +++++++++--
 6 files changed, 171 insertions(+), 79 deletions(-)

diff --git 
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/CompressedSubset.java
 
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/CompressedSubset.java
index 72c93d2e25..48750c39b0 100644
--- 
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/CompressedSubset.java
+++ 
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/CompressedSubset.java
@@ -102,7 +102,7 @@ final class CompressedSubset extends DataSubset {
     CompressedSubset(final DataCube source, final TiledGridResource.Subset 
subset) throws DataStoreException {
         super(source, subset);
         long afterLastBand = sourceScanlineStride - sourcePixelStride;
-        final int between  = Math.multiplyExact(sourcePixelStride, 
Math.toIntExact(getSubsampling(X_DIMENSION) - 1));
+        final int between  = Math.multiplyExact(sourcePixelStride, 
Math.toIntExact(getSubsampling(xDimension) - 1));
         if (includedBands != null && sourcePixelStride > 1) {
             final int[] skips = new int[includedBands.length];
             final int m = skips.length - 1;
@@ -184,12 +184,12 @@ final class CompressedSubset extends DataSubset {
                      final long[] subsampling, final Point location) throws 
IOException, DataStoreException
     {
         final DataType dataType = getDataType();
-        final int  width        = pixelCount(lower, upper, subsampling, 
X_DIMENSION);
-        final int  height       = pixelCount(lower, upper, subsampling, 
Y_DIMENSION);
+        final int  width        = pixelCount(lower, upper, subsampling, 
xDimension);
+        final int  height       = pixelCount(lower, upper, subsampling, 
yDimension);
         final int  chunksPerRow = width * (targetPixelStride / 
samplesPerChunk);
         final int  betweenRows  = Math.toIntExact(subsampling[1] - 1);
-        final long head         = beforeFirstBand + sourcePixelStride * 
(lower[X_DIMENSION]);
-        final long tail         = afterLastBand   - sourcePixelStride * 
(lower[X_DIMENSION] + (width-1)*subsampling[X_DIMENSION]);
+        final long head         = beforeFirstBand + sourcePixelStride * 
(lower[xDimension]);
+        final long tail         = afterLastBand   - sourcePixelStride * 
(lower[xDimension] + (width-1)*subsampling[xDimension]);
         /*
          * `head` and `tail` are the number of sample values to skip at the 
beginning and end of each row.
          * `betweenPixels` is the number of sample values to skip between each 
pixel, but the actual skips
@@ -211,7 +211,7 @@ final class CompressedSubset extends DataSubset {
                     source.getCompression(),              // The compression 
method.
                     source.getPredictor(),                // The mathematical 
operator to apply after decompression.
                     sourcePixelStride,                    // Number of sample 
values per pixel in the source image.
-                    toIntExact(getTileSize(X_DIMENSION)), // Number of pixels 
in a row of source image.
+                    toIntExact(getTileSize(xDimension)),  // Number of pixels 
in a row of source image.
                     chunksPerRow,                         // Number of pixels 
per row in target image.
                     samplesPerChunk,                      // Number of sample 
values per pixel.
                     skipAfterChunks,                      // Number of sample 
values to skip between pixels.
diff --git 
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/DataCube.java
 
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/DataCube.java
index c5ec2f001e..d9fd5c52e5 100644
--- 
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/DataCube.java
+++ 
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/DataCube.java
@@ -197,7 +197,7 @@ abstract class DataCube extends TiledGridResource 
implements StoreResource {
      */
     @Override
     protected final boolean canReadTruncatedTiles(int dim, boolean suggested) {
-        return suggested | (dim >= 1);      // Y_DIMENSION.
+        return suggested | (dim >= 1);      // yDimension = 1.
     }
 
     /**
diff --git 
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/DataSubset.java
 
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/DataSubset.java
index 943f67d9dd..1923a65834 100644
--- 
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/DataSubset.java
+++ 
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/DataSubset.java
@@ -512,8 +512,8 @@ class DataSubset extends TiledGridCoverage implements 
Localized {
     {
         final DataType type = getDataType();
         final int sampleSize = type.size();     // Assumed same as 
`SampleModel.getSampleSize(…)` by preconditions.
-        final long width  = subtractExact(upper[X_DIMENSION], 
lower[X_DIMENSION]);
-        final long height = subtractExact(upper[Y_DIMENSION], 
lower[Y_DIMENSION]);
+        final long width  = subtractExact(upper[xDimension], 
lower[xDimension]);
+        final long height = subtractExact(upper[yDimension], 
lower[yDimension]);
         /*
          * The number of bytes to read should not be greater than `byteCount`. 
It may be smaller however if only
          * a subregion is read. Note that the `length` value may be different 
than `capacity` if the tile to read
@@ -521,15 +521,15 @@ class DataSubset extends TiledGridCoverage implements 
Localized {
          * This length is used only for verification purpose so it does not 
need to be exact.
          */
         final long length = ceilDiv(width * height * sourcePixelStride * 
sampleSize, Byte.SIZE);
-        final long[] size = new long[] {sourceScanlineStride, 
getTileSize(Y_DIMENSION)};
+        final long[] size = new long[] {sourceScanlineStride, 
getTileSize(yDimension)};
         /*
          * If we use an interleaved sample model, each "element" from 
`HyperRectangleReader` perspective is actually a
          * group of `sourcePixelStride` values. Note that in such case, we 
cannot handle subsampling on the first axis.
          * Such case should be handled by the `CompressedSubset` subclass 
instead, even if there is no compression.
          */
-        assert sourcePixelStride == 1 || subsampling[X_DIMENSION] == 1;
-        lower[X_DIMENSION] *= sourcePixelStride;
-        upper[X_DIMENSION] *= sourcePixelStride;
+        assert sourcePixelStride == 1 || subsampling[xDimension] == 1;
+        lower[xDimension] *= sourcePixelStride;
+        upper[xDimension] *= sourcePixelStride;
         /*
          * Read each plane ("banks" in Java2D terminology). Note that a single 
bank contains all bands
          * in the interleaved sample model case. This block assumes that each 
bank element contains
diff --git 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/TiledDeferredImage.java
 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/TiledDeferredImage.java
index 50812101ee..c8936935d1 100644
--- 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/TiledDeferredImage.java
+++ 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/TiledDeferredImage.java
@@ -61,10 +61,10 @@ final class TiledDeferredImage extends BatchComputedImage {
                        final TiledGridCoverage.TileIterator iterator)
     {
         super(iterator.getCoverage().model, properties);
-        this.width    = imageSize[TiledGridCoverage.X_DIMENSION];
-        this.height   = imageSize[TiledGridCoverage.Y_DIMENSION];
-        this.minTileX = tileLower[TiledGridCoverage.X_DIMENSION];
-        this.minTileY = tileLower[TiledGridCoverage.Y_DIMENSION];
+        this.width    = imageSize[iterator.xDimension];
+        this.height   = imageSize[iterator.yDimension];
+        this.minTileX = tileLower[iterator.xDimension];
+        this.minTileY = tileLower[iterator.yDimension];
         this.iterator = iterator;
     }
 
@@ -75,12 +75,12 @@ final class TiledDeferredImage extends BatchComputedImage {
 
     /** Returns the minimum <var>x</var> coordinate (inclusive) of this image. 
*/
     @Override public final int getMinX() {
-        return iterator.getTileOrigin(TiledGridCoverage.X_DIMENSION);
+        return iterator.getTileOrigin(iterator.xDimension);
     }
 
     /** Returns the minimum <var>y</var> coordinate (inclusive) of this image. 
*/
     @Override public final int getMinY() {
-        return iterator.getTileOrigin(TiledGridCoverage.Y_DIMENSION);
+        return iterator.getTileOrigin(iterator.yDimension);
     }
 
     /** Returns the number of pixels along X axis in the whole rendered image. 
*/
diff --git 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/TiledGridCoverage.java
 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/TiledGridCoverage.java
index 06498ac4d7..44f0bae9eb 100644
--- 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/TiledGridCoverage.java
+++ 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/TiledGridCoverage.java
@@ -81,12 +81,6 @@ import org.opengis.coordinate.MismatchedDimensionException;
  * @since   1.7
  */
 public abstract class TiledGridCoverage extends GridCoverage {
-    /**
-     * The dimensions of <var>x</var> and <var>y</var> axes.
-     * Static constants for now, may become configurable fields in the future.
-     */
-    protected static final int X_DIMENSION = 0, Y_DIMENSION = 1;
-
     /**
      * The area to read in unit of the full coverage (without subsampling).
      * This is the intersection between user-specified domain and the source
@@ -209,6 +203,26 @@ public abstract class TiledGridCoverage extends 
GridCoverage {
      */
     protected final int[] includedBands;
 
+    /**
+     * The dimension of the grid which is mapped to the <var>x</var> axis 
(column indexes) in rendered images.
+     * This is the value of the {@code xDimension} argument in the last call 
to the
+     * {@link TiledGridResource#setRasterDimension(int, int)} method before 
this coverage has been constructed.
+     * This value is usually 0.
+     *
+     * @see #readTiles(TileIterator)
+     */
+    protected final int xDimension;
+
+    /**
+     * The dimension of the grid which is mapped to the <var>y</var> axis (row 
indexes) in rendered images.
+     * This is the value of the {@code yDimension} argument in the last call 
to the
+     * {@link TiledGridResource#setRasterDimension(int, int)} method before 
this coverage has been constructed.
+     * This value is usually 1.
+     *
+     * @see #readTiles(TileIterator)
+     */
+    protected final int yDimension;
+
     /**
      * Cache of rasters read by this {@code TiledGridCoverage}. This cache may 
be shared with other coverages
      * created for the same {@link TiledGridResource} resource. For each 
value, the raster {@code minX} and
@@ -262,7 +276,8 @@ public abstract class TiledGridCoverage extends 
GridCoverage {
      */
     protected TiledGridCoverage(final TiledGridResource.Subset subset) {
         super(subset.domain, subset.ranges);
-        final GridExtent extent = subset.domain.getExtent();
+        xDimension          = subset.xDimension();
+        yDimension          = subset.yDimension();
         deferredTileReading = subset.deferredTileReading();     // May be 
shorter than other arrays or the grid geometry.
         readExtent          = subset.readExtent;
         subsampling         = subset.subsampling;
@@ -274,7 +289,7 @@ public abstract class TiledGridCoverage extends 
GridCoverage {
         tmcOfFirstTile      = new long[dimension];
         tileStrides         = new int [dimension];
         final int[] subSize = new int [dimension];
-
+        final GridExtent extent = subset.domain.getExtent();
         @SuppressWarnings("LocalVariableHidesMemberVariable")
         long indexOfFirstTile = 0;
         int  tileStride       = 1;
@@ -295,8 +310,8 @@ public abstract class TiledGridCoverage extends 
GridCoverage {
          */
         @SuppressWarnings("LocalVariableHidesMemberVariable")
         SampleModel model = subset.modelForBandSubset;
-        if (model.getWidth() != subSize[X_DIMENSION] || model.getHeight() != 
subSize[Y_DIMENSION]) {
-            model = model.createCompatibleSampleModel(subSize[X_DIMENSION], 
subSize[Y_DIMENSION]);
+        if (model.getWidth() != subSize[xDimension] || model.getHeight() != 
subSize[yDimension]) {
+            model = model.createCompatibleSampleModel(subSize[xDimension], 
subSize[yDimension]);
         }
         this.model      = model;
         this.colors     = subset.colorsForBandSubset;
@@ -484,10 +499,10 @@ public abstract class TiledGridCoverage extends 
GridCoverage {
         if (extent == null) {
             return null;
         }
-        return new Rectangle(toIntExact(extent.getLow (X_DIMENSION)),
-                             toIntExact(extent.getLow (Y_DIMENSION)),
-                             toIntExact(extent.getSize(X_DIMENSION)),
-                             toIntExact(extent.getSize(Y_DIMENSION)));
+        return new Rectangle(toIntExact(extent.getLow (xDimension)),
+                             toIntExact(extent.getLow (yDimension)),
+                             toIntExact(extent.getSize(xDimension)),
+                             toIntExact(extent.getSize(yDimension)));
     }
 
     /**
@@ -512,9 +527,9 @@ public abstract class TiledGridCoverage extends 
GridCoverage {
             }
         }
         final int[] selectedDimensions = 
sliceExtent.getSubspaceDimensions(BIDIMENSIONAL);
-        if (selectedDimensions[1] != 1) {
+        if (selectedDimensions[0] != xDimension || selectedDimensions[1] != 
yDimension) {
             // TODO
-            throw new UnsupportedOperationException("Non-horizontal slices not 
yet implemented.");
+            throw new UnsupportedOperationException("Slices in arbitrary 
dimensions not yet implemented.");
         }
         final RenderedImage image;
         try {
@@ -550,7 +565,7 @@ public abstract class TiledGridCoverage extends 
GridCoverage {
              * Prepare an iterator over all tiles to read, together with the 
following properties:
              *    - Two-dimensional conversion from pixel coordinates to "real 
world" coordinates.
              */
-            final var iterator = new TileIterator(tileLower, tileUpper, 
offsetAOI, dimension);
+            final var iterator = new TileIterator(tileLower, tileUpper, 
offsetAOI, dimension, xDimension, yDimension);
             final Map<String,Object> properties = 
DeferredProperty.forGridGeometry(gridGeometry, selectedDimensions);
             if (deferredTileReading) {
                 image = new TiledDeferredImage(imageSize, tileLower, 
properties, iterator);
@@ -561,8 +576,8 @@ public abstract class TiledGridCoverage extends 
GridCoverage {
                  */
                 final Raster[] result = readTiles(iterator);
                 image = new TiledImage(properties, colors,
-                        imageSize[X_DIMENSION], imageSize[Y_DIMENSION],
-                        tileLower[X_DIMENSION], tileLower[Y_DIMENSION], 
result);
+                        imageSize[xDimension], imageSize[yDimension],
+                        tileLower[xDimension], tileLower[yDimension], result);
             }
         } catch (DisjointExtentException | CannotEvaluateException e) {
             throw e;
@@ -582,6 +597,11 @@ public abstract class TiledGridCoverage extends 
GridCoverage {
      * of the iterator position as an instant ({@link Snapshot}).
      */
     protected static abstract class AOI {
+        /**
+         * The dimension of the <var>x</var> and <var>y</var> axes in rendered 
images.
+         */
+        final int xDimension, yDimension;
+
         /**
          * Tile Matrix Coordinates (TMC) relative to the enclosing {@link 
TiledGridCoverage}.
          * Tile (0,0) is the tile in the upper-left corner of this {@link 
TiledGridCoverage},
@@ -628,7 +648,9 @@ public abstract class TiledGridCoverage extends 
GridCoverage {
         /**
          * Creates a new area of interest.
          */
-        AOI(final int[] tmcInSubset, final int[] uncroppedTileLocation) {
+        AOI(final int xDimension, final int yDimension, final int[] 
tmcInSubset, final int[] uncroppedTileLocation) {
+            this.xDimension  = xDimension;
+            this.yDimension  = yDimension;
             this.tmcInSubset = tmcInSubset;
             this.uncroppedTileLocation = uncroppedTileLocation;
         }
@@ -703,8 +725,8 @@ public abstract class TiledGridCoverage extends 
GridCoverage {
                  * Found a tile, but the sample model may be different because 
band order may be different.
                  * In any cases, we need to make sure that the raster starts 
at the expected coordinates.
                  */
-                final int x = getTileOrigin(X_DIMENSION);
-                final int y = getTileOrigin(Y_DIMENSION);
+                final int x = getTileOrigin(xDimension);
+                final int y = getTileOrigin(yDimension);
                 final SampleModel model = coverage.model;
                 if (model.equals(tile.getSampleModel())) {
                     if (tile.getMinX() == x && tile.getMinY() == y) {
@@ -763,8 +785,8 @@ public abstract class TiledGridCoverage extends 
GridCoverage {
          * @return a newly created, initially empty raster.
          */
         public WritableRaster createRaster() {
-            final int x = getTileOrigin(X_DIMENSION);
-            final int y = getTileOrigin(Y_DIMENSION);
+            final int x = getTileOrigin(xDimension);
+            final int y = getTileOrigin(yDimension);
             return Raster.createWritableRaster(getCoverage().model, new 
Point(x, y));
         }
 
@@ -781,8 +803,8 @@ public abstract class TiledGridCoverage extends 
GridCoverage {
          * @see Raster#createTranslatedChild(int, int)
          */
         public Raster moveRaster(final Raster raster) {
-            final int x = getTileOrigin(X_DIMENSION);
-            final int y = getTileOrigin(Y_DIMENSION);
+            final int x = getTileOrigin(xDimension);
+            final int y = getTileOrigin(yDimension);
             if (raster.getMinX() == x && raster.getMinY() == y) {
                 return raster;
             }
@@ -811,8 +833,8 @@ public abstract class TiledGridCoverage extends 
GridCoverage {
             if (uncroppedTileLocation == null) {
                 return Optional.empty();    // Usual case.
             }
-            return Optional.of(new Point(uncroppedTileLocation[X_DIMENSION],
-                                         uncroppedTileLocation[Y_DIMENSION]));
+            return Optional.of(new Point(uncroppedTileLocation[xDimension],
+                                         uncroppedTileLocation[yDimension]));
         }
 
         /**
@@ -861,10 +883,10 @@ public abstract class TiledGridCoverage extends 
GridCoverage {
             final long[] upper = new long[BIDIMENSIONAL];
             if (getRegionInsideTile(lower, upper, null, subsampled)) {
                 return new Rectangle(
-                        toIntExact(lower[X_DIMENSION]),
-                        toIntExact(lower[Y_DIMENSION]),
-                        toIntExact(subtractExact(upper[X_DIMENSION], 
lower[X_DIMENSION])),
-                        toIntExact(subtractExact(upper[Y_DIMENSION], 
lower[Y_DIMENSION])));
+                        toIntExact(lower[xDimension]),
+                        toIntExact(lower[yDimension]),
+                        toIntExact(subtractExact(upper[xDimension], 
lower[xDimension])),
+                        toIntExact(subtractExact(upper[yDimension], 
lower[yDimension])));
             }
             return null;
         }
@@ -1000,8 +1022,14 @@ public abstract class TiledGridCoverage extends 
GridCoverage {
          * @param  offsetAOI  pixel coordinates to assign to the upper-left 
corner of the subsampled region to render.
          * @param  dimension  number of dimension of the {@code 
TiledGridCoverage} grid extent.
          */
-        TileIterator(final int[] tileLower, final int[] tileUpper, final int[] 
offsetAOI, final int dimension) {
-            super(tileLower.clone(), uncroppedTileLocation(tileLower));
+        TileIterator(final int[] tileLower,
+                     final int[] tileUpper,
+                     final int[] offsetAOI,
+                     final int dimension,
+                     final int xDimension,
+                     final int yDimension)
+        {
+            super(xDimension, yDimension, tileLower.clone(), 
uncroppedTileLocation(tileLower));
             this.tileLower = tileLower;
             this.tileUpper = tileUpper;
             this.offsetAOI = offsetAOI;
@@ -1060,7 +1088,7 @@ public abstract class TiledGridCoverage extends 
GridCoverage {
             for (int i = Math.min(endTile.length, upper.length); --i >= 0;) {
                 upper[i] = Math.max(lower[i], Math.min(upper[i], endTile[i]));
             }
-            return new TileIterator(lower, upper, offset, offset.length);
+            return new TileIterator(lower, upper, offset, offset.length, 
xDimension, yDimension);
         }
 
         /**
@@ -1145,10 +1173,10 @@ public abstract class TiledGridCoverage extends 
GridCoverage {
             long x, y;      // Convenience for casting `int` to `long`.
             final long d = tight ? 1 : 0;
             final var r = new Rectangle();
-            r.x      = toIntExact(resourceToImage(x = bounds.x,          
X_DIMENSION, false));
-            r.y      = toIntExact(resourceToImage(y = bounds.y,          
Y_DIMENSION, false));
-            r.width  = toIntExact(resourceToImage(x + bounds.width  - d, 
X_DIMENSION, true) - r.x + d);
-            r.height = toIntExact(resourceToImage(y + bounds.height - d, 
Y_DIMENSION, true) - r.y + d);
+            r.x      = toIntExact(resourceToImage(x = bounds.x,          
xDimension, false));
+            r.y      = toIntExact(resourceToImage(y = bounds.y,          
yDimension, false));
+            r.width  = toIntExact(resourceToImage(x + bounds.width  - d, 
xDimension, true) - r.x + d);
+            r.height = toIntExact(resourceToImage(y + bounds.height - d, 
yDimension, true) - r.y + d);
             return r;
         }
 
@@ -1173,10 +1201,10 @@ public abstract class TiledGridCoverage extends 
GridCoverage {
             long x, y;      // Convenience for casting `int` to `long`.
             final long d = tight ? 1 : 0;
             final var r = new Rectangle();
-            r.x      = toIntExact(imageToResource(x = bounds.x,          
X_DIMENSION));
-            r.y      = toIntExact(imageToResource(y = bounds.y,          
Y_DIMENSION));
-            r.width  = toIntExact(imageToResource(x + bounds.width  - d, 
X_DIMENSION) - r.x + d);
-            r.height = toIntExact(imageToResource(y + bounds.height - d, 
Y_DIMENSION) - r.y + d);
+            r.x      = toIntExact(imageToResource(x = bounds.x,          
xDimension));
+            r.y      = toIntExact(imageToResource(y = bounds.y,          
yDimension));
+            r.width  = toIntExact(imageToResource(x + bounds.width  - d, 
xDimension) - r.x + d);
+            r.height = toIntExact(imageToResource(y + bounds.height - d, 
yDimension) - r.y + d);
             return r;
         }
 
@@ -1275,12 +1303,12 @@ public abstract class TiledGridCoverage extends 
GridCoverage {
          * @param iterator  the iterator for which to create a snapshot of its 
current position.
          */
         public Snapshot(final AOI iterator) {
-            super(iterator.tmcInSubset.clone(), 
iterator.uncroppedTileLocation);
+            super(iterator.xDimension, iterator.yDimension, 
iterator.tmcInSubset.clone(), iterator.uncroppedTileLocation);
             coverage           = iterator.getCoverage();
             indexInResultArray = iterator.indexInResultArray;
             indexInTileVector  = iterator.indexInTileVector;
-            originX            = iterator.getTileOrigin(X_DIMENSION);
-            originY            = iterator.getTileOrigin(Y_DIMENSION);
+            originX            = iterator.getTileOrigin(xDimension);
+            originY            = iterator.getTileOrigin(yDimension);
         }
 
         /**
@@ -1299,11 +1327,9 @@ public abstract class TiledGridCoverage extends 
GridCoverage {
          */
         @Override
         final int getTileOrigin(final int dimension) {
-            switch (dimension) {
-                case X_DIMENSION: return originX;
-                case Y_DIMENSION: return originY;
-                default: throw new AssertionError(dimension);
-            }
+            if (dimension == xDimension) return originX;
+            if (dimension == yDimension) return originY;
+            throw new AssertionError(dimension);
         }
     }
 
@@ -1356,10 +1382,14 @@ public abstract class TiledGridCoverage extends 
GridCoverage {
      * (0,0) is the tile in the upper-left corner of this {@code 
TiledGridCoverage} (not necessarily the upper-left
      * corner of the image in the {@link TiledGridResource}).
      *
-     * The {@link Raster#getMinX()} and {@code getMinY()} coordinates of 
returned rasters
+     * <p>The {@link Raster#getMinX()} and {@code getMinY()} coordinates of 
returned rasters
      * shall start at the values given by {@link 
TileIterator#getTileOrigin(int)}.
      * Each tile in the returned array shall be stored at the index given by
-     * {@link TileIterator#getTileIndexInResultArray()}.
+     * {@link TileIterator#getTileIndexInResultArray()}.</p>
+     *
+     * <p>The <var>x</var> axis of the raster shall be the grid dimension 
specified by {@link #xDimension}.
+     * Likewise, the <var>y</var> axis shall be the dimension specified by 
{@link #yDimension}.
+     * These dimensions are usually 0 and 1 respectively.</p>
      *
      * <p>This method must be thread-safe. It is implementer responsibility to 
ensure synchronization,
      * for example using {@link 
TiledGridResource#getSynchronizationLock()}.</p>
@@ -1370,6 +1400,8 @@ public abstract class TiledGridCoverage extends 
GridCoverage {
      *         but the main ones are {@link java.io.IOException} for I/O 
errors and various {@link RuntimeException}
      *         subtypes for Java2D errors.
      *
+     * @see #xDimension
+     * @see #yDimension
      * @see TileIterator#createRaster()
      * @see TileIterator#getTileIndexInResultArray()
      */
diff --git 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/TiledGridResource.java
 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/TiledGridResource.java
index 12f595eb6c..245f2fa590 100644
--- 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/TiledGridResource.java
+++ 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/TiledGridResource.java
@@ -47,10 +47,10 @@ import org.apache.sis.storage.DataStoreException;
 import org.apache.sis.storage.RasterLoadingStrategy;
 import org.apache.sis.measure.NumberRange;
 import org.apache.sis.util.ArraysExt;
+import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.internal.shared.Numerics;
 import org.apache.sis.util.collection.WeakValueHashMap;
-import static org.apache.sis.storage.tiling.TiledGridCoverage.X_DIMENSION;
-import static org.apache.sis.storage.tiling.TiledGridCoverage.Y_DIMENSION;
 
 // Specific to the geoapi-3.1 and geoapi-4.0 branches:
 import org.opengis.coverage.CannotEvaluateException;
@@ -92,6 +92,9 @@ public abstract class TiledGridResource extends 
AbstractGridCoverageResource {
     /**
      * Number of dimensions in a rendered image.
      * Used for identifying codes where a two-dimensional slice is assumed.
+     *
+     * @see #xDimension
+     * @see #yDimension
      */
     private static final int BIDIMENSIONAL = 2;
 
@@ -156,6 +159,18 @@ public abstract class TiledGridResource extends 
AbstractGridCoverageResource {
      */
     private RasterLoadingStrategy loadingStrategy;
 
+    /**
+     * The dimension of the grid which is mapped to the <var>x</var> axis 
(column indexes) in rendered images.
+     * The default value is 0.
+     */
+    private int xDimension;
+
+    /**
+     * The dimension of the grid which is mapped to the <var>y</var> axis (row 
indexes) in rendered images.
+     * The default value is 1.
+     */
+    private int yDimension;
+
     /**
      * Creates a new resource.
      *
@@ -163,6 +178,35 @@ public abstract class TiledGridResource extends 
AbstractGridCoverageResource {
      */
     protected TiledGridResource(final Resource parent) {
         super(parent);
+        yDimension = 1;
+    }
+
+    /**
+     * Sets the mapping from grid dimensions to image axes.
+     * This method specifies the dimensions of the slices obtained
+     * when {@linkplain TiledGridCoverage#readTiles reading tiles}.
+     *
+     * <p>If this method is never invoked, then by default
+     * the dimension 0 of the grid is mapped to the image <var>x</var> axis and
+     * the dimension 1 of the grid is mapped to the image <var>y</var> 
axis.</p>
+     *
+     * @param  xDimension  dimension of the grid which is mapped to the 
<var>x</var> axis (column indexes) in rendered images.
+     * @param  yDimension  dimension of the grid which is mapped to the 
<var>y</var> axis (row indexes) in rendered images.
+     * @throws IllegalArgumentException if {@code xDimension} or {@code 
yDimension} is negative, or the two values are equal.
+     * @throws DataStoreException if another error occurred while setting the 
mapping from grid dimensions to image axes.
+     *
+     * @see TiledGridCoverage#xDimension
+     * @see TiledGridCoverage#yDimension
+     */
+    protected void setRasterDimension(final int xDimension, final int 
yDimension) throws DataStoreException {
+        final int max = getGridGeometry().getDimension() - 1;
+        ArgumentChecks.ensureBetween("xDimension", 0, max, xDimension);
+        ArgumentChecks.ensureBetween("yDimension", 0, max, yDimension);
+        if (xDimension == yDimension) {
+            throw new 
IllegalArgumentException(Errors.format(Errors.Keys.IllegalArgumentValue_2, 
"yDimension", "xDimension"));
+        }
+        this.xDimension = xDimension;
+        this.yDimension = yDimension;
     }
 
     /**
@@ -315,8 +359,8 @@ public abstract class TiledGridResource extends 
AbstractGridCoverageResource {
      */
     protected SampleModel getSampleModel(final int[] bands) throws 
DataStoreException {
         final int[] tileSize = getTileSize();
-        final int width  = tileSize[X_DIMENSION];
-        final int height = tileSize[Y_DIMENSION];
+        final int width  = tileSize[xDimension];
+        final int height = tileSize[yDimension];
         final ColorModel colors = getColorModel(bands);
         if (colors != null) {
             return colors.createCompatibleSampleModel(width, height);
@@ -471,7 +515,7 @@ check:  if (dataType.isInteger()) {
 
         /**
          * The sample model for the bands to read (not the full set of bands 
in the resource).
-         * The width is {@code tileSize[X_DIMENSION]} and the height it {@code 
tileSize[Y_DIMENSION]},
+         * The width is {@code tileSize[xDimension]} and the height it {@code 
tileSize[yDimension]},
          * i.e. subsampling is <strong>not</strong> applied.
          */
         final SampleModel modelForBandSubset;
@@ -553,7 +597,7 @@ check:  if (dataType.isInteger()) {
                      * ("atome size" of 1) and disable subsampling otherwise 
for avoiding code complexity.
                      */
                     maxSubsmp[i] = (atomSize == 1) ? Long.MAX_VALUE : 1;
-                    chunkSize[i] = (i == X_DIMENSION || i == Y_DIMENSION) ? 
span : 1;
+                    chunkSize[i] = (i == xDimension() || i == yDimension()) ? 
span : 1;
                 }
                 /*
                  * Build the domain in units of subsampled pixels, and get the 
same extent (`readExtent`)
@@ -673,7 +717,23 @@ check:  if (dataType.isInteger()) {
          * @return whether the values to read on a row are contiguous.
          */
         public boolean isXContiguous() {
-            return includedBands == null && subsampling[X_DIMENSION] == 1;
+            return includedBands == null && subsampling[xDimension()] == 1;
+        }
+
+        /**
+         * Returns dimension of the grid which is mapped to the <var>x</var> 
axis (column indexes) in rendered images.
+         * This is usually 0.
+         */
+        final int xDimension() {
+            return xDimension;
+        }
+
+        /**
+         * Returns dimension of the grid which is mapped to the <var>y</var> 
axis (row indexes) in rendered images.
+         * This is usually 1.
+         */
+        final int yDimension() {
+            return yDimension;
         }
 
         /**

Reply via email to