Search in sources :

Example 6 with SpatialContext

use of org.locationtech.spatial4j.context.SpatialContext in project elasticsearch by elastic.

the class GeoUtilsTests method testPrefixTreeCellSizes.

public void testPrefixTreeCellSizes() {
    assertThat(GeoUtils.EARTH_SEMI_MAJOR_AXIS, equalTo(DistanceUtils.EARTH_EQUATORIAL_RADIUS_KM * 1000));
    assertThat(GeoUtils.quadTreeCellWidth(0), lessThanOrEqualTo(GeoUtils.EARTH_EQUATOR));
    SpatialContext spatialContext = new SpatialContext(true);
    GeohashPrefixTree geohashPrefixTree = new GeohashPrefixTree(spatialContext, GeohashPrefixTree.getMaxLevelsPossible() / 2);
    Cell gNode = geohashPrefixTree.getWorldCell();
    for (int i = 0; i < geohashPrefixTree.getMaxLevels(); i++) {
        double width = GeoUtils.geoHashCellWidth(i);
        double height = GeoUtils.geoHashCellHeight(i);
        double size = GeoUtils.geoHashCellSize(i);
        double degrees = 360.0 * width / GeoUtils.EARTH_EQUATOR;
        int level = GeoUtils.quadTreeLevelsForPrecision(size);
        assertThat(GeoUtils.quadTreeCellWidth(level), lessThanOrEqualTo(width));
        assertThat(GeoUtils.quadTreeCellHeight(level), lessThanOrEqualTo(height));
        assertThat(GeoUtils.geoHashLevelsForPrecision(size), equalTo(geohashPrefixTree.getLevelForDistance(degrees)));
        assertThat("width at level " + i, gNode.getShape().getBoundingBox().getWidth(), equalTo(360.d * width / GeoUtils.EARTH_EQUATOR));
        assertThat("height at level " + i, gNode.getShape().getBoundingBox().getHeight(), equalTo(180.d * height / GeoUtils.EARTH_POLAR_DISTANCE));
        gNode = gNode.getNextLevelCells(null).next();
    }
    QuadPrefixTree quadPrefixTree = new QuadPrefixTree(spatialContext);
    Cell qNode = quadPrefixTree.getWorldCell();
    for (int i = 0; i < quadPrefixTree.getMaxLevels(); i++) {
        double degrees = 360.0 / (1L << i);
        double width = GeoUtils.quadTreeCellWidth(i);
        double height = GeoUtils.quadTreeCellHeight(i);
        double size = GeoUtils.quadTreeCellSize(i);
        int level = GeoUtils.quadTreeLevelsForPrecision(size);
        assertThat(GeoUtils.quadTreeCellWidth(level), lessThanOrEqualTo(width));
        assertThat(GeoUtils.quadTreeCellHeight(level), lessThanOrEqualTo(height));
        assertThat(GeoUtils.quadTreeLevelsForPrecision(size), equalTo(quadPrefixTree.getLevelForDistance(degrees)));
        assertThat("width at level " + i, qNode.getShape().getBoundingBox().getWidth(), equalTo(360.d * width / GeoUtils.EARTH_EQUATOR));
        assertThat("height at level " + i, qNode.getShape().getBoundingBox().getHeight(), equalTo(180.d * height / GeoUtils.EARTH_POLAR_DISTANCE));
        qNode = qNode.getNextLevelCells(null).next();
    }
}
Also used : SpatialContext(org.locationtech.spatial4j.context.SpatialContext) QuadPrefixTree(org.apache.lucene.spatial.prefix.tree.QuadPrefixTree) Cell(org.apache.lucene.spatial.prefix.tree.Cell) GeoPoint(org.elasticsearch.common.geo.GeoPoint) GeohashPrefixTree(org.apache.lucene.spatial.prefix.tree.GeohashPrefixTree)

Example 7 with SpatialContext

use of org.locationtech.spatial4j.context.SpatialContext in project lucene-solr by apache.

the class SpatialArgsTest method calcDistanceFromErrPct.

@Test
public void calcDistanceFromErrPct() {
    final SpatialContext ctx = SpatialContext.GEO;
    //distErrPct
    final double DEP = 0.5;
    //the result is the diagonal distance from the center to the closest corner,
    // times distErrPct
    Shape superwide = ctx.makeRectangle(-180, 180, 0, 0);
    //0 distErrPct means 0 distance always
    assertEquals(0, SpatialArgs.calcDistanceFromErrPct(superwide, 0, ctx), 0);
    assertEquals(180 * DEP, SpatialArgs.calcDistanceFromErrPct(superwide, DEP, ctx), 0);
    Shape supertall = ctx.makeRectangle(0, 0, -90, 90);
    assertEquals(90 * DEP, SpatialArgs.calcDistanceFromErrPct(supertall, DEP, ctx), 0);
    Shape upperhalf = ctx.makeRectangle(-180, 180, 0, 90);
    assertEquals(45 * DEP, SpatialArgs.calcDistanceFromErrPct(upperhalf, DEP, ctx), 0.0001);
    Shape midCircle = ctx.makeCircle(0, 0, 45);
    assertEquals(60 * DEP, SpatialArgs.calcDistanceFromErrPct(midCircle, DEP, ctx), 0.0001);
}
Also used : SpatialContext(org.locationtech.spatial4j.context.SpatialContext) Shape(org.locationtech.spatial4j.shape.Shape) Test(org.junit.Test)

Example 8 with SpatialContext

use of org.locationtech.spatial4j.context.SpatialContext in project lucene-solr by apache.

the class PortedSolr3Test method parameters.

@ParametersFactory(argumentFormatting = "strategy=%s")
public static Iterable<Object[]> parameters() {
    List<Object[]> ctorArgs = new ArrayList<>();
    SpatialContext ctx = SpatialContext.GEO;
    SpatialPrefixTree grid;
    SpatialStrategy strategy;
    grid = new GeohashPrefixTree(ctx, 12);
    strategy = new RecursivePrefixTreeStrategy(grid, "recursive_geohash");
    ctorArgs.add(new Object[] { strategy.getFieldName(), strategy });
    grid = new QuadPrefixTree(ctx, 25);
    strategy = new RecursivePrefixTreeStrategy(grid, "recursive_quad");
    ctorArgs.add(new Object[] { strategy.getFieldName(), strategy });
    grid = new GeohashPrefixTree(ctx, 12);
    strategy = new TermQueryPrefixTreeStrategy(grid, "termquery_geohash");
    ctorArgs.add(new Object[] { strategy.getFieldName(), strategy });
    strategy = PointVectorStrategy.newInstance(ctx, "pointvector");
    ctorArgs.add(new Object[] { strategy.getFieldName(), strategy });
    strategy = PointVectorStrategy.newInstance(ctx, "pointvector_legacy");
    ctorArgs.add(new Object[] { strategy.getFieldName(), strategy });
    return ctorArgs;
}
Also used : SpatialContext(org.locationtech.spatial4j.context.SpatialContext) QuadPrefixTree(org.apache.lucene.spatial.prefix.tree.QuadPrefixTree) ArrayList(java.util.ArrayList) RecursivePrefixTreeStrategy(org.apache.lucene.spatial.prefix.RecursivePrefixTreeStrategy) SpatialPrefixTree(org.apache.lucene.spatial.prefix.tree.SpatialPrefixTree) TermQueryPrefixTreeStrategy(org.apache.lucene.spatial.prefix.TermQueryPrefixTreeStrategy) GeohashPrefixTree(org.apache.lucene.spatial.prefix.tree.GeohashPrefixTree) ParametersFactory(com.carrotsearch.randomizedtesting.annotations.ParametersFactory)

Example 9 with SpatialContext

use of org.locationtech.spatial4j.context.SpatialContext in project lucene-solr by apache.

the class SpatialHeatmapFacets method getHeatmapForField.

/** Called by {@link org.apache.solr.request.SimpleFacets} to compute heatmap facets. */
public static NamedList<Object> getHeatmapForField(String fieldKey, String fieldName, ResponseBuilder rb, SolrParams params, DocSet docSet) throws IOException {
    //get the strategy from the field type
    final SchemaField schemaField = rb.req.getSchema().getField(fieldName);
    final FieldType type = schemaField.getType();
    final PrefixTreeStrategy strategy;
    final DistanceUnits distanceUnits;
    // note: the two instanceof conditions is not ideal, versus one. If we start needing to add more then refactor.
    if ((type instanceof AbstractSpatialPrefixTreeFieldType)) {
        AbstractSpatialPrefixTreeFieldType rptType = (AbstractSpatialPrefixTreeFieldType) type;
        strategy = (PrefixTreeStrategy) rptType.getStrategy(fieldName);
        distanceUnits = rptType.getDistanceUnits();
    } else if (type instanceof RptWithGeometrySpatialField) {
        RptWithGeometrySpatialField rptSdvType = (RptWithGeometrySpatialField) type;
        strategy = rptSdvType.getStrategy(fieldName).getIndexStrategy();
        distanceUnits = rptSdvType.getDistanceUnits();
    } else {
        //FYI we support the term query one too but few people use that one
        throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "heatmap field needs to be of type " + SpatialRecursivePrefixTreeFieldType.class + " or " + RptWithGeometrySpatialField.class);
    }
    final SpatialContext ctx = strategy.getSpatialContext();
    //get the bbox (query Rectangle)
    String geomStr = params.getFieldParam(fieldKey, FacetParams.FACET_HEATMAP_GEOM);
    final Shape boundsShape = geomStr == null ? ctx.getWorldBounds() : SpatialUtils.parseGeomSolrException(geomStr, ctx);
    //get the grid level (possibly indirectly via distErr or distErrPct)
    final int gridLevel;
    Integer gridLevelObj = params.getFieldInt(fieldKey, FacetParams.FACET_HEATMAP_LEVEL);
    final int maxGridLevel = strategy.getGrid().getMaxLevels();
    if (gridLevelObj != null) {
        gridLevel = gridLevelObj;
        if (gridLevel <= 0 || gridLevel > maxGridLevel) {
            throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, FacetParams.FACET_HEATMAP_LEVEL + " should be > 0 and <= " + maxGridLevel);
        }
    } else {
        //SpatialArgs has utility methods to resolve a 'distErr' from optionally set distErr & distErrPct. Arguably that
        // should be refactored to feel less weird than using it like this.
        SpatialArgs spatialArgs = new SpatialArgs(SpatialOperation.Intersects, /*ignored*/
        boundsShape == null ? ctx.getWorldBounds() : boundsShape);
        final Double distErrObj = params.getFieldDouble(fieldKey, FacetParams.FACET_HEATMAP_DIST_ERR);
        if (distErrObj != null) {
            // convert distErr units based on configured units
            spatialArgs.setDistErr(distErrObj * distanceUnits.multiplierFromThisUnitToDegrees());
        }
        spatialArgs.setDistErrPct(params.getFieldDouble(fieldKey, FacetParams.FACET_HEATMAP_DIST_ERR_PCT));
        double distErr = spatialArgs.resolveDistErr(ctx, DEFAULT_DIST_ERR_PCT);
        if (distErr <= 0) {
            throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, FacetParams.FACET_HEATMAP_DIST_ERR_PCT + " or " + FacetParams.FACET_HEATMAP_DIST_ERR + " should be > 0 or instead provide " + FacetParams.FACET_HEATMAP_LEVEL + "=" + maxGridLevel + " if you insist on maximum detail");
        }
        //The SPT (grid) can lookup a grid level satisfying an error distance constraint
        gridLevel = strategy.getGrid().getLevelForDistance(distErr);
    }
    //Compute!
    final HeatmapFacetCounter.Heatmap heatmap;
    try {
        heatmap = HeatmapFacetCounter.calcFacets(strategy, rb.req.getSearcher().getTopReaderContext(), // turn DocSet into Bits
        getTopAcceptDocs(docSet, rb.req.getSearcher()), boundsShape, gridLevel, // will throw if exceeded
        params.getFieldInt(fieldKey, FacetParams.FACET_HEATMAP_MAX_CELLS, 100_000));
    } catch (IllegalArgumentException e) {
        //e.g. too many cells
        throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, e.toString(), e);
    }
    //Populate response
    NamedList<Object> result = new NamedList<>();
    result.add("gridLevel", gridLevel);
    result.add("columns", heatmap.columns);
    result.add("rows", heatmap.rows);
    result.add("minX", heatmap.region.getMinX());
    result.add("maxX", heatmap.region.getMaxX());
    result.add("minY", heatmap.region.getMinY());
    result.add("maxY", heatmap.region.getMaxY());
    boolean hasNonZero = false;
    for (int count : heatmap.counts) {
        if (count > 0) {
            hasNonZero = true;
            break;
        }
    }
    formatCountsAndAddToNL(fieldKey, rb, params, heatmap.columns, heatmap.rows, hasNonZero ? heatmap.counts : null, result);
    return result;
}
Also used : HeatmapFacetCounter(org.apache.lucene.spatial.prefix.HeatmapFacetCounter) SpatialArgs(org.apache.lucene.spatial.query.SpatialArgs) SpatialContext(org.locationtech.spatial4j.context.SpatialContext) Shape(org.locationtech.spatial4j.shape.Shape) NamedList(org.apache.solr.common.util.NamedList) FieldType(org.apache.solr.schema.FieldType) AbstractSpatialPrefixTreeFieldType(org.apache.solr.schema.AbstractSpatialPrefixTreeFieldType) SpatialRecursivePrefixTreeFieldType(org.apache.solr.schema.SpatialRecursivePrefixTreeFieldType) SchemaField(org.apache.solr.schema.SchemaField) RptWithGeometrySpatialField(org.apache.solr.schema.RptWithGeometrySpatialField) DistanceUnits(org.apache.solr.util.DistanceUnits) SolrException(org.apache.solr.common.SolrException) PrefixTreeStrategy(org.apache.lucene.spatial.prefix.PrefixTreeStrategy) AbstractSpatialPrefixTreeFieldType(org.apache.solr.schema.AbstractSpatialPrefixTreeFieldType)

Example 10 with SpatialContext

use of org.locationtech.spatial4j.context.SpatialContext 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)

Aggregations

SpatialContext (org.locationtech.spatial4j.context.SpatialContext)12 QuadPrefixTree (org.apache.lucene.spatial.prefix.tree.QuadPrefixTree)4 Shape (org.locationtech.spatial4j.shape.Shape)4 ArrayList (java.util.ArrayList)3 GeohashPrefixTree (org.apache.lucene.spatial.prefix.tree.GeohashPrefixTree)3 SpatialPrefixTree (org.apache.lucene.spatial.prefix.tree.SpatialPrefixTree)3 Test (org.junit.Test)3 Point (org.locationtech.spatial4j.shape.Point)3 Rectangle (org.locationtech.spatial4j.shape.Rectangle)3 ParametersFactory (com.carrotsearch.randomizedtesting.annotations.ParametersFactory)2 RecursivePrefixTreeStrategy (org.apache.lucene.spatial.prefix.RecursivePrefixTreeStrategy)2 TermQueryPrefixTreeStrategy (org.apache.lucene.spatial.prefix.TermQueryPrefixTreeStrategy)2 Cell (org.apache.lucene.spatial.prefix.tree.Cell)2 SpatialArgsParser (org.apache.lucene.spatial.query.SpatialArgsParser)2 SolrException (org.apache.solr.common.SolrException)2 SchemaField (org.apache.solr.schema.SchemaField)2 InputStream (java.io.InputStream)1 AbstractMap (java.util.AbstractMap)1 HashMap (java.util.HashMap)1 Map (java.util.Map)1