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 e86ef7f  Complete Canvas.getGridGeometry() - not yet tested.
e86ef7f is described below

commit e86ef7faa7421e32c4447c5be5d71fd15f2bb560
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Mon Feb 10 12:59:28 2020 +0100

    Complete Canvas.getGridGeometry() - not yet tested.
---
 .../java/org/apache/sis/internal/map/Canvas.java   | 129 ++++++++++++++-----
 .../org/apache/sis/internal/map/CanvasExtent.java  | 136 ++++++++++++++++++---
 .../org/apache/sis/internal/map/PlanarCanvas.java  |  22 ++--
 3 files changed, 231 insertions(+), 56 deletions(-)

diff --git 
a/core/sis-portrayal/src/main/java/org/apache/sis/internal/map/Canvas.java 
b/core/sis-portrayal/src/main/java/org/apache/sis/internal/map/Canvas.java
index 50b8292..c01ae8d 100644
--- a/core/sis-portrayal/src/main/java/org/apache/sis/internal/map/Canvas.java
+++ b/core/sis-portrayal/src/main/java/org/apache/sis/internal/map/Canvas.java
@@ -32,7 +32,6 @@ import org.opengis.referencing.operation.MathTransform;
 import org.opengis.referencing.operation.TransformException;
 import org.opengis.referencing.datum.PixelInCell;
 import org.opengis.util.FactoryException;
-import org.apache.sis.util.ArraysExt;
 import org.apache.sis.util.Utilities;
 import org.apache.sis.util.Localized;
 import org.apache.sis.util.ArgumentChecks;
@@ -226,6 +225,7 @@ public class Canvas extends Observable implements Localized 
{
      * @see #DISPLAY_BOUNDS_PROPERTY
      * @see #getDisplayBounds()
      * @see #getDisplayCRS()
+     * @see #setDisplayBounds(Envelope)
      */
     final GeneralEnvelope displayBounds;
 
@@ -236,6 +236,7 @@ public class Canvas extends Observable implements Localized 
{
      *
      * @see #POINT_OF_INTEREST_PROPERTY
      * @see #getPointOfInterest()
+     * @see #setPointOfInterest(DirectPosition)
      */
     private GeneralDirectPosition pointOfInterest;
 
@@ -247,6 +248,8 @@ public class Canvas extends Observable implements Localized 
{
      * <p>There is no setter method for this property. It is computed from 
{@link #pointOfInterest}
      * and {@link #objectiveCRS} (indirectly, through {@link 
#multidimToObjective}) and should be
      * recomputed when any of those properties changed.</p>
+     *
+     * @see #getGridGeometry()
      */
     private DirectPosition objectivePOI;
 
@@ -257,6 +260,15 @@ public class Canvas extends Observable implements 
Localized {
      *
      * <p>There is no setter method for this property. It is computed from 
{@link #pointOfInterest}
      * and {@link #objectiveCRS} and should be recomputed when any of those 
properties changed.</p>
+     *
+     * <p>In current implementation, this transform may depend on the zoom 
level and viewed geographic
+     * area at the time this transform has been computed. The transform could 
be slightly different if
+     * it has been computed at the time a different geographic area was 
viewed. Those variations may
+     * exist because {@link #findTransform(CoordinateReferenceSystem, 
CoordinateReferenceSystem)} takes
+     * in account the current viewing conditions. We may need to revisit this 
behavior in the future if
+     * it appears to be a problem.</p>
+     *
+     * @see #getGridGeometry()
      */
     private MathTransform multidimToObjective;
 
@@ -269,6 +281,8 @@ public class Canvas extends Observable implements Localized 
{
      * Otherwise {@linkplain #supplementalDimensions supplemental dimensions} 
are added on a best effort
      * basis: some supplemental dimensions may be missing if we have not been 
able to separate components
      * from the Point Of Interest CRS.</p>
+     *
+     * @see #getGridGeometry()
      */
     private CoordinateReferenceSystem augmentedObjectiveCRS;
 
@@ -280,10 +294,34 @@ public class Canvas extends Observable implements 
Localized {
      *
      * <p>The value of this field is invalid if {@link #augmentedObjectiveCRS} 
is {@code null}.
      * Those two fields are computed together.</p>
+     *
+     * @see #getGridGeometry()
      */
     private long supplementalDimensions;
 
     /**
+     * Type of each grid axis (column, row, vertical, temporal, …) or {@code 
null} if unspecified.
+     * This is only a help for debugging purpose, by providing more 
information to the developers.
+     * Those types should not be used for any "real" work.
+     *
+     * @see #getGridGeometry()
+     */
+    private DimensionNameType[] axisTypes;
+
+    /**
+     * The grid geometry, computed when first needed and reset to {@code null} 
when invalidated.
+     * This is invalidated when any {@link Canvas} property is modified. In 
particular, this is
+     * invalidated every time that the {@link #objectiveToDisplay} transform 
changes. Note that
+     * "objective to display" changes happen much more often than changes in 
other properties.
+     *
+     * <p>The {@link #augmentedObjectiveCRS}, {@link #supplementalDimensions}, 
{@link #multidimToObjective},
+     * {@link #objectivePOI} and {@link #axisTypes} objects are intermediate 
calculations with typically a
+     * longer lifetime than {@code gridGeometry}. They are saved for faster 
recomputation of grid geometry
+     * when only the {@link #objectiveToDisplay} transform has changed.</p>
+     */
+    private GridGeometry gridGeometry;
+
+    /**
      * The factory to use for creating coordinate operations. This factory 
allow us to specify the area
      * of interest (the geographic region shown by this {@code Canvas}) and 
the desired resolution.
      *
@@ -338,10 +376,16 @@ public class Canvas extends Observable implements 
Localized {
     }
 
     /**
-     * Returns name of display axes, or {@code null} if unknown.
+     * Gets the name of display axes and stores them in the given array. Those 
display axis names
+     * are used for debugging purposes only, as an additional information 
provided to developers.
+     * Those names should not be used for any "real" work. The default 
implementation does nothing
+     * since this base {@link Canvas} class does not know well the geometry of 
the display device.
+     * It is okay to leave elements to {@code null}.
+     *
+     * @param  axisTypes  where to store the name of display axes. The array 
length will be
+     *                    at least {@link #getDisplayDimensions()} (it will 
often be longer).
      */
-    DimensionNameType[] getDisplayAxes() {
-        return null;
+    void getDisplayAxes(final DimensionNameType[] axisTypes) {
     }
 
     /**
@@ -449,6 +493,8 @@ public class Canvas extends Observable implements Localized 
{
                     objectivePOI          = poiInNew;               // Set 
only after everything else succeeded.
                     multidimToObjective   = poiToNew;
                     augmentedObjectiveCRS = null;                   // Will be 
recomputed when first needed.
+                    axisTypes             = null;
+                    gridGeometry          = null;
                 }
             } catch (FactoryException | TransformException e) {
                 throw new 
RenderException(errors().getString(Errors.Keys.CanNotSetPropertyValue_1, 
OBJECTIVE_CRS_PROPERTY), e);
@@ -654,6 +700,8 @@ public class Canvas extends Observable implements Localized 
{
             pointOfInterest       = copy;                                      
     // Set only after transform succeeded.
             multidimToObjective   = mt;
             augmentedObjectiveCRS = null;                                      
     // Will be recomputed when first needed.
+            axisTypes             = null;
+            gridGeometry          = null;
             firePropertyChange(POINT_OF_INTEREST_PROPERTY, oldValue, 
newValue);     // Do not publish reference to `copy`.
         } catch (FactoryException | TransformException e) {
             throw new 
RenderException(errors().getString(Errors.Keys.CanNotSetPropertyValue_1, 
POINT_OF_INTEREST_PROPERTY), e);
@@ -663,82 +711,105 @@ public class Canvas extends Observable implements 
Localized {
     /**
      * Returns canvas properties (CRS, display bounds, conversion) 
encapsulated in a grid geometry.
      * This is a convenience method for interoperability with grid coverage 
API.
-     * The grid geometry elements are mapped to canvas properties as below:
+     * The set of {@link GridGeometry} dimensions includes all the dimensions 
of the objective CRS,
+     * augmented with all (if possible) or some supplemental dimensions found 
in the point of interest.
+     * For example if the canvas manages only (<var>x</var>,<var>y</var>) 
coordinates but the point of
+     * interest includes also a <var>t</var> coordinate, then a third 
dimension (which we call the
+     * <cite>supplemental dimension</cite>) for <var>t</var> is added to the 
CRS, {@link GridExtent}
+     * and "grid to CRS" transform of the returned grid geometry.
      *
      * <table>
-     *   <caption>Canvas to grid geometry properties</caption>
+     *   <caption>Canvas properties → grid geometry properties</caption>
      *   <tr>
      *     <th>Grid geometry element</th>
-     *     <th>Canvas property</th>
+     *     <th>Base dimensions</th>
+     *     <th>Supplemental dimensions</th>
      *   </tr><tr>
      *     <td>{@link GridGeometry#getCoordinateReferenceSystem()}</td>
      *     <td>{@link #getObjectiveCRS()}.</td>
+     *     <td>Some of <code>{@linkplain 
#getPointOfInterest()}.getCoordinateReferenceSystem()</code></td>
      *   </tr><tr>
      *     <td>{@link GridGeometry#getExtent()}</td>
      *     <td>{@link #getDisplayBounds()} rounded to enclosing integers</td>
+     *     <td>[0 … 0]</td>
      *   </tr><tr>
      *     <td>{@link GridGeometry#getGridToCRS(PixelInCell)}</td>
      *     <td>Inverse of {@link #getObjectiveToDisplay()}</td>
+     *     <td>Some {@linkplain #getPointOfInterest() point of interest} 
coordinates as translation term.</td>
      *   </tr>
      * </table>
      *
-     * All those elements are augmented with supplemental dimensions found in 
the point of interest.
-     * For example if the canvas shows only (<var>x</var>,<var>y</var>) 
coordinates but the point of
-     * interest also includes a <var>t</var> value, then a third dimension for 
<var>t</var> is added
-     * to the CRS, extent and transform of the returned grid geometry.
+     * The {@link GridGeometry#getGridToCRS(PixelInCell)} transform built by 
this method is always a {@link LinearTransform}.
+     * This linearity implies that the grid geometry CRS can not be the Point 
Of Interest (POI) CRS, unless conversion
+     * from POI CRS to objective CRS is linear.
      *
-     * @return a grid geometry encapsulating canvas properties.
+     * @return a grid geometry encapsulating canvas properties, including 
supplemental dimensions if possible.
      * @throws RenderException if the grid geometry can not be computed.
      */
     public GridGeometry getGridGeometry() throws RenderException {
-        try {
+        if (gridGeometry == null) try {
             /*
              * If not already done, create a multi-dimensional CRS composed of 
`objectiveCRS`
              * with supplemental dimensions appended. This CRS needs to be 
recreated only if
-             * the Point of Interest changed, or if the objective CRS changed.
+             * the Point of Interest and/or the objective CRS changed since 
last call.
              */
             if (augmentedObjectiveCRS == null) {
                 if (pointOfInterest != null) {
+                    final CoordinateReferenceSystem crs = 
pointOfInterest.getCoordinateReferenceSystem();
                     final ArrayList<CoordinateReferenceSystem> components = 
new ArrayList<>(4);
                     components.add(objectiveCRS);
-                    supplementalDimensions = 
CanvasExtent.findSupplementalDimensions(
-                            pointOfInterest.getCoordinateReferenceSystem(),
+                    /*
+                     * `findSupplementalDimensions(…)` tries to complete the 
`components` list on a best effort basis.
+                     * We have no guarantees that all supplemental dimensions 
will be included. The set of dimensions
+                     * actually appended is encoded in 
`supplementalDimensions` bits.
+                     */
+                    supplementalDimensions = 
CanvasExtent.findSupplementalDimensions(crs,
                             multidimToObjective.derivative(pointOfInterest), 
components);
                     augmentedObjectiveCRS = 
CRS.compound(components.toArray(new 
CoordinateReferenceSystem[components.size()]));
+                    if (Utilities.equalsIgnoreMetadata(augmentedObjectiveCRS, 
crs)) {
+                        augmentedObjectiveCRS = crs;
+                    }
                 } else {
                     augmentedObjectiveCRS = objectiveCRS;
                 }
+                /*
+                 * The axis types are for information purposes only, for 
making debugging easier.
+                 * It will typically contains the (column, row) names, maybe 
completed with up or
+                 * time names.
+                 */
+                axisTypes = 
CanvasExtent.suggestAxisTypes(augmentedObjectiveCRS, getDisplayDimensions());
+                getDisplayAxes(axisTypes);
             }
             /*
-             * Create the `gridToCRS` using the "display to objective" 
transform augmented with POI coordinate
-             * values in supplemental dimensions. Note: 
`getObjectiveToDisplay()` should never return null.
+             * Create the `gridToCRS` transform using the "display to 
objective" transform augmented with POI
+             * coordinate values in supplemental dimensions. Those coordinate 
values will be stored in the
+             * translation terms of the `gridToCRS` matrix.
              */
-            LinearTransform gridToCRS = getObjectiveToDisplay().inverse();
+            final LinearTransform objectiveToDisplay = 
getObjectiveToDisplay();         // Should never be null.
+            LinearTransform gridToCRS = objectiveToDisplay.inverse();
             if (supplementalDimensions != 0) {
                 gridToCRS = 
CanvasExtent.createGridToCRS(gridToCRS.getMatrix(), pointOfInterest, 
supplementalDimensions);
             }
             /*
              * Create the grid extent with a number of dimensions that include 
the supplemental dimensions.
-             * The cell indices range of all supplemental dimensions is [0 … 
0].
+             * The cell indices range of all supplemental dimensions is [0 … 
0]. If a point of interest is
+             * available, the `GridExtent` will contain the grid coordinates 
of that point.
              */
             final GridExtent extent;
             if (displayBounds.isEmpty()) {
                 extent = null;
             } else {
-                final int dimension = gridToCRS.getSourceDimensions();
-                final long[] lower = new long[dimension];
-                final long[] upper = new long[dimension];
-                for (int i = displayBounds.getDimension(); --i >= 0;) {
-                    lower[i] = (long) Math.floor(displayBounds.getMinimum(i));
-                    upper[i] = (long) Math.ceil (displayBounds.getMaximum(i));
+                DirectPosition poi = objectivePOI;
+                if (poi != null) {
+                    poi = objectiveToDisplay.transform(objectivePOI, null);
                 }
-                final DimensionNameType[] axisTypes = 
ArraysExt.resize(getDisplayAxes(), dimension);
-                extent = new GridExtent(axisTypes, lower, upper, false);
+                extent = CanvasExtent.create(displayBounds, poi, axisTypes, 
gridToCRS.getSourceDimensions());
             }
-            return new GridGeometry(extent, PixelInCell.CELL_CORNER, 
gridToCRS, augmentedObjectiveCRS);
+            gridGeometry = new GridGeometry(extent, PixelInCell.CELL_CORNER, 
gridToCRS, augmentedObjectiveCRS);
         } catch (FactoryException | TransformException e) {
             throw new 
RenderException(errors().getString(Errors.Keys.CanNotCompute_1, 
"gridGeometry"), e);
         }
+        return gridGeometry;
     }
 
     public void setGridGeometry(final GridGeometry geometry) throws 
RenderException {
diff --git 
a/core/sis-portrayal/src/main/java/org/apache/sis/internal/map/CanvasExtent.java
 
b/core/sis-portrayal/src/main/java/org/apache/sis/internal/map/CanvasExtent.java
index 28616c6..cba3ae9 100644
--- 
a/core/sis-portrayal/src/main/java/org/apache/sis/internal/map/CanvasExtent.java
+++ 
b/core/sis-portrayal/src/main/java/org/apache/sis/internal/map/CanvasExtent.java
@@ -19,24 +19,97 @@ package org.apache.sis.internal.map;
 import java.util.List;
 import org.opengis.geometry.DirectPosition;
 import org.opengis.referencing.operation.Matrix;
+import org.opengis.referencing.cs.AxisDirection;
+import org.opengis.referencing.cs.CoordinateSystem;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.metadata.spatial.DimensionNameType;
 import org.apache.sis.referencing.CRS;
 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.operation.transform.LinearTransform;
+import org.apache.sis.coverage.grid.GridGeometry;
+import org.apache.sis.coverage.grid.GridExtent;
+import org.apache.sis.geometry.GeneralEnvelope;
+import org.apache.sis.internal.referencing.AxisDirections;
 import org.apache.sis.internal.util.Numerics;
 
 
 /**
+ * A {@link GridExtent} which remembers the {@link 
Canvas#getPointOfInterest()} coordinates.
+ * This class contains also static help functions for the construction of 
{@link GridGeometry}.
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @version 1.1
  * @since   1.1
  * @module
  */
-final class CanvasExtent {
-    private CanvasExtent() {
+final class CanvasExtent extends GridExtent {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = 195789629521760720L;
+
+    /**
+     * The grid coordinates of a representative point. The {@code 
CanvasExtent} point of interest
+     * is the {@code Canvas} point of interest converted to (typically) pixel 
coordinates.
+     *
+     * @see #getPointOfInterest()
+     */
+    private final double[] pointOfInterest;
+
+    /**
+     * Creates a new grid extent.
+     *
+     * @param  axisTypes        the type of each grid axis, or {@code null} if 
unspecified.
+     * @param  lower            the valid minimum grid coordinates (inclusive).
+     * @param  upper            the valid maximum grid coordinates (exclusive).
+     * @param  pointOfInterest  the grid coordinates of a representative point.
+     */
+    private CanvasExtent(final DimensionNameType[] axisTypes, final long[] 
lower, final long[] upper, final double[] pointOfInterest) {
+        super(axisTypes, lower, upper, false);
+        this.pointOfInterest = pointOfInterest;
+    }
+
+    /**
+     * Returns the grid coordinates of a representative point.
+     * This is the canvas point of interest converted to (typically) pixel 
coordinates.
+     *
+     * @see Canvas#getPointOfInterest()
+     */
+    @Override
+    public double[] getPointOfInterest() {
+        return pointOfInterest.clone();
+    }
+
+    /**
+     * Creates a new grid extent from the given display bounds.
+     * All supplemental dimensions will have the [0 … 0] grid range.
+     * If a point of interest is available, its coordinates will be remembered.
+     *
+     * @param  bounds     bounds of the display device, typically in pixel 
units.
+     * @param  poi        point of interest in pixel units, or {@code null} if 
unknown.
+     * @param  axisTypes  name of display axes, or {@code null} if unknown.
+     * @param  agmDim     augmented number of dimensions (i.e. including 
supplemental dimensions).
+     * @return grid extent computed from the given display bounds.
+     */
+    static GridExtent create(final GeneralEnvelope bounds, final 
DirectPosition poi,
+                             final DimensionNameType[] axisTypes, final int 
agmDim)
+    {
+        final long[] lower = new long[agmDim];
+        final long[] upper = new long[agmDim];
+        for (int i = bounds.getDimension(); --i >= 0;) {
+            lower[i] = (long) Math.floor(bounds.getLower(i));
+            upper[i] = (long) Math.ceil (bounds.getUpper(i));
+        }
+        if (poi == null) {
+            return new GridExtent(axisTypes, lower, upper, false);
+        }
+        final double[] c = new double[agmDim];
+        for (int i = poi.getDimension(); --i >= 0;) {
+            c[i] = poi.getOrdinate(i);
+        }
+        return new CanvasExtent(axisTypes, lower, upper, c);
     }
 
     /**
@@ -75,12 +148,12 @@ final class CanvasExtent {
         }
         mask ^= Numerics.bitmask(srcDim) - 1;           // Sources NOT used by 
any target dimension.
         /*
-         * Now we know the source dimensions of the CRS components to add in 
the specified list.
+         * Now we know the source dimensions of the CRS components to add in 
the `addTo` list.
          * We must ask for CRS components using ranges as much as possible. 
For example if some
-         * supplemental dimensions are 1,2,3 then we must as the component in 
range 1 inclusive
-         * to 4 exclusive. This is done easily we bits arithmetic. If we can 
get all components,
-         * the `supplementalDimensions` final value will be the `mask` initial 
value. If we had
-         * to discard some components, then those long values will differ.
+         * supplemental dimensions are 1,2,3 then we must ask the component in 
range 1 inclusive
+         * to 4 exclusive. This is done easily with bits arithmetic. If we can 
get all components,
+         * the `supplementalDimensions` final value will be the `mask` initial 
value. If we had to
+         * discard some components, then `supplementalDimensions` will have 
less bits than `mask`.
          */
         long supplementalDimensions = 0;
         while (mask != 0) {
@@ -110,18 +183,53 @@ final class CanvasExtent {
             final DirectPosition pointOfInterest, long supplementalDimensions)
     {
         final int srcDim = displayToObjective.getNumCol();
-        final int tgtDim = displayToObjective.getNumRow() + 
Long.bitCount(supplementalDimensions);
-        final MatrixSIS gridToCRS = Matrices.createIdentity(tgtDim + 1);
+        final int tgtDim = displayToObjective.getNumRow();
+        final int agmDim = tgtDim + Long.bitCount(supplementalDimensions);
+        final MatrixSIS gridToCRS = Matrices.createZero(agmDim + 1, agmDim + 
1);
+        int j;
+        for (j=0; j<tgtDim; j++) {
+            for (int i=0; i<srcDim; i++) {
+                gridToCRS.setElement(j,i, displayToObjective.getElement(j,i));
+            }
+        }
+        // Continue adding rows.
         while (supplementalDimensions != 0) {
             final int n = Long.numberOfTrailingZeros(supplementalDimensions);
-            gridToCRS.setElement(n, tgtDim, pointOfInterest.getOrdinate(n));
+            gridToCRS.setElement(j, j, Double.NaN);
+            gridToCRS.setElement(j++, agmDim, pointOfInterest.getOrdinate(n));
             supplementalDimensions &= ~(1L << n);
         }
-        for (int j=0; j<tgtDim; j++) {
-            for (int i=0; i<srcDim; i++) {
-                gridToCRS.setElement(j,i, displayToObjective.getElement(j,i));
+        return MathTransforms.linear(gridToCRS);
+    }
+
+    /**
+     * Suggests axis types for supplemental dimensions not managed by the 
{@link Canvas}.
+     * Those types are only a help for debugging purpose, by providing more 
information
+     * to the developers. They should not be used for any "real" work.
+     *
+     * @param  crs               the coordinate reference system to use for 
inferring axis types.
+     * @param  displayDimension  number of dimensions managed by the {@link 
Canvas}.
+     * @return suggested axis types. Never null, but contains null elements.
+     *
+     * @see Canvas#axisTypes
+     */
+    static DimensionNameType[] suggestAxisTypes(final 
CoordinateReferenceSystem crs, final int displayDimension) {
+        if (crs != null) {
+            final CoordinateSystem cs = crs.getCoordinateSystem();
+            if (cs != null) {                                       // Should 
never be null, but we are paranoiac.
+                int i = cs.getDimension();
+                final DimensionNameType[] axisTypes = new DimensionNameType[i];
+                while (--i >= displayDimension) {
+                    final AxisDirection dir = 
AxisDirections.absolute(cs.getAxis(i).getDirection());
+                    if (AxisDirection.FUTURE.equals(dir)) {
+                        axisTypes[i] = DimensionNameType.TIME;
+                    } else if (AxisDirection.UP.equals(dir)) {
+                        axisTypes[i] = DimensionNameType.VERTICAL;
+                    }
+                }
+                return axisTypes;
             }
         }
-        return MathTransforms.linear(gridToCRS);
+        return new DimensionNameType[displayDimension];
     }
 }
diff --git 
a/core/sis-portrayal/src/main/java/org/apache/sis/internal/map/PlanarCanvas.java
 
b/core/sis-portrayal/src/main/java/org/apache/sis/internal/map/PlanarCanvas.java
index 68e6c8f..e7e8ca2 100644
--- 
a/core/sis-portrayal/src/main/java/org/apache/sis/internal/map/PlanarCanvas.java
+++ 
b/core/sis-portrayal/src/main/java/org/apache/sis/internal/map/PlanarCanvas.java
@@ -55,14 +55,6 @@ public abstract class PlanarCanvas extends Canvas {
     private static final int BIDIMENSIONAL = 2;
 
     /**
-     * Name of grid axes in {@link org.apache.sis.coverage.grid.GridGeometry} 
extent.
-     */
-    private static final DimensionNameType[] DISPLAY_AXES = {
-        DimensionNameType.COLUMN,
-        DimensionNameType.ROW
-    };
-
-    /**
      * The display Coordinate Reference System used by all {@code 
PlanarCanvas} instances.
      */
     private static final DefaultEngineeringCRS DISPLAY_CRS;
@@ -106,13 +98,17 @@ public abstract class PlanarCanvas extends Canvas {
     }
 
     /**
-     * Returns name of display axes, or {@code null} if unknown.
-     * Caller shall not modify the returned array (it is not cloned).
+     * Gets the name of display axes and stores them in the given array. Those 
display axis names
+     * are used for debugging purposes only, as an additional information 
provided to developers.
+     * Those names should not be used for any "real" work.
+     *
+     * @param  axisTypes  where to store the name of display axes. The array 
length will
+     *                    be at least {@link #BIDIMENSIONAL} (it will often be 
longer).
      */
     @Override
-    @SuppressWarnings("ReturnOfCollectionOrArrayField")
-    final DimensionNameType[] getDisplayAxes() {
-        return DISPLAY_AXES;
+    final void getDisplayAxes(final DimensionNameType[] axisTypes) {
+        axisTypes[0] = DimensionNameType.COLUMN;
+        axisTypes[1] = DimensionNameType.ROW;
     }
 
     /**

Reply via email to