/** Returns the bounding box over an array of polygons */ public static Rectangle fromPolygon(Polygon[] polygons) { // compute bounding box double minLat = Double.POSITIVE_INFINITY; double maxLat = Double.NEGATIVE_INFINITY; double minLon = Double.POSITIVE_INFINITY; double maxLon = Double.NEGATIVE_INFINITY; for (int i = 0;i < polygons.length; i++) { minLat = Math.min(polygons[i].minLat, minLat); maxLat = Math.max(polygons[i].maxLat, maxLat); minLon = Math.min(polygons[i].minLon, minLon); maxLon = Math.max(polygons[i].maxLon, maxLon); } return new Rectangle(minLat, maxLat, minLon, maxLon); }
final int maxLon = encodeLongitude(boundingBox.maxLon); if (maxLat < minLat || (boundingBox.crossesDateline() == false && maxLon < minLon)) { if (boundingBox.crossesDateline()) { maxLon2 += 1L << 32; // wrap final int boxMaxLon = boxMinLon + (1 << lonShift) - 1; relations[i * maxLonDelta + j] = (byte) boxToRelation.apply(new Rectangle( decodeLatitude(boxMinLat), decodeLatitude(boxMaxLat), decodeLongitude(boxMinLon), decodeLongitude(boxMaxLon))).ordinal();
(cx > maxLon && dx > maxLon); if (Rectangle.containsPoint(cy, cx, minLat, maxLat, minLon, maxLon) || Rectangle.containsPoint(dy, dx, minLat, maxLat, minLon, maxLon)) { return true;
/** Create a predicate that checks whether points are within a distance of a given point. * It works by computing the bounding box around the circle that is defined * by the given points/distance and splitting it into between 1024 and 4096 * smaller boxes (4096*0.75^2=2304 on average). Then for each sub box, it * computes the relation between this box and the distance query. Finally at * search time, it first computes the sub box that the point belongs to, * most of the time, no distance computation will need to be performed since * all points from the sub box will either be in or out of the circle. * @lucene.internal */ public static DistancePredicate createDistancePredicate(double lat, double lon, double radiusMeters) { final Rectangle boundingBox = Rectangle.fromPointDistance(lat, lon, radiusMeters); final double axisLat = Rectangle.axisLat(lat, radiusMeters); final double distanceSortKey = GeoUtils.distanceQuerySortKey(radiusMeters); final Function<Rectangle, Relation> boxToRelation = box -> GeoUtils.relate( box.minLat, box.maxLat, box.minLon, box.maxLon, lat, lon, distanceSortKey, axisLat); final Grid subBoxes = createSubBoxes(boundingBox, boxToRelation); return new DistancePredicate( subBoxes.latShift, subBoxes.lonShift, subBoxes.latBase, subBoxes.lonBase, subBoxes.maxLatDelta, subBoxes.maxLonDelta, subBoxes.relations, lat, lon, distanceSortKey); }
@Override public void setBottom(int slot) { bottom = values[slot]; // make bounding box(es) to exclude non-competitive hits, but start // sampling if we get called way too much: don't make gobs of bounding // boxes if comparator hits a worst case order (e.g. backwards distance order) if (setBottomCounter < 1024 || (setBottomCounter & 0x3F) == 0x3F) { Rectangle box = Rectangle.fromPointDistance(latitude, longitude, haversin2(bottom)); // pre-encode our box to our integer encoding, so we don't have to decode // to double values for uncompetitive hits. This has some cost! minLat = encodeLatitude(box.minLat); maxLat = encodeLatitude(box.maxLat); if (box.crossesDateline()) { // box1 minLon = Integer.MIN_VALUE; maxLon = encodeLongitude(box.maxLon); // box2 minLon2 = encodeLongitude(box.minLon); } else { minLon = encodeLongitude(box.minLon); maxLon = encodeLongitude(box.maxLon); // disable box2 minLon2 = Integer.MAX_VALUE; } } setBottomCounter++; }
@Override public Weight createWeight(IndexSearcher searcher, boolean needsScores, float boost) throws IOException { Rectangle box = Rectangle.fromPointDistance(latitude, longitude, radiusMeters); if (box.crossesDateline()) { final double axisLat = Rectangle.axisLat(latitude, radiusMeters);
/** check if point is within a rectangle * todo: move this to lucene Rectangle class */ public static boolean rectangleContainsPoint(Rectangle r, double lat, double lon) { if (lat >= r.minLat && lat <= r.maxLat) { // if rectangle crosses the dateline we only check if the lon is >= min or max return r.crossesDateline() ? lon >= r.minLon || lon <= r.maxLon : lon >= r.minLon && lon <= r.maxLon; } return false; }
bbox = Rectangle.fromPointDistance(lat, lon, inclusiveUpperPoint); if ("memory".equals(optimizeBbox)) { boundingBoxFilter = null;
/** Create a predicate that checks whether points are within a polygon. * It works the same way as {@link #createDistancePredicate}. * @lucene.internal */ public static PolygonPredicate createPolygonPredicate(Polygon[] polygons, Polygon2D tree) { final Rectangle boundingBox = Rectangle.fromPolygon(polygons); final Function<Rectangle, Relation> boxToRelation = box -> tree.relate( box.minLat, box.maxLat, box.minLon, box.maxLon); final Grid subBoxes = createSubBoxes(boundingBox, boxToRelation); return new PolygonPredicate( subBoxes.latShift, subBoxes.lonShift, subBoxes.latBase, subBoxes.lonBase, subBoxes.maxLatDelta, subBoxes.maxLonDelta, subBoxes.relations, tree); }
private void maybeUpdateBBox() { if (setBottomCounter < 1024 || (setBottomCounter & 0x3F) == 0x3F) { NearestHit hit = hitQueue.peek(); Rectangle box = Rectangle.fromPointDistance(pointLat, pointLon, hit.distanceMeters); //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++; }
@Override public Weight createWeight(IndexSearcher searcher, boolean needsScores, float boost) throws IOException { Rectangle box = Rectangle.fromPointDistance(latitude, longitude, radiusMeters); if (box.crossesDateline()) { final double axisLat = Rectangle.axisLat(latitude, radiusMeters);
/** check if point is within a rectangle * todo: move this to lucene Rectangle class */ public static boolean rectangleContainsPoint(Rectangle r, double lat, double lon) { if (lat >= r.minLat && lat <= r.maxLat) { // if rectangle crosses the dateline we only check if the lon is >= min or max return r.crossesDateline() ? lon >= r.minLon || lon <= r.maxLon : lon >= r.minLon && lon <= r.maxLon; } return false; }
/** Create a predicate that checks whether points are within a distance of a given point. * It works by computing the bounding box around the circle that is defined * by the given points/distance and splitting it into between 1024 and 4096 * smaller boxes (4096*0.75^2=2304 on average). Then for each sub box, it * computes the relation between this box and the distance query. Finally at * search time, it first computes the sub box that the point belongs to, * most of the time, no distance computation will need to be performed since * all points from the sub box will either be in or out of the circle. * @lucene.internal */ public static DistancePredicate createDistancePredicate(double lat, double lon, double radiusMeters) { final Rectangle boundingBox = Rectangle.fromPointDistance(lat, lon, radiusMeters); final double axisLat = Rectangle.axisLat(lat, radiusMeters); final double distanceSortKey = GeoUtils.distanceQuerySortKey(radiusMeters); final Function<Rectangle, Relation> boxToRelation = box -> GeoUtils.relate( box.minLat, box.maxLat, box.minLon, box.maxLon, lat, lon, distanceSortKey, axisLat); final Grid subBoxes = createSubBoxes(boundingBox, boxToRelation); return new DistancePredicate( subBoxes.latShift, subBoxes.lonShift, subBoxes.latBase, subBoxes.lonBase, subBoxes.maxLatDelta, subBoxes.maxLonDelta, subBoxes.relations, lat, lon, distanceSortKey); }
final Rectangle box = Rectangle.fromPolygon(polygons); final byte minLat[] = new byte[Integer.BYTES]; final byte maxLat[] = new byte[Integer.BYTES];
return new Rectangle(toDegrees(minLat), toDegrees(maxLat), toDegrees(minLon), toDegrees(maxLon));
final int maxLon = encodeLongitude(boundingBox.maxLon); if (maxLat < minLat || (boundingBox.crossesDateline() == false && maxLon < minLon)) { if (boundingBox.crossesDateline()) { maxLon2 += 1L << 32; // wrap final int boxMaxLon = boxMinLon + (1 << lonShift) - 1; relations[i * maxLonDelta + j] = (byte) boxToRelation.apply(new Rectangle( decodeLatitude(boxMinLat), decodeLatitude(boxMaxLat), decodeLongitude(boxMinLon), decodeLongitude(boxMaxLon))).ordinal();
@Override public void setBottom(int slot) { bottom = values[slot]; // make bounding box(es) to exclude non-competitive hits, but start // sampling if we get called way too much: don't make gobs of bounding // boxes if comparator hits a worst case order (e.g. backwards distance order) if (setBottomCounter < 1024 || (setBottomCounter & 0x3F) == 0x3F) { Rectangle box = Rectangle.fromPointDistance(latitude, longitude, haversin2(bottom)); // pre-encode our box to our integer encoding, so we don't have to decode // to double values for uncompetitive hits. This has some cost! minLat = encodeLatitude(box.minLat); maxLat = encodeLatitude(box.maxLat); if (box.crossesDateline()) { // box1 minLon = Integer.MIN_VALUE; maxLon = encodeLongitude(box.maxLon); // box2 minLon2 = encodeLongitude(box.minLon); } else { minLon = encodeLongitude(box.minLon); maxLon = encodeLongitude(box.maxLon); // disable box2 minLon2 = Integer.MAX_VALUE; } } setBottomCounter++; }
/** check if point is within a rectangle * todo: move this to lucene Rectangle class */ public static boolean rectangleContainsPoint(Rectangle r, double lat, double lon) { if (lat >= r.minLat && lat <= r.maxLat) { // if rectangle crosses the dateline we only check if the lon is >= min or max return r.crossesDateline() ? lon >= r.minLon || lon <= r.maxLon : lon >= r.minLon && lon <= r.maxLon; } return false; }
return Rectangle.containsPoint(ay, ax, minY, maxY, minX, maxX);
/** Create a predicate that checks whether points are within a polygon. * It works the same way as {@link #createDistancePredicate}. * @lucene.internal */ public static PolygonPredicate createPolygonPredicate(Polygon[] polygons, Polygon2D tree) { final Rectangle boundingBox = Rectangle.fromPolygon(polygons); final Function<Rectangle, Relation> boxToRelation = box -> tree.relate( box.minLat, box.maxLat, box.minLon, box.maxLon); final Grid subBoxes = createSubBoxes(boundingBox, boxToRelation); return new PolygonPredicate( subBoxes.latShift, subBoxes.lonShift, subBoxes.latBase, subBoxes.lonBase, subBoxes.maxLatDelta, subBoxes.maxLonDelta, subBoxes.relations, tree); }