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
commit c71a1d11dc2d70cfb050d815e4ab4bba7e5097cb Author: Martin Desruisseaux <[email protected]> AuthorDate: Fri Jul 1 18:23:37 2022 +0200 Better implementation of `getDomain(…)` on inverse transforms. Remove infinite values in Mercator.getDomain(…). --- .../referencing/operation/projection/Mercator.java | 11 ++-- .../operation/projection/NormalizedProjection.java | 2 +- .../operation/projection/TransverseMercator.java | 12 ++-- .../operation/transform/AbstractMathTransform.java | 7 +-- .../operation/transform/DomainDefinition.java | 67 ++++++++++++++++------ 5 files changed, 63 insertions(+), 36 deletions(-) diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Mercator.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Mercator.java index 11d5b4b0fd..90097ef0a1 100644 --- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Mercator.java +++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Mercator.java @@ -27,7 +27,7 @@ import org.opengis.referencing.operation.MathTransform; import org.opengis.referencing.operation.MathTransformFactory; import org.opengis.referencing.operation.OperationMethod; import org.opengis.referencing.operation.TransformException; -import org.apache.sis.geometry.GeneralEnvelope; +import org.apache.sis.geometry.Envelope2D; import org.apache.sis.internal.referencing.provider.Mercator1SP; import org.apache.sis.internal.referencing.provider.Mercator2SP; import org.apache.sis.internal.referencing.provider.MercatorSpherical; @@ -402,12 +402,9 @@ subst: if ((variant.spherical || eccentricity == 0) && getClass() == Mercator.c * @since 1.3 */ @Override - public final Optional<Envelope> getDomain(final DomainDefinition criteria) { - final double limit = (variant == Variant.MILLER) ? PI/2 : PI/2 * (84d/90); - final GeneralEnvelope domain = new GeneralEnvelope(2); - domain.setRange(0, NEGATIVE_INFINITY, POSITIVE_INFINITY); - domain.setRange(1, -limit, +limit); - return Optional.of(domain); + public Optional<Envelope> getDomain(final DomainDefinition criteria) { + final double limit = (variant == Variant.MILLER) ? -PI/2 : -PI/2 * (84d/90); + return Optional.of(new Envelope2D(null, -0.5, limit, 1, -2*limit)); } /** diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/NormalizedProjection.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/NormalizedProjection.java index f8582c5bae..8b7e0c16a5 100644 --- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/NormalizedProjection.java +++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/NormalizedProjection.java @@ -129,7 +129,7 @@ import static java.util.logging.Logger.getLogger; * @author André Gosselin (MPO) * @author Rueben Schulz (UBC) * @author Rémi Maréchal (Geomatys) - * @version 1.2 + * @version 1.3 * * @see ContextualParameters * @see <a href="https://mathworld.wolfram.com/MapProjection.html">Map projections on MathWorld</a> diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/TransverseMercator.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/TransverseMercator.java index cb227afa1f..10ee4214b5 100644 --- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/TransverseMercator.java +++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/TransverseMercator.java @@ -26,7 +26,7 @@ import org.opengis.referencing.operation.MathTransform; import org.opengis.referencing.operation.MathTransformFactory; import org.opengis.referencing.operation.Matrix; import org.opengis.referencing.operation.OperationMethod; -import org.apache.sis.geometry.GeneralEnvelope; +import org.apache.sis.geometry.Envelope2D; import org.apache.sis.referencing.operation.matrix.Matrix2; import org.apache.sis.referencing.operation.matrix.MatrixSIS; import org.apache.sis.referencing.operation.transform.DomainDefinition; @@ -383,10 +383,12 @@ public class TransverseMercator extends NormalizedProjection { * @since 1.3 */ @Override - public final Optional<Envelope> getDomain(final DomainDefinition criteria) { - final GeneralEnvelope domain = new GeneralEnvelope(2); - domain.setRange(0, -PI/2 * (40d/90), +PI/2 * (40d/90)); - domain.setRange(1, -PI/2 * (84d/90), +PI/2 * (84d/90)); + public Optional<Envelope> getDomain(final DomainDefinition criteria) { + final Envelope2D domain = new Envelope2D(); + domain.x = -PI/2 * (40d/90); + domain.y = -PI/2 * (84d/90); + domain.width = -2 * domain.x; + domain.height = -2 * domain.y; return Optional.of(domain); } diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform.java index efe0307a20..8e3709d859 100644 --- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform.java +++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform.java @@ -31,7 +31,6 @@ import org.opengis.referencing.operation.MathTransformFactory; import org.opengis.referencing.operation.TransformException; import org.opengis.referencing.operation.NoninvertibleTransformException; import org.opengis.referencing.operation.OperationMethod; -import org.apache.sis.geometry.Envelopes; import org.apache.sis.geometry.GeneralDirectPosition; import org.apache.sis.parameter.Parameterized; import org.apache.sis.referencing.operation.matrix.Matrices; @@ -1125,13 +1124,11 @@ public abstract class AbstractMathTransform extends FormattableObject * @since 1.3 */ @Override - public Optional<Envelope> getDomain(DomainDefinition criteria) throws TransformException { + public Optional<Envelope> getDomain(final DomainDefinition criteria) throws TransformException { final MathTransform inverse = inverse(); if (inverse instanceof AbstractMathTransform) { final Optional<Envelope> domain = ((AbstractMathTransform) inverse).getDomain(criteria); - if (domain.isPresent()) { - return Optional.of(Envelopes.transform(inverse, domain.get())); - } + return Optional.ofNullable(criteria.intersectOrTransform(domain.orElse(null), inverse)); } return Optional.empty(); } diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DomainDefinition.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DomainDefinition.java index 32d198c066..868536b017 100644 --- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DomainDefinition.java +++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DomainDefinition.java @@ -17,12 +17,13 @@ package org.apache.sis.referencing.operation.transform; import java.util.Optional; -import org.apache.sis.geometry.Envelopes; import org.opengis.geometry.Envelope; import org.opengis.referencing.operation.MathTransform; import org.opengis.referencing.operation.TransformException; import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.apache.sis.referencing.CRS; +import org.apache.sis.util.ArgumentChecks; +import org.apache.sis.geometry.Envelopes; import org.apache.sis.geometry.GeneralEnvelope; @@ -147,7 +148,13 @@ public class DomainDefinition { */ public void estimate(final MathTransform evaluated) throws TransformException { if (evaluated instanceof AbstractMathTransform) { - intersect(((AbstractMathTransform) evaluated).getDomain(this).orElse(null)); + Envelope domain = ((AbstractMathTransform) evaluated).getDomain(this).orElse(null); + if (domain != null) { + if (stepToDomain != null) { + domain = Envelopes.transform(stepToDomain.concatenation(), domain); + } + intersect(domain); + } } } @@ -197,29 +204,53 @@ public class DomainDefinition { /** * Sets the domain to the intersection of current domain with the specified envelope. - * The envelope coordinates shall be in units of the inputs of the {@link MathTransform} given to - * {@link #estimate(MathTransform)}. If that method is invoked recursively in a chain of transforms, - * then this method will automatically transform the given envelope to the units of the inputs of the - * first transform in the chain. If the given domain is {@code null}, then this method does nothing. + * The envelope coordinates shall be in units of the inputs of the first {@link MathTransform} + * given to {@link #estimate(MathTransform)}. If that method is invoked recursively in a chain + * of transforms, callers are responsible for converting the envelope. + * + * @param domain the domain to intersect with. + */ + public void intersect(final Envelope domain) { + ArgumentChecks.ensureNonNull("domain", domain); + if (limits == null) { + limits = domain; + } else { + if (intersection == null) { + limits = intersection = new GeneralEnvelope(limits); + } + intersection.intersect(domain); + } + } + + /** + * Transforms the given envelope, then either returns it or delegates to {@link #intersect(Envelope)}. + * If {@code prefix} was the only transform applied, then the transformed envelope is returned. + * Otherwise the transformed envelope is intersected with current domain and {@code null} is returned. + * + * <p>This method behavior allows opportunistic implementation of + * {@link org.apache.sis.referencing.operation.transform.AbstractMathTransform.Inverse#getDomain(DomainDefinition)}. + * When above-cited method is invoked directly by users, they should get the transformed envelope because there is + * no other transform queued in {@link #stepToDomain}. But if above-cited method is invoked for a transform in the + * middle of a transforms chain, then the transformed envelope can not be returned because it would not be in the + * CRS expected by method contract. But because that situation is specific to {@link ConcatenatedTransform}, + * it should be unnoticed by users.</p> * * @param domain the domain to intersect with, or {@code null} if none. - * @throws TransformException if the envelope can not be transformed to the domain of the first step - * in a chain of transforms. + * @param prefix a transform to apply on the envelope before other transforms. + * @return the transformed envelope if {@code prefix} was the only transform applied, or {@code null} otherwise. + * @throws TransformException if the envelope can not be transformed to the domain of the first transform step. */ - public void intersect(Envelope domain) throws TransformException { + final Envelope intersectOrTransform(Envelope domain, MathTransform prefix) throws TransformException { if (domain != null) { if (stepToDomain != null) { - domain = Envelopes.transform(stepToDomain.concatenation(), domain); - } - if (limits == null) { - limits = domain; - } else { - if (intersection == null) { - limits = intersection = new GeneralEnvelope(limits); - } - intersection.intersect(domain); + prefix = MathTransforms.concatenate(prefix, stepToDomain.concatenation()); + domain = Envelopes.transform(prefix, domain); + intersect(domain); + return null; } + domain = Envelopes.transform(prefix, domain); } + return domain; } /**
