Fix test bug RE -180/+180 ambiguity. seed: 349A33E5B7DF73A2:5681B850511BD076

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1597815 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
David Wayne Smiley 2014-05-27 16:13:32 +00:00
parent 1b9c63fc9d
commit e9906a334b
1 changed files with 59 additions and 13 deletions

View File

@ -67,18 +67,15 @@ public class SpatialOpRecursivePrefixTreeTest extends StrategyTestCase {
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 SpatialOpRecursivePrefixTreeTest extends StrategyTestCase {
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 SpatialOpRecursivePrefixTreeTest extends StrategyTestCase {
), 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 SpatialOpRecursivePrefixTreeTest extends StrategyTestCase {
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 SpatialOpRecursivePrefixTreeTest extends StrategyTestCase {
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)