Java源码示例:org.apache.lucene.util.SloppyMath

示例1
private void maybeUpdateBBox() {
  if (setBottomCounter < 1024 || (setBottomCounter & 0x3F) == 0x3F) {
    NearestHit hit = hitQueue.peek();
    Rectangle box = Rectangle.fromPointDistance(pointLat, pointLon,
        SloppyMath.haversinMeters(hit.distanceSortKey));
    //System.out.println("    update bbox to " + box);
    minLat = box.minLat;
    maxLat = box.maxLat;
    if (box.crossesDateline()) {
      // box1
      minLon = Double.NEGATIVE_INFINITY;
      maxLon = box.maxLon;
      // box2
      minLon2 = box.minLon;
    } else {
      minLon = box.minLon;
      maxLon = box.maxLon;
      // disable box2
      minLon2 = Double.POSITIVE_INFINITY;
    }
  }
  setBottomCounter++;
}
 
示例2
private static double approxBestDistance(double minLat, double maxLat, double minLon, double maxLon, double pointLat, double pointLon) {
  
  // TODO: can we make this the trueBestDistance?  I.e., minimum distance between the point and ANY point on the box?  we can speed things
  // up if so, but not enrolling any BKD cell whose true best distance is > bottom of the current hit queue

  if (pointLat >= minLat && pointLat <= maxLat && pointLon >= minLon && pointLon <= maxLon) {
    // point is inside the cell!
    return 0.0;
  }

  double d1 = SloppyMath.haversinSortKey(pointLat, pointLon, minLat, minLon);
  double d2 = SloppyMath.haversinSortKey(pointLat, pointLon, minLat, maxLon);
  double d3 = SloppyMath.haversinSortKey(pointLat, pointLon, maxLat, maxLon);
  double d4 = SloppyMath.haversinSortKey(pointLat, pointLon, maxLat, minLon);
  return Math.min(Math.min(d1, d2), Math.min(d3, d4));
}
 
示例3
double sortKey(int doc) throws IOException {
  if (doc > currentDocs.docID()) {
    currentDocs.advance(doc);
  }
  double minValue = Double.POSITIVE_INFINITY;
  if (doc == currentDocs.docID()) {
    setValues();
    int numValues = currentDocs.docValueCount();
    for (int i = 0; i < numValues; i++) {
      long encoded = currentValues[i];
      double docLatitude = decodeLatitude((int)(encoded >> 32));
      double docLongitude = decodeLongitude((int)(encoded & 0xFFFFFFFF));
      minValue = Math.min(minValue, SloppyMath.haversinSortKey(latitude, longitude, docLatitude, docLongitude));
    }
  }
  return minValue;
}
 
示例4
public void testHaversinOpto() {
  int iters = atLeast(100);
  for (int i = 0; i < iters; i++) {
    double lat = GeoTestUtil.nextLatitude();
    double lon = GeoTestUtil.nextLongitude();
    double radius = 50000000 * random().nextDouble();
    Rectangle box = Rectangle.fromPointDistance(lat, lon, radius);

    if (box.maxLon - lon < 90 && lon - box.minLon < 90) {
      double minPartialDistance = Math.max(SloppyMath.haversinSortKey(lat, lon, lat, box.maxLon),
                                           SloppyMath.haversinSortKey(lat, lon, box.maxLat, lon));

      for (int j = 0; j < 10000; j++) {
        double point[] = GeoTestUtil.nextPointNear(box);
        double lat2 = point[0];
        double lon2 = point[1];
        // if the point is within radius, then it should be <= our sort key
        if (SloppyMath.haversinMeters(lat, lon, lat2, lon2) <= radius) {
          assertTrue(SloppyMath.haversinSortKey(lat, lon, lat2, lon2) <= minPartialDistance);
        }
      }
    }
  }
}
 
示例5
@Override
public boolean contains(double x, double y) {
  if (crossesDateline) {
    if (Component2D.containsPoint(x, y, rectangle.minLon, GeoUtils.MAX_LON_INCL, rectangle.minLat, rectangle.maxLat) ||
        Component2D.containsPoint(x, y, GeoUtils.MIN_LON_INCL, rectangle.maxLon, rectangle.minLat, rectangle.maxLat)) {
      return SloppyMath.haversinSortKey(y, x, this.centerLat, this.centerLon) <= sortKey;
    }
  } else {
    if (Component2D.containsPoint(x, y, rectangle.minLon, rectangle.maxLon, rectangle.minLat, rectangle.maxLat)) {
      return SloppyMath.haversinSortKey(y, x, this.centerLat, this.centerLon) <= sortKey;
    }
  }
  return false;
}
 
示例6
/**
 * Compute the relation between the provided box and distance query.
 * This only works for boxes that do not cross the dateline.
 */
public static PointValues.Relation relate(
    double minLat, double maxLat, double minLon, double maxLon,
    double lat, double lon, double distanceSortKey, double axisLat) {

  if (minLon > maxLon) {
    throw new IllegalArgumentException("Box crosses the dateline");
  }

  if ((lon < minLon || lon > maxLon) && (axisLat + Rectangle.AXISLAT_ERROR < minLat || axisLat - Rectangle.AXISLAT_ERROR > maxLat)) {
    // circle not fully inside / crossing axis
    if (SloppyMath.haversinSortKey(lat, lon, minLat, minLon) > distanceSortKey &&
        SloppyMath.haversinSortKey(lat, lon, minLat, maxLon) > distanceSortKey &&
        SloppyMath.haversinSortKey(lat, lon, maxLat, minLon) > distanceSortKey &&
        SloppyMath.haversinSortKey(lat, lon, maxLat, maxLon) > distanceSortKey) {
      // no points inside
      return Relation.CELL_OUTSIDE_QUERY;
    }
  }

  if (within90LonDegrees(lon, minLon, maxLon) &&
      SloppyMath.haversinSortKey(lat, lon, minLat, minLon) <= distanceSortKey &&
      SloppyMath.haversinSortKey(lat, lon, minLat, maxLon) <= distanceSortKey &&
      SloppyMath.haversinSortKey(lat, lon, maxLat, minLon) <= distanceSortKey &&
      SloppyMath.haversinSortKey(lat, lon, maxLat, maxLon) <= distanceSortKey) {
    // we are fully enclosed, collect everything within this subtree
    return Relation.CELL_INSIDE_QUERY;
  }

  return Relation.CELL_CROSSES_QUERY;
}
 
示例7
private double getDistanceKeyFromEncoded(long encoded) {
  int latitudeBits = (int)(encoded >> 32);
  int longitudeBits = (int)(encoded & 0xFFFFFFFF);
  double lat = GeoEncodingUtils.decodeLatitude(latitudeBits);
  double lon = GeoEncodingUtils.decodeLongitude(longitudeBits);
  return SloppyMath.haversinSortKey(originLat, originLon, lat, lon);
}
 
示例8
@Override
public int compareBottom(int doc) throws IOException {
  if (doc > currentDocs.docID()) {
    currentDocs.advance(doc);
  }
  if (doc < currentDocs.docID()) {
    return Double.compare(bottom, Double.POSITIVE_INFINITY);
  }

  setValues();

  int numValues = currentDocs.docValueCount();

  int cmp = -1;
  for (int i = 0; i < numValues; i++) {
    long encoded = currentValues[i];

    // test bounding box
    int latitudeBits = (int)(encoded >> 32);
    if (latitudeBits < minLat || latitudeBits > maxLat) {
      continue;
    }
    int longitudeBits = (int)(encoded & 0xFFFFFFFF);
    if ((longitudeBits < minLon || longitudeBits > maxLon) && (longitudeBits < minLon2)) {
      continue;
    }

    // only compute actual distance if its inside "competitive bounding box"
    double docLatitude = decodeLatitude(latitudeBits);
    double docLongitude = decodeLongitude(longitudeBits);
    cmp = Math.max(cmp, Double.compare(bottom, SloppyMath.haversinSortKey(latitude, longitude, docLatitude, docLongitude)));
    // once we compete in the PQ, no need to continue.
    if (cmp > 0) {
      return cmp;
    }
  }
  return cmp;
}
 
示例9
public void testBoundingBoxOpto() {
  int iters = atLeast(100);
  for (int i = 0; i < iters; i++) {
    double lat = GeoTestUtil.nextLatitude();
    double lon = GeoTestUtil.nextLongitude();
    double radius = 50000000 * random().nextDouble();
    Rectangle box = Rectangle.fromPointDistance(lat, lon, radius);
    final Rectangle box1;
    final Rectangle box2;
    if (box.crossesDateline()) {
      box1 = new Rectangle(box.minLat, box.maxLat, -180, box.maxLon);
      box2 = new Rectangle(box.minLat, box.maxLat, box.minLon, 180);
    } else {
      box1 = box;
      box2 = null;
    }

    for (int j = 0; j < 1000; j++) {
      double point[] = GeoTestUtil.nextPointNear(box);
      double lat2 = point[0];
      double lon2 = point[1];
      // if the point is within radius, then it should be in our bounding box
      if (SloppyMath.haversinMeters(lat, lon, lat2, lon2) <= radius) {
        assertTrue(lat >= box.minLat && lat <= box.maxLat);
        assertTrue(lon >= box1.minLon && lon <= box1.maxLon || (box2 != null && lon >= box2.minLon && lon <= box2.maxLon));
      }
    }
  }
}
 
示例10
static boolean isDisjoint(double centerLat, double centerLon, double radius, double axisLat, double latMin, double latMax, double lonMin, double lonMax) {
  if ((centerLon < lonMin || centerLon > lonMax) && (axisLat+ Rectangle.AXISLAT_ERROR < latMin || axisLat- Rectangle.AXISLAT_ERROR > latMax)) {
    // circle not fully inside / crossing axis
    if (SloppyMath.haversinMeters(centerLat, centerLon, latMin, lonMin) > radius &&
        SloppyMath.haversinMeters(centerLat, centerLon, latMin, lonMax) > radius &&
        SloppyMath.haversinMeters(centerLat, centerLon, latMax, lonMin) > radius &&
        SloppyMath.haversinMeters(centerLat, centerLon, latMax, lonMax) > radius) {
      // no points inside
      return true;
    }
  }

  return false;
}
 
示例11
/**
 * Return an approximate value of the diameter of the earth (in meters) at the given latitude (in radians).
 */
public static double earthDiameter(double latitude) {
    // SloppyMath impl returns a result in kilometers
    return SloppyMath.earthDiameter(latitude) * 1000;
}
 
示例12
public void testNearestNeighborRandom() throws Exception {
  
  int numPoints = atLeast(1000);
  Directory dir;
  if (numPoints > 100000) {
    dir = newFSDirectory(createTempDir(getClass().getSimpleName()));
  } else {
    dir = newDirectory();
  }
  double[] lats = new double[numPoints];
  double[] lons = new double[numPoints];

  IndexWriterConfig iwc = getIndexWriterConfig();
  iwc.setMergePolicy(newLogMergePolicy());
  iwc.setMergeScheduler(new SerialMergeScheduler());
  RandomIndexWriter w = new RandomIndexWriter(random(), dir, iwc);
  for(int id=0;id<numPoints;id++) {
    lats[id] = quantizeLat(GeoTestUtil.nextLatitude());
    lons[id] = quantizeLon(GeoTestUtil.nextLongitude());
    Document doc = new Document();
    doc.add(new LatLonPoint("point", lats[id], lons[id]));
    doc.add(new LatLonDocValuesField("point", lats[id], lons[id]));
    doc.add(new StoredField("id", id));
    w.addDocument(doc);
  }

  if (random().nextBoolean()) {
    w.forceMerge(1);
  }

  DirectoryReader r = w.getReader();
  if (VERBOSE) {      
    System.out.println("TEST: reader=" + r);
  }
  // can't wrap because we require Lucene60PointsFormat directly but e.g. ParallelReader wraps with its own points impl:
  IndexSearcher s = newSearcher(r, false);
  int iters = atLeast(100);
  for(int iter=0;iter<iters;iter++) {
    if (VERBOSE) {      
      System.out.println("\nTEST: iter=" + iter);
    }
    double pointLat = GeoTestUtil.nextLatitude();
    double pointLon = GeoTestUtil.nextLongitude();

    // dumb brute force search to get the expected result:
    FieldDoc[] expectedHits = new FieldDoc[lats.length];
    for(int id=0;id<lats.length;id++) {
      double distance = SloppyMath.haversinMeters(pointLat, pointLon, lats[id], lons[id]);
      FieldDoc hit = new FieldDoc(id, 0.0f, new Object[] {Double.valueOf(distance)});
      expectedHits[id] = hit;
    }

    Arrays.sort(expectedHits, new Comparator<FieldDoc>() {
        @Override
        public int compare(FieldDoc a, FieldDoc  b) {
          int cmp = Double.compare(((Double) a.fields[0]).doubleValue(), ((Double) b.fields[0]).doubleValue());
          if (cmp != 0) {
            return cmp;
          }
          // tie break by smaller docID:
          return a.doc - b.doc;
        }
      });

    int topN = TestUtil.nextInt(random(), 1, lats.length);

    if (VERBOSE) {
      System.out.println("\nhits for pointLat=" + pointLat + " pointLon=" + pointLon);
    }

    // Also test with MatchAllDocsQuery, sorting by distance:
    TopFieldDocs fieldDocs = s.search(new MatchAllDocsQuery(), topN, new Sort(LatLonDocValuesField.newDistanceSort("point", pointLat, pointLon)));

    ScoreDoc[] hits = LatLonPointPrototypeQueries.nearest(s, "point", pointLat, pointLon, topN).scoreDocs;
    for(int i=0;i<topN;i++) {
      FieldDoc expected = expectedHits[i];
      FieldDoc expected2 = (FieldDoc) fieldDocs.scoreDocs[i];
      FieldDoc actual = (FieldDoc) hits[i];
      Document actualDoc = r.document(actual.doc);

      if (VERBOSE) {
        System.out.println("hit " + i);
        System.out.println("  expected id=" + expected.doc+ " lat=" + lats[expected.doc] + " lon=" + lons[expected.doc]
            + " distance=" + ((Double) expected.fields[0]).doubleValue() + " meters");
        System.out.println("  actual id=" + actualDoc.getField("id") + " distance=" + actual.fields[0] + " meters");
      }

      assertEquals(expected.doc, actual.doc);
      assertEquals(((Double) expected.fields[0]).doubleValue(), ((Double) actual.fields[0]).doubleValue(), 0.0);

      assertEquals(expected2.doc, actual.doc);
      assertEquals(((Double) expected2.fields[0]).doubleValue(), ((Double) actual.fields[0]).doubleValue(), 0.0);
    }
  }

  r.close();
  w.close();
  dir.close();
}
 
示例13
/** 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]);
}
 
示例14
private int getStepCount(double minLat, double maxLat, double minLon, double maxLon) {
  double distanceMeters = SloppyMath.haversinMeters(minLat, minLon, maxLat, maxLon);
  return Math.max(1, (int) Math.round((distanceMeters / 1000.0) / MAX_KM_PER_STEP));
}
 
示例15
private static void inverseHaversin(StringBuilder b, double centerLat, double centerLon, double radiusMeters) {
  double angle = 0;
  int steps = 100;

  newAngle:
  while (angle < 360) {
    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;
    double lastDistanceMeters = 0.0;
    //System.out.println("angle " + angle + " slope=" + slope);
    while (true) {
      double lat = wrapLat(centerLat + y * factor);
      double lon = wrapLon(centerLon + x * factor);
      double distanceMeters = SloppyMath.haversinMeters(centerLat, centerLon, lat, lon);

      if (last == 1 && distanceMeters < lastDistanceMeters) {
        // For large enough circles, some angles are not possible:
        //System.out.println("  done: give up on angle " + angle);
        angle += 360./steps;
        continue newAngle;
      }
      if (last == -1 && distanceMeters > lastDistanceMeters) {
        // For large enough circles, some angles are not possible:
        //System.out.println("  done: give up on angle " + angle);
        angle += 360./steps;
        continue newAngle;
      }
      lastDistanceMeters = distanceMeters;

      //System.out.println("  iter lat=" + lat + " lon=" + lon + " distance=" + distanceMeters + " vs " + radiusMeters);
      if (Math.abs(distanceMeters - radiusMeters) < 0.1) {
        b.append("          [").append(lat).append(", ").append(lon).append("],\n");
        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;
      }
    }
    angle += 360./steps;
  }
}
 
示例16
private double getDistanceFromEncoded(long encoded) {
  return SloppyMath.haversinMeters(getDistanceKeyFromEncoded(encoded));
}
 
示例17
static double haversin2(double partial) {
  if (Double.isInfinite(partial)) {
    return partial;
  }
  return SloppyMath.haversinMeters(partial);
}
 
示例18
public void testRandomCircleToBBox() throws Exception {
  int iters = atLeast(100);
  for(int iter=0;iter<iters;iter++) {

    double centerLat = GeoTestUtil.nextLatitude();
    double centerLon = GeoTestUtil.nextLongitude();

    final double radiusMeters;
    if (random().nextBoolean()) {
      // Approx 4 degrees lon at the equator:
      radiusMeters = random().nextDouble() * 444000;
    } else {
      radiusMeters = random().nextDouble() * 50000000;
    }

    // TODO: randomly quantize radius too, to provoke exact math errors?

    Rectangle bbox = Rectangle.fromPointDistance(centerLat, centerLon, radiusMeters);

    int numPointsToTry = 1000;
    for(int i=0;i<numPointsToTry;i++) {

      double point[] = GeoTestUtil.nextPointNear(bbox);
      double lat = point[0];
      double lon = point[1];

      double distanceMeters = SloppyMath.haversinMeters(centerLat, centerLon, lat, lon);

      // Haversin says it's within the circle:
      boolean haversinSays = distanceMeters <= radiusMeters;

      // BBox says its within the box:
      boolean bboxSays;
      if (bbox.crossesDateline()) {
        if (lat >= bbox.minLat && lat <= bbox.maxLat) {
          bboxSays = lon <= bbox.maxLon || lon >= bbox.minLon;
        } else {
          bboxSays = false;
        }
      } else {
        bboxSays = lat >= bbox.minLat && lat <= bbox.maxLat && lon >= bbox.minLon && lon <= bbox.maxLon;
      }

      if (haversinSays) {
        if (bboxSays == false) {
          System.out.println("centerLat=" + centerLat + " centerLon=" + centerLon + " radiusMeters=" + radiusMeters);
          System.out.println("  bbox: lat=" + bbox.minLat + " to " + bbox.maxLat + " lon=" + bbox.minLon + " to " + bbox.maxLon);
          System.out.println("  point: lat=" + lat + " lon=" + lon);
          System.out.println("  haversin: " + distanceMeters);
          fail("point was within the distance according to haversin, but the bbox doesn't contain it");
        }
      } else {
        // it's fine if haversin said it was outside the radius and bbox said it was inside the box
      }
    }
  }
}
 
示例19
public void testBasics() throws IOException {
  Directory dir = newDirectory();
  RandomIndexWriter w = new RandomIndexWriter(random(), dir, newIndexWriterConfig()
      .setMergePolicy(newLogMergePolicy(random().nextBoolean())));
  Document doc = new Document();
  LatLonPoint point = new LatLonPoint("foo", 0.0, 0.0);
  doc.add(point);
  LatLonDocValuesField docValue = new LatLonDocValuesField("foo",0.0, 0.0);
  doc.add(docValue);

  double pivotDistance = 5000;//5k

  point.setLocationValue(-7, -7);
  docValue.setLocationValue(-7, -7);
  w.addDocument(doc);

  point.setLocationValue(9, 9);
  docValue.setLocationValue(9, 9);
  w.addDocument(doc);


  point.setLocationValue(8, 8);
  docValue.setLocationValue(8, 8);
  w.addDocument(doc);

  point.setLocationValue(4, 4);
  docValue.setLocationValue(4, 4);
  w.addDocument(doc);

  point.setLocationValue(-1, -1);
  docValue.setLocationValue(-1, -1);
  w.addDocument(doc);

  DirectoryReader reader = w.getReader();
  IndexSearcher searcher = newSearcher(reader);
  
  Query q = LatLonPoint.newDistanceFeatureQuery("foo", 3, 10, 10, pivotDistance);
  TopScoreDocCollector collector = TopScoreDocCollector.create(2, null, 1);
  searcher.search(q, collector);
  TopDocs topHits = collector.topDocs();
  assertEquals(2, topHits.scoreDocs.length);

  double distance1 = SloppyMath.haversinMeters(GeoEncodingUtils.decodeLatitude(GeoEncodingUtils.encodeLatitude(9)) , GeoEncodingUtils.decodeLongitude(GeoEncodingUtils.encodeLongitude(9)), 10,10);
  double distance2 = SloppyMath.haversinMeters(GeoEncodingUtils.decodeLatitude(GeoEncodingUtils.encodeLatitude(8)) , GeoEncodingUtils.decodeLongitude(GeoEncodingUtils.encodeLongitude(8)), 10,10);

  CheckHits.checkEqual(q,
      new ScoreDoc[] {
          new ScoreDoc(1, (float) (3f * (pivotDistance / (pivotDistance + distance1)))),
          new ScoreDoc(2, (float) (3f * (pivotDistance / (pivotDistance + distance2))))
      },
      topHits.scoreDocs);

  distance1 = SloppyMath.haversinMeters(GeoEncodingUtils.decodeLatitude(GeoEncodingUtils.encodeLatitude(9)) , GeoEncodingUtils.decodeLongitude(GeoEncodingUtils.encodeLongitude(9)), 9,9);
  distance2 = SloppyMath.haversinMeters(GeoEncodingUtils.decodeLatitude(GeoEncodingUtils.encodeLatitude(8)) , GeoEncodingUtils.decodeLongitude(GeoEncodingUtils.encodeLongitude(8)), 9,9);

  q = LatLonPoint.newDistanceFeatureQuery("foo", 3, 9, 9,  pivotDistance);
  collector = TopScoreDocCollector.create(2, null, 1);
  searcher.search(q, collector);
  topHits = collector.topDocs();
  assertEquals(2, topHits.scoreDocs.length);
  CheckHits.checkExplanations(q, "", searcher);

  CheckHits.checkEqual(q,
      new ScoreDoc[] {
          new ScoreDoc(1, (float) (3f * (pivotDistance / (pivotDistance + distance1)))),
          new ScoreDoc(2, (float) (3f * (pivotDistance / (pivotDistance + distance2))))
      },
      topHits.scoreDocs);
  
  reader.close();
  w.close();
  dir.close();
}
 
示例20
public void testCrossesDateLine() throws IOException {
  Directory dir = newDirectory();
  RandomIndexWriter w = new RandomIndexWriter(random(), dir, newIndexWriterConfig()
      .setMergePolicy(newLogMergePolicy(random().nextBoolean())));
  Document doc = new Document();
  LatLonPoint point = new LatLonPoint("foo", 0.0, 0.0);
  doc.add(point);
  LatLonDocValuesField docValue = new LatLonDocValuesField("foo",0.0, 0.0);
  doc.add(docValue);

  double pivotDistance = 5000;//5k

  point.setLocationValue(0, -179);
  docValue.setLocationValue(0, -179);
  w.addDocument(doc);

  point.setLocationValue(0, 176);
  docValue.setLocationValue(0, 176);
  w.addDocument(doc);

  point.setLocationValue(0, -150);
  docValue.setLocationValue(0, -150);
  w.addDocument(doc);

  point.setLocationValue(0, -140);
  docValue.setLocationValue(0, -140);
  w.addDocument(doc);

  point.setLocationValue(0, 140);
  docValue.setLocationValue(01, 140);
  w.addDocument(doc);

  DirectoryReader reader = w.getReader();
  IndexSearcher searcher = newSearcher(reader);

  Query q = LatLonPoint.newDistanceFeatureQuery("foo", 3, 0, 179, pivotDistance);
  TopScoreDocCollector collector = TopScoreDocCollector.create(2, null, 1);
  searcher.search(q, collector);
  TopDocs topHits = collector.topDocs();
  assertEquals(2, topHits.scoreDocs.length);

  double distance1 = SloppyMath.haversinMeters(GeoEncodingUtils.decodeLatitude(GeoEncodingUtils.encodeLatitude(0)) , GeoEncodingUtils.decodeLongitude(GeoEncodingUtils.encodeLongitude(-179)), 0,179);
  double distance2 = SloppyMath.haversinMeters(GeoEncodingUtils.decodeLatitude(GeoEncodingUtils.encodeLatitude(0)) , GeoEncodingUtils.decodeLongitude(GeoEncodingUtils.encodeLongitude(176)), 0,179);

  CheckHits.checkEqual(q,
      new ScoreDoc[] {
          new ScoreDoc(0, (float) (3f * (pivotDistance / (pivotDistance + distance1)))),
          new ScoreDoc(1, (float) (3f * (pivotDistance / (pivotDistance + distance2))))
      },
      topHits.scoreDocs);

  reader.close();
  w.close();
  dir.close();
}
 
示例21
public void testMissingValue() throws IOException {
  Directory dir = newDirectory();
  RandomIndexWriter w = new RandomIndexWriter(random(), dir, newIndexWriterConfig()
      .setMergePolicy(newLogMergePolicy(random().nextBoolean())));
  Document doc = new Document();
  LatLonPoint point = new LatLonPoint("foo", 0, 0);
  doc.add(point);
  LatLonDocValuesField docValue = new LatLonDocValuesField("foo", 0, 0);
  doc.add(docValue);

  point.setLocationValue(3, 3);
  docValue.setLocationValue(3, 3);
  w.addDocument(doc);

  w.addDocument(new Document());

  point.setLocationValue(7, 7);
  docValue.setLocationValue(7, 7);
  w.addDocument(doc);

  DirectoryReader reader = w.getReader();
  IndexSearcher searcher = newSearcher(reader);
  
  Query q = LatLonPoint.newDistanceFeatureQuery("foo", 3, 10, 10, 5);
  TopScoreDocCollector collector = TopScoreDocCollector.create(3, null, 1);
  searcher.search(q, collector);
  TopDocs topHits = collector.topDocs();
  assertEquals(2, topHits.scoreDocs.length);

  double distance1 = SloppyMath.haversinMeters(GeoEncodingUtils.decodeLatitude(GeoEncodingUtils.encodeLatitude(7)) , GeoEncodingUtils.decodeLongitude(GeoEncodingUtils.encodeLongitude(7)), 10,10);
  double distance2 = SloppyMath.haversinMeters(GeoEncodingUtils.decodeLatitude(GeoEncodingUtils.encodeLatitude(3)) , GeoEncodingUtils.decodeLongitude(GeoEncodingUtils.encodeLongitude(3)), 10,10);

  CheckHits.checkEqual(q,
      new ScoreDoc[] {
          new ScoreDoc(2, (float) (3f * (5. / (5. + distance1)))),
          new ScoreDoc(0, (float) (3f * (5. / (5. + distance2))))
      },
      topHits.scoreDocs);

  CheckHits.checkExplanations(q, "", searcher);

  reader.close();
  w.close();
  dir.close();
}
 
示例22
public double compute(double[] a, double[] b) throws DimensionMismatchException {
  return SloppyMath.haversinMeters(a[0], a[1], b[0], b[1]);
}
 
示例23
/** Return the distance (in meters) between 2 lat,lon geo points using the haversine method implemented by lucene */
public static double arcDistance(double lat1, double lon1, double lat2, double lon2) {
    return SloppyMath.haversinMeters(lat1, lon1, lat2, lon2);
}
 
示例24
/**
 * Return the distance (in meters) between 2 lat,lon geo points using a simple tangential plane
 * this provides a faster alternative to {@link GeoUtils#arcDistance} but is inaccurate for distances greater than
 * 4 decimal degrees
 */
public static double planeDistance(double lat1, double lon1, double lat2, double lon2) {
    double x = (lon2 - lon1) * SloppyMath.TO_RADIANS * Math.cos((lat2 + lat1) / 2.0 * SloppyMath.TO_RADIANS);
    double y = (lat2 - lat1) * SloppyMath.TO_RADIANS;
    return Math.sqrt(x * x + y * y) * EARTH_MEAN_RADIUS;
}