You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by mi...@apache.org on 2016/04/13 11:49:13 UTC

lucene-solr:master: improve randomized polygon generation to sometimes include regular ngons

Repository: lucene-solr
Updated Branches:
  refs/heads/master 67f6283ce -> e076b4c5b


improve randomized polygon generation to sometimes include regular ngons


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/e076b4c5
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/e076b4c5
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/e076b4c5

Branch: refs/heads/master
Commit: e076b4c5b485599941d15fe08683c54831e84564
Parents: 67f6283
Author: Mike McCandless <mi...@apache.org>
Authored: Wed Apr 13 05:51:38 2016 -0400
Committer: Mike McCandless <mi...@apache.org>
Committed: Wed Apr 13 05:51:38 2016 -0400

----------------------------------------------------------------------
 .../java/org/apache/lucene/geo/GeoTestUtil.java | 85 ++++++++++++++++++++
 1 file changed, 85 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e076b4c5/lucene/test-framework/src/java/org/apache/lucene/geo/GeoTestUtil.java
----------------------------------------------------------------------
diff --git a/lucene/test-framework/src/java/org/apache/lucene/geo/GeoTestUtil.java b/lucene/test-framework/src/java/org/apache/lucene/geo/GeoTestUtil.java
index 9e719c0..f7d4eae 100644
--- a/lucene/test-framework/src/java/org/apache/lucene/geo/GeoTestUtil.java
+++ b/lucene/test-framework/src/java/org/apache/lucene/geo/GeoTestUtil.java
@@ -20,6 +20,7 @@ import java.util.ArrayList;
 import java.util.Random;
 
 import org.apache.lucene.util.NumericUtils;
+import org.apache.lucene.util.SloppyMath;
 import org.apache.lucene.util.TestUtil;
 
 import com.carrotsearch.randomizedtesting.RandomizedContext;
@@ -135,10 +136,94 @@ public class GeoTestUtil {
                            nextLongitudeNear(otherLongitude), nextLongitudeNear(otherLongitude), false);
   }
 
+  /** Makes an n-gon, centered at the provided lat/lon, and each vertex approximately
+   *  distanceMeters away from the center.
+   *
+   * Do not invoke me across the dateline or a pole!! */
+  public static Polygon createRegularPolygon(double centerLat, double centerLon, double radiusMeters, int gons) {
+
+    // System.out.println("MAKE POLY: centerLat=" + centerLat + " centerLon=" + centerLon + " radiusMeters=" + radiusMeters + " gons=" + gons);
+
+    double[][] result = new double[2][];
+    result[0] = new double[gons+1];
+    result[1] = new double[gons+1];
+    //System.out.println("make gon=" + gons);
+    for(int i=0;i<gons;i++) {
+      double angle = 360.0-i*(360.0/gons);
+      //System.out.println("  angle " + angle);
+      double x = Math.cos(Math.toRadians(angle));
+      double y = Math.sin(Math.toRadians(angle));
+      double factor = 2.0;
+      double step = 1.0;
+      int last = 0;
+
+      //System.out.println("angle " + angle + " slope=" + slope);
+      // Iterate out along one spoke until we hone in on the point that's nearly exactly radiusMeters from the center:
+      while (true) {
+
+        // TODO: we could in fact cross a pole?  Just do what surpriseMePolygon does?
+        double lat = centerLat + y * factor;
+        GeoUtils.checkLatitude(lat);
+        double lon = centerLon + x * factor;
+        GeoUtils.checkLongitude(lon);
+        double distanceMeters = SloppyMath.haversinMeters(centerLat, centerLon, lat, lon);
+
+        //System.out.println("  iter lat=" + lat + " lon=" + lon + " distance=" + distanceMeters + " vs " + radiusMeters);
+        if (Math.abs(distanceMeters - radiusMeters) < 0.1) {
+          // Within 10 cm: close enough!
+          result[0][i] = lat;
+          result[1][i] = lon;
+          break;
+        }
+
+        if (distanceMeters > radiusMeters) {
+          // too big
+          //System.out.println("    smaller");
+          factor -= step;
+          if (last == 1) {
+            //System.out.println("      half-step");
+            step /= 2.0;
+          }
+          last = -1;
+        } else if (distanceMeters < radiusMeters) {
+          // too small
+          //System.out.println("    bigger");
+          factor += step;
+          if (last == -1) {
+            //System.out.println("      half-step");
+            step /= 2.0;
+          }
+          last = 1;
+        }
+      }
+    }
+
+    // close poly
+    result[0][gons] = result[0][0];
+    result[1][gons] = result[1][0];
+
+    //System.out.println("  polyLats=" + Arrays.toString(result[0]));
+    //System.out.println("  polyLons=" + Arrays.toString(result[1]));
+
+    return new Polygon(result[0], result[1]);
+  }
+
   /** returns next pseudorandom polygon */
   public static Polygon nextPolygon() {
     if (random().nextBoolean()) {
       return surpriseMePolygon(null, null);
+    } else if (random().nextInt(10) == 1) {
+      // this poly is slow to create ... only do it 10% of the time:
+      while (true) {
+        int gons = TestUtil.nextInt(random(), 4, 500);
+        // So the poly can cover at most 50% of the earth's surface:
+        double radiusMeters = random().nextDouble() * GeoUtils.EARTH_MEAN_RADIUS_METERS * Math.PI / 2.0 + 1.0;
+        try {
+          return createRegularPolygon(nextLatitude(), nextLongitude(), radiusMeters, gons);
+        } catch (IllegalArgumentException iae) {
+          // we tried to cross dateline or pole ... try again
+        }
+      }
     }
 
     Rectangle box = nextBoxInternal(nextLatitude(), nextLatitude(), nextLongitude(), nextLongitude(), false);