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)