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: Move the computation of initial zoom to the MapCanvas parent class, so it can be used by other implementations than `CoverageView`.
Date Wed, 04 Mar 2020 23:18: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 da15d49  Move the computation of initial zoom to the MapCanvas parent class, so it
can be used by other implementations than `CoverageView`.
da15d49 is described below

commit da15d494adace9c7fc1ae0da9e65f2f853911c1a
Author: Martin Desruisseaux <martin.desruisseaux@geomatys.com>
AuthorDate: Thu Mar 5 00:17:41 2020 +0100

    Move the computation of initial zoom to the MapCanvas parent class, so it can be used
by other implementations than `CoverageView`.
---
 .../org/apache/sis/gui/coverage/CoverageView.java  | 53 +++-----------
 .../java/org/apache/sis/gui/map/MapCanvas.java     | 84 +++++++++++++++++++---
 .../org/apache/sis/internal/map/PlanarCanvas.java  |  2 +-
 .../sis/referencing/operation/matrix/Matrices.java |  4 +-
 4 files changed, 89 insertions(+), 54 deletions(-)

diff --git a/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/CoverageView.java
b/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/CoverageView.java
index 5499897..8857c60 100644
--- a/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/CoverageView.java
+++ b/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/CoverageView.java
@@ -40,14 +40,9 @@ import org.apache.sis.coverage.grid.GridCoverage;
 import org.apache.sis.coverage.grid.GridExtent;
 import org.apache.sis.coverage.grid.GridGeometry;
 import org.apache.sis.internal.gui.ImageRenderings;
-import org.apache.sis.internal.map.RenderException;
 import org.apache.sis.gui.map.MapCanvas;
-import org.apache.sis.geometry.Envelope2D;
 import org.apache.sis.util.collection.BackingStoreException;
-import org.apache.sis.referencing.operation.matrix.Matrices;
-import org.apache.sis.referencing.operation.matrix.MatrixSIS;
 import org.apache.sis.referencing.operation.matrix.AffineTransforms2D;
-import org.apache.sis.referencing.operation.transform.LinearTransform;
 import org.apache.sis.referencing.operation.transform.MathTransforms;
 
 
@@ -130,12 +125,6 @@ final class CoverageView extends MapCanvas {
     private final StatusBar statusBar;
 
     /**
-     * Whether {@link #objectiveToDisplay} needs to be recomputed.
-     * We differ this recomputation until all parameters are known.
-     */
-    private boolean invalidObjectiveToDisplay;
-
-    /**
      * Creates a new two-dimensional canvas for {@link RenderedImage}.
      */
     public CoverageView() {
@@ -351,7 +340,17 @@ final class CoverageView extends MapCanvas {
             gridToCRS = null;
             errorOccurred(e);
         }
-        invalidObjectiveToDisplay = true;
+        Envelope visibleArea = null;
+        if (gridToCRS != null && geometry.isDefined(GridGeometry.ENVELOPE)) {
+            visibleArea = geometry.getEnvelope();
+        } else if (geometry.isDefined(GridGeometry.EXTENT)) try {
+            final GridExtent extent = geometry.getExtent();
+            visibleArea = extent.toEnvelope(MathTransforms.identity(extent.getDimension()));
+        } catch (TransformException e) {
+            // Should never happen because we asked for an identity transform.
+            errorOccurred(e);
+        }
+        setObjectiveBounds(visibleArea);
     }
 
     /**
@@ -366,36 +365,6 @@ final class CoverageView extends MapCanvas {
             return null;
         }
         /*
-         * Compute the `objectiveToDisplay` only before the first rendering, because the
display
-         * bounds may not be known before (it may be zero at the time `setImage(…)` is
invoked).
-         * This code is executed only once for a new image.
-         */
-        if (invalidObjectiveToDisplay) try {
-            invalidObjectiveToDisplay = false;
-            final Envelope bounds;
-            final GridGeometry geometry = getCoverage().getGridGeometry();
-            if (gridToCRS != null && geometry.isDefined(GridGeometry.ENVELOPE)) {
-                bounds = geometry.getEnvelope();
-            } else if (geometry.isDefined(GridGeometry.EXTENT)) {
-                final GridExtent extent = geometry.getExtent();
-                bounds = extent.toEnvelope(MathTransforms.identity(extent.getDimension()));
-            } else {
-                bounds = null;
-            }
-            LinearTransform tr;
-            if (bounds != null) {
-                final Envelope2D db = getDisplayBounds();
-                final MatrixSIS m = Matrices.createTransform(bounds, db);
-                Matrices.forceUniformScale(m, 0, new double[] {db.width / 2, db.height /
2});
-                tr = MathTransforms.linear(m);
-            } else {
-                tr = MathTransforms.identity(ImageLoader.BIDIMENSIONAL);
-            }
-            setObjectiveToDisplay(tr);
-        } catch (RenderException | TransformException e) {
-            errorOccurred(e);
-        }
-        /*
          * At each rendering operation, compute the transform from `data` cell coordinates
to pixel coordinates
          * of the image shown in this view. We do this computation every times because `objectiveToDisplay`
may
          * vary at any time, and also because we need a new `AffineTransform` instance anyway
(we can not reuse
diff --git a/application/sis-javafx/src/main/java/org/apache/sis/gui/map/MapCanvas.java b/application/sis-javafx/src/main/java/org/apache/sis/gui/map/MapCanvas.java
index b53cd8f..36e394e 100644
--- a/application/sis-javafx/src/main/java/org/apache/sis/gui/map/MapCanvas.java
+++ b/application/sis-javafx/src/main/java/org/apache/sis/gui/map/MapCanvas.java
@@ -33,13 +33,19 @@ import javafx.scene.layout.Pane;
 import javafx.beans.Observable;
 import javafx.concurrent.Task;
 import javafx.util.Callback;
+import org.opengis.geometry.Envelope;
+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.geometry.Envelope2D;
+import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.internal.util.Numerics;
 import org.apache.sis.internal.coverage.j2d.ColorModelFactory;
 import org.apache.sis.internal.gui.BackgroundThreads;
 import org.apache.sis.internal.gui.ExceptionReporter;
 import org.apache.sis.internal.map.PlanarCanvas;
 import org.apache.sis.internal.map.RenderException;
-import org.apache.sis.internal.util.Numerics;
 
 
 /**
@@ -101,6 +107,16 @@ public abstract class MapCanvas extends PlanarCanvas {
     protected final Pane view;
 
     /**
+     * The data bounds to use for computing the initial value of {@link #objectiveToDisplay}.
+     * This is reset to {@code null} after the transform has been computed.
+     * We differ this recomputation until all parameters are known.
+     *
+     * @see #setObjectiveBounds(Envelope)
+     * @see #invalidObjectiveToDisplay
+     */
+    private Envelope objectiveBounds;
+
+    /**
      * Incremented when the map needs to be rendered again.
      *
      * @see #renderedContentStamp
@@ -130,6 +146,12 @@ public abstract class MapCanvas extends PlanarCanvas {
     private boolean sizeChanged;
 
     /**
+     * Whether {@link #objectiveToDisplay} needs to be recomputed.
+     * We differ this recomputation until all parameters are known.
+     */
+    private boolean invalidObjectiveToDisplay;
+
+    /**
      * Creates a new canvas for JavaFX application.
      *
      * @param  locale  the locale to use for labels and some messages, or {@code null} for
default.
@@ -175,6 +197,22 @@ public abstract class MapCanvas extends PlanarCanvas {
     }
 
     /**
+     * Sets the data bounds to use for computing the initial value of {@link #objectiveToDisplay}.
+     * This method should be invoked only when new data have been loaded, or when the caller
wants
+     * to discard any zoom or translation and reset the view of the given bounds.
+     *
+     * @param  visibleArea  bounding box in objective CRS of the initial area to show,
+     *         or {@code null} if unknown (in which case an identity transform will be set).
+     *
+     * @see #setObjectiveCRS(CoordinateReferenceSystem)
+     */
+    protected void setObjectiveBounds(final Envelope visibleArea) {
+        ArgumentChecks.ensureDimensionMatches("bounds", BIDIMENSIONAL, visibleArea);
+        objectiveBounds = visibleArea;
+        invalidObjectiveToDisplay = true;
+    }
+
+    /**
      * Starts a background task for any process for loading or rendering the map.
      * This {@code MapCanvas} class invokes this method for rendering the map,
      * but subclasses can also invoke this method for other purposes.
@@ -312,19 +350,45 @@ public abstract class MapCanvas extends PlanarCanvas {
             return;
         }
         renderedContentStamp = contentChangeCount;
-        /*
-         * If a new canvas size is known, inform the parent `PlanarCanvas` about that.
-         * It may cause a recomputation of the "objective to display" transform.
-         */
-        if (sizeChanged) try {
-            sizeChanged = false;
-            Envelope2D bounds = new Envelope2D(null, view.getLayoutX(), view.getLayoutY(),
view.getWidth(), view.getHeight());
-            if (bounds.isEmpty()) return;
-            setDisplayBounds(bounds);
+        try {
+            /*
+             * If a new canvas size is known, inform the parent `PlanarCanvas` about that.
+             * It may cause a recomputation of the "objective to display" transform.
+             */
+            if (sizeChanged) {
+                sizeChanged = false;
+                Envelope2D bounds = new Envelope2D(null, view.getLayoutX(), view.getLayoutY(),
view.getWidth(), view.getHeight());
+                if (bounds.isEmpty()) return;
+                setDisplayBounds(bounds);
+            }
+            /*
+             * Compute the `objectiveToDisplay` only before the first rendering, because
the display
+             * bounds may not be known before (it may be zero at the time `MapCanvas` is
initialized).
+             * This code is executed only once for a new map.
+             */
+            if (invalidObjectiveToDisplay) {
+                invalidObjectiveToDisplay = false;
+                LinearTransform tr;
+                final Envelope source = objectiveBounds;
+                if (objectiveBounds != null) {
+                    objectiveBounds = null;
+                    final Envelope2D target = getDisplayBounds();
+                    final MatrixSIS m = Matrices.createTransform(source, target);
+                    Matrices.forceUniformScale(m, 0, new double[] {target.width / 2, target.height
/ 2});
+                    tr = MathTransforms.linear(m);
+                } else {
+                    tr = MathTransforms.identity(BIDIMENSIONAL);
+                }
+                setObjectiveToDisplay(tr);
+            }
         } catch (RenderException ex) {
             errorOccurred(ex);
             return;
         }
+        /*
+         * Invoke `createRenderer()` only after we finished above configuration, because
that method may take
+         * a snapshot of current canvas state in preparation for use in background threads.
+         */
         final Renderer context = createRenderer();
         if (context == null || !context.initialize(view)) {
             return;
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 b0c8792..c8851c2 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
@@ -52,7 +52,7 @@ public abstract class PlanarCanvas extends Canvas {
     /**
      * The {@value} constant for identifying code specific to bi-dimensional case.
      */
-    private static final int BIDIMENSIONAL = 2;
+    protected static final int BIDIMENSIONAL = 2;
 
     /**
      * The display Coordinate Reference System used by all {@code PlanarCanvas} instances.
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrices.java
b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrices.java
index a69d52d..50dcff0 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrices.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrices.java
@@ -846,6 +846,8 @@ public final class Matrices extends Static {
      *
      * @param  matrix    the matrix in which to uniformize scale factors. Will be modified
in-place.
      * @param  selector  a value between 0 for smallest scale magnitude and 1 for largest
scale magnitude (inclusive).
+     *                   Values outside [0 … 1] range are authorized, but will result in
scale factors outside the
+     *                   range of current scale factors in the given matrix.
      * @param  shift     compensation for the translation terms, or {@code null} if none.
      * @return {@code true} if the given matrix changed as a result of this method call.
      *
@@ -853,7 +855,7 @@ public final class Matrices extends Static {
      */
     public static boolean forceUniformScale(final Matrix matrix, final double selector, final
double[] shift) {
         ArgumentChecks.ensureNonNull("matrix", matrix);
-        ArgumentChecks.ensureBetween("selector", 0, 1, selector);
+        ArgumentChecks.ensureFinite("selector", selector);
         final int srcDim = matrix.getNumCol() - 1;
         final int tgtDim = matrix.getNumRow() - 1;
         ArgumentChecks.ensureDimensionMatches("shift", tgtDim, shift);


Mime
View raw message