sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ama...@apache.org
Subject [sis] 12/22: fix(Feature): Add CRS resolution strategy for filter operations.
Date Thu, 14 Nov 2019 11:46:46 GMT
This is an automated email from the ASF dual-hosted git repository.

amanin pushed a commit to branch refactor/sql-store
in repository https://gitbox.apache.org/repos/asf/sis.git

commit bea8309f0e3ca8e8bf2c4d11c599d60a8686d01c
Author: Alexis Manin <amanin@apache.org>
AuthorDate: Thu Oct 10 11:16:48 2019 +0200

    fix(Feature): Add CRS resolution strategy for filter operations.
---
 .../java/org/apache/sis/filter/CRSMatching.java    | 106 ++++++++++++++++++++
 .../java/org/apache/sis/filter/ST_Intersects.java  | 110 +++++++++++++++------
 .../java/org/apache/sis/filter/package-info.java   |  45 ++++++++-
 .../test/java/org/apache/sis/filter/SQLMMTest.java |  43 +++++++-
 .../sis/internal/feature/GeometriesTestCase.java   |   2 +-
 .../main/java/org/apache/sis/referencing/CRS.java  |  80 +++++++--------
 6 files changed, 307 insertions(+), 79 deletions(-)

diff --git a/core/sis-feature/src/main/java/org/apache/sis/filter/CRSMatching.java b/core/sis-feature/src/main/java/org/apache/sis/filter/CRSMatching.java
new file mode 100644
index 0000000..23dfdf2
--- /dev/null
+++ b/core/sis-feature/src/main/java/org/apache/sis/filter/CRSMatching.java
@@ -0,0 +1,106 @@
+package org.apache.sis.filter;
+
+import java.util.Optional;
+
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.referencing.operation.CoordinateOperation;
+import org.opengis.util.FactoryException;
+
+import org.apache.sis.referencing.CRS;
+import org.apache.sis.util.Utilities;
+import org.apache.sis.util.collection.BackingStoreException;
+
+import static org.apache.sis.referencing.IdentifiedObjects.getIdentifierOrName;
+
+/**
+ * TODO: improve CRS conversion/suggestion by allowing user to input a geographic region
of interest.
+ */
+@FunctionalInterface
+public interface CRSMatching {
+
+    static CRSMatching left(final CoordinateReferenceSystem source) {
+        if (source == null) {
+            return other -> {
+                if (other == null) return new NullMatch();
+                else throw new IllegalArgumentException("No match can be established with
given CRS because source one is null.");
+            };
+        } else {
+            return other -> {
+                if (other == null) throw new IllegalArgumentException("No match can be established
with previous CRS because input one is null");
+                final CoordinateReferenceSystem commonCrs = CRS.suggestCommonTarget(null,
source, other);
+                if (commonCrs == null) throw new IllegalArgumentException(String.format(
+                        "No common space can be found between %s and %s",
+                        getIdentifierOrName(source), getIdentifierOrName(other)
+                ));
+                return new DefaultMatch(commonCrs, source, other);
+            };
+        }
+    }
+
+    Match right(final CoordinateReferenceSystem other);
+
+    interface Match {
+        Optional<CoordinateReferenceSystem> getCommonCRS();
+        Optional<CoordinateOperation> fromLeft();
+        Optional<CoordinateOperation> fromRight();
+    }
+
+    final class NullMatch implements Match {
+
+        @Override
+        public Optional<CoordinateReferenceSystem> getCommonCRS() {
+            return Optional.empty();
+        }
+
+        @Override
+        public Optional<CoordinateOperation> fromLeft() {
+            return Optional.empty();
+        }
+
+        @Override
+        public Optional<CoordinateOperation> fromRight() {
+            return Optional.empty();
+        }
+    }
+
+    final class DefaultMatch implements Match {
+
+        final CoordinateReferenceSystem commonCRS;
+        final Optional<CoordinateOperation> fromLeft;
+        final Optional<CoordinateOperation> fromRight;
+
+        public DefaultMatch(CoordinateReferenceSystem commonCRS, CoordinateReferenceSystem
left, CoordinateReferenceSystem right) {
+            this.commonCRS = commonCRS;
+            try {
+                fromLeft = createOp(left, commonCRS);
+                fromRight = createOp(right, commonCRS);
+            } catch (FactoryException e) {
+                throw new BackingStoreException(e);
+            }
+        }
+
+        @Override
+        public Optional<CoordinateReferenceSystem> getCommonCRS() {
+            return Optional.of(commonCRS);
+        }
+
+        @Override
+        public Optional<CoordinateOperation> fromLeft() {
+            return fromLeft;
+        }
+
+        @Override
+        public Optional<CoordinateOperation> fromRight() {
+            return fromRight;
+        }
+    }
+
+    static Optional<CoordinateOperation> createOp(final CoordinateReferenceSystem source,
final CoordinateReferenceSystem target) throws FactoryException {
+        if (Utilities.equalsIgnoreMetadata(source, target)) {
+            return Optional.empty();
+        } else {
+            final CoordinateOperation op = CRS.findOperation(source, target, null);
+            return Optional.of(op);
+        }
+    }
+}
diff --git a/core/sis-feature/src/main/java/org/apache/sis/filter/ST_Intersects.java b/core/sis-feature/src/main/java/org/apache/sis/filter/ST_Intersects.java
index 407d291..f5ddf46 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/filter/ST_Intersects.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/filter/ST_Intersects.java
@@ -1,5 +1,7 @@
 package org.apache.sis.filter;
 
+import java.util.AbstractMap;
+import java.util.Map;
 import java.util.function.Predicate;
 
 import org.opengis.filter.FilterVisitor;
@@ -7,8 +9,14 @@ import org.opengis.filter.expression.Expression;
 import org.opengis.filter.expression.Literal;
 import org.opengis.filter.spatial.Intersects;
 import org.opengis.geometry.Geometry;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.referencing.operation.CoordinateOperation;
+import org.opengis.referencing.operation.TransformException;
+import org.opengis.util.FactoryException;
 
 import org.apache.sis.internal.feature.GeometryWrapper;
+import org.apache.sis.internal.feature.jts.JTS;
+import org.apache.sis.util.collection.BackingStoreException;
 
 import org.locationtech.jts.geom.prep.PreparedGeometry;
 import org.locationtech.jts.geom.prep.PreparedGeometryFactory;
@@ -38,11 +46,12 @@ public class ST_Intersects implements Intersects {
         ensureNonNull("Left operand", left);
         ensureNonNull("Right operand", right);
         if (left instanceof Literal && right instanceof Literal) {
-            intersects = constantOp((Literal) left, (Literal) right);
+            final boolean constantResult = nonOptimizedIntersects(null);
+            intersects = it -> constantResult;
         } else if (left instanceof Literal) {
-            intersects = intersect(right, (Literal) left);
+            intersects = intersect((Literal) left, right);
         } else if (right instanceof Literal) {
-            intersects = intersect(left, (Literal) right);
+            intersects = intersect((Literal) right, left);
         } else intersects = this::nonOptimizedIntersects;
     }
 
@@ -50,46 +59,83 @@ public class ST_Intersects implements Intersects {
         final Object leftEval = left.evaluate(candidate);
         final Object rightEval = right.evaluate(candidate);
         if (leftEval == null || rightEval == null) return false;
-        return toJTS(leftEval).intersects(toJTS(rightEval));
+
+        final Map.Entry<org.locationtech.jts.geom.Geometry, CoordinateReferenceSystem>
leftEntry = toJTS(leftEval);
+        final Map.Entry<org.locationtech.jts.geom.Geometry, CoordinateReferenceSystem>
rightEntry = toJTS(rightEval);
+        final CRSMatching.Match match = CRSMatching.left(leftEntry.getValue()).right(rightEntry.getValue());
+
+        final org.locationtech.jts.geom.Geometry leftGeom = match.fromLeft()
+                .map(op -> transformSilently(leftEntry.getKey(), op))
+                .orElse(leftEntry.getKey());
+        final org.locationtech.jts.geom.Geometry rightGeom = match.fromRight()
+                .map(op -> transformSilently(rightEntry.getKey(), op))
+                .orElse(rightEntry.getKey());
+
+        return leftGeom.intersects(rightGeom);
     }
 
-    private static org.locationtech.jts.geom.Geometry toJTS(Object value) {
-        if (value instanceof GeometryWrapper) value = ((GeometryWrapper) value).geometry;
-        if (value instanceof org.locationtech.jts.geom.Geometry) return (org.locationtech.jts.geom.Geometry)
value;
-        throw new UnsupportedOperationException("Unsupported geometry type: "+value.getClass().getCanonicalName());
+    private static org.locationtech.jts.geom.Geometry transformSilently(org.locationtech.jts.geom.Geometry
target, CoordinateOperation op) {
+        try {
+            return JTS.transform(target, op);
+        } catch (TransformException e) {
+            throw new BackingStoreException(e);
+        }
     }
 
-    private Predicate constantOp(Literal left, Literal right) {
-        final boolean result = left.getValue() != null
-                && right.getValue() != null
-                && toJTS(left.getValue()).intersects(toJTS(right.getValue()));
-        return it -> result;
+    private static Map.Entry<org.locationtech.jts.geom.Geometry, CoordinateReferenceSystem>
toJTS(Object value) {
+        CoordinateReferenceSystem crs = null;
+        if (value instanceof Geometry) crs = ((Geometry) value).getCoordinateReferenceSystem();
+        if (value instanceof GeometryWrapper) value = ((GeometryWrapper) value).geometry;
+        if (value instanceof org.locationtech.jts.geom.Geometry) {
+            final org.locationtech.jts.geom.Geometry geom = (org.locationtech.jts.geom.Geometry)
value;
+            if (crs == null) {
+                try {
+                    crs = JTS.getCoordinateReferenceSystem(geom);
+                } catch (FactoryException e) {
+                    throw new BackingStoreException("Cannot extract CRS from operand", e);
+                }
+            }
+            return new AbstractMap.SimpleImmutableEntry<>(geom, crs);
+        }
+        throw new UnsupportedOperationException("Unsupported geometry type: "+value.getClass().getCanonicalName());
     }
 
-    private static Predicate intersect(Expression left, Literal right) {
-        Object value = right.getValue();
+    private static Predicate intersect(Literal left, Expression right) {
+        Object value = left.getValue();
         ensureNonNull("Literal value", value);
         // TODO: make more consistent strategy once Geometry API is stable.
-        if (value instanceof GeometryWrapper) value = ((GeometryWrapper) value).geometry;
-        if (value instanceof org.locationtech.jts.geom.Geometry) {
-            final PreparedGeometry pg = new PreparedGeometryFactory().create((org.locationtech.jts.geom.Geometry)
value);
+        try {
+            final Map.Entry<org.locationtech.jts.geom.Geometry, CoordinateReferenceSystem>
leftEntry = toJTS(value);
+            final CRSMatching crsMatching = CRSMatching.left(leftEntry.getValue());
+            final PreparedGeometry optimizedGeom = new PreparedGeometryFactory().create((org.locationtech.jts.geom.Geometry)
value);
             return it -> {
-                Object val = left.evaluate(it);
+                Object val = right.evaluate(it);
                 if (val == null) return false;
-                return pg.intersects(toJTS(val));
+                final Map.Entry<org.locationtech.jts.geom.Geometry, CoordinateReferenceSystem>
rightEntry = toJTS(val);
+                final CRSMatching.Match match = crsMatching.right(rightEntry.getValue());
+                final org.locationtech.jts.geom.Geometry rightGeom = match.fromRight()
+                        .map(op -> transformSilently(rightEntry.getKey(), op))
+                        .orElse(rightEntry.getKey());
+                return match.fromLeft()
+                        .map(op -> transformSilently(leftEntry.getKey(), op))
+                        .map(geom -> geom.intersects(rightGeom))
+                        .orElseGet(() -> optimizedGeom.intersects(rightGeom));
             };
-        } else if (value instanceof Geometry) {
-            final Geometry geom = (Geometry) value;
-            return it -> {
-                final Geometry newVal = left.evaluate(it, Geometry.class);
-                if (newVal == null) {
-                    final Object testVal = left.evaluate(it);
-                    if (testVal == null) return false;
-                    throw new UnsupportedOperationException("Unsupported geometry type: "+testVal.getClass().getCanonicalName());
-                }
-                return geom.intersects(newVal);
-            };
-        } else throw new UnsupportedOperationException("Unsupported geometry type: "+value.getClass().getCanonicalName());
+        } catch (UnsupportedOperationException e) {
+            if (value instanceof Geometry) {
+                final Geometry geom = (Geometry) value;
+                return it -> {
+                    final Geometry newVal = left.evaluate(it, Geometry.class);
+                    if (newVal == null) {
+                        final Object testVal = left.evaluate(it);
+                        if (testVal == null) return false;
+                        throw new UnsupportedOperationException("Unsupported geometry type:
"+testVal.getClass().getCanonicalName());
+                    }
+                    return geom.intersects(newVal);
+                };
+            }
+        }
+        throw new UnsupportedOperationException("Unsupported geometry type: "+value.getClass().getCanonicalName());
     }
 
     @Override
diff --git a/core/sis-feature/src/main/java/org/apache/sis/filter/package-info.java b/core/sis-feature/src/main/java/org/apache/sis/filter/package-info.java
index 7291456..cc40a87 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/filter/package-info.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/filter/package-info.java
@@ -19,12 +19,53 @@
  * Filters features according their properties.
  * A <cite>filter expression</cite> is a construct used to constraint a feature
set to a subset.
  *
+ * All operations in this package try to follow rules of both following standards:
+ * <ul>
+ *     <li><a href="https://www.iso.org/fr/standard/53698.html">ISO/IEC 13249-3:2011
- SQLMM</a></li>
+ *     <li><a href="http://docs.opengeospatial.org/is/09-026r2/09-026r2.html">OGC®
Filter Encoding 2.0 Encoding Standard</a></li>
+ * </ul>
+ *
+ * <div class="section">General considerations:</div>
+ * <div class="section">Coordinate reference system handling:</div>
+ * As stated by Filter encoding 2.0.2, section 7.8.4, heterogeneous coordinate reference
systems must be handled by
+ * libraries, one way or another. The standard does not define any strategy. As Apache-SIS
contains a powerful
+ * transform system, we'll try to handle differences in the following way:
+ * <ul>
+ *     <li>
+ *         If all evaluated geometries define a srid, but their not the same, we'll try to
project them in a common
+ *         space. The strategy will be guided by {@link org.apache.sis.referencing.CRS#suggestCommonTarget(org.opengis.metadata.extent.GeographicBoundingBox,
org.opengis.referencing.crs.CoordinateReferenceSystem...) Referencing utility method}.
+ *         If it cannot provide a common space, we will fail any ongoing operation.
+ *     </li>
+ *     <li>
+ *         Missing information:
+ *         <ul>
+ *              <li>If no geometry contains any srid, consider they're defined in the
same space, and proceed</li>
+ *              <li>If one geometry define a CRS but the other do not, consider that
an ambiguity resides: fail.</li>
+ *         </ul>
+ *     </li>
+ * </ul>
+ *
+ * <div class="section">Optimisations</div>
+ * For now, few to no optimisation is done in the operators. Most of important ones would
require one of the two
+ * following things:
+ * <ul>
+ *     <li>
+ *         Context information: Filters does not know in advance the feature type they're
operating upon, which is
+ *         vital to define some calculus parameters, as property value conversion strategy,
spatial system changes, etc.
+ *         Such information would allow operators to prepare data at initialisation time.
+ *     </li>
+ *     <li>
+ *         User hints: some operations could be set faster at the cost of precision. To activate
such things, it would
+ *         require user consent. Most naïve example is spatial reference system conversion,
which could be de-activated
+ *         for systems with nearly equal parameters (see {@link org.apache.sis.util.Utilities#equalsApproximately(java.lang.Object,
java.lang.Object)}.
+ *     </li>
+ * </ul>
+ * extra-information for
+ * the operator, as well as hints from the user to allow sac
  * @author  Johann Sorel (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
  * @version 1.0
  *
- * @see <a href="http://docs.opengeospatial.org/is/09-026r2/09-026r2.html">OGC® Filter
Encoding 2.0 Encoding Standard</a>
- *
  * @since 1.0
  * @module
  */
diff --git a/core/sis-feature/src/test/java/org/apache/sis/filter/SQLMMTest.java b/core/sis-feature/src/test/java/org/apache/sis/filter/SQLMMTest.java
index 75a2fbc..8b2cda5 100644
--- a/core/sis-feature/src/test/java/org/apache/sis/filter/SQLMMTest.java
+++ b/core/sis-feature/src/test/java/org/apache/sis/filter/SQLMMTest.java
@@ -25,6 +25,7 @@ import org.opengis.filter.expression.Literal;
 import org.opengis.filter.expression.PropertyName;
 import org.opengis.geometry.Envelope;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.referencing.crs.ProjectedCRS;
 
 import org.apache.sis.feature.builder.FeatureTypeBuilder;
 import org.apache.sis.geometry.GeneralEnvelope;
@@ -40,6 +41,7 @@ import org.locationtech.jts.geom.LineString;
 import org.locationtech.jts.geom.LinearRing;
 import org.locationtech.jts.geom.Point;
 
+import static org.apache.sis.internal.feature.GeometriesTestCase.expectFailFast;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
@@ -170,22 +172,53 @@ public class SQLMMTest extends TestCase {
         });
 
         final Literal lring = factory.literal(ring);
-        ST_Intersects st = new ST_Intersects(new Expression[]{factory.literal(gf.createPoint(new
Coordinate(2, 4))), lring});
+        ST_Intersects st = intersects(factory.literal(gf.createPoint(new Coordinate(2, 4))),
lring);
         // Ensure argument nullity does not modify behavior
         assertFalse("Unexpected intersection", st.evaluate(null));
         assertFalse("Unexpected intersection", st.evaluate(new Object()));
 
         // Border should intersect
         final Feature f = mock();
-        f.setPropertyValue(P_NAME, gf.createPoint(second));
+        final Point point = gf.createPoint(second);
+        f.setPropertyValue(P_NAME, point);
         final PropertyName geomName = factory.property(P_NAME);
-        st = new ST_Intersects(new Expression[]{geomName, lring});
+        st = intersects(geomName, lring);
         assertTrue("Border point should intersect triangle", st.evaluate(f));
         // Ensure inverting expression does not modify behavior.
-        st = new ST_Intersects(new Expression[]{lring, geomName});
+        st = intersects(lring, geomName);
         assertTrue("Border point should intersect triangle", st.evaluate(f));
 
-        // TODO: add CRS checking tests.
+        // Ensure CRS conversion works as expected (see package-info).
+        // Missing
+        point.setUserData(CommonCRS.defaultGeographic());
+        expectFailFast(() -> intersects(geomName, lring).evaluate(f), IllegalArgumentException.class);
+        final Literal lPoint = factory.literal(point);
+        expectFailFast(() -> intersects(lPoint, lring).evaluate(null), IllegalArgumentException.class);
+
+        // Disjoint
+        final ProjectedCRS nadUtm = CommonCRS.NAD27.universal(32, 37);
+        final ProjectedCRS wgsUtm = CommonCRS.WGS84.universal(-2, 4);
+
+        point.setUserData(nadUtm);
+        ring.setUserData(wgsUtm);
+        expectFailFast(() -> intersects(geomName, lring).evaluate(f), IllegalArgumentException.class);
+        expectFailFast(() -> intersects(lPoint, lring).evaluate(null), IllegalArgumentException.class);
+
+        // TODO: activate back after fixing CRS.suggestCommonTarget
+        // utm domain contained in CRS:84
+//        ring.setUserData(CommonCRS.defaultGeographic());
+//        assertTrue("Intersection should be found when CRS are compatible", intersects(geomName,
lring).evaluate(f));
+//        assertTrue("Intersection should be found when CRS are compatible", intersects(lPoint,
lring).evaluate(null));
+
+        // Common base CRS
+//        ring.setUserData(CommonCRS.WGS84.universal(0, 0));
+//        point.setUserData(CommonCRS.WGS84.universal(7, 8));
+//        assertTrue("Intersection should be found when CRS are compatible", intersects(geomName,
lring).evaluate(f));
+//        assertTrue("Intersection should be found when CRS are compatible", intersects(lPoint,
lring).evaluate(null));
+    }
+
+    private static ST_Intersects intersects(final Expression left, Expression right) {
+        return new ST_Intersects(new Expression[]{left, right});
     }
 
     /**
diff --git a/core/sis-feature/src/test/java/org/apache/sis/internal/feature/GeometriesTestCase.java
b/core/sis-feature/src/test/java/org/apache/sis/internal/feature/GeometriesTestCase.java
index 7aa7a44..f49d481 100644
--- a/core/sis-feature/src/test/java/org/apache/sis/internal/feature/GeometriesTestCase.java
+++ b/core/sis-feature/src/test/java/org/apache/sis/internal/feature/GeometriesTestCase.java
@@ -194,7 +194,7 @@ public abstract strictfp class GeometriesTestCase extends TestCase {
         expectFailFast(() -> factory.tryConvertToGeometry(wrapped3d, NONE), IllegalArgumentException.class);
     }
 
-    private static void expectFailFast(Callable whichMustFail, Class<? extends Exception>...
expectedErrorTypes) {
+    public static void expectFailFast(Callable whichMustFail, Class<? extends Exception>...
expectedErrorTypes) {
         try {
             final Object result = whichMustFail.call();
             fail("Fail fast expected, but successfully returned "+result);
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
index 1b9b49d..a8912d4 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
@@ -16,82 +16,84 @@
  */
 package org.apache.sis.referencing;
 
-import java.util.Map;
-import java.util.List;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.List;
+import java.util.Map;
 import java.util.logging.LogRecord;
-import org.opengis.util.FactoryException;
+
 import org.opengis.geometry.Envelope;
-import org.opengis.referencing.NoSuchAuthorityCodeException;
+import org.opengis.geometry.Geometry;
+import org.opengis.metadata.citation.Citation;
+import org.opengis.metadata.extent.BoundingPolygon;
+import org.opengis.metadata.extent.Extent;
+import org.opengis.metadata.extent.GeographicBoundingBox;
+import org.opengis.metadata.extent.GeographicExtent;
 import org.opengis.referencing.IdentifiedObject;
-import org.opengis.referencing.cs.CartesianCS;
-import org.opengis.referencing.cs.EllipsoidalCS;
-import org.opengis.referencing.cs.AxisDirection;
-import org.opengis.referencing.cs.CoordinateSystem;
-import org.opengis.referencing.cs.CoordinateSystemAxis;
+import org.opengis.referencing.NoSuchAuthorityCodeException;
+import org.opengis.referencing.crs.CRSAuthorityFactory;
 import org.opengis.referencing.crs.CRSFactory;
-import org.opengis.referencing.crs.SingleCRS;
 import org.opengis.referencing.crs.CompoundCRS;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
-import org.opengis.referencing.crs.CRSAuthorityFactory;
+import org.opengis.referencing.crs.EngineeringCRS;
+import org.opengis.referencing.crs.GeneralDerivedCRS;
 import org.opengis.referencing.crs.GeodeticCRS;
 import org.opengis.referencing.crs.GeographicCRS;
-import org.opengis.referencing.crs.GeneralDerivedCRS;
 import org.opengis.referencing.crs.ProjectedCRS;
+import org.opengis.referencing.crs.SingleCRS;
 import org.opengis.referencing.crs.TemporalCRS;
 import org.opengis.referencing.crs.VerticalCRS;
-import org.opengis.referencing.crs.EngineeringCRS;
+import org.opengis.referencing.cs.AxisDirection;
+import org.opengis.referencing.cs.CartesianCS;
+import org.opengis.referencing.cs.CoordinateSystem;
+import org.opengis.referencing.cs.CoordinateSystemAxis;
+import org.opengis.referencing.cs.EllipsoidalCS;
 import org.opengis.referencing.datum.Datum;
 import org.opengis.referencing.datum.GeodeticDatum;
 import org.opengis.referencing.operation.Conversion;
-import org.opengis.referencing.operation.OperationNotFoundException;
-import org.opengis.metadata.citation.Citation;
-import org.opengis.metadata.extent.Extent;
-import org.opengis.metadata.extent.BoundingPolygon;
-import org.opengis.metadata.extent.GeographicBoundingBox;
-import org.opengis.metadata.extent.GeographicExtent;
 import org.opengis.referencing.operation.CoordinateOperation;
+import org.opengis.referencing.operation.OperationNotFoundException;
 import org.opengis.referencing.operation.TransformException;
-import org.apache.sis.measure.Units;
+import org.opengis.util.FactoryException;
+
 import org.apache.sis.geometry.Envelopes;
 import org.apache.sis.geometry.GeneralEnvelope;
 import org.apache.sis.internal.referencing.AxisDirections;
+import org.apache.sis.internal.referencing.CoordinateOperations;
+import org.apache.sis.internal.referencing.DefinitionVerifier;
 import org.apache.sis.internal.referencing.EllipsoidalHeightCombiner;
 import org.apache.sis.internal.referencing.PositionalAccuracyConstant;
-import org.apache.sis.internal.referencing.CoordinateOperations;
 import org.apache.sis.internal.referencing.ReferencingUtilities;
-import org.apache.sis.internal.referencing.DefinitionVerifier;
 import org.apache.sis.internal.referencing.Resources;
 import org.apache.sis.internal.system.DefaultFactories;
-import org.apache.sis.internal.system.Modules;
 import org.apache.sis.internal.system.Loggers;
+import org.apache.sis.internal.system.Modules;
 import org.apache.sis.internal.util.Numerics;
-import org.apache.sis.referencing.cs.AxisFilter;
-import org.apache.sis.referencing.cs.CoordinateSystems;
-import org.apache.sis.referencing.cs.DefaultVerticalCS;
+import org.apache.sis.measure.Units;
+import org.apache.sis.metadata.iso.extent.DefaultGeographicBoundingBox;
+import org.apache.sis.metadata.iso.extent.Extents;
+import org.apache.sis.referencing.crs.DefaultCompoundCRS;
+import org.apache.sis.referencing.crs.DefaultEngineeringCRS;
 import org.apache.sis.referencing.crs.DefaultGeographicCRS;
 import org.apache.sis.referencing.crs.DefaultProjectedCRS;
 import org.apache.sis.referencing.crs.DefaultVerticalCRS;
-import org.apache.sis.referencing.crs.DefaultCompoundCRS;
-import org.apache.sis.referencing.crs.DefaultEngineeringCRS;
+import org.apache.sis.referencing.cs.AxisFilter;
+import org.apache.sis.referencing.cs.CoordinateSystems;
+import org.apache.sis.referencing.cs.DefaultVerticalCS;
+import org.apache.sis.referencing.factory.GeodeticObjectFactory;
+import org.apache.sis.referencing.factory.UnavailableFactoryException;
 import org.apache.sis.referencing.operation.AbstractCoordinateOperation;
 import org.apache.sis.referencing.operation.CoordinateOperationContext;
-import org.apache.sis.referencing.operation.DefaultCoordinateOperationFactory;
 import org.apache.sis.referencing.operation.DefaultConversion;
-import org.apache.sis.referencing.factory.GeodeticObjectFactory;
-import org.apache.sis.referencing.factory.UnavailableFactoryException;
-import org.apache.sis.metadata.iso.extent.DefaultGeographicBoundingBox;
-import org.apache.sis.metadata.iso.extent.Extents;
-import org.apache.sis.util.resources.Errors;
-import org.apache.sis.util.logging.Logging;
-import org.apache.sis.util.logging.WarningListener;
+import org.apache.sis.referencing.operation.DefaultCoordinateOperationFactory;
 import org.apache.sis.util.ArgumentChecks;
-import org.apache.sis.util.Utilities;
 import org.apache.sis.util.Static;
+import org.apache.sis.util.Utilities;
+import org.apache.sis.util.logging.Logging;
+import org.apache.sis.util.logging.WarningListener;
+import org.apache.sis.util.resources.Errors;
 
 // Branch-dependent imports
-import org.opengis.geometry.Geometry;
 
 
 /**
@@ -431,7 +433,7 @@ public final class CRS extends Static {
      * Suggests a coordinate reference system which could be a common target for coordinate
operations having the
      * given sources. This method compares the {@linkplain #getGeographicBoundingBox(CoordinateReferenceSystem)
      * domain of validity} of all given CRSs. If a CRS has a domain of validity that contains
the domain of all other
-     * CRS, than that CRS is returned. Otherwise this method verifies if a {@linkplain GeneralDerivedCRS#getBaseCRS()
+     * CRS, then that CRS is returned. Otherwise this method verifies if a {@linkplain GeneralDerivedCRS#getBaseCRS()
      * base CRS} (usually a {@linkplain org.apache.sis.referencing.crs.DefaultGeographicCRS
geographic CRS} instance)
      * would be suitable. If no suitable CRS is found, then this method returns {@code null}.
      *


Mime
View raw message