use of org.locationtech.spatial4j.shape.Rectangle in project lucene-solr by apache.
the class BBoxValueSource method getValues.
@Override
public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
LeafReader reader = readerContext.reader();
final NumericDocValues minX = DocValues.getNumeric(reader, strategy.field_minX);
final NumericDocValues minY = DocValues.getNumeric(reader, strategy.field_minY);
final NumericDocValues maxX = DocValues.getNumeric(reader, strategy.field_maxX);
final NumericDocValues maxY = DocValues.getNumeric(reader, strategy.field_maxY);
//reused
final Rectangle rect = strategy.getSpatialContext().makeRectangle(0, 0, 0, 0);
return new FunctionValues() {
private int lastDocID = -1;
private double getDocValue(NumericDocValues values, int doc) throws IOException {
int curDocID = values.docID();
if (doc > curDocID) {
curDocID = values.advance(doc);
}
if (doc == curDocID) {
return Double.longBitsToDouble(values.longValue());
} else {
return 0.0;
}
}
@Override
public Object objectVal(int doc) throws IOException {
if (doc < lastDocID) {
throw new AssertionError("docs were sent out-of-order: lastDocID=" + lastDocID + " vs doc=" + doc);
}
lastDocID = doc;
double minXValue = getDocValue(minX, doc);
if (minX.docID() != doc) {
return null;
} else {
double minYValue = getDocValue(minY, doc);
double maxXValue = getDocValue(maxX, doc);
double maxYValue = getDocValue(maxY, doc);
rect.reset(minXValue, maxXValue, minYValue, maxYValue);
return rect;
}
}
@Override
public String strVal(int doc) throws IOException {
//TODO support WKT output once Spatial4j does
Object v = objectVal(doc);
return v == null ? null : v.toString();
}
@Override
public boolean exists(int doc) throws IOException {
getDocValue(minX, doc);
return minX.docID() == doc;
}
@Override
public Explanation explain(int doc) throws IOException {
return Explanation.match(Float.NaN, toString(doc));
}
@Override
public String toString(int doc) throws IOException {
return description() + '=' + strVal(doc);
}
};
}
use of org.locationtech.spatial4j.shape.Rectangle in project lucene-solr by apache.
the class SpatialArgs method calcDistanceFromErrPct.
/**
* Computes the distance given a shape and the {@code distErrPct}. The
* algorithm is the fraction of the distance from the center of the query
* shape to its closest bounding box corner.
*
* @param shape Mandatory.
* @param distErrPct 0 to 0.5
* @param ctx Mandatory
* @return A distance (in degrees).
*/
public static double calcDistanceFromErrPct(Shape shape, double distErrPct, SpatialContext ctx) {
if (distErrPct < 0 || distErrPct > 0.5) {
throw new IllegalArgumentException("distErrPct " + distErrPct + " must be between [0 to 0.5]");
}
if (distErrPct == 0 || shape instanceof Point) {
return 0;
}
Rectangle bbox = shape.getBoundingBox();
//Compute the distance from the center to a corner. Because the distance
// to a bottom corner vs a top corner can vary in a geospatial scenario,
// take the closest one (greater precision).
Point ctr = bbox.getCenter();
double y = (ctr.getY() >= 0 ? bbox.getMaxY() : bbox.getMinY());
double diagonalDist = ctx.getDistCalc().distance(ctr, bbox.getMaxX(), y);
return diagonalDist * distErrPct;
}
use of org.locationtech.spatial4j.shape.Rectangle in project lucene-solr by apache.
the class SpatialDistanceQuery method createSpatialQuery.
@Override
public Query createSpatialQuery(QParser parser, SpatialOptions options) {
Point point = SpatialUtils.parsePointSolrException(options.pointStr, SpatialContext.GEO);
// lat & lon in degrees
double latCenter = point.getY();
double lonCenter = point.getX();
double distDeg = DistanceUtils.dist2Degrees(options.distance, options.radius);
Rectangle bbox = DistanceUtils.calcBoxByDistFromPtDEG(latCenter, lonCenter, distDeg, SpatialContext.GEO, null);
double latMin = bbox.getMinY();
double latMax = bbox.getMaxY();
double lonMin, lonMax, lon2Min, lon2Max;
if (bbox.getCrossesDateLine()) {
lonMin = -180;
lonMax = bbox.getMaxX();
lon2Min = bbox.getMinX();
lon2Max = 180;
} else {
lonMin = bbox.getMinX();
lonMax = bbox.getMaxX();
lon2Min = -180;
lon2Max = 180;
}
IndexSchema schema = parser.getReq().getSchema();
// Now that we've figured out the ranges, build them!
SchemaField latSF = subField(options.field, LAT, schema);
SchemaField lonSF = subField(options.field, LON, schema);
SpatialDistanceQuery spatial = new SpatialDistanceQuery();
if (options.bbox) {
BooleanQuery.Builder result = new BooleanQuery.Builder();
Query latRange = latSF.getType().getRangeQuery(parser, latSF, String.valueOf(latMin), String.valueOf(latMax), true, true);
result.add(latRange, BooleanClause.Occur.MUST);
if (lonMin != -180 || lonMax != 180) {
Query lonRange = lonSF.getType().getRangeQuery(parser, lonSF, String.valueOf(lonMin), String.valueOf(lonMax), true, true);
if (lon2Min != -180 || lon2Max != 180) {
// another valid longitude range
BooleanQuery.Builder bothLons = new BooleanQuery.Builder();
bothLons.add(lonRange, BooleanClause.Occur.SHOULD);
lonRange = lonSF.getType().getRangeQuery(parser, lonSF, String.valueOf(lon2Min), String.valueOf(lon2Max), true, true);
bothLons.add(lonRange, BooleanClause.Occur.SHOULD);
lonRange = bothLons.build();
}
result.add(lonRange, BooleanClause.Occur.MUST);
}
spatial.bboxQuery = result.build();
}
spatial.origField = options.field.getName();
spatial.latSource = latSF.getType().getValueSource(latSF, parser);
spatial.lonSource = lonSF.getType().getValueSource(lonSF, parser);
spatial.latMin = latMin;
spatial.latMax = latMax;
spatial.lonMin = lonMin;
spatial.lonMax = lonMax;
spatial.lon2Min = lon2Min;
spatial.lon2Max = lon2Max;
spatial.lon2 = lon2Min != -180 || lon2Max != 180;
spatial.latCenter = latCenter;
spatial.lonCenter = lonCenter;
spatial.dist = options.distance;
spatial.planetRadius = options.radius;
spatial.calcDist = !options.bbox;
return spatial;
}
use of org.locationtech.spatial4j.shape.Rectangle in project lucene-solr by apache.
the class TestBBoxStrategy method testAlongDatelineOppositeSign.
/** See https://github.com/spatial4j/spatial4j/issues/85 */
@Test
public void testAlongDatelineOppositeSign() throws IOException {
// Due to Spatial4j bug #85, we can't simply do:
// testOperation(indexedShape,
// SpatialOperation.IsWithin,
// queryShape, true);
//both on dateline but expressed using opposite signs
setupGeo();
final Rectangle indexedShape = ctx.makeRectangle(180, 180, -10, 10);
final Rectangle queryShape = ctx.makeRectangle(-180, -180, -20, 20);
final SpatialOperation operation = SpatialOperation.IsWithin;
//yes it is within
final boolean match = true;
//the rest is super.testOperation without leading assert:
adoc("0", indexedShape);
commit();
Query query = strategy.makeQuery(new SpatialArgs(operation, queryShape));
SearchResults got = executeQuery(query, 1);
assert got.numFound <= 1 : "unclean test env";
if ((got.numFound == 1) != match)
fail(operation + " I:" + indexedShape + " Q:" + queryShape);
//clean up after ourselves
deleteAll();
}
use of org.locationtech.spatial4j.shape.Rectangle in project lucene-solr by apache.
the class Geo3dShape method getBoundingBox.
@Override
public Rectangle getBoundingBox() {
//volatile read once
Rectangle bbox = this.boundingBox;
if (bbox == null) {
LatLonBounds bounds = new LatLonBounds();
shape.getBounds(bounds);
double leftLon;
double rightLon;
if (bounds.checkNoLongitudeBound()) {
leftLon = -180.0;
rightLon = 180.0;
} else {
leftLon = bounds.getLeftLongitude().doubleValue() * DistanceUtils.RADIANS_TO_DEGREES;
rightLon = bounds.getRightLongitude().doubleValue() * DistanceUtils.RADIANS_TO_DEGREES;
}
double minLat;
if (bounds.checkNoBottomLatitudeBound()) {
minLat = -90.0;
} else {
minLat = bounds.getMinLatitude().doubleValue() * DistanceUtils.RADIANS_TO_DEGREES;
}
double maxLat;
if (bounds.checkNoTopLatitudeBound()) {
maxLat = 90.0;
} else {
maxLat = bounds.getMaxLatitude().doubleValue() * DistanceUtils.RADIANS_TO_DEGREES;
}
bbox = new RectangleImpl(leftLon, rightLon, minLat, maxLat, ctx).getBuffered(ROUNDOFF_ADJUSTMENT, ctx);
this.boundingBox = bbox;
}
return bbox;
}
Aggregations