Search in sources :

Example 31 with Rectangle

use of org.locationtech.spatial4j.shape.Rectangle in project lucene-solr by apache.

the class TestSolr4Spatial method checkHits.

private void checkHits(String fieldName, boolean exact, String ptStr, double distKM, double sphereRadius, int count, int... docIds) throws ParseException {
    if (exact && fieldName.equalsIgnoreCase("bbox")) {
        // bbox field only supports rectangular query
        return;
    }
    String[] tests = new String[docIds != null && docIds.length > 0 ? docIds.length + 1 : 1];
    //test for presence of required ids first
    int i = 0;
    if (docIds != null && docIds.length > 0) {
        for (int docId : docIds) {
            tests[i++] = "//result/doc/*[@name='id'][.='" + docId + "']";
        }
    }
    //check total length last; maybe response includes ids it shouldn't.  Nicer to check this last instead of first so
    // that there may be a more specific detailed id to investigate.
    tests[i++] = "*[count(//doc)=" + count + "]";
    //Test using the Lucene spatial syntax
    {
        //never actually need the score but lets test
        String score = randomScoreMode();
        double distDEG = DistanceUtils.dist2Degrees(distKM, DistanceUtils.EARTH_MEAN_RADIUS_KM);
        Point point = SpatialUtils.parsePoint(ptStr, SpatialContext.GEO);
        String circleStr = "BUFFER(POINT(" + point.getX() + " " + point.getY() + ")," + distDEG + ")";
        String shapeStr;
        if (exact) {
            shapeStr = circleStr;
        } else {
            //bbox
            //the GEO is an assumption
            SpatialContext ctx = SpatialContext.GEO;
            Rectangle bbox = ctx.readShapeFromWkt(circleStr).getBoundingBox();
            shapeStr = "ENVELOPE(" + bbox.getMinX() + ", " + bbox.getMaxX() + ", " + bbox.getMaxY() + ", " + bbox.getMinY() + ")";
        }
        //FYI default distErrPct=0.025 works with the tests in this file
        assertQ(req("fl", "id", "q", "*:*", "rows", "1000", "fq", "{!field f=" + fieldName + (score == null ? "" : " score=" + score) + "}Intersects(" + shapeStr + ")"), tests);
    }
    //Test using geofilt
    {
        assertQ(req("fl", "id", "q", "*:*", "rows", "1000", "fq", "{!" + (exact ? "geofilt" : "bbox") + " sfield=" + fieldName + " pt='" + ptStr + "' d=" + distKM + " sphere_radius=" + sphereRadius + "}"), tests);
    }
}
Also used : SpatialContext(org.locationtech.spatial4j.context.SpatialContext) Rectangle(org.locationtech.spatial4j.shape.Rectangle) Point(org.locationtech.spatial4j.shape.Point) Point(org.locationtech.spatial4j.shape.Point)

Example 32 with Rectangle

use of org.locationtech.spatial4j.shape.Rectangle in project lucene-solr by apache.

the class SpatialStrategy method makeRecipDistanceValueSource.

/**
   * Returns a ValueSource with values ranging from 1 to 0, depending inversely
   * on the distance from {@link #makeDistanceValueSource(org.locationtech.spatial4j.shape.Point,double)}.
   * The formula is {@code c/(d + c)} where 'd' is the distance and 'c' is
   * one tenth the distance to the farthest edge from the center. Thus the
   * scores will be 1 for indexed points at the center of the query shape and as
   * low as ~0.1 at its furthest edges.
   */
public final ValueSource makeRecipDistanceValueSource(Shape queryShape) {
    Rectangle bbox = queryShape.getBoundingBox();
    double diagonalDist = ctx.getDistCalc().distance(ctx.makePoint(bbox.getMinX(), bbox.getMinY()), bbox.getMaxX(), bbox.getMaxY());
    double distToEdge = diagonalDist * 0.5;
    //one tenth
    float c = (float) distToEdge * 0.1f;
    return new ReciprocalFloatFunction(makeDistanceValueSource(queryShape.getCenter(), 1.0), 1f, c, c);
}
Also used : Rectangle(org.locationtech.spatial4j.shape.Rectangle) ReciprocalFloatFunction(org.apache.lucene.queries.function.valuesource.ReciprocalFloatFunction)

Example 33 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 34 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 35 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)

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