sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject [sis] branch geoapi-4.0 updated: Complete Canvas.getGridGeometry() - not yet tested.
Date Mon, 10 Feb 2020 11:59:49 GMT
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 <martin.desruisseaux@geomatys.com>
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;
     }
 
     /**


Mime
View raw message