sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ama...@apache.org
Subject [sis] 03/04: refactor(Feature): Merge duplicate bbox and intersection operators (SQLMM and Filter encoding)
Date Fri, 15 Nov 2019 15:45:05 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 65e7ddd0f361d1255cccf934aec9aef7442b5cd7
Author: Alexis Manin <amanin@apache.org>
AuthorDate: Fri Nov 15 15:34:37 2019 +0100

    refactor(Feature): Merge duplicate bbox and intersection operators (SQLMM and Filter encoding)
    
    Chosen bbox  and intersect filters are more strict in terms of common space definition.
They are less dependant of JTS also. and efforts of optimisation at built are done (though
more powerful ones would be possible if more context information were given to them)
---
 .../java/org/apache/sis/filter/BinaryFunction.java |  12 +-
 .../java/org/apache/sis/filter/CRSMatching.java    |  81 ++++++-
 .../java/org/apache/sis/filter/DefaultBBOX.java    |  22 +-
 .../apache/sis/filter/DefaultFilterFactory.java    |   2 +-
 .../java/org/apache/sis/filter/ST_Intersects.java  |  39 +---
 .../org/apache/sis/filter/SpatialFunction.java     | 242 +++------------------
 .../apache/sis/internal/feature/Geometries.java    |   4 +-
 .../java/org/apache/sis/internal/feature/JTS.java  |   2 +-
 .../test/java/org/apache/sis/filter/SQLMMTest.java |  24 +-
 9 files changed, 139 insertions(+), 289 deletions(-)

diff --git a/core/sis-feature/src/main/java/org/apache/sis/filter/BinaryFunction.java b/core/sis-feature/src/main/java/org/apache/sis/filter/BinaryFunction.java
index e7ddda1..341b9e1 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/filter/BinaryFunction.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/filter/BinaryFunction.java
@@ -16,17 +16,19 @@
  */
 package org.apache.sis.filter;
 
+import java.math.BigDecimal;
+import java.math.BigInteger;
 import java.util.Arrays;
 import java.util.Collection;
-import java.math.BigInteger;
-import java.math.BigDecimal;
-import org.apache.sis.util.Numbers;
-import org.apache.sis.math.Fraction;
+
+import org.opengis.filter.expression.Expression;
+
 import org.apache.sis.math.DecimalFunctions;
+import org.apache.sis.math.Fraction;
 import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.util.Numbers;
 
 // Branch-dependent imports
-import org.opengis.filter.expression.Expression;
 
 
 /**
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
index 23dfdf2..c85b512 100644
--- 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
@@ -2,8 +2,10 @@ package org.apache.sis.filter;
 
 import java.util.Optional;
 
+import org.opengis.metadata.extent.GeographicBoundingBox;
 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.referencing.CRS;
@@ -13,6 +15,10 @@ import org.apache.sis.util.collection.BackingStoreException;
 import static org.apache.sis.referencing.IdentifiedObjects.getIdentifierOrName;
 
 /**
+ * Tries to find a common space for two given CRS operands. The common space is defined using
{@link CRS#suggestCommonTarget(GeographicBoundingBox, CoordinateReferenceSystem...)}.
+ * Usage: initialize through {@link #left(CoordinateReferenceSystem)}, giving your first
(left) operand as argument.
+ * Then use {@link #right(CoordinateReferenceSystem)} to specify the other (right) operand.
+ *
  * TODO: improve CRS conversion/suggestion by allowing user to input a geographic region
of interest.
  */
 @FunctionalInterface
@@ -37,15 +43,45 @@ public interface CRSMatching {
         }
     }
 
-    Match right(final CoordinateReferenceSystem other);
+    Match right(final CoordinateReferenceSystem rightCrs);
+
+    /**
+     * Defines that a common space has been found for both input operands.
+     */
+    abstract class Match {
+
+        /**
+         *
+         * @return If both input CRS were null, an empty shell. Otherwise, the common space
defined by {@link CRS#suggestCommonTarget(GeographicBoundingBox, CoordinateReferenceSystem...)}.
+         * Note that it can be one of the original systems (in which cas one of the operations
provided will be empty),
+         * or a third-party one (common geographic base, for example).
+         */
+        abstract Optional<CoordinateReferenceSystem> getCommonCRS();
+
+        /**
+         *
+         * @return Coordinate operation to use for going from left operand system to common
space. Can be empty if the
+         * common space is equal to left operand system.
+         */
+        abstract Optional<CoordinateOperation> fromLeft();
+
+        /**
+         *
+         * @return Coordinate operation to use for going from right operand system to common
space. Can be empty if the
+         *         common space is equal to right operand system.
+         */
+        abstract Optional<CoordinateOperation> fromRight();
+
+        public final <L> L transformLeftToCommon(L leftValue, Transformer<L>
operator) throws TransformException {
+            return transform(leftValue, fromLeft(), operator);
+        }
 
-    interface Match {
-        Optional<CoordinateReferenceSystem> getCommonCRS();
-        Optional<CoordinateOperation> fromLeft();
-        Optional<CoordinateOperation> fromRight();
+        public final <R> R transformRightToCommon(R rightValue, Transformer<R>
operator) throws TransformException {
+            return transform(rightValue, fromRight(), operator);
+        }
     }
 
-    final class NullMatch implements Match {
+    final class NullMatch extends Match {
 
         @Override
         public Optional<CoordinateReferenceSystem> getCommonCRS() {
@@ -63,17 +99,17 @@ public interface CRSMatching {
         }
     }
 
-    final class DefaultMatch implements Match {
+    final class DefaultMatch extends Match {
 
         final CoordinateReferenceSystem commonCRS;
         final Optional<CoordinateOperation> fromLeft;
         final Optional<CoordinateOperation> fromRight;
 
-        public DefaultMatch(CoordinateReferenceSystem commonCRS, CoordinateReferenceSystem
left, CoordinateReferenceSystem right) {
+        public DefaultMatch(CoordinateReferenceSystem commonCRS, CoordinateReferenceSystem
leftCrs, CoordinateReferenceSystem rightCrs) {
             this.commonCRS = commonCRS;
             try {
-                fromLeft = createOp(left, commonCRS);
-                fromRight = createOp(right, commonCRS);
+                fromLeft = createOp(leftCrs, commonCRS);
+                fromRight = createOp(rightCrs, commonCRS);
             } catch (FactoryException e) {
                 throw new BackingStoreException(e);
             }
@@ -103,4 +139,29 @@ public interface CRSMatching {
             return Optional.of(op);
         }
     }
+
+    /**
+     * TODO: We should NOT accept factory exception here. The transform uses an already built
coordinate operation, no
+     * CRS factory should be needed in the process.
+     * @param <T> Type of object to transform (envelope, geometry, etc.).
+     */
+    @FunctionalInterface
+    interface Transformer<T> {
+        T apply(T operand, CoordinateOperation op) throws TransformException, FactoryException;
+    }
+
+    static <T> T transform(T in, Optional<CoordinateOperation> coordOp, Transformer<T>
transformer) throws TransformException {
+        try {
+            return coordOp.map(op -> {
+                try {
+                    return transformer.apply(in, op);
+                } catch (TransformException | FactoryException e) {
+                    throw new BackingStoreException(e);
+                }
+            })
+                    .orElse(in);
+        } catch (BackingStoreException e) {
+            throw e.unwrapOrRethrow(TransformException.class);
+        }
+    }
 }
diff --git a/core/sis-feature/src/main/java/org/apache/sis/filter/DefaultBBOX.java b/core/sis-feature/src/main/java/org/apache/sis/filter/DefaultBBOX.java
index 450d563..85ff6b2 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/filter/DefaultBBOX.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/filter/DefaultBBOX.java
@@ -55,7 +55,7 @@ import org.apache.sis.util.collection.BackingStoreException;
  *
  *     TODO: CRS check.
  */
-final class DefaultBBOX implements BBOX, Serializable {
+final class DefaultBBOX extends SpatialFunction implements BBOX, Serializable {
 
     private static final long serialVersionUID = 3068335120981348484L;
 
@@ -65,8 +65,9 @@ final class DefaultBBOX implements BBOX, Serializable {
     private transient Predicate intersects;
 
     DefaultBBOX(Expression left, Expression right) {
-        this.left = left;
-        this.right = right;
+        super(left == null ? Expression.NIL : left, right == null ? Expression.NIL : right);
+        this.left = left == Expression.NIL ? null : left;
+        this.right = right == Expression.NIL ? null : right;
         init();
     }
 
@@ -89,16 +90,6 @@ final class DefaultBBOX implements BBOX, Serializable {
     }
 
     @Override
-    public Expression getExpression1() {
-        return left;
-    }
-
-    @Override
-    public Expression getExpression2() {
-        return right;
-    }
-
-    @Override
     public boolean evaluate(Object object) {
         return intersects.test(object);
     }
@@ -230,6 +221,11 @@ final class DefaultBBOX implements BBOX, Serializable {
     }
 
     @Override
+    protected String getName() {
+        return BBOX.NAME;
+    }
+
+    @Override
     public int hashCode() {
         return Objects.hash(left, right);
     }
diff --git a/core/sis-feature/src/main/java/org/apache/sis/filter/DefaultFilterFactory.java
b/core/sis-feature/src/main/java/org/apache/sis/filter/DefaultFilterFactory.java
index 291f3d9..6c2c9dc 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/filter/DefaultFilterFactory.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/filter/DefaultFilterFactory.java
@@ -322,7 +322,7 @@ public class DefaultFilterFactory implements FilterFactory2 {
      */
     @Override
     public Intersects intersects(final Expression left, final Expression right) {
-        return new ST_Intersects(new Expression[]{left, right});
+        return new ST_Intersects(left, right);
     }
 
     /**
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 63ce1e6..a77f21c 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
@@ -20,7 +20,6 @@ import java.io.IOException;
 import java.io.Serializable;
 import java.util.AbstractMap;
 import java.util.Map;
-import java.util.Objects;
 import java.util.function.Predicate;
 
 import org.opengis.filter.FilterVisitor;
@@ -40,27 +39,24 @@ import org.apache.sis.util.collection.BackingStoreException;
 import org.locationtech.jts.geom.prep.PreparedGeometry;
 import org.locationtech.jts.geom.prep.PreparedGeometryFactory;
 
-import static org.apache.sis.util.ArgumentChecks.ensureNonEmpty;
 import static org.apache.sis.util.ArgumentChecks.ensureNonNull;
 
 /**
  * TODO: refine once Geometry API is stable.
  */
-public final class ST_Intersects implements Intersects, Serializable {
+public final class ST_Intersects extends SpatialFunction implements Intersects, Serializable
{
 
-    public static final String NAME = "ST_Intersect";
+    public static final String NAME = "ST_Intersects";
 
     final Expression left;
     final Expression right;
 
     private transient Predicate intersects;
 
-    public ST_Intersects(Expression[] parameters) {
-        ensureNonEmpty("Parameters", parameters);
-        if (parameters.length != 2) throw new IllegalArgumentException("2 parameters are
expected for intersection, but "+parameters.length+" are provided");
-
-        left = parameters[0];
-        right = parameters[1];
+    public ST_Intersects(Expression left, Expression right) {
+        super(left, right);
+        this.left = left;
+        this.right = right;
         init();
     }
 
@@ -161,16 +157,6 @@ public final class ST_Intersects implements Intersects, Serializable
{
     }
 
     @Override
-    public Expression getExpression1() {
-        return left;
-    }
-
-    @Override
-    public Expression getExpression2() {
-        return right;
-    }
-
-    @Override
     public boolean evaluate(Object object) {
         return intersects.test(object);
     }
@@ -181,17 +167,8 @@ public final class ST_Intersects implements Intersects, Serializable
{
     }
 
     @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-        ST_Intersects that = (ST_Intersects) o;
-        return left.equals(that.left) &&
-                right.equals(that.right);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(left, right);
+    protected String getName() {
+        return org.opengis.filter.spatial.Intersects.NAME;
     }
 
     /**
diff --git a/core/sis-feature/src/main/java/org/apache/sis/filter/SpatialFunction.java b/core/sis-feature/src/main/java/org/apache/sis/filter/SpatialFunction.java
index 32794fa..205764b 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/filter/SpatialFunction.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/filter/SpatialFunction.java
@@ -18,43 +18,35 @@ package org.apache.sis.filter;
 
 import java.math.BigDecimal;
 import java.math.BigInteger;
-import java.util.logging.Level;
-import java.util.logging.Logger;
 import javax.measure.Unit;
 import javax.measure.UnitConverter;
-import org.apache.sis.coverage.grid.GridCoverage;
-import org.apache.sis.internal.feature.AttributeConvention;
-import org.apache.sis.internal.feature.Geometries;
-import org.apache.sis.math.Fraction;
-import org.apache.sis.measure.Units;
-import org.apache.sis.referencing.CRS;
-import org.apache.sis.referencing.CommonCRS;
-import org.apache.sis.referencing.IdentifiedObjects;
-import org.apache.sis.util.ObjectConverters;
-import org.apache.sis.util.UnconvertibleObjectException;
-import org.apache.sis.util.Utilities;
-import org.apache.sis.util.collection.BackingStoreException;
-import org.locationtech.jts.geom.Coordinate;
-import org.locationtech.jts.geom.Geometry;
-import org.locationtech.jts.geom.GeometryFactory;
-import org.locationtech.jts.geom.LinearRing;
-import org.locationtech.jts.geom.Polygon;
-import org.locationtech.jts.geom.prep.PreparedGeometry;
-import org.locationtech.jts.geom.prep.PreparedGeometryFactory;
+
 import org.opengis.feature.Feature;
 import org.opengis.feature.PropertyNotFoundException;
 import org.opengis.filter.FilterVisitor;
 import org.opengis.filter.expression.Expression;
 import org.opengis.filter.expression.PropertyName;
 import org.opengis.filter.spatial.BinarySpatialOperator;
-import org.opengis.geometry.Envelope;
-import org.opengis.geometry.MismatchedDimensionException;
 import org.opengis.referencing.NoSuchAuthorityCodeException;
 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.coverage.grid.GridCoverage;
+import org.apache.sis.internal.feature.AttributeConvention;
+import org.apache.sis.internal.feature.Geometries;
+import org.apache.sis.internal.feature.WrapResolution;
+import org.apache.sis.math.Fraction;
+import org.apache.sis.measure.Units;
+import org.apache.sis.referencing.CRS;
+import org.apache.sis.setup.GeometryLibrary;
+import org.apache.sis.util.ObjectConverters;
+import org.apache.sis.util.UnconvertibleObjectException;
+import org.apache.sis.util.Utilities;
+
+import org.locationtech.jts.geom.Geometry;
+
 /**
  *
  * @author  Johann Sorel (Geomatys)
@@ -64,12 +56,13 @@ import org.opengis.util.FactoryException;
  */
 abstract class SpatialFunction extends BinaryFunction implements BinarySpatialOperator {
 
-    private static final LinearRing[] EMPTY_RINGS = new LinearRing[0];
-    private static final GeometryFactory GEOMETRY_FACTORY = new GeometryFactory();
-    private static final PreparedGeometryFactory PREPARED_FACTORY = new PreparedGeometryFactory();
-
     private static CoordinateReferenceSystem MERCATOR;
 
+    /**
+     * TODO: We should generify this. But too much code already depends on JTS, so for now
I hack this
+     */
+    private static final Geometries<Geometry> SIS_GEOMETRY_FACTORY = (Geometries<Geometry>)
Geometries.implementation(GeometryLibrary.JTS);
+
     private static CoordinateReferenceSystem getMercator() throws FactoryException {
         if (MERCATOR == null) {
             MERCATOR = CRS.forCode("EPSG:3395");
@@ -121,11 +114,9 @@ abstract class SpatialFunction extends BinaryFunction implements BinarySpatialOp
 
         Geometry candidate;
         if (value instanceof GridCoverage) {
-            candidate = (Geometry) value;
-        } else if (value instanceof GridCoverage) {
             //use the coverage envelope
             final GridCoverage coverage = (GridCoverage) value;
-            candidate = toGeometry(coverage.getGridGeometry().getEnvelope());
+            candidate = SIS_GEOMETRY_FACTORY.tryConvertToGeometry(coverage.getGridGeometry().getEnvelope(),
WrapResolution.SPLIT);
         } else {
             try {
                 candidate = ObjectConverters.convert(value, Geometry.class);
@@ -138,69 +129,23 @@ abstract class SpatialFunction extends BinaryFunction implements BinarySpatialOp
     }
 
     /**
-     * Envelope to geometry.
-     */
-    private static Polygon toGeometry(final Envelope env) {
-        final Coordinate[] coordinates = new Coordinate[]{
-            new Coordinate(env.getMinimum(0), env.getMinimum(1)),
-            new Coordinate(env.getMinimum(0), env.getMaximum(1)),
-            new Coordinate(env.getMaximum(0), env.getMaximum(1)),
-            new Coordinate(env.getMaximum(0), env.getMinimum(1)),
-            new Coordinate(env.getMinimum(0), env.getMinimum(1))};
-        final LinearRing ring = GEOMETRY_FACTORY.createLinearRing(coordinates);
-        Polygon polygon = GEOMETRY_FACTORY.createPolygon(ring, new LinearRing[0]);
-        polygon.setUserData(env.getCoordinateReferenceSystem());
-        return polygon;
-    }
-
-    /**
-     * Envelope to prepared geometry.
-     */
-    private static PreparedGeometry toPreparedGeometry(final Envelope env){
-        double minX = env.getMinimum(0);
-        double minY = env.getMinimum(1);
-        double maxX = env.getMaximum(0);
-        double maxY = env.getMaximum(1);
-        if (Double.isNaN(minX) || Double.isInfinite(minX)) minX = Double.MIN_VALUE;
-        if (Double.isNaN(minY) || Double.isInfinite(minY)) minY = Double.MIN_VALUE;
-        if (Double.isNaN(maxX) || Double.isInfinite(maxX)) maxX = Double.MAX_VALUE;
-        if (Double.isNaN(maxY) || Double.isInfinite(maxY)) maxY = Double.MAX_VALUE;
-
-        final Coordinate[] coords = new Coordinate[5];
-        coords[0] = new Coordinate(minX, minY);
-        coords[1] = new Coordinate(minX, maxY);
-        coords[2] = new Coordinate(maxX, maxY);
-        coords[3] = new Coordinate(maxX, minY);
-        coords[4] = new Coordinate(minX, minY);
-        final LinearRing ring = GEOMETRY_FACTORY.createLinearRing(coords);
-        Geometry geom = GEOMETRY_FACTORY.createPolygon(ring, EMPTY_RINGS);
-        return PREPARED_FACTORY.create(geom);
-    }
-
-    /**
      * Reproject geometries to the same CRS if needed and if possible.
      */
     private static Geometry[] toSameCRS(final Geometry leftGeom, final Geometry rightGeom)
-            throws NoSuchAuthorityCodeException, FactoryException, TransformException {
+            throws FactoryException, TransformException {
 
         final CoordinateReferenceSystem leftCRS = Geometries.getCoordinateReferenceSystem(leftGeom);
         final CoordinateReferenceSystem rightCRS = Geometries.getCoordinateReferenceSystem(rightGeom);
 
-        if (leftCRS == null || rightCRS == null) {
-            //one or both geometries doesn't have a defined CRS, we assume that both
-            //are in the same CRS
-            return new Geometry[]{leftGeom, rightGeom};
-        } else if (Utilities.equalsIgnoreMetadata(leftCRS, rightCRS)) {
-            //both are in the same CRS, nothing to reproject
-            return new Geometry[]{leftGeom, rightGeom};
-        }
-
-        //we choose to reproject the right operand.
-        //there is no special reason to make this choice but we must make one.
-        //perhaps there could be a way to determine a best crs ?
-        final CoordinateOperation trs = CRS.findOperation(rightCRS, leftCRS, null);
+        final CRSMatching.Match match = CRSMatching
+                .left(leftCRS)
+                .right(rightCRS);
 
-        return new Geometry[]{leftGeom, (Geometry) Geometries.transform(rightGeom, trs)};
+        final CRSMatching.Transformer<Geometry> projectGeom = (g, op) -> SIS_GEOMETRY_FACTORY.tryTransform(g,
op, null);
+        return new Geometry[]{
+                match.transformLeftToCommon(leftGeom, projectGeom),
+                match.transformRightToCommon(rightGeom, projectGeom)
+        };
     }
 
     /**
@@ -282,133 +227,6 @@ abstract class SpatialFunction extends BinaryFunction implements BinarySpatialOp
         }
     }
 
-
-    /**
-     * The {@value #NAME} filter.
-     */
-    static final class BBOX extends SpatialFunction implements org.opengis.filter.spatial.BBOX
{
-
-        /**
-         * For cross-version compatibility.
-         */
-        private static final long serialVersionUID = -4806881904891000892L;
-
-        //cache the bbox geometry
-        private transient PreparedGeometry boundingGeometry;
-        private final org.locationtech.jts.geom.Envelope boundingEnv;
-        private final CoordinateReferenceSystem crs;
-
-        private final Envelope env;
-
-        BBOX(Expression expression, Envelope env) {
-            super(expression, new LeafExpression.Literal(env));
-            this.env = env;
-            boundingGeometry = toPreparedGeometry(env);
-            boundingEnv = boundingGeometry.getGeometry().getEnvelopeInternal();
-            final CoordinateReferenceSystem crsFilter = env.getCoordinateReferenceSystem();
-            if (crsFilter != null) {
-                this.crs = crsFilter;
-            } else {
-                // In CQL if crs is not specified, it is EPSG:4326
-                this.crs = CommonCRS.WGS84.normalizedGeographic();
-            }
-        }
-
-        private PreparedGeometry getPreparedGeometry(){
-            if (boundingGeometry == null) {
-                boundingGeometry = toPreparedGeometry(env);
-            }
-            return boundingGeometry;
-        }
-
-        @Override
-        protected String getName() {
-            return NAME;
-        }
-
-        @Override
-        public String getPropertyName() {
-            if (expression1 instanceof PropertyName) {
-                return ((PropertyName) expression1).getPropertyName();
-            }
-            return null;
-        }
-
-        @Override
-        public String getSRS() {
-            try {
-                return IdentifiedObjects.lookupURN(env.getCoordinateReferenceSystem(), null);
-            } catch (FactoryException ex) {
-                throw new BackingStoreException(ex.getMessage(), ex);
-            }
-        }
-
-        @Override
-        public double getMinX() {
-            return env.getMinimum(0);
-        }
-
-        @Override
-        public double getMinY() {
-            return env.getMinimum(1);
-        }
-
-        @Override
-        public double getMaxX() {
-            return env.getMaximum(0);
-        }
-
-        @Override
-        public double getMaxY() {
-            return env.getMaximum(1);
-        }
-
-        @Override
-        public boolean evaluate(Object object) {
-            Geometry candidate = toGeometry(object, expression1);
-
-            if (candidate == null) {
-                return false;
-            }
-
-            //we don't know in which crs it is, try to find it
-            CoordinateReferenceSystem candidateCrs = null;
-            try {
-                candidateCrs = Geometries.getCoordinateReferenceSystem(candidate);
-            } catch (FactoryException ex) {
-                warning(ex);
-            }
-
-            //if we don't know the crs, we will assume it's the objective crs already
-            if (candidateCrs != null) {
-                //reproject in objective crs if needed
-                if (!Utilities.equalsIgnoreMetadata(this.crs, candidateCrs)) {
-                    try {
-                        candidate = (Geometry) Geometries.transform(candidate, CRS.findOperation(candidateCrs,
this.crs, null));
-                    } catch (MismatchedDimensionException | TransformException | FactoryException
ex) {
-                        warning(ex);
-                        return false;
-                    }
-                }
-            }
-
-            final org.locationtech.jts.geom.Envelope candidateEnv = candidate.getEnvelopeInternal();
-
-            if (boundingEnv.contains(candidateEnv) || candidateEnv.contains(boundingEnv))
{
-                return true;
-            } else if (boundingEnv.intersects(candidateEnv)) {
-                return getPreparedGeometry().intersects(candidate);
-            } else {
-                return false;
-            }
-        }
-
-        @Override
-        public Object accept(FilterVisitor visitor, Object extraData) {
-            return visitor.visit(this, extraData);
-        }
-    }
-
     /**
      * The {@value #NAME} filter.
      */
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Geometries.java
b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Geometries.java
index fa6856d..4849071 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Geometries.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Geometries.java
@@ -475,7 +475,7 @@ public abstract class Geometries<G> {
      *
      * @see #tryGetCoordinateReferenceSystem(Object)
      */
-    Object tryTransform(Object geometry, CoordinateOperation operation, CoordinateReferenceSystem
targetCRS)
+    public G tryTransform(Object geometry, CoordinateOperation operation, CoordinateReferenceSystem
targetCRS)
             throws FactoryException, TransformException
     {
         if (rootClass.isInstance(geometry)) {
@@ -595,7 +595,7 @@ public abstract class Geometries<G> {
     /**
      * See {@link Geometries#toGeometry(Envelope, WrapResolution)}.
      */
-    Object tryConvertToGeometry(final Envelope env, WrapResolution resolution) {
+    public G tryConvertToGeometry(final Envelope env, WrapResolution resolution) {
         // Ensure that we can isolate an horizontal part in the given envelope.
         final int x;
         if (env.getDimension() == 2) {
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/JTS.java b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/JTS.java
index 17f826c..0c9920b 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/JTS.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/JTS.java
@@ -433,7 +433,7 @@ add:    for (;;) {
      * @see #tryGetCoordinateReferenceSystem(Object)
      */
     @Override
-    Geometry tryTransform(final Object geometry, final CoordinateOperation operation, final
CoordinateReferenceSystem targetCRS)
+    public Geometry tryTransform(final Object geometry, final CoordinateOperation operation,
final CoordinateReferenceSystem targetCRS)
             throws FactoryException, TransformException
     {
         if (geometry instanceof Geometry) {
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 2d6d724..feba114 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
@@ -271,16 +271,16 @@ public final strictfp class SQLMMTest extends TestCase {
     @Test
     public void ST_Intersects() {
         try {
-            new ST_Intersects(null);
-            fail("ST_Intersects operator should accept exactly 2 parameters");
+            new ST_Intersects(null, null);
+            fail("ST_Intersects operator should not accept null parameters");
         } catch (NullArgumentException e) {
             // expected behavior
         }
 
         try {
-            new ST_Intersects(new Expression[3]);
-            fail("ST_Intersects operator should accept exactly 2 parameters");
-        } catch (IllegalArgumentException e) {
+            new ST_Intersects(null, factory.literal(new GeneralEnvelope(2)));
+            fail("ST_Intersects operator should not accept null parameters");
+        } catch (NullArgumentException e) {
             // expected behavior
         }
 
@@ -291,7 +291,7 @@ public final strictfp class SQLMMTest extends TestCase {
         });
 
         final Literal lring = factory.literal(ring);
-        ST_Intersects st = intersects(factory.literal(geometryFactory.createPoint(new Coordinate(2,
4))), lring);
+        ST_Intersects st = new ST_Intersects(factory.literal(geometryFactory.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()));
@@ -301,18 +301,18 @@ public final strictfp class SQLMMTest extends TestCase {
         final Point point = geometryFactory.createPoint(second);
         f.setPropertyValue(P_NAME, point);
         final PropertyName geomName = factory.property(P_NAME);
-        st = intersects(geomName, lring);
+        st = new ST_Intersects(geomName, lring);
         assertTrue("Border point should intersect triangle", st.evaluate(f));
         // Ensure inverting expression does not modify behavior.
-        st = intersects(lring, geomName);
+        st = new ST_Intersects(lring, geomName);
         assertTrue("Border point should intersect triangle", st.evaluate(f));
 
         // Ensure CRS conversion works as expected (see package-info).
         // Missing
         point.setUserData(CommonCRS.defaultGeographic());
-        expectFailFast(() -> intersects(geomName, lring).evaluate(f), IllegalArgumentException.class);
+        expectFailFast(() -> new ST_Intersects(geomName, lring).evaluate(f), IllegalArgumentException.class);
         final Literal lPoint = factory.literal(point);
-        expectFailFast(() -> intersects(lPoint, lring).evaluate(null), IllegalArgumentException.class);
+        expectFailFast(() -> new ST_Intersects(lPoint, lring).evaluate(null), IllegalArgumentException.class);
 
         // utm domain contained in CRS:84
         /* TODO: this is broken. We have to reproject geometries each time we change CRS.
@@ -330,10 +330,6 @@ public final strictfp class SQLMMTest extends TestCase {
         */
     }
 
-    private static ST_Intersects intersects(final Expression left, Expression right) {
-        return new ST_Intersects(new Expression[]{left, right});
-    }
-
     @Test
     public void ST_Envelope() {
         try {


Mime
View raw message