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/05/27 18:13:32 UTC
svn commit: r1597815 -
/lucene/dev/trunk/lucene/spatial/src/test/org/apache/lucene/spatial/prefix/SpatialOpRecursivePrefixTreeTest.java
Author: dsmiley
Date: Tue May 27 16:13:32 2014
New Revision: 1597815
URL: http://svn.apache.org/r1597815
Log:
Fix test bug RE -180/+180 ambiguity. seed: 349A33E5B7DF73A2:5681B850511BD076
Modified:
lucene/dev/trunk/lucene/spatial/src/test/org/apache/lucene/spatial/prefix/SpatialOpRecursivePrefixTreeTest.java
Modified: lucene/dev/trunk/lucene/spatial/src/test/org/apache/lucene/spatial/prefix/SpatialOpRecursivePrefixTreeTest.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/spatial/src/test/org/apache/lucene/spatial/prefix/SpatialOpRecursivePrefixTreeTest.java?rev=1597815&r1=1597814&r2=1597815&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/spatial/src/test/org/apache/lucene/spatial/prefix/SpatialOpRecursivePrefixTreeTest.java (original)
+++ lucene/dev/trunk/lucene/spatial/src/test/org/apache/lucene/spatial/prefix/SpatialOpRecursivePrefixTreeTest.java Tue May 27 16:13:32 2014
@@ -67,18 +67,15 @@ public class SpatialOpRecursivePrefixTre
static final int ITERATIONS = 10;
private SpatialPrefixTree grid;
-
- @Before
- public void setUp() throws Exception {
- super.setUp();
- deleteAll();
- }
+ private SpatialContext ctx2D;
public void setupGrid(int maxLevels) throws IOException {
if (randomBoolean())
setupQuadGrid(maxLevels);
else
setupGeohashGrid(maxLevels);
+ setupCtx2D(ctx);
+
//((PrefixTreeStrategy) strategy).setDistErrPct(0);//fully precise to grid
((RecursivePrefixTreeStrategy)strategy).setPruneLeafyBranches(randomBoolean());
@@ -86,6 +83,16 @@ public class SpatialOpRecursivePrefixTre
System.out.println("Strategy: " + strategy.toString());
}
+ private void setupCtx2D(SpatialContext ctx) {
+ if (!ctx.isGeo())
+ ctx2D = ctx;
+ //A non-geo version of ctx.
+ SpatialContextFactory ctxFactory = new SpatialContextFactory();
+ ctxFactory.geo = false;
+ ctxFactory.worldBounds = ctx.getWorldBounds();
+ ctx2D = ctxFactory.newSpatialContext();
+ }
+
private void setupQuadGrid(int maxLevels) {
//non-geospatial makes this test a little easier (in gridSnap), and using boundary values 2^X raises
// the prospect of edge conditions we want to test, plus makes for simpler numbers (no decimals).
@@ -186,6 +193,16 @@ public class SpatialOpRecursivePrefixTre
), 1).numFound==1);//match
}
+ @Test
+ public void testShapePair() {
+ ctx = SpatialContext.GEO;
+ setupCtx2D(ctx);
+
+ Shape leftShape = new ShapePair(ctx.makeRectangle(-74, -56, -8, 1), ctx.makeRectangle(-180, 134, -90, 90), true);
+ Shape queryShape = ctx.makeRectangle(-180, 180, -90, 90);
+ assertEquals(SpatialRelation.WITHIN, leftShape.relate(queryShape));
+ }
+
//Override so we can index parts of a pair separately, resulting in the detailLevel
// being independent for each shape vs the whole thing
@Override
@@ -404,22 +421,43 @@ public class SpatialOpRecursivePrefixTre
private class ShapePair extends ShapeCollection<Shape> {
final Shape shape1, shape2;
- final boolean biasContainsThenWithin;//a hack
+ final Shape shape1_2D, shape2_2D;//not geo (bit of a hack)
+ final boolean biasContainsThenWithin;
public ShapePair(Shape shape1, Shape shape2, boolean containsThenWithin) {
super(Arrays.asList(shape1, shape2), ctx);
this.shape1 = shape1;
this.shape2 = shape2;
+ this.shape1_2D = toNonGeo(shape1);
+ this.shape2_2D = toNonGeo(shape2);
biasContainsThenWithin = containsThenWithin;
}
+ private Shape toNonGeo(Shape shape) {
+ if (!ctx.isGeo())
+ return shape;//already non-geo
+ if (shape instanceof Rectangle) {
+ Rectangle rect = (Rectangle) shape;
+ if (rect.getCrossesDateLine()) {
+ return new ShapePair(
+ ctx2D.makeRectangle(rect.getMinX(), 180, rect.getMinY(), rect.getMaxY()),
+ ctx2D.makeRectangle(-180, rect.getMaxX(), rect.getMinY(), rect.getMaxY()),
+ biasContainsThenWithin);
+ } else {
+ return ctx2D.makeRectangle(rect.getMinX(), rect.getMaxX(), rect.getMinY(), rect.getMaxY());
+ }
+ }
+ //no need to do others; this addresses the -180/+180 ambiguity corner test problem
+ return shape;
+ }
+
@Override
public SpatialRelation relate(Shape other) {
SpatialRelation r = relateApprox(other);
- if (r == CONTAINS)
- return r;
if (r == DISJOINT)
return r;
+ if (r == CONTAINS)
+ return r;
if (r == WITHIN && !biasContainsThenWithin)
return r;
@@ -429,15 +467,23 @@ public class SpatialOpRecursivePrefixTre
if (!pairTouches)
return r;
//test all 4 corners
+ // Note: awkwardly, we use a non-geo context for this because in geo, -180 & +180 are the same place, which means
+ // that "other" might wrap the world horizontally and yet all it's corners could be in shape1 (or shape2) even
+ // though shape1 is only adjacent to the dateline. I couldn't think of a better way to handle this.
Rectangle oRect = (Rectangle)other;
- if (relate(ctx.makePoint(oRect.getMinX(), oRect.getMinY())) == CONTAINS
- && relate(ctx.makePoint(oRect.getMinX(), oRect.getMaxY())) == CONTAINS
- && relate(ctx.makePoint(oRect.getMaxX(), oRect.getMinY())) == CONTAINS
- && relate(ctx.makePoint(oRect.getMaxX(), oRect.getMaxY())) == CONTAINS)
+ if (cornerContainsNonGeo(oRect.getMinX(), oRect.getMinY())
+ && cornerContainsNonGeo(oRect.getMinX(), oRect.getMaxY())
+ && cornerContainsNonGeo(oRect.getMaxX(), oRect.getMinY())
+ && cornerContainsNonGeo(oRect.getMaxX(), oRect.getMaxY()) )
return CONTAINS;
return r;
}
+ private boolean cornerContainsNonGeo(double x, double y) {
+ Shape pt = ctx2D.makePoint(x, y);
+ return shape1_2D.relate(pt).intersects() || shape2_2D.relate(pt).intersects();
+ }
+
private SpatialRelation relateApprox(Shape other) {
if (biasContainsThenWithin) {
if (shape1.relate(other) == CONTAINS || shape1.equals(other)