Search in sources :

Example 26 with Rectangle

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);
        }
    };
}
Also used : NumericDocValues(org.apache.lucene.index.NumericDocValues) LeafReader(org.apache.lucene.index.LeafReader) Rectangle(org.locationtech.spatial4j.shape.Rectangle) FunctionValues(org.apache.lucene.queries.function.FunctionValues)

Example 27 with Rectangle

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;
}
Also used : Rectangle(org.locationtech.spatial4j.shape.Rectangle) Point(org.locationtech.spatial4j.shape.Point)

Example 28 with Rectangle

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;
}
Also used : BooleanQuery(org.apache.lucene.search.BooleanQuery) Query(org.apache.lucene.search.Query) BooleanQuery(org.apache.lucene.search.BooleanQuery) Rectangle(org.locationtech.spatial4j.shape.Rectangle) Point(org.locationtech.spatial4j.shape.Point)

Example 29 with Rectangle

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();
}
Also used : SpatialArgs(org.apache.lucene.spatial.query.SpatialArgs) Query(org.apache.lucene.search.Query) Rectangle(org.locationtech.spatial4j.shape.Rectangle) SpatialOperation(org.apache.lucene.spatial.query.SpatialOperation) Test(org.junit.Test)

Example 30 with Rectangle

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;
}
Also used : Rectangle(org.locationtech.spatial4j.shape.Rectangle) RectangleImpl(org.locationtech.spatial4j.shape.impl.RectangleImpl) LatLonBounds(org.apache.lucene.spatial3d.geom.LatLonBounds)

Aggregations

Rectangle (org.locationtech.spatial4j.shape.Rectangle)36 Point (org.locationtech.spatial4j.shape.Point)10 Test (org.junit.Test)8 Shape (org.locationtech.spatial4j.shape.Shape)7 ArrayList (java.util.ArrayList)5 Query (org.apache.lucene.search.Query)5 Coordinate (com.vividsolutions.jts.geom.Coordinate)3 FunctionValues (org.apache.lucene.queries.function.FunctionValues)3 BooleanQuery (org.apache.lucene.search.BooleanQuery)3 SpatialArgs (org.apache.lucene.spatial.query.SpatialArgs)3 SpatialOperation (org.apache.lucene.spatial.query.SpatialOperation)3 GeoShape (org.apache.lucene.spatial3d.geom.GeoShape)3 SpatialContext (org.locationtech.spatial4j.context.SpatialContext)3 Map (java.util.Map)2 LeafReader (org.apache.lucene.index.LeafReader)2 NumericDocValues (org.apache.lucene.index.NumericDocValues)2 ConstantScoreQuery (org.apache.lucene.search.ConstantScoreQuery)2 TermQuery (org.apache.lucene.search.TermQuery)2 UnsupportedSpatialOperation (org.apache.lucene.spatial.query.UnsupportedSpatialOperation)2 GeoPoint (org.apache.lucene.spatial3d.geom.GeoPoint)2