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 8f0d46beeff512ad684071e93334d27a8c4297f5 Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Wed Sep 15 13:56:51 2021 +0200 Add basic Java2D support for a few filter/expression operations. --- .../apache/sis/internal/feature/Geometries.java | 4 +- .../apache/sis/internal/feature/esri/Factory.java | 1 - .../apache/sis/internal/feature/esri/Wrapper.java | 2 +- .../apache/sis/internal/feature/j2d/Factory.java | 64 +++++++ .../sis/internal/feature/j2d/PointWrapper.java | 115 +++++++++++- .../apache/sis/internal/feature/j2d/Wrapper.java | 199 ++++++++++++++++++++- .../sis/internal/filter/GeometryConverter.java | 2 +- .../BinarySpatialFilterUsingJava2D_Test.java | 102 +++++++++++ .../internal/filter/sqlmm/RegistryTestCase.java | 2 +- .../filter/sqlmm/RegistryUsingESRI_Test.java | 12 +- ...SRI_Test.java => RegistryUsingJava2D_Test.java} | 28 +-- .../apache/sis/test/suite/FeatureTestSuite.java | 2 + 12 files changed, 506 insertions(+), 27 deletions(-) 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 fd28438..d650f9a 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 @@ -379,9 +379,7 @@ public abstract class Geometries<G> implements Serializable { * @return geometry built from the given components. * @throws ClassCastException if the given object is not an array or a collection of supported geometry components. */ - public GeometryWrapper<G> createFromComponents(GeometryType type, Object components) { - throw new UnsupportedOperationException(); - } + public abstract GeometryWrapper<G> createFromComponents(GeometryType type, Object components); /** * Creates a polyline made of points describing a rectangle whose start point is the lower left corner. diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/esri/Factory.java b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/esri/Factory.java index 7fcc179..6437cb9 100644 --- a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/esri/Factory.java +++ b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/esri/Factory.java @@ -191,7 +191,6 @@ public final class Factory extends Geometries<Geometry> { * @throws ClassCastException if the given object is not an array or a collection of supported geometry components. */ @Override - @SuppressWarnings("fallthrough") public GeometryWrapper<Geometry> createFromComponents(final GeometryType type, final Object components) { /* * No exhaustive `if (x instanceof y)` checks in this method. diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/esri/Wrapper.java b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/esri/Wrapper.java index 1981004..60dc2b7 100644 --- a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/esri/Wrapper.java +++ b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/esri/Wrapper.java @@ -212,7 +212,7 @@ add: for (Geometry next = geometry;;) { } /** - * All predicates recognized by {@link #predicate(SpatialOperatorName, Geometry)}. + * All predicates recognized by {@link #predicateSameCRS(SpatialOperatorName, GeometryWrapper)}. * Array indices are {@link SpatialOperatorName#ordinal()} values. */ @SuppressWarnings({"unchecked","rawtypes"}) diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/j2d/Factory.java b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/j2d/Factory.java index 08055f5..6434c64 100644 --- a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/j2d/Factory.java +++ b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/j2d/Factory.java @@ -16,6 +16,9 @@ */ package org.apache.sis.internal.feature.j2d; +import java.util.Arrays; +import java.util.Iterator; +import java.util.Collection; import java.awt.Shape; import java.awt.geom.Line2D; import java.awt.geom.Path2D; @@ -24,8 +27,10 @@ import java.nio.ByteBuffer; import java.io.ObjectStreamException; import org.apache.sis.setup.GeometryLibrary; import org.apache.sis.internal.feature.Geometries; +import org.apache.sis.internal.feature.GeometryType; import org.apache.sis.internal.feature.GeometryWrapper; import org.apache.sis.internal.referencing.j2d.ShapeUtilities; +import org.apache.sis.internal.util.CollectionsExt; import org.apache.sis.math.Vector; import org.apache.sis.util.UnsupportedImplementationException; @@ -247,10 +252,69 @@ public final class Factory extends Geometries<Shape> { for (final Shape geometry : shapes) { path.append(geometry, false); } + // path.trimToSize(); // TODO: uncomment with JDK10. return new Wrapper(path); } /** + * Creates a geometry from components. + * The expected {@code components} type depend on the target geometry type: + * <ul> + * <li>If {@code type} is a multi-geometry, then the components shall be an array of {@link Shape} elements.</li> + * <li>Otherwise the components shall be an array or collection of {@link Point2D} instances.</li> + * </ul> + * + * @param type type of geometry to create. + * @param components the components. Valid classes depend on the type of geometry to create. + * @return geometry built from the given components. + * @throws ClassCastException if the given object is not an array or a collection of supported geometry components. + */ + @Override + @SuppressWarnings("fallthrough") + public GeometryWrapper<Shape> createFromComponents(final GeometryType type, final Object components) { + /* + * No exhaustive `if (x instanceof y)` checks in this method. + * `ClassCastException` shall be handled by the caller. + */ + final Collection<?> data = (components instanceof Collection<?>) + ? (Collection<?>) components : Arrays.asList((Object[]) components); + /* + * Java2D API does not distinguish between single geometry and geometry collection. + * So if the number of components is 1, there is no reason to create a new geometry object. + */ + Shape geometry = (Shape) CollectionsExt.singletonOrNull(data); + if (geometry == null) { + boolean isFloat = true; + for (final Object component : data) { + isFloat = ShapeUtilities.isFloat(component); + if (!isFloat) break; + } + final Path2D path = createPath(isFloat, 20); + if (type.isCollection()) { + for (final Object component : data) { + path.append((Shape) component, false); + } + } else { + final Iterator<?> it = data.iterator(); + if (it.hasNext()) { + Point2D p = (Point2D) it.next(); + path.moveTo(p.getX(), p.getY()); + while (it.hasNext()) { + p = (Point2D) it.next(); + path.lineTo(p.getX(), p.getY()); + } + if (type == GeometryType.POLYGON) { + path.closePath(); + } + } + } + // path.trimToSize(); // TODO: uncomment with JDK10. + geometry = path; + } + return new Wrapper(geometry); + } + + /** * Well Known Text (WKT) parsing not supported with Java2D. */ @Override diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/j2d/PointWrapper.java b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/j2d/PointWrapper.java index d8b8d1a..7c238a7 100644 --- a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/j2d/PointWrapper.java +++ b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/j2d/PointWrapper.java @@ -17,8 +17,12 @@ package org.apache.sis.internal.feature.j2d; import java.awt.Shape; +import java.awt.Point; +import java.awt.Rectangle; import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; import java.util.Iterator; +import java.util.function.BiPredicate; import org.opengis.geometry.DirectPosition; import org.apache.sis.geometry.DirectPosition2D; import org.apache.sis.geometry.GeneralEnvelope; @@ -27,6 +31,7 @@ import org.apache.sis.internal.feature.GeometryWithCRS; import org.apache.sis.internal.feature.GeometryWrapper; import org.apache.sis.internal.filter.sqlmm.SQLMM; import org.apache.sis.util.Debug; +import org.opengis.filter.SpatialOperatorName; /** @@ -42,7 +47,7 @@ final class PointWrapper extends GeometryWithCRS<Shape> { /** * The wrapped implementation. */ - private final Point2D point; + final Point2D point; /** * Creates a new wrapper around the given point. @@ -120,6 +125,39 @@ final class PointWrapper extends GeometryWithCRS<Shape> { } /** + * Applies a filter predicate between this geometry and another geometry. + * This method assumes that the two geometries are in the same CRS (this is not verified). + */ + @Override + protected boolean predicateSameCRS(final SpatialOperatorName type, final GeometryWrapper<Shape> other) { + final int ordinal = type.ordinal(); + if (ordinal >= 0 && ordinal < PREDICATES.length) { + final BiPredicate<PointWrapper,Object> op = PREDICATES[ordinal]; + if (op != null) { + return op.test(this, other); + } + } + return super.predicateSameCRS(type, other); + } + + /** + * All predicates recognized by {@link #predicateSameCRS(SpatialOperatorName, GeometryWrapper)}. + * Array indices are {@link SpatialOperatorName#ordinal()} values. + */ + @SuppressWarnings({"unchecked","rawtypes"}) + private static final BiPredicate<PointWrapper,Object>[] PREDICATES = + new BiPredicate[SpatialOperatorName.OVERLAPS.ordinal() + 1]; + static { + PREDICATES[SpatialOperatorName.BBOX .ordinal()] = // Fallback on intersects. + PREDICATES[SpatialOperatorName.OVERLAPS .ordinal()] = // Fallback on intersects. + PREDICATES[SpatialOperatorName.INTERSECTS.ordinal()] = PointWrapper::intersect; + PREDICATES[SpatialOperatorName.WITHIN .ordinal()] = PointWrapper::within; + PREDICATES[SpatialOperatorName.CONTAINS .ordinal()] = // Fallback on equals. + PREDICATES[SpatialOperatorName.EQUALS .ordinal()] = PointWrapper::equal; + PREDICATES[SpatialOperatorName.DISJOINT .ordinal()] = (w,o) -> !w.intersect(o); + } + + /** * Applies a SQLMM operation on this geometry. * * @param operation the SQLMM operation to apply. @@ -128,14 +166,87 @@ final class PointWrapper extends GeometryWithCRS<Shape> { * @return result of the specified operation. */ @Override + @SuppressWarnings("fallthrough") protected Object operationSameCRS(final SQLMM operation, final GeometryWrapper<Shape> other, final Object argument) { switch (operation) { - case ST_Centroid: return point.clone(); + case ST_Dimension: + case ST_CoordDim: return 2; + case ST_Is3D: + case ST_IsMeasured: return Boolean.FALSE; + case ST_Centroid: return point.clone(); + case ST_Envelope: return getEnvelope(); + case ST_Boundary: { + if (point instanceof Point) { + final Point p = (Point) point; + final Rectangle r = new Rectangle(); + r.x = p.x; + r.y = p.y; + return r; + } else if (point instanceof Point2D.Float) { + final Point2D.Float p = (Point2D.Float) point; + final Rectangle2D.Float r = new Rectangle2D.Float(); + r.x = p.x; + r.y = p.y; + return r; + } else { + final Rectangle2D.Double r = new Rectangle2D.Double(); + r.x = point.getX(); + r.y = point.getY(); + return r; + } + } + case ST_Overlaps: // Falback on "within". + case ST_Within: return within(other); + case ST_Intersects: return intersect(other); + case ST_Disjoint: return !intersect(other); + case ST_Contains: // Fallback on "equals". + case ST_Equals: return equal(other); default: return super.operationSameCRS(operation, other, argument); } } /** + * Estimates whether the wrapped geometry is equal to the geometry of the given wrapper. + * + * @param wrapper instance of {@link PointWrapper}. + */ + private boolean equal(final Object wrapper) { // "s" omitted for avoiding confusion with super.equals(…). + if (wrapper instanceof PointWrapper) { + final Point2D p = ((PointWrapper) wrapper).point; + return Double.doubleToLongBits(point.getX()) == Double.doubleToLongBits(p.getX()) + && Double.doubleToLongBits(point.getY()) == Double.doubleToLongBits(p.getY()); + } + return false; + } + + /** + * Estimates whether the wrapped geometry is contained by the geometry of the given wrapper. + * This method may conservatively returns {@code false} if an accurate computation would be + * too expansive. + * + * @param wrapper instance of {@link Wrapper}. + */ + private boolean within(final Object wrapper) { + return (wrapper instanceof Wrapper) && (((Wrapper) wrapper).geometry).contains(point); + } + + /** + * Estimates whether the wrapped geometry intersects the geometry of the given wrapper. + * This method may conservatively returns {@code true} if an accurate computation would + * be too expansive. + * + * @param wrapper instance of {@link Wrapper} or {@link PointWrapper}. + * @throws ClassCastException if the given object is not a recognized wrapper. + */ + private boolean intersect(final Object wrapper) { // "s" omitted for avoiding confusion with super.intersects(…). + if (wrapper instanceof PointWrapper) { + return point.equals(((PointWrapper) wrapper).point); + } else { + return within(wrapper); + } + } + + /** * Builds a WKT representation of the wrapped point. */ @Override diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/j2d/Wrapper.java b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/j2d/Wrapper.java index 4178386..a37af34 100644 --- a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/j2d/Wrapper.java +++ b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/j2d/Wrapper.java @@ -18,11 +18,14 @@ package org.apache.sis.internal.feature.j2d; import java.util.List; import java.util.Iterator; +import java.util.function.BiPredicate; import java.awt.Shape; +import java.awt.geom.Area; import java.awt.geom.Path2D; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.awt.geom.RectangularShape; +import java.awt.geom.PathIterator; import org.opengis.geometry.DirectPosition; import org.apache.sis.geometry.GeneralEnvelope; import org.apache.sis.geometry.DirectPosition2D; @@ -31,9 +34,13 @@ import org.apache.sis.internal.feature.GeometryWithCRS; import org.apache.sis.internal.feature.GeometryWrapper; import org.apache.sis.internal.filter.sqlmm.SQLMM; import org.apache.sis.internal.referencing.j2d.ShapeUtilities; +import org.apache.sis.internal.jdk9.JDK9; import org.apache.sis.util.ArraysExt; import org.apache.sis.util.Debug; +// Branch-dependent imports +import org.opengis.filter.SpatialOperatorName; + /** * The wrapper of Java2D geometries. @@ -49,7 +56,7 @@ final class Wrapper extends GeometryWithCRS<Shape> { /** * The wrapped implementation. */ - private final Shape geometry; + final Shape geometry; /** * Creates a new wrapper around the given geometry. @@ -75,6 +82,14 @@ final class Wrapper extends GeometryWithCRS<Shape> { } /** + * Returns the geometry as an {@link Area} object, creating it on the fly if necessary. + * The returned area shall not be modified because it may be the {@link #geometry} instance. + */ + private Area area() { + return (geometry instanceof Area) ? (Area) geometry : new Area(geometry); + } + + /** * Returns the Java2D envelope as an Apache SIS implementation. * * @return the envelope of the geometry. @@ -185,6 +200,39 @@ add: for (;;) { } /** + * Applies a filter predicate between this geometry and another geometry. + * This method assumes that the two geometries are in the same CRS (this is not verified). + */ + @Override + protected boolean predicateSameCRS(final SpatialOperatorName type, final GeometryWrapper<Shape> other) { + final int ordinal = type.ordinal(); + if (ordinal >= 0 && ordinal < PREDICATES.length) { + final BiPredicate<Wrapper,Object> op = PREDICATES[ordinal]; + if (op != null) { + return op.test(this, other); + } + } + return super.predicateSameCRS(type, other); + } + + /** + * All predicates recognized by {@link #predicateSameCRS(SpatialOperatorName, GeometryWrapper)}. + * Array indices are {@link SpatialOperatorName#ordinal()} values. + */ + @SuppressWarnings({"unchecked","rawtypes"}) + private static final BiPredicate<Wrapper,Object>[] PREDICATES = + new BiPredicate[SpatialOperatorName.OVERLAPS.ordinal() + 1]; + static { + PREDICATES[SpatialOperatorName.OVERLAPS .ordinal()] = // Fallback on intersects. + PREDICATES[SpatialOperatorName.INTERSECTS.ordinal()] = Wrapper::intersect; + PREDICATES[SpatialOperatorName.CONTAINS .ordinal()] = Wrapper::contain; + PREDICATES[SpatialOperatorName.WITHIN .ordinal()] = Wrapper::within; + PREDICATES[SpatialOperatorName.BBOX .ordinal()] = Wrapper::bbox; + PREDICATES[SpatialOperatorName.EQUALS .ordinal()] = Wrapper::equal; + PREDICATES[SpatialOperatorName.DISJOINT .ordinal()] = (w,o) -> !w.intersect(o); + } + + /** * Applies a SQLMM operation on this geometry. * * @param operation the SQLMM operation to apply. @@ -194,14 +242,163 @@ add: for (;;) { */ @Override protected Object operationSameCRS(final SQLMM operation, final GeometryWrapper<Shape> other, final Object argument) { + final Shape result; switch (operation) { + case ST_Dimension: + case ST_CoordDim: return 2; + case ST_Is3D: + case ST_IsMeasured: return Boolean.FALSE; + case ST_IsEmpty: { + if (geometry instanceof RectangularShape) { + return ((RectangularShape) geometry).isEmpty(); + } else { + return geometry.getPathIterator(null).isDone(); + } + } + case ST_Overlaps: // Our approximate algorithm can not distinguish with intersects. + case ST_Intersects: return intersect(other); + case ST_Disjoint: return !intersect(other); + case ST_Contains: return contain (other); + case ST_Within: return within (other); + case ST_Equals: return equal (other); + case ST_Envelope: return getEnvelope(); + case ST_Boundary: result = geometry.getBounds2D(); break; case ST_Centroid: { final RectangularShape frame = (geometry instanceof RectangularShape) ? (RectangularShape) geometry : geometry.getBounds2D(); return new Point2D.Double(frame.getCenterX(), frame.getCenterY()); } + case ST_Intersection: { + final Area area = new Area(geometry); + area.intersect(((Wrapper) other).area()); + result = area; + break; + } + case ST_Union: { + final Area area = new Area(geometry); + area.add(((Wrapper) other).area()); + result = area; + break; + } + case ST_Difference: { + final Area area = new Area(geometry); + area.subtract(((Wrapper) other).area()); + result = area; + break; + } + case ST_SymDifference: { + final Area area = new Area(geometry); + area.exclusiveOr(((Wrapper) other).area()); + result = area; + break; + } default: return super.operationSameCRS(operation, other, argument); } + // No metadata to copy in current version. + return result; + } + + /** + * Estimates whether the wrapped geometry is equal to the geometry of the given wrapper. + * + * @param wrapper instance of {@link Wrapper}. + */ + private boolean equal(final Object wrapper) { // "s" omitted for avoiding confusion with super.equals(…). + if (wrapper instanceof Wrapper) { + final Shape other = ((Wrapper) wrapper).geometry; + final PathIterator it1 = geometry.getPathIterator(null); + final PathIterator it2 = other.getPathIterator(null); + if (it1.getWindingRule() == it2.getWindingRule()) { + final double[] p1 = new double[6]; + final double[] p2 = new double[6]; + while (!it1.isDone()) { + if (it2.isDone()) return false; + final int c = it1.currentSegment(p1); + if (c != it2.currentSegment(p2)) { + return false; + } + it1.next(); + it2.next(); + final int n; + switch (c) { + case PathIterator.SEG_CLOSE: continue; + case PathIterator.SEG_MOVETO: + case PathIterator.SEG_LINETO: n=2; break; + case PathIterator.SEG_QUADTO: n=4; break; + default: n=6; break; + } + if (!JDK9.equals(p1, 0, n, p2, 0, n)) { + return false; + } + } + return it2.isDone(); + } + } + return false; + } + + /** + * Estimates whether the wrapped geometry is contained by the geometry of the given wrapper. + * This method may conservatively returns {@code false} if an accurate computation would be + * too expansive. + * + * @param wrapper instance of {@link Wrapper}. + */ + private boolean within(final Object wrapper) { + if (wrapper instanceof Wrapper) { + final Shape other = ((Wrapper) wrapper).geometry; + return other.contains(geometry.getBounds2D()); + } + return false; + } + + /** + * Estimates whether the wrapped geometry contains the geometry of the given wrapper. + * This method may conservatively returns {@code false} if an accurate computation would + * be too expansive. + * + * @param wrapper instance of {@link Wrapper} or {@link PointWrapper}. + * @throws ClassCastException if the given object is not a recognized wrapper. + */ + private boolean contain(final Object wrapper) { // "s" omitted for avoiding confusion with super.contains(…). + if (wrapper instanceof PointWrapper) { + return geometry.contains(((PointWrapper) wrapper).point); + } + final Shape other = ((Wrapper) wrapper).geometry; + return geometry.contains(other.getBounds2D()); + } + + /** + * Estimates whether the wrapped geometry intersects the geometry of the given wrapper. + * This method may conservatively returns {@code true} if an accurate computation would + * be too expansive. + * + * @param wrapper instance of {@link Wrapper} or {@link PointWrapper}. + * @throws ClassCastException if the given object is not a recognized wrapper. + */ + private boolean intersect(final Object wrapper) { // "s" omitted for avoiding confusion with super.intersects(…). + if (wrapper instanceof PointWrapper) { + return geometry.contains(((PointWrapper) wrapper).point); + } + final Shape other = ((Wrapper) wrapper).geometry; + return geometry.intersects(other.getBounds2D()) && other.intersects(geometry.getBounds2D()); + } + + /** + * Estimates whether the wrapped geometry intersects the geometry of the given wrapper, testing only + * the bounding box of the {@code wrapper} argument. This method may be more accurate than required + * by OGC Filter Encoding specification in that this geometry is not simplified to a bounding box. + * But Java2D implementations sometime use bounding box approximation, so the result may be the same. + * + * @param wrapper instance of {@link Wrapper} or {@link PointWrapper}. + * @throws ClassCastException if the given object is not a recognized wrapper. + */ + private boolean bbox(final Object wrapper) { + if (wrapper instanceof PointWrapper) { + return geometry.contains(((PointWrapper) wrapper).point); + } + final Shape other = ((Wrapper) wrapper).geometry; + return geometry.intersects(other.getBounds2D()); } /** diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/GeometryConverter.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/GeometryConverter.java index ba048a7..cb7da80 100644 --- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/GeometryConverter.java +++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/GeometryConverter.java @@ -138,7 +138,7 @@ final class GeometryConverter<R,G> extends Node implements Optimization.OnExpres * If we can not do that, check how to propagate the wrap-around policy from some context. * * @param input the geometry to evaluate with this expression. - * @return the geometry boundary. + * @return the geometry wrapper, or {@code null} if the evaluated value is null. * @throws InvalidFilterValueException if the expression result is not an instance of a supported type. */ @Override diff --git a/core/sis-feature/src/test/java/org/apache/sis/filter/BinarySpatialFilterUsingJava2D_Test.java b/core/sis-feature/src/test/java/org/apache/sis/filter/BinarySpatialFilterUsingJava2D_Test.java new file mode 100644 index 0000000..5fccd95 --- /dev/null +++ b/core/sis-feature/src/test/java/org/apache/sis/filter/BinarySpatialFilterUsingJava2D_Test.java @@ -0,0 +1,102 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.sis.filter; + +import java.awt.Shape; +import org.junit.Ignore; +import org.junit.Test; + + +/** + * Tests {@link BinarySpatialFilter} implementations using ESRI library. + * + * @author Martin Desruisseaux (Geomatys) + * @version 1.1 + * @since 1.1 + * @module + */ +public final strictfp class BinarySpatialFilterUsingJava2D_Test extends BinarySpatialFilterTestCase<Shape> { + /** + * Creates a new test. + */ + public BinarySpatialFilterUsingJava2D_Test() { + super(Shape.class); + } + + /** + * Test ignored for now (not yet mapped to a Java2D operation). + */ + @Test + @Override + @Ignore("Not yet mapped to a Java2D operation.") + public void testTouches() { + } + + /** + * Test ignored for now (not yet mapped to a Java2D operation). + */ + @Test + @Override + @Ignore("Not yet mapped to a Java2D operation.") + public void testCrosses() { + } + + /** + * Test ignored for now (not yet mapped to a Java2D operation). + */ + @Test + @Override + @Ignore("Not yet mapped to a Java2D operation.") + public void testOverlaps() { + } + + /** + * Test ignored for now (not yet mapped to a Java2D operation). + */ + @Test + @Override + @Ignore("Not yet mapped to a Java2D operation.") + public void testDWithin() { + } + + /** + * Test ignored for now (not yet mapped to a Java2D operation). + */ + @Test + @Override + @Ignore("Not yet mapped to a Java2D operation.") + public void testBeyond() { + } + + /** + * Test ignored for now (not yet mapped to a Java2D operation). + */ + @Test + @Override + @Ignore("Not yet mapped to a Java2D operation.") + public void testWithReprojection() { + } + + /** + * Test ignored for now because {@link java.awt.geom.Path2D} does not implement {@code equals(Object)}. + */ + @Test + @Ignore + @Override + public void testSerialization() { + } +} diff --git a/core/sis-feature/src/test/java/org/apache/sis/internal/filter/sqlmm/RegistryTestCase.java b/core/sis-feature/src/test/java/org/apache/sis/internal/filter/sqlmm/RegistryTestCase.java index 4c158ed..d9c3f4f 100644 --- a/core/sis-feature/src/test/java/org/apache/sis/internal/filter/sqlmm/RegistryTestCase.java +++ b/core/sis-feature/src/test/java/org/apache/sis/internal/filter/sqlmm/RegistryTestCase.java @@ -356,7 +356,7 @@ public abstract strictfp class RegistryTestCase<G> extends TestCase { // Border should intersect. Also use Feature instead of Literal as a source. final Feature feature = createFeatureWithGeometry(library.polygonClass); final ValueReference<Feature,?> ref = factory.property(P_NAME, library.polygonClass); - point = library.createPoint(1.2, 0.2); + point = library.createPoint(0.2, 0.3); function = factory.function("ST_Intersects", ref, factory.literal(point)); assertEquals(Boolean.TRUE, function.apply(feature)); diff --git a/core/sis-feature/src/test/java/org/apache/sis/internal/filter/sqlmm/RegistryUsingESRI_Test.java b/core/sis-feature/src/test/java/org/apache/sis/internal/filter/sqlmm/RegistryUsingESRI_Test.java index 149d100..8c6a236 100644 --- a/core/sis-feature/src/test/java/org/apache/sis/internal/filter/sqlmm/RegistryUsingESRI_Test.java +++ b/core/sis-feature/src/test/java/org/apache/sis/internal/filter/sqlmm/RegistryUsingESRI_Test.java @@ -40,12 +40,6 @@ public final strictfp class RegistryUsingESRI_Test extends RegistryTestCase<Geom @Test @Override - @Ignore("Current implementation ignores the distance parameter.") - public void testSimplify() { - } - - @Test - @Override @Ignore("Reprojection not yet implemented.") public void testTransform() { } @@ -70,6 +64,12 @@ public final strictfp class RegistryUsingESRI_Test extends RegistryTestCase<Geom @Test @Override + @Ignore("Current implementation ignores the distance parameter.") + public void testSimplify() { + } + + @Test + @Override @Ignore("Operation not yet implemented.") public void testSimplifyPreserveTopology() { } diff --git a/core/sis-feature/src/test/java/org/apache/sis/internal/filter/sqlmm/RegistryUsingESRI_Test.java b/core/sis-feature/src/test/java/org/apache/sis/internal/filter/sqlmm/RegistryUsingJava2D_Test.java similarity index 81% copy from core/sis-feature/src/test/java/org/apache/sis/internal/filter/sqlmm/RegistryUsingESRI_Test.java copy to core/sis-feature/src/test/java/org/apache/sis/internal/filter/sqlmm/RegistryUsingJava2D_Test.java index 149d100..2f9b1f7 100644 --- a/core/sis-feature/src/test/java/org/apache/sis/internal/filter/sqlmm/RegistryUsingESRI_Test.java +++ b/core/sis-feature/src/test/java/org/apache/sis/internal/filter/sqlmm/RegistryUsingJava2D_Test.java @@ -16,13 +16,13 @@ */ package org.apache.sis.internal.filter.sqlmm; -import com.esri.core.geometry.Geometry; +import java.awt.Shape; import org.junit.Ignore; import org.junit.Test; /** - * Tests {@link SpatialFunction} implementations using JTS library. + * Tests {@link SpatialFunction} implementations using Java2D. * * @author Johann Sorel (Geomatys) * @author Martin Desruisseaux (Geomatys) @@ -30,18 +30,12 @@ import org.junit.Test; * @since 1.1 * @module */ -public final strictfp class RegistryUsingESRI_Test extends RegistryTestCase<Geometry> { +public final strictfp class RegistryUsingJava2D_Test extends RegistryTestCase<Shape> { /** * Creates a new test. */ - public RegistryUsingESRI_Test() { - super(Geometry.class, false); - } - - @Test - @Override - @Ignore("Current implementation ignores the distance parameter.") - public void testSimplify() { + public RegistryUsingJava2D_Test() { + super(Shape.class, false); } @Test @@ -71,6 +65,18 @@ public final strictfp class RegistryUsingESRI_Test extends RegistryTestCase<Geom @Test @Override @Ignore("Operation not yet implemented.") + public void testBuffer() { + } + + @Test + @Override + @Ignore("Operation not yet implemented.") + public void testSimplify() { + } + + @Test + @Override + @Ignore("Operation not yet implemented.") public void testSimplifyPreserveTopology() { } } diff --git a/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java b/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java index 55be51d..dfe80ee 100644 --- a/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java +++ b/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java @@ -60,12 +60,14 @@ import org.junit.runners.Suite; org.apache.sis.filter.TemporalFilterTest.class, org.apache.sis.filter.BinarySpatialFilterUsingJTS_Test.class, org.apache.sis.filter.BinarySpatialFilterUsingESRI_Test.class, + org.apache.sis.filter.BinarySpatialFilterUsingJava2D_Test.class, org.apache.sis.internal.feature.AttributeConventionTest.class, org.apache.sis.internal.feature.GeometryTypeTest.class, org.apache.sis.internal.filter.FunctionNamesTest.class, org.apache.sis.internal.filter.sqlmm.SQLMMTest.class, org.apache.sis.internal.filter.sqlmm.RegistryUsingJTS_Test.class, org.apache.sis.internal.filter.sqlmm.RegistryUsingESRI_Test.class, + org.apache.sis.internal.filter.sqlmm.RegistryUsingJava2D_Test.class, org.apache.sis.internal.feature.j2d.ShapePropertiesTest.class, org.apache.sis.internal.feature.j2d.FlatShapeTest.class, org.apache.sis.internal.feature.j2d.FactoryTest.class,