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 e429a0e09b Replace `GridEvaluator` class by `GridCoverage.Evaluator` 
interface.
e429a0e09b is described below

commit e429a0e09b97b35d488da64c4a89401d320767a3
Author: Martin Desruisseaux <martin.desruisse...@geomatys.com>
AuthorDate: Thu Aug 4 16:06:55 2022 +0200

    Replace `GridEvaluator` class by `GridCoverage.Evaluator` interface.
    
    https://issues.apache.org/jira/browse/SIS-554
---
 .../org/apache/sis/gui/map/ValuesUnderCursor.java  |   5 +-
 .../org/apache/sis/coverage/BandedCoverage.java    |  32 +++++-
 .../sis/coverage/grid/BufferedGridCoverage.java    |   6 +-
 .../sis/coverage/grid/ConvertedGridCoverage.java   |  87 ++++----------
 .../sis/coverage/grid/DerivedGridCoverage.java     |   9 +-
 .../apache/sis/coverage/grid/EvaluatorWrapper.java | 126 +++++++++++++++++++++
 .../coverage/grid/FractionalGridCoordinates.java   |   6 +-
 .../org/apache/sis/coverage/grid/GridCoverage.java |  84 +++++++++++++-
 .../apache/sis/coverage/grid/GridCoverage2D.java   |   6 +-
 .../apache/sis/coverage/grid/GridEvaluator.java    |  24 ++--
 .../org/apache/sis/coverage/grid/GridExtent.java   |   2 +-
 .../sis/coverage/grid/GridCoverage2DTest.java      |  13 +--
 12 files changed, 288 insertions(+), 112 deletions(-)

diff --git 
a/application/sis-javafx/src/main/java/org/apache/sis/gui/map/ValuesUnderCursor.java
 
b/application/sis-javafx/src/main/java/org/apache/sis/gui/map/ValuesUnderCursor.java
index d618731a48..8ec168b956 100644
--- 
a/application/sis-javafx/src/main/java/org/apache/sis/gui/map/ValuesUnderCursor.java
+++ 
b/application/sis-javafx/src/main/java/org/apache/sis/gui/map/ValuesUnderCursor.java
@@ -42,7 +42,6 @@ import 
org.apache.sis.referencing.operation.transform.TransferFunction;
 import org.apache.sis.gui.coverage.CoverageCanvas;
 import org.apache.sis.coverage.grid.GridExtent;
 import org.apache.sis.coverage.grid.GridCoverage;
-import org.apache.sis.coverage.grid.GridEvaluator;
 import org.apache.sis.coverage.SampleDimension;
 import org.apache.sis.coverage.Category;
 import org.apache.sis.internal.system.Modules;
@@ -211,7 +210,7 @@ public abstract class ValuesUnderCursor {
         /**
          * The object computing or interpolation sample values in the coverage.
          */
-        private GridEvaluator evaluator;
+        private GridCoverage.Evaluator evaluator;
 
         /**
          * The selection status of each band.
@@ -480,7 +479,7 @@ public abstract class ValuesUnderCursor {
          * @param  point  the cursor location in arbitrary CRS, or {@code 
null} if outside canvas region.
          * @return string representation of data under given position, or 
{@code null} if none.
          *
-         * @see GridEvaluator#apply(DirectPosition)
+         * @see GridCoverage.Evaluator#apply(DirectPosition)
          */
         @Override
         public String evaluate(final DirectPosition point) {
diff --git 
a/core/sis-feature/src/main/java/org/apache/sis/coverage/BandedCoverage.java 
b/core/sis-feature/src/main/java/org/apache/sis/coverage/BandedCoverage.java
index df5cec01bd..11d4140e53 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/coverage/BandedCoverage.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/coverage/BandedCoverage.java
@@ -49,7 +49,7 @@ import org.opengis.referencing.crs.CoordinateReferenceSystem;
  * {@link Evaluator#apply(DirectPosition)} method signatures.
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
- * @version 1.2
+ * @version 1.3
  * @since   1.1
  * @module
  */
@@ -114,7 +114,7 @@ public abstract class BandedCoverage {
      *
      * <h4>Multi-threading</h4>
      * {@code Evaluator}s are not thread-safe. For computing sample values 
concurrently,
-     * a new {@link Evaluator} instance should be created for each thread by 
invoking this
+     * a new {@code Evaluator} instance should be created for each thread by 
invoking this
      * method multiply times.
      *
      * @return a new function for computing or interpolating sample values.
@@ -131,7 +131,7 @@ public abstract class BandedCoverage {
      *
      * @author  Johann Sorel (Geomatys)
      * @author  Martin Desruisseaux (Geomatys)
-     * @version 1.1
+     * @version 1.3
      *
      * @see BandedCoverage#evaluator()
      *
@@ -141,6 +141,7 @@ public abstract class BandedCoverage {
     public interface Evaluator extends Function<DirectPosition, double[]> {
         /**
          * Returns the coverage from which this evaluator is computing sample 
values.
+         * This is the coverage on which the {@link 
BandedCoverage#evaluator()} method has been invoked.
          *
          * @return the source of sample values for this evaluator.
          */
@@ -165,6 +166,31 @@ public abstract class BandedCoverage {
          */
         void setNullIfOutside(boolean flag);
 
+        /**
+         * Returns {@code true} if this evaluator is allowed to wraparound 
coordinates that are outside the coverage.
+         * The initial value is {@code false}. This method may continue to 
return {@code false} even after a call to
+         * {@code setWraparoundEnabled(true)} if no wraparound axis has been 
found in the coverage CRS,
+         * or if automatic wraparound is not supported.
+         *
+         * @return {@code true} if this evaluator may wraparound coordinates 
that are outside the coverage.
+         *
+         * @since 1.3
+         */
+        boolean isWraparoundEnabled();
+
+        /**
+         * Specifies whether this evaluator is allowed to wraparound 
coordinates that are outside the coverage.
+         * If {@code true} and if a given coordinate is outside the coverage, 
then this evaluator may translate
+         * the point along a wraparound axis in an attempt to get the point 
inside the coverage. For example if
+         * the coverage CRS has a longitude axis, then the evaluator may 
translate the longitude value by a
+         * multiple of 360°.
+         *
+         * @param  allow  whether to allow wraparound of coordinates that are 
outside the coverage.
+         *
+         * @since 1.3
+         */
+        void setWraparoundEnabled(final boolean allow);
+
         /**
          * Returns a sequence of double values for a given point in the 
coverage.
          * The CRS of the given point may be any coordinate reference system;
diff --git 
a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/BufferedGridCoverage.java
 
b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/BufferedGridCoverage.java
index 8f20214e49..ec53dc5663 100644
--- 
a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/BufferedGridCoverage.java
+++ 
b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/BufferedGridCoverage.java
@@ -232,11 +232,11 @@ public class BufferedGridCoverage extends GridCoverage {
      * Creates a new function for computing or interpolating sample values at 
given locations.
      *
      * <h4>Multi-threading</h4>
-     * {@code GridEvaluator}s are not thread-safe. For computing sample values 
concurrently,
-     * a new {@link GridEvaluator} instance should be created for each thread.
+     * {@code Evaluator}s are not thread-safe. For computing sample values 
concurrently,
+     * a new {@link Evaluator} instance should be created for each thread.
      */
     @Override
-    public GridEvaluator evaluator() {
+    public Evaluator evaluator() {
         return new CellAccessor(this);
     }
 
diff --git 
a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/ConvertedGridCoverage.java
 
b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/ConvertedGridCoverage.java
index 582912140d..b3f2b6d9aa 100644
--- 
a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/ConvertedGridCoverage.java
+++ 
b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/ConvertedGridCoverage.java
@@ -16,14 +16,12 @@
  */
 package org.apache.sis.coverage.grid;
 
-import java.util.Map;
 import java.util.List;
 import java.util.Arrays;
 import java.util.ArrayList;
 import java.util.Optional;
 import java.awt.image.RenderedImage;
 import org.opengis.geometry.DirectPosition;
-import org.opengis.coverage.CannotEvaluateException;
 import org.opengis.referencing.operation.MathTransform1D;
 import org.opengis.referencing.operation.TransformException;
 import org.opengis.referencing.operation.NoninvertibleTransformException;
@@ -34,6 +32,9 @@ import org.apache.sis.measure.NumberRange;
 import org.apache.sis.image.DataType;
 import org.apache.sis.image.ImageProcessor;
 
+// Branch-dependent imports
+import org.opengis.coverage.CannotEvaluateException;
+
 
 /**
  * Decorates a {@link GridCoverage} in order to convert sample values on the 
fly.
@@ -43,7 +44,7 @@ import org.apache.sis.image.ImageProcessor;
  *   <li>In calls to {@link #render(GridExtent)}, sample values are converted 
when first needed
  *       on a tile-by-tile basis then cached for future reuse. Note however 
that discarding the
  *       returned image may result in the lost of cached tiles.</li>
- *   <li>In calls to {@link GridEvaluator#apply(DirectPosition)}, the 
conversion is applied
+ *   <li>In calls to {@link GridCoverage.Evaluator#apply(DirectPosition)}, the 
conversion is applied
  *       on-the-fly each time in order to avoid the potentially costly tile 
computations.</li>
  * </ul>
  *
@@ -232,76 +233,33 @@ final class ConvertedGridCoverage extends 
DerivedGridCoverage {
      * Creates a new function for computing or interpolating sample values at 
given locations.
      *
      * <h4>Multi-threading</h4>
-     * {@code GridEvaluator}s are not thread-safe. For computing sample values 
concurrently,
-     * a new {@link GridEvaluator} instance should be created for each thread.
+     * {@code Evaluator}s are not thread-safe. For computing sample values 
concurrently,
+     * a new {@link Evaluator} instance should be created for each thread.
      */
     @Override
-    public GridEvaluator evaluator() {
-        return new SampleConverter(this);
+    public Evaluator evaluator() {
+        return new SampleConverter();
     }
 
     /**
-     * Implementation of evaluator returned by {@link #evaluator()}.
+     * Implementation of evaluator returned by {@link 
ConvertedGridCoverage#evaluator()}.
+     * This evaluator delegates all operations to the {@link #source} coverage 
and converts
+     * the returned sample values.
      */
-    private static final class SampleConverter extends GridEvaluator {
-        /**
-         * The evaluator provided by source coverage.
-         */
-        private final GridEvaluator evaluator;
-
-        /**
-         * Conversions from {@linkplain #source source} values to converted 
values.
-         */
-        private final MathTransform1D[] converters;
-
+    private final class SampleConverter extends EvaluatorWrapper {
         /**
          * Creates a new evaluator for the enclosing coverage.
          */
-        SampleConverter(final ConvertedGridCoverage coverage) {
-            super(coverage);
-            evaluator  = coverage.source.evaluator();
-            converters = coverage.converters;
-        }
-
-        /**
-         * Returns the default slice where to perform evaluation, or an empty 
map if unspecified.
-         */
-        @Override
-        public Map<Integer,Long> getDefaultSlice() {
-            return evaluator.getDefaultSlice();
-        }
-
-        /**
-         * Sets the default slice where to perform evaluation when the points 
do not have enough dimensions.
-         */
-        @Override
-        public void setDefaultSlice(Map<Integer,Long> slice) {
-            evaluator.setDefaultSlice(slice);
+        SampleConverter() {
+            super(source.evaluator());
         }
 
         /**
-         * Returns {@code true} if this evaluator is allowed to wraparound 
coordinates that are outside the grid.
+         * Returns the enclosing coverage.
          */
         @Override
-        public boolean isWraparoundEnabled() {
-            return evaluator.isWraparoundEnabled();
-        }
-
-        /**
-         * Specifies whether this evaluator is allowed to wraparound 
coordinates that are outside the grid.
-         */
-        @Override
-        public void setWraparoundEnabled(final boolean allow) {
-            evaluator.setWraparoundEnabled(allow);
-        }
-
-        /**
-         * Forwards configuration to the wrapped evaluator.
-         */
-        @Override
-        public void setNullIfOutside(final boolean flag) {
-            evaluator.setNullIfOutside(flag);
-            super.setNullIfOutside(flag);
+        public GridCoverage getCoverage() {
+            return ConvertedGridCoverage.this;
         }
 
         /**
@@ -313,8 +271,9 @@ final class ConvertedGridCoverage extends 
DerivedGridCoverage {
          */
         @Override
         public double[] apply(final DirectPosition point) throws 
CannotEvaluateException {
-            final double[] values = evaluator.apply(point);
+            final double[] values = super.apply(point);
             if (values != null) try {
+                final MathTransform1D[] converters = 
ConvertedGridCoverage.this.converters;
                 for (int i=0; i<converters.length; i++) {
                     values[i] = converters[i].transform(values[i]);
                 }
@@ -323,14 +282,6 @@ final class ConvertedGridCoverage extends 
DerivedGridCoverage {
             }
             return values;
         }
-
-        /**
-         * Converts the specified geospatial position to grid coordinates.
-         */
-        @Override
-        public FractionalGridCoordinates toGridCoordinates(final 
DirectPosition point) throws TransformException {
-            return evaluator.toGridCoordinates(point);
-        }
     }
 
     /**
diff --git 
a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/DerivedGridCoverage.java
 
b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/DerivedGridCoverage.java
index 67c0f3ce60..e91dffc900 100644
--- 
a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/DerivedGridCoverage.java
+++ 
b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/DerivedGridCoverage.java
@@ -94,13 +94,12 @@ abstract class DerivedGridCoverage extends GridCoverage {
      * That function accepts {@link DirectPosition} in arbitrary Coordinate 
Reference System;
      * conversions to grid indices are applied by the {@linkplain #source} as 
needed.
      *
-     * @todo The results returned by {@link 
GridEvaluator#toGridCoordinates(DirectPosition)}
-     *       would need to be transformed. But it would force us to return a 
wrapper, which
-     *       would add an indirection level for all others (more important) 
method calls.
-     *       Is it worth to do so?
+     * @todo The results returned by {@link 
GridCoverage.Evaluator#toGridCoordinates(DirectPosition)}
+     *       would need to be transformed. But it would force us to return a 
wrapper, which would add
+     *       an indirection level for all others (more important) method 
calls. Is it worth to do so?
      */
     @Override
-    public GridEvaluator evaluator() {
+    public Evaluator evaluator() {
         return source.evaluator();
     }
 
diff --git 
a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/EvaluatorWrapper.java
 
b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/EvaluatorWrapper.java
new file mode 100644
index 0000000000..014335bcb7
--- /dev/null
+++ 
b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/EvaluatorWrapper.java
@@ -0,0 +1,126 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.coverage.grid;
+
+import java.util.Map;
+import org.opengis.geometry.DirectPosition;
+import org.opengis.referencing.operation.TransformException;
+
+// Branch-dependent imports
+import org.opengis.coverage.CannotEvaluateException;
+
+
+/**
+ * An evaluator which delegates all operations to another evaluator.
+ * The default implementation of all methods except {@link #getCoverage()} 
delegates to the source evaluator.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 1.3
+ * @since   1.3
+ * @module
+ */
+abstract class EvaluatorWrapper implements GridCoverage.Evaluator {
+    /**
+     * The evaluator provided by source coverage.
+     * This is where all operations are delegated.
+     */
+    private final GridCoverage.Evaluator source;
+
+    /**
+     * Creates a new evaluator wrapper.
+     *
+     * @param  source  the evaluator to wrap.
+     */
+    EvaluatorWrapper(final GridCoverage.Evaluator source) {
+        this.source = source;
+    }
+
+    /**
+     * Returns whether to return {@code null} instead of throwing an exception 
if a point is outside coverage bounds.
+     */
+    @Override
+    public boolean isNullIfOutside() {
+        return source.isNullIfOutside();
+    }
+
+    /**
+     * Specifies whether to return {@code null} instead of throwing an 
exception if a point is outside coverage bounds.
+     */
+    @Override
+    public void setNullIfOutside(final boolean flag) {
+        source.setNullIfOutside(flag);
+    }
+
+    /**
+     * Returns {@code true} if this evaluator is allowed to wraparound 
coordinates that are outside the grid.
+     */
+    @Override
+    public boolean isWraparoundEnabled() {
+        return source.isWraparoundEnabled();
+    }
+
+    /**
+     * Specifies whether this evaluator is allowed to wraparound coordinates 
that are outside the grid.
+     */
+    @Override
+    public void setWraparoundEnabled(final boolean allow) {
+        source.setWraparoundEnabled(allow);
+    }
+
+    /**
+     * Returns the default slice where to perform evaluation, or an empty map 
if unspecified.
+     * This method should be overridden if this evaluator has been created for 
a coverage
+     * with a different grid geometry than the coverage of the wrapped 
evaluator.
+     */
+    @Override
+    public Map<Integer,Long> getDefaultSlice() {
+        return source.getDefaultSlice();
+    }
+
+    /**
+     * Sets the default slice where to perform evaluation when the points do 
not have enough dimensions.
+     * This method should be overridden if this evaluator has been created for 
a coverage
+     * with a different grid geometry than the coverage of the wrapped 
evaluator.
+     */
+    @Override
+    public void setDefaultSlice(Map<Integer,Long> slice) {
+        source.setDefaultSlice(slice);
+    }
+
+    /**
+     * Converts the specified geospatial position to grid coordinates.
+     * This method should be overridden if this evaluator has been created for 
a coverage
+     * with a different grid geometry than the coverage of the wrapped 
evaluator.
+     */
+    @Override
+    public FractionalGridCoordinates toGridCoordinates(final DirectPosition 
point) throws TransformException {
+        return source.toGridCoordinates(point);
+    }
+
+    /**
+     * Returns a sequence of double values for a given point in the coverage.
+     * This method should be overridden if this evaluator is for a coverage
+     * doing some on-the-fly conversion of sample values.
+     *
+     * @param  point  the coordinate point where to evaluate.
+     * @throws CannotEvaluateException if the values can not be computed.
+     */
+    @Override
+    public double[] apply(final DirectPosition point) throws 
CannotEvaluateException {
+        return source.apply(point);
+    }
+}
diff --git 
a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/FractionalGridCoordinates.java
 
b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/FractionalGridCoordinates.java
index d91504dd87..2995c448ee 100644
--- 
a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/FractionalGridCoordinates.java
+++ 
b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/FractionalGridCoordinates.java
@@ -50,7 +50,7 @@ import org.apache.sis.util.resources.Errors;
  * @author  Martin Desruisseaux (Geomatys)
  * @version 1.2
  *
- * @see GridEvaluator#toGridCoordinates(DirectPosition)
+ * @see GridCoverage.Evaluator#toGridCoordinates(DirectPosition)
  *
  * @since 1.1
  * @module
@@ -71,7 +71,7 @@ public class FractionalGridCoordinates implements 
GridCoordinates, Serializable
      *
      * <div class="note"><b>Note:</b>
      * {@code FractionalGridCoordinates} are usually not created directly, but 
are instead obtained
-     * indirectly for example from the {@linkplain 
GridEvaluator#toGridCoordinates(DirectPosition)
+     * indirectly for example from the {@linkplain 
GridCoverage.Evaluator#toGridCoordinates(DirectPosition)
      * conversion of a geospatial position}.</div>
      *
      * @param  dimension  the number of dimensions.
@@ -348,7 +348,7 @@ public class FractionalGridCoordinates implements 
GridCoordinates, Serializable
      * @return the grid coordinates converted using the given transform.
      * @throws TransformException if the grid coordinates can not be converted 
by {@code gridToCRS}.
      *
-     * @see GridEvaluator#toGridCoordinates(DirectPosition)
+     * @see GridCoverage.Evaluator#toGridCoordinates(DirectPosition)
      */
     public DirectPosition toPosition(final MathTransform gridToCRS) throws 
TransformException {
         return gridToCRS.transform(new Position(this), null);
diff --git 
a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridCoverage.java 
b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridCoverage.java
index bd0425eedb..f6de832713 100644
--- 
a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridCoverage.java
+++ 
b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridCoverage.java
@@ -16,6 +16,7 @@
  */
 package org.apache.sis.coverage.grid;
 
+import java.util.Map;
 import java.util.List;
 import java.util.Locale;
 import java.util.Optional;
@@ -26,6 +27,7 @@ import org.opengis.geometry.DirectPosition;
 import org.opengis.geometry.MismatchedDimensionException;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.opengis.referencing.operation.MathTransform1D;
+import org.opengis.referencing.operation.TransformException;
 import org.opengis.referencing.operation.NoninvertibleTransformException;
 import org.apache.sis.internal.util.UnmodifiableArrayList;
 import org.apache.sis.measure.NumberRange;
@@ -301,8 +303,8 @@ public abstract class GridCoverage extends BandedCoverage {
      * conversions to grid indices are applied as needed.
      *
      * <h4>Multi-threading</h4>
-     * {@code GridEvaluator}s are not thread-safe. For computing sample values 
concurrently,
-     * a new {@link GridEvaluator} instance should be created for each thread 
by invoking this
+     * {@code Evaluator}s are not thread-safe. For computing sample values 
concurrently,
+     * a new {@code Evaluator} instance should be created for each thread by 
invoking this
      * method multiply times.
      *
      * @return a new function for computing or interpolating sample values.
@@ -310,10 +312,86 @@ public abstract class GridCoverage extends BandedCoverage 
{
      * @since 1.1
      */
     @Override
-    public GridEvaluator evaluator() {
+    public Evaluator evaluator() {
         return new GridEvaluator(this);
     }
 
+    /**
+     * Interpolates values of sample dimensions at given positions.
+     * Values are computed by calls to {@link #apply(DirectPosition)} and are 
returned as {@code double[]}.
+     * This method extends {@link BandedCoverage.Evaluator} with the addition 
of some methods specific to
+     * gridded data.
+     *
+     * <h2>Multi-threading</h2>
+     * Evaluators are not thread-safe. An instance of {@code Evaluator} should 
be created
+     * for each thread that need to interpolate sample values.
+     *
+     * @author  Johann Sorel (Geomatys)
+     * @author  Martin Desruisseaux (Geomatys)
+     * @version 1.3
+     *
+     * @see GridCoverage#evaluator()
+     *
+     * @since 1.3
+     * @module
+     */
+    public interface Evaluator extends BandedCoverage.Evaluator {
+        /**
+         * Returns the coverage from which this evaluator is fetching sample 
values.
+         * This is the coverage on which the {@link GridCoverage#evaluator()} 
method has been invoked.
+         *
+         * @return the source of sample values for this evaluator.
+         */
+        @Override
+        GridCoverage getCoverage();
+
+        /**
+         * Returns the default slice where to perform evaluation, or an empty 
map if unspecified.
+         * Keys are dimensions from 0 inclusive to {@link 
GridGeometry#getDimension()} exclusive,
+         * and values are the grid coordinates of the slice in the dimension 
specified by the key.
+         *
+         * <p>This information allows to invoke {@link #apply(DirectPosition)} 
with for example
+         * two-dimensional points even if the underlying coverage is 
three-dimensional.
+         * The missing coordinate values are replaced by the values provided 
in the map.</p>
+         *
+         * @return the default slice where to perform evaluation, or an empty 
map if unspecified.
+         */
+        Map<Integer,Long> getDefaultSlice();
+
+        /**
+         * Sets the default slice where to perform evaluation when the points 
do not have enough dimensions.
+         * A {@code null} argument restores the default value, which is to 
infer the slice from the coverage
+         * grid geometry.
+         *
+         * @param  slice  the default slice where to perform evaluation, or an 
empty map if none.
+         * @throws IllegalArgumentException if the map contains an illegal 
dimension or grid coordinate value.
+         *
+         * @see GridExtent#getSliceCoordinates()
+         */
+        void setDefaultSlice(Map<Integer,Long> slice);
+
+        /**
+         * Converts the specified geospatial position to grid coordinates. If 
the given position is associated to
+         * a non-null coordinate reference system (CRS) different than the 
{@linkplain #getCoverage() coverage} CRS,
+         * then this method automatically transforms that position to the 
{@linkplain #getCoordinateReferenceSystem()
+         * coverage CRS} before to compute grid coordinates.
+         *
+         * <p>This method does not put any restriction on the grid coordinates 
result.
+         * The result may be outside the {@linkplain GridGeometry#getExtent() 
grid extent}
+         * if the {@linkplain GridGeometry#getGridToCRS(PixelInCell) grid to 
CRS} transform allows it.</p>
+         *
+         * @param  point  geospatial coordinates (in arbitrary CRS) to 
transform to grid coordinates.
+         * @return the grid coordinates for the given geospatial coordinates.
+         * @throws IncompleteGridGeometryException if the {@linkplain 
GridCoverage#getGridGeometry() grid geometry}
+         *         does not define a "grid to CRS" transform, or if the given 
point has a non-null CRS but the
+         *         coverage does not {@linkplain 
GridCoverage#getCoordinateReferenceSystem() have a CRS}.
+         * @throws TransformException if the given coordinates can not be 
transformed.
+         *
+         * @see FractionalGridCoordinates#toPosition(MathTransform)
+         */
+        FractionalGridCoordinates toGridCoordinates(final DirectPosition 
point) throws TransformException;
+    }
+
     /**
      * Returns a two-dimensional slice of grid data as a rendered image. The 
given {@code sliceExtent} argument specifies
      * the coordinates of the slice in all dimensions that are not in the 
two-dimensional image. For example if this grid
diff --git 
a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridCoverage2D.java
 
b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridCoverage2D.java
index 273e8b2e53..82e2e81127 100644
--- 
a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridCoverage2D.java
+++ 
b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridCoverage2D.java
@@ -502,13 +502,13 @@ public class GridCoverage2D extends GridCoverage {
      * Creates a new function for computing or interpolating sample values at 
given locations.
      *
      * <h4>Multi-threading</h4>
-     * {@code GridEvaluator}s are not thread-safe. For computing sample values 
concurrently,
-     * a new {@link GridEvaluator} instance should be created for each thread.
+     * {@code Evaluator}s are not thread-safe. For computing sample values 
concurrently,
+     * a new {@code Evaluator} instance should be created for each thread.
      *
      * @since 1.1
      */
     @Override
-    public GridEvaluator evaluator() {
+    public Evaluator evaluator() {
         return new PixelAccessor();
     }
 
diff --git 
a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridEvaluator.java
 
b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridEvaluator.java
index a13ca901d3..85014e7280 100644
--- 
a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridEvaluator.java
+++ 
b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridEvaluator.java
@@ -53,7 +53,7 @@ import static java.util.logging.Logger.getLogger;
 
 
 /**
- * Computes or interpolates values of sample dimensions at given positions.
+ * Default implementation of {@link GridCoverage.Evaluator} for interpolating 
values at given positions.
  * Values are computed by calls to {@link #apply(DirectPosition)} and are 
returned as {@code double[]}.
  *
  * <h2>Multi-threading</h2>
@@ -72,7 +72,7 @@ import static java.util.logging.Logger.getLogger;
  * @since 1.1
  * @module
  */
-public class GridEvaluator implements GridCoverage.Evaluator {
+class GridEvaluator implements GridCoverage.Evaluator {
     /**
      * The coverage in which to evaluate sample values.
      */
@@ -170,8 +170,7 @@ public class GridEvaluator implements 
GridCoverage.Evaluator {
 
     /**
      * Returns the coverage from which this evaluator is fetching sample 
values.
-     * This is usually the coverage on which the {@link 
GridCoverage#evaluator()} method has been invoked,
-     * but not necessarily. Implementations are allowed to use a different 
coverage for efficiency.
+     * This is the coverage on which the {@link GridCoverage#evaluator()} 
method has been invoked.
      *
      * @return the source of sample values for this evaluator.
      */
@@ -193,6 +192,7 @@ public class GridEvaluator implements 
GridCoverage.Evaluator {
      *
      * @since 1.3
      */
+    @Override
     @SuppressWarnings("ReturnOfCollectionOrArrayField")     // Because the map 
is unmodifiable.
     public Map<Integer,Long> getDefaultSlice() {
         if (slice == null) {
@@ -214,6 +214,7 @@ public class GridEvaluator implements 
GridCoverage.Evaluator {
      *
      * @since 1.3
      */
+    @Override
     @SuppressWarnings("AssignmentToCollectionOrArrayFieldFromParameter")
     public void setDefaultSlice(Map<Integer,Long> slice) {
         if (!Objects.equals(this.slice, slice)) {
@@ -243,6 +244,7 @@ public class GridEvaluator implements 
GridCoverage.Evaluator {
      *
      * @since 1.2
      */
+    @Override
     public boolean isWraparoundEnabled() {
         return (wraparoundAxes != 0);
     }
@@ -258,6 +260,7 @@ public class GridEvaluator implements 
GridCoverage.Evaluator {
      *
      * @since 1.2
      */
+    @Override
     public void setWraparoundEnabled(final boolean allow) {
         wraparoundAxes = 0;
         if (allow) try {
@@ -410,28 +413,25 @@ public class GridEvaluator implements 
GridCoverage.Evaluator {
     }
 
     /**
-     * Converts the specified geospatial position to grid coordinates. If the 
given position
-     * is associated to a non-null coordinate reference system (CRS) different 
than the
-     * {@linkplain #coverage} CRS, then this method automatically transforms 
that position to the
+     * Converts the specified geospatial position to grid coordinates.
+     * If the given position is associated to a non-null coordinate reference 
system (CRS) different than the
+     * {@linkplain #getCoverage() coverage} CRS, then this method 
automatically transforms that position to the
      * {@linkplain GridCoverage#getCoordinateReferenceSystem() coverage CRS} 
before to compute grid coordinates.
      *
      * <p>This method does not put any restriction on the grid coordinates 
result.
      * The result may be outside the {@linkplain GridGeometry#getExtent() grid 
extent}
      * if the {@linkplain GridGeometry#getGridToCRS(PixelInCell) grid to CRS} 
transform allows it.</p>
      *
-     * <p>The grid coordinates are relative to the grid of the coverage 
returned by {@link #getCoverage()}.
-     * This is usually the coverage on which the {@link 
GridCoverage#evaluator()} method has been invoked,
-     * but not necessarily. Implementations are allowed to use a different 
coverage for efficiency.</p>
-     *
      * @param  point  geospatial coordinates (in arbitrary CRS) to transform 
to grid coordinates.
      * @return the grid coordinates for the given geospatial coordinates.
      * @throws IncompleteGridGeometryException if the {@linkplain 
GridCoverage#getGridGeometry() grid geometry}
      *         does not define a "grid to CRS" transform, or if the given 
point has a non-null CRS but the
-     *         {@linkplain #coverage} does not {@linkplain 
GridCoverage#getCoordinateReferenceSystem() have a CRS}.
+     *         coverage does not {@linkplain 
GridCoverage#getCoordinateReferenceSystem() have a CRS}.
      * @throws TransformException if the given coordinates can not be 
transformed.
      *
      * @see FractionalGridCoordinates#toPosition(MathTransform)
      */
+    @Override
     public FractionalGridCoordinates toGridCoordinates(final DirectPosition 
point) throws TransformException {
         ArgumentChecks.ensureNonNull("point", point);
         try {
diff --git 
a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridExtent.java 
b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridExtent.java
index 382c111eb3..e71d284659 100644
--- 
a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridExtent.java
+++ 
b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridExtent.java
@@ -841,7 +841,7 @@ public class GridExtent implements GridEnvelope, 
LenientComparable, Serializable
      *
      * @return grid coordinates for all dimensions where the grid has a size 
of 1.
      *
-     * @see GridEvaluator#setDefaultSlice(Map)
+     * @see GridCoverage.Evaluator#setDefaultSlice(Map)
      *
      * @since 1.3
      */
diff --git 
a/core/sis-feature/src/test/java/org/apache/sis/coverage/grid/GridCoverage2DTest.java
 
b/core/sis-feature/src/test/java/org/apache/sis/coverage/grid/GridCoverage2DTest.java
index bf19bdeb57..33d1abf21a 100644
--- 
a/core/sis-feature/src/test/java/org/apache/sis/coverage/grid/GridCoverage2DTest.java
+++ 
b/core/sis-feature/src/test/java/org/apache/sis/coverage/grid/GridCoverage2DTest.java
@@ -191,11 +191,11 @@ public strictfp class GridCoverage2DTest extends TestCase 
{
     }
 
     /**
-     * Tests {@link GridEvaluator#apply(DirectPosition)}.
+     * Tests {@link GridCoverage.Evaluator#apply(DirectPosition)}.
      */
     @Test
     public void testEvaluator() {
-        final GridEvaluator evaluator = createTestCoverage().evaluator();
+        final GridCoverage.Evaluator evaluator = 
createTestCoverage().evaluator();
         /*
          * Test evaluation at indeger indices. No interpolation should be 
applied.
          */
@@ -227,11 +227,8 @@ public strictfp class GridCoverage2DTest extends TestCase {
     }
 
     /**
-     * Tests {@link GridEvaluator#apply(DirectPosition)} with a wraparound on 
the longitude axis.
+     * Tests {@link GridCoverage.Evaluator#apply(DirectPosition)} with a 
wraparound on the longitude axis.
      * This method tests a coordinate that would be outside the grid if 
wraparound was not applied.
-     *
-     * @todo Not yet implemented. One potential place where to implement this 
functionality could be
-     *       {@link GridEvaluator#toGridPosition(DirectPosition)}.
      */
     @Test
     @DependsOnMethod("testEvaluator")
@@ -239,12 +236,12 @@ public strictfp class GridCoverage2DTest extends TestCase 
{
         final Matrix3 gridToCRS = new Matrix3();
         gridToCRS.m00 = 100;        // Scale
         gridToCRS.m02 = 100;        // Offset
-        final GridEvaluator evaluator = 
createTestCoverage(MathTransforms.linear(gridToCRS)).evaluator();
+        final GridCoverage.Evaluator evaluator = 
createTestCoverage(MathTransforms.linear(gridToCRS)).evaluator();
         evaluator.setWraparoundEnabled(true);
         assertArrayEquals(new double[] {2}, evaluator.apply(new 
DirectPosition2D(100, 0)), STRICT);
         assertArrayEquals(new double[] {5}, evaluator.apply(new 
DirectPosition2D(200, 0)), STRICT);
         /*
-         * Following tests fail if wraparound is not applied by 
`GridEvaluator`.
+         * Following tests fail if wraparound is not applied by 
`GridCoverage.Evaluator`.
          */
         assertArrayEquals(new double[] {5}, evaluator.apply(new 
DirectPosition2D(200 - 360, 0)), STRICT);
         assertArrayEquals(new double[] {2}, evaluator.apply(new 
DirectPosition2D(100 - 360, 0)), STRICT);

Reply via email to