From commits-return-13348-apmail-sis-commits-archive=sis.apache.org@sis.apache.org Wed Mar 4 23:18:51 2020 Return-Path: X-Original-To: apmail-sis-commits-archive@www.apache.org Delivered-To: apmail-sis-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [207.244.88.153]) by minotaur.apache.org (Postfix) with SMTP id B67B019096 for ; Wed, 4 Mar 2020 23:18:50 +0000 (UTC) Received: (qmail 16135 invoked by uid 500); 4 Mar 2020 23:18:50 -0000 Delivered-To: apmail-sis-commits-archive@sis.apache.org Received: (qmail 16114 invoked by uid 500); 4 Mar 2020 23:18:50 -0000 Mailing-List: contact commits-help@sis.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: sis-dev@sis.apache.org Delivered-To: mailing list commits@sis.apache.org Received: (qmail 16105 invoked by uid 99); 4 Mar 2020 23:18:49 -0000 Received: from ec2-52-202-80-70.compute-1.amazonaws.com (HELO gitbox.apache.org) (52.202.80.70) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 04 Mar 2020 23:18:49 +0000 Received: by gitbox.apache.org (ASF Mail Server at gitbox.apache.org, from userid 33) id 668D78DACA; Wed, 4 Mar 2020 23:18:49 +0000 (UTC) Date: Wed, 04 Mar 2020 23:18:49 +0000 To: "commits@sis.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`. MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Message-ID: <158336392917.21886.16613086928173461468@gitbox.apache.org> From: desruisseaux@apache.org X-Git-Host: gitbox.apache.org X-Git-Repo: sis X-Git-Refname: refs/heads/geoapi-4.0 X-Git-Reftype: branch X-Git-Oldrev: 8f5c5076edf0a38cbb93e6a17693e44c23060512 X-Git-Newrev: da15d494adace9c7fc1ae0da9e65f2f853911c1a X-Git-Rev: da15d494adace9c7fc1ae0da9e65f2f853911c1a X-Git-NotificationType: ref_changed_plus_diff X-Git-Multimail-Version: 1.5.dev Auto-Submitted: auto-generated 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 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);