You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ds...@apache.org on 2014/07/08 21:50:22 UTC
svn commit: r1608922 - in /lucene/dev/trunk/lucene: ./
spatial/src/java/org/apache/lucene/spatial/query/ spatial/src/test-files/
spatial/src/test/org/apache/lucene/spatial/query/
Author: dsmiley
Date: Tue Jul 8 19:50:22 2014
New Revision: 1608922
URL: http://svn.apache.org/r1608922
Log:
LUCENE-5771: SpatialOperation refactoring: (OGC alias names, removed area requirement, fixed overlap definition)
Modified:
lucene/dev/trunk/lucene/CHANGES.txt
lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/query/SpatialArgs.java
lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/query/SpatialOperation.java
lucene/dev/trunk/lucene/spatial/src/test-files/simple-Queries-BBox.txt
lucene/dev/trunk/lucene/spatial/src/test/org/apache/lucene/spatial/query/SpatialArgsParserTest.java
Modified: lucene/dev/trunk/lucene/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/CHANGES.txt?rev=1608922&r1=1608921&r2=1608922&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/CHANGES.txt (original)
+++ lucene/dev/trunk/lucene/CHANGES.txt Tue Jul 8 19:50:22 2014
@@ -114,6 +114,11 @@ API Changes
* LUCENE-5692: DisjointSpatialFilter is deprecated (used by RecursivePrefixTreeStrategy)
(David Smiley)
+* LUCENE-5771: SpatialOperation's predicate names are now aliased to OGC standard names.
+ Thus you can use: Disjoint, Equals, Intersects, Overlaps, Within, Contains, Covers,
+ CoveredBy. The area requirement on the predicates was removed, and Overlaps' definition
+ was fixed. (David Smiley)
+
Optimizations
* LUCENE-5780: Make OrdinalMap more memory-efficient, especially in case the
Modified: lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/query/SpatialArgs.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/query/SpatialArgs.java?rev=1608922&r1=1608921&r2=1608922&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/query/SpatialArgs.java (original)
+++ lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/query/SpatialArgs.java Tue Jul 8 19:50:22 2014
@@ -87,9 +87,6 @@ public class SpatialArgs {
/** Check if the arguments make sense -- throw an exception if not */
public void validate() throws IllegalArgumentException {
- if (operation.isTargetNeedsArea() && !shape.hasArea()) {
- throw new IllegalArgumentException(operation + " only supports geometry with area");
- }
if (distErr != null && distErrPct != null)
throw new IllegalArgumentException("Only distErr or distErrPct can be specified.");
}
Modified: lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/query/SpatialOperation.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/query/SpatialOperation.java?rev=1608922&r1=1608921&r2=1608922&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/query/SpatialOperation.java (original)
+++ lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/query/SpatialOperation.java Tue Jul 8 19:50:22 2014
@@ -29,88 +29,114 @@ import java.util.Locale;
import java.util.Map;
/**
- * A clause that compares a stored geometry to a supplied geometry. For more
- * explanation of each operation, consider looking at the source implementation
- * of {@link #evaluate(com.spatial4j.core.shape.Shape, com.spatial4j.core.shape.Shape)}.
+ * A predicate that compares a stored geometry to a supplied geometry. It's enum-like. For more
+ * explanation of each predicate, consider looking at the source implementation
+ * of {@link #evaluate(com.spatial4j.core.shape.Shape, com.spatial4j.core.shape.Shape)}. It's important
+ * to be aware that Lucene-spatial makes no distinction of shape boundaries, unlike many standardized
+ * definitions. Nor does it make dimensional distinctions (e.g. line vs polygon).
+ * You can lookup a predicate by "Covers" or "Contains", for example, and you will get the
+ * same underlying predicate implementation.
*
+ * @see <a href="http://en.wikipedia.org/wiki/DE-9IM">DE-9IM at Wikipedia, based on OGC specs</a>
* @see <a href="http://edndoc.esri.com/arcsde/9.1/general_topics/understand_spatial_relations.htm">
* ESRIs docs on spatial relations</a>
*
* @lucene.experimental
*/
public abstract class SpatialOperation implements Serializable {
+ //TODO rename to SpatialPredicate. Use enum? LUCENE-5771
+
// Private registry
- private static final Map<String, SpatialOperation> registry = new HashMap<>();
+ private static final Map<String, SpatialOperation> registry = new HashMap<>();//has aliases
private static final List<SpatialOperation> list = new ArrayList<>();
// Geometry Operations
- /** Bounding box of the *indexed* shape. */
- public static final SpatialOperation BBoxIntersects = new SpatialOperation("BBoxIntersects", true, false, false) {
+ /** Bounding box of the *indexed* shape, then {@link #Intersects}. */
+ public static final SpatialOperation BBoxIntersects = new SpatialOperation("BBoxIntersects") {
@Override
public boolean evaluate(Shape indexedShape, Shape queryShape) {
return indexedShape.getBoundingBox().relate(queryShape).intersects();
}
};
- /** Bounding box of the *indexed* shape. */
- public static final SpatialOperation BBoxWithin = new SpatialOperation("BBoxWithin", true, false, false) {
+ /** Bounding box of the *indexed* shape, then {@link #IsWithin}. */
+ public static final SpatialOperation BBoxWithin = new SpatialOperation("BBoxWithin") {
+ {
+ register("BBoxCoveredBy");//alias -- the better name
+ }
@Override
public boolean evaluate(Shape indexedShape, Shape queryShape) {
Rectangle bbox = indexedShape.getBoundingBox();
return bbox.relate(queryShape) == SpatialRelation.WITHIN || bbox.equals(queryShape);
}
};
- public static final SpatialOperation Contains = new SpatialOperation("Contains", true, true, false) {
+ /** Meets the "Covers" OGC definition (boundary-neutral). */
+ public static final SpatialOperation Contains = new SpatialOperation("Contains") {
+ {
+ register("Covers");//alias -- the better name
+ }
@Override
public boolean evaluate(Shape indexedShape, Shape queryShape) {
- return indexedShape.hasArea() && indexedShape.relate(queryShape) == SpatialRelation.CONTAINS || indexedShape.equals(queryShape);
+ return indexedShape.relate(queryShape) == SpatialRelation.CONTAINS || indexedShape.equals(queryShape);
}
};
- public static final SpatialOperation Intersects = new SpatialOperation("Intersects", true, false, false) {
+ /** Meets the "Intersects" OGC definition. */
+ public static final SpatialOperation Intersects = new SpatialOperation("Intersects") {
@Override
public boolean evaluate(Shape indexedShape, Shape queryShape) {
return indexedShape.relate(queryShape).intersects();
}
};
- public static final SpatialOperation IsEqualTo = new SpatialOperation("IsEqualTo", false, false, false) {
+ /** Meets the "Equals" OGC definition. */
+ public static final SpatialOperation IsEqualTo = new SpatialOperation("Equals") {
+ {
+ register("IsEqualTo");//alias (deprecated)
+ }
@Override
public boolean evaluate(Shape indexedShape, Shape queryShape) {
return indexedShape.equals(queryShape);
}
};
- public static final SpatialOperation IsDisjointTo = new SpatialOperation("IsDisjointTo", false, false, false) {
+ /** Meets the "Disjoint" OGC definition. */
+ public static final SpatialOperation IsDisjointTo = new SpatialOperation("Disjoint") {
+ {
+ register("IsDisjointTo");//alias (deprecated)
+ }
@Override
public boolean evaluate(Shape indexedShape, Shape queryShape) {
return ! indexedShape.relate(queryShape).intersects();
}
};
- public static final SpatialOperation IsWithin = new SpatialOperation("IsWithin", true, false, true) {
+ /** Meets the "CoveredBy" OGC definition (boundary-neutral). */
+ public static final SpatialOperation IsWithin = new SpatialOperation("Within") {
+ {
+ register("IsWithin");//alias (deprecated)
+ register("CoveredBy");//alias -- the more appropriate name.
+ }
@Override
public boolean evaluate(Shape indexedShape, Shape queryShape) {
- return queryShape.hasArea() && (indexedShape.relate(queryShape) == SpatialRelation.WITHIN || indexedShape.equals(queryShape));
+ return indexedShape.relate(queryShape) == SpatialRelation.WITHIN || indexedShape.equals(queryShape);
}
};
- public static final SpatialOperation Overlaps = new SpatialOperation("Overlaps", true, false, true) {
+ /** Almost meets the "Overlaps" OGC definition, but boundary-neutral (boundary==interior). */
+ public static final SpatialOperation Overlaps = new SpatialOperation("Overlaps") {
@Override
public boolean evaluate(Shape indexedShape, Shape queryShape) {
- return queryShape.hasArea() && indexedShape.relate(queryShape).intersects();
+ return indexedShape.relate(queryShape) == SpatialRelation.INTERSECTS;//not Contains or Within or Disjoint
}
};
- // Member variables
- private final boolean scoreIsMeaningful;
- private final boolean sourceNeedsArea;
- private final boolean targetNeedsArea;
private final String name;
- protected SpatialOperation(String name, boolean scoreIsMeaningful, boolean sourceNeedsArea, boolean targetNeedsArea) {
+ protected SpatialOperation(String name) {
this.name = name;
- this.scoreIsMeaningful = scoreIsMeaningful;
- this.sourceNeedsArea = sourceNeedsArea;
- this.targetNeedsArea = targetNeedsArea;
+ register(name);
+ list.add( this );
+ }
+
+ protected void register(String name) {
registry.put(name, this);
registry.put(name.toUpperCase(Locale.ROOT), this);
- list.add( this );
}
public static SpatialOperation get( String v ) {
@@ -143,20 +169,6 @@ public abstract class SpatialOperation i
*/
public abstract boolean evaluate(Shape indexedShape, Shape queryShape);
- // ================================================= Getters / Setters =============================================
-
- public boolean isScoreIsMeaningful() {
- return scoreIsMeaningful;
- }
-
- public boolean isSourceNeedsArea() {
- return sourceNeedsArea;
- }
-
- public boolean isTargetNeedsArea() {
- return targetNeedsArea;
- }
-
public String getName() {
return name;
}
Modified: lucene/dev/trunk/lucene/spatial/src/test-files/simple-Queries-BBox.txt
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/spatial/src/test-files/simple-Queries-BBox.txt?rev=1608922&r1=1608921&r2=1608922&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/spatial/src/test-files/simple-Queries-BBox.txt (original)
+++ lucene/dev/trunk/lucene/spatial/src/test-files/simple-Queries-BBox.txt Tue Jul 8 19:50:22 2014
@@ -3,6 +3,7 @@ C5 @ BBoxWithin(ENVELOPE(-6, 6, 6, -6))
C10 @ Contains(ENVELOPE(-6, 6, 6, -6))
C10 @ IsEqualTo(ENVELOPE(-10, 10, 10, -10))
C5 C10 @ Intersects(ENVELOPE(-2, 2, 2, -2))
-C5 C10 @ Overlaps(ENVELOPE(-2, 2, 2, -2))
+ @ Overlaps(ENVELOPE(-2, 2, 2, -2))
+C5 @ Overlaps(ENVELOPE(-2, 2, 8, -2))
C5 C10 @ BBoxIntersects(ENVELOPE(-2, 2, 2, -2))
NW15 @ IsDisjointTo(ENVELOPE(-10, 10, 10, -10))
\ No newline at end of file
Modified: lucene/dev/trunk/lucene/spatial/src/test/org/apache/lucene/spatial/query/SpatialArgsParserTest.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/spatial/src/test/org/apache/lucene/spatial/query/SpatialArgsParserTest.java?rev=1608922&r1=1608921&r2=1608922&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/spatial/src/test/org/apache/lucene/spatial/query/SpatialArgsParserTest.java (original)
+++ lucene/dev/trunk/lucene/spatial/src/test/org/apache/lucene/spatial/query/SpatialArgsParserTest.java Tue Jul 8 19:50:22 2014
@@ -22,7 +22,9 @@ import com.spatial4j.core.shape.Rectangl
import org.apache.lucene.util.LuceneTestCase;
import org.junit.Test;
+import java.text.ParseException;
+//Tests SpatialOperation somewhat too
public class SpatialArgsParserTest extends LuceneTestCase {
private SpatialContext ctx = SpatialContext.GEO;
@@ -59,6 +61,22 @@ public class SpatialArgsParserTest exten
}
catch (Exception ex) {//expected
}
+
+ assertAlias(SpatialOperation.IsWithin, "CoveredBy");
+ assertAlias(SpatialOperation.IsWithin, "COVEREDBY");
+ assertAlias(SpatialOperation.IsWithin, "coveredBy");
+ assertAlias(SpatialOperation.IsWithin, "Within");
+ assertAlias(SpatialOperation.IsEqualTo, "Equals");
+ assertAlias(SpatialOperation.IsDisjointTo, "disjoint");
+ assertAlias(SpatialOperation.Contains, "Covers");
+ }
+
+ private void assertAlias(SpatialOperation op, final String name) throws ParseException {
+ String arg;
+ SpatialArgs out;
+ arg = name + "(Point(0 0))";
+ out = new SpatialArgsParser().parse(arg, ctx);
+ assertEquals(op, out.getOperation());
}
}