From commits-return-13657-apmail-sis-commits-archive=sis.apache.org@sis.apache.org Tue Jun 16 10:05:18 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 B902C19A42 for ; Tue, 16 Jun 2020 10:05:17 +0000 (UTC) Received: (qmail 2941 invoked by uid 500); 16 Jun 2020 10:05:16 -0000 Delivered-To: apmail-sis-commits-archive@sis.apache.org Received: (qmail 2923 invoked by uid 500); 16 Jun 2020 10:05:16 -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 2866 invoked by uid 99); 16 Jun 2020 10:05:16 -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; Tue, 16 Jun 2020 10:05:16 +0000 Received: by gitbox.apache.org (ASF Mail Server at gitbox.apache.org, from userid 33) id 75CA58146F; Tue, 16 Jun 2020 10:05:16 +0000 (UTC) Date: Tue, 16 Jun 2020 10:05:16 +0000 To: "commits@sis.apache.org" Subject: [sis] branch geoapi-4.0 updated: Change of projection in MapCanvas need to use an orthonormal matrix for preserving the projection aspect. MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Message-ID: <159230191641.22229.857676728207713982@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: 0265dc639a6b3c0a54a95f78b16212d8ffdab7f9 X-Git-Newrev: 256c6e812e6fd97e2f39de1d43663b0eec1b20c1 X-Git-Rev: 256c6e812e6fd97e2f39de1d43663b0eec1b20c1 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 256c6e8 Change of projection in MapCanvas need to use an orthonormal matrix for preserving the projection aspect. 256c6e8 is described below commit 256c6e812e6fd97e2f39de1d43663b0eec1b20c1 Author: Martin Desruisseaux AuthorDate: Tue Jun 16 11:56:46 2020 +0200 Change of projection in MapCanvas need to use an orthonormal matrix for preserving the projection aspect. --- .../main/java/org/apache/sis/portrayal/Canvas.java | 80 ++++++++++++++++++++-- .../referencing/operation/matrix/MatrixSIS.java | 2 +- .../operation/transform/MathTransforms.java | 2 +- 3 files changed, 78 insertions(+), 6 deletions(-) diff --git a/core/sis-portrayal/src/main/java/org/apache/sis/portrayal/Canvas.java b/core/sis-portrayal/src/main/java/org/apache/sis/portrayal/Canvas.java index ff52a94..7f67e9c 100644 --- a/core/sis-portrayal/src/main/java/org/apache/sis/portrayal/Canvas.java +++ b/core/sis-portrayal/src/main/java/org/apache/sis/portrayal/Canvas.java @@ -46,12 +46,15 @@ import org.apache.sis.measure.Units; import org.apache.sis.referencing.CRS; import org.apache.sis.referencing.IdentifiedObjects; 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.referencing.operation.transform.TransformSeparator; import org.apache.sis.referencing.operation.DefaultCoordinateOperationFactory; import org.apache.sis.internal.referencing.CoordinateOperations; import org.apache.sis.internal.referencing.ReferencingUtilities; +import org.apache.sis.internal.referencing.DirectPositionView; +import org.apache.sis.internal.util.DoubleDouble; import org.apache.sis.coverage.grid.IncompleteGridGeometryException; import org.apache.sis.coverage.grid.GridGeometry; import org.apache.sis.coverage.grid.GridExtent; @@ -492,7 +495,7 @@ public class Canvas extends Observable implements Localized { * *

If the transform between old and new CRS is not identity, then this method recomputes * the objective to display conversion in a way preserving the display coordinates - * of the {@link #getPointOfInterest() point of interest}, together with the scales, shapes and + * of the {@link #getPointOfInterest() point of interest}, together with the scales and * orientations of features in close neighborhood of that point. * This calculation may cause {@value #OBJECTIVE_TO_DISPLAY_PROPERTY} property change event * to be sent to listeners, in addition of above-cited {@value #OBJECTIVE_CRS_PROPERTY} @@ -537,12 +540,12 @@ public class Canvas extends Observable implements Localized { */ final MathTransform poiToNew = findTransform(pointOfInterest.getCoordinateReferenceSystem(), newValue); final DirectPosition poiInNew = poiToNew.transform(pointOfInterest, allocatePosition()); - final LinearTransform cancel = MathTransforms.tangent(newToOld, poiInNew); - final MathTransform result = MathTransforms.concatenate(cancel, oldObjectiveToDisplay); + final MathTransform change = orthogonalTangent(newToOld, poiInNew.getCoordinate()); + final MathTransform result = MathTransforms.concatenate(change, oldObjectiveToDisplay); /* * The result is the new `objectiveToTransform` such as the display is unchanged around POI. * That transform should be an instance of `LinearTransform` because the two concatenated - * transforms were linear, but we nevertheless invoke `tangent(…)` again as a safety; + * transforms were linear, but we nevertheless invoke `tangent(…)` as a safety; * normally it should just return the `result` as-is. */ newObjectiveToDisplay = MathTransforms.tangent(result, poiInNew); @@ -566,6 +569,75 @@ public class Canvas extends Observable implements Localized { } /** + * Computes the approximate change from a new {@link #objectiveToDisplay} to the old one for keeping the + * Point Of Interest (POI) at the same location. The given {@code newToOld} argument is the change as a + * potentially non-linear transform. The transform returned by this method is a linear approximation of + * {@code newToOld} {@linkplain MathTransforms#tangent tangent} at the POI, but with orthogonal vectors. + * In other words, the returned transform may apply a uniform scale, a rotation or flip axes, but no shear. + * + * @param newToOld the change as a potentially non-linear transform. + * @param poiInNew point of interest in the coordinates of the new objective CRS. + * @return an approximation of {@code newToOld} with only uniform scale, rotation and axis flips. + * + * @see MathTransforms#tangent(MathTransform, DirectPosition) + */ + private static MathTransform orthogonalTangent(final MathTransform newToOld, final double[] poiInNew) + throws TransformException, RenderException + { + final double[] poiInOld = new double[newToOld.getTargetDimensions()]; + final MatrixSIS derivative = MatrixSIS.castOrCopy(MathTransforms.derivativeAndTransform(newToOld, poiInNew, 0, poiInOld, 0)); + final MatrixSIS magnitudes = derivative.normalizeColumns(); + final MatrixSIS affine = Matrices.createAffine(derivative, new DirectPositionView.Double(poiInOld)); + final int srcDim = magnitudes.getNumCol(); + final DoubleDouble scale = new DoubleDouble(); // Will be set to average magnitude value. + for (int i=0; iThis method is useful when the matrix is a diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/MathTransforms.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/MathTransforms.java index 75e90b1..356de2f 100644 --- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/MathTransforms.java +++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/MathTransforms.java @@ -737,10 +737,10 @@ public final class MathTransforms extends Static { public static LinearTransform tangent(final MathTransform toApproximate, final DirectPosition tangentPoint) throws TransformException { + ArgumentChecks.ensureNonNull("toApproximate", toApproximate); if (toApproximate instanceof LinearTransform) { return (LinearTransform) toApproximate; } - ArgumentChecks.ensureNonNull("toApproximate", toApproximate); final int srcDim = toApproximate.getSourceDimensions(); ArgumentChecks.ensureDimensionMatches("tangentPoint", srcDim, tangentPoint); final int tgtDim = toApproximate.getTargetDimensions();