Search in sources :

Example 6 with Point

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

the class RandomSpatialOpFuzzyPrefixTreeTest method doTest.

@SuppressWarnings("fallthrough")
private void doTest(final SpatialOperation operation) throws IOException {
    //first show that when there's no data, a query will result in no results
    {
        Query query = strategy.makeQuery(new SpatialArgs(operation, randomRectangle()));
        SearchResults searchResults = executeQuery(query, 1);
        assertEquals(0, searchResults.numFound);
    }
    final boolean biasContains = (operation == SpatialOperation.Contains);
    //Main index loop:
    Map<String, Shape> indexedShapes = new LinkedHashMap<>();
    //grid snapped
    Map<String, Shape> indexedShapesGS = new LinkedHashMap<>();
    final int numIndexedShapes = randomIntBetween(1, 6);
    boolean indexedAtLeastOneShapePair = false;
    final boolean pointsOnly = ((PrefixTreeStrategy) strategy).isPointsOnly();
    for (int i = 0; i < numIndexedShapes; i++) {
        String id = "" + i;
        Shape indexedShape;
        int R = random().nextInt(12);
        if (R == 0) {
            //1 in 12
            indexedShape = null;
        } else if (R == 1 || pointsOnly) {
            //1 in 12
            //just one point
            indexedShape = randomPoint();
        } else if (R <= 4) {
            //3 in 12
            //comprised of more than one shape
            indexedShape = randomShapePairRect(biasContains);
            indexedAtLeastOneShapePair = true;
        } else {
            //just one rect
            indexedShape = randomRectangle();
        }
        indexedShapes.put(id, indexedShape);
        indexedShapesGS.put(id, gridSnap(indexedShape));
        adoc(id, indexedShape);
        if (random().nextInt(10) == 0)
            //intermediate commit, produces extra segments
            commit();
    }
    //delete some documents randomly
    Iterator<String> idIter = indexedShapes.keySet().iterator();
    while (idIter.hasNext()) {
        String id = idIter.next();
        if (random().nextInt(10) == 0) {
            deleteDoc(id);
            idIter.remove();
            indexedShapesGS.remove(id);
        }
    }
    commit();
    //Main query loop:
    final int numQueryShapes = atLeast(20);
    for (int i = 0; i < numQueryShapes; i++) {
        int scanLevel = randomInt(grid.getMaxLevels());
        ((RecursivePrefixTreeStrategy) strategy).setPrefixGridScanLevel(scanLevel);
        final Shape queryShape;
        switch(randomInt(10)) {
            case 0:
                queryShape = randomPoint();
                break;
            case 4:
                //choose an existing indexed shape
                if (!indexedShapes.isEmpty()) {
                    Shape tmp = indexedShapes.values().iterator().next();
                    if (tmp instanceof Point || tmp instanceof Rectangle) {
                        //avoids null and shapePair
                        queryShape = tmp;
                        break;
                    }
                }
            default:
                queryShape = randomRectangle();
        }
        final Shape queryShapeGS = gridSnap(queryShape);
        final boolean opIsDisjoint = operation == SpatialOperation.IsDisjointTo;
        //Generate truth via brute force:
        // We ensure true-positive matches (if the predicate on the raw shapes match
        //  then the search should find those same matches).
        // approximations, false-positive matches
        //true-positives
        Set<String> expectedIds = new LinkedHashSet<>();
        //false-positives (unless disjoint)
        Set<String> secondaryIds = new LinkedHashSet<>();
        for (Map.Entry<String, Shape> entry : indexedShapes.entrySet()) {
            String id = entry.getKey();
            Shape indexedShapeCompare = entry.getValue();
            if (indexedShapeCompare == null)
                continue;
            Shape queryShapeCompare = queryShape;
            if (operation.evaluate(indexedShapeCompare, queryShapeCompare)) {
                expectedIds.add(id);
                if (opIsDisjoint) {
                    //if no longer intersect after buffering them, for disjoint, remember this
                    indexedShapeCompare = indexedShapesGS.get(id);
                    queryShapeCompare = queryShapeGS;
                    if (!operation.evaluate(indexedShapeCompare, queryShapeCompare))
                        secondaryIds.add(id);
                }
            } else if (!opIsDisjoint) {
                //buffer either the indexed or query shape (via gridSnap) and try again
                if (operation == SpatialOperation.Intersects) {
                    indexedShapeCompare = indexedShapesGS.get(id);
                    queryShapeCompare = queryShapeGS;
                //TODO Unfortunately, grid-snapping both can result in intersections that otherwise
                // wouldn't happen when the grids are adjacent. Not a big deal but our test is just a
                // bit more lenient.
                } else if (operation == SpatialOperation.Contains) {
                    indexedShapeCompare = indexedShapesGS.get(id);
                } else if (operation == SpatialOperation.IsWithin) {
                    queryShapeCompare = queryShapeGS;
                }
                if (operation.evaluate(indexedShapeCompare, queryShapeCompare))
                    secondaryIds.add(id);
            }
        }
        //Search and verify results
        SpatialArgs args = new SpatialArgs(operation, queryShape);
        if (queryShape instanceof ShapePair)
            //a hack; we want to be more detailed than gridSnap(queryShape)
            args.setDistErrPct(0.0);
        Query query = strategy.makeQuery(args);
        SearchResults got = executeQuery(query, 100);
        Set<String> remainingExpectedIds = new LinkedHashSet<>(expectedIds);
        for (SearchResult result : got.results) {
            String id = result.getId();
            boolean removed = remainingExpectedIds.remove(id);
            if (!removed && (!opIsDisjoint && !secondaryIds.contains(id))) {
                fail("Shouldn't match", id, indexedShapes, indexedShapesGS, queryShape);
            }
        }
        if (opIsDisjoint)
            remainingExpectedIds.removeAll(secondaryIds);
        if (!remainingExpectedIds.isEmpty()) {
            String id = remainingExpectedIds.iterator().next();
            fail("Should have matched", id, indexedShapes, indexedShapesGS, queryShape);
        }
    }
}
Also used : LinkedHashSet(java.util.LinkedHashSet) SpatialArgs(org.apache.lucene.spatial.query.SpatialArgs) Shape(org.locationtech.spatial4j.shape.Shape) Query(org.apache.lucene.search.Query) Rectangle(org.locationtech.spatial4j.shape.Rectangle) Point(org.locationtech.spatial4j.shape.Point) Point(org.locationtech.spatial4j.shape.Point) LinkedHashMap(java.util.LinkedHashMap) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map)

Example 7 with Point

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

the class HeatmapFacetCounterTest method testQueryCircle.

@Test
public void testQueryCircle() throws IOException {
    //overwrite setUp; non-geo bounds is more straight-forward; otherwise 88,88 would actually be practically north,
    final SpatialContextFactory spatialContextFactory = new SpatialContextFactory();
    spatialContextFactory.geo = false;
    spatialContextFactory.worldBounds = new RectangleImpl(-90, 90, -90, 90, null);
    ctx = spatialContextFactory.newSpatialContext();
    final int LEVEL = 4;
    grid = new QuadPrefixTree(ctx, LEVEL);
    strategy = new RecursivePrefixTreeStrategy(grid, getTestClass().getSimpleName());
    Circle circle = ctx.makeCircle(0, 0, 89);
    //top-right, inside bbox of circle but not the circle
    adoc("0", ctx.makePoint(88, 88));
    //clearly inside; dead center in fact
    adoc("1", ctx.makePoint(0, 0));
    commit();
    final HeatmapFacetCounter.Heatmap heatmap = HeatmapFacetCounter.calcFacets((PrefixTreeStrategy) strategy, indexSearcher.getTopReaderContext(), null, circle, LEVEL, 1000);
    //assert that only one point is found, not 2
    boolean foundOne = false;
    for (int count : heatmap.counts) {
        switch(count) {
            case 0:
                break;
            case 1:
                //this is the first
                assertFalse(foundOne);
                foundOne = true;
                break;
            default:
                fail("counts should be 0 or 1: " + count);
        }
    }
    assertTrue(foundOne);
}
Also used : Circle(org.locationtech.spatial4j.shape.Circle) SpatialContextFactory(org.locationtech.spatial4j.context.SpatialContextFactory) QuadPrefixTree(org.apache.lucene.spatial.prefix.tree.QuadPrefixTree) RectangleImpl(org.locationtech.spatial4j.shape.impl.RectangleImpl) Point(org.locationtech.spatial4j.shape.Point) Test(org.junit.Test)

Example 8 with Point

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

the class HeatmapFacetCounterTest method validateHeatmapResult.

private void validateHeatmapResult(Rectangle inputRange, int facetLevel, HeatmapFacetCounter.Heatmap heatmap) throws IOException {
    final Rectangle heatRect = heatmap.region;
    assertTrue(heatRect.relate(inputRange) == SpatialRelation.CONTAINS || heatRect.equals(inputRange));
    final double cellWidth = heatRect.getWidth() / heatmap.columns;
    final double cellHeight = heatRect.getHeight() / heatmap.rows;
    for (int c = 0; c < heatmap.columns; c++) {
        for (int r = 0; r < heatmap.rows; r++) {
            final int facetCount = heatmap.getCount(c, r);
            double x = DistanceUtils.normLonDEG(heatRect.getMinX() + c * cellWidth + cellWidth / 2);
            double y = DistanceUtils.normLatDEG(heatRect.getMinY() + r * cellHeight + cellHeight / 2);
            Point pt = ctx.makePoint(x, y);
            assertEquals(countMatchingDocsAtLevel(pt, facetLevel), facetCount);
        }
    }
}
Also used : Rectangle(org.locationtech.spatial4j.shape.Rectangle) Point(org.locationtech.spatial4j.shape.Point) Point(org.locationtech.spatial4j.shape.Point)

Example 9 with Point

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

the class JtsPolygonTest method testBadPrefixTreePrune.

/**
   * A PrefixTree pruning optimization gone bad.
   * See <a href="https://issues.apache.org/jira/browse/LUCENE-4770">LUCENE-4770</a>.
   */
@Test
public void testBadPrefixTreePrune() throws Exception {
    Shape area = ctx.readShapeFromWkt("POLYGON((-122.83 48.57, -122.77 48.56, -122.79 48.53, -122.83 48.57))");
    SpatialPrefixTree trie = new QuadPrefixTree(ctx, 12);
    TermQueryPrefixTreeStrategy strategy = new TermQueryPrefixTreeStrategy(trie, "geo");
    Document doc = new Document();
    doc.add(new TextField("id", "1", Store.YES));
    Field[] fields = strategy.createIndexableFields(area, 0.025);
    for (Field field : fields) {
        doc.add(field);
    }
    addDocument(doc);
    Point upperleft = ctx.makePoint(-122.88, 48.54);
    Point lowerright = ctx.makePoint(-122.82, 48.62);
    Query query = strategy.makeQuery(new SpatialArgs(SpatialOperation.Intersects, ctx.makeRectangle(upperleft, lowerright)));
    commit();
    TopDocs search = indexSearcher.search(query, 10);
    ScoreDoc[] scoreDocs = search.scoreDocs;
    for (ScoreDoc scoreDoc : scoreDocs) {
        System.out.println(indexSearcher.doc(scoreDoc.doc));
    }
    assertEquals(1, search.totalHits);
}
Also used : SpatialArgs(org.apache.lucene.spatial.query.SpatialArgs) Shape(org.locationtech.spatial4j.shape.Shape) Query(org.apache.lucene.search.Query) SpatialPrefixTree(org.apache.lucene.spatial.prefix.tree.SpatialPrefixTree) Point(org.locationtech.spatial4j.shape.Point) Document(org.apache.lucene.document.Document) ScoreDoc(org.apache.lucene.search.ScoreDoc) TopDocs(org.apache.lucene.search.TopDocs) Field(org.apache.lucene.document.Field) TextField(org.apache.lucene.document.TextField) QuadPrefixTree(org.apache.lucene.spatial.prefix.tree.QuadPrefixTree) TextField(org.apache.lucene.document.TextField) Test(org.junit.Test)

Example 10 with Point

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

the class SpatialPrefixTreeTest method testBadPrefixTreePrune.

/**
   * A PrefixTree pruning optimization gone bad, applicable when optimize=true.
   * See <a href="https://issues.apache.org/jira/browse/LUCENE-4770">LUCENE-4770</a>.
   */
@Test
public void testBadPrefixTreePrune() throws Exception {
    trie = new QuadPrefixTree(ctx, 12);
    TermQueryPrefixTreeStrategy strategy = new TermQueryPrefixTreeStrategy(trie, "geo");
    Document doc = new Document();
    doc.add(new TextField("id", "1", Store.YES));
    Shape area = ctx.makeRectangle(-122.82, -122.78, 48.54, 48.56);
    Field[] fields = strategy.createIndexableFields(area, 0.025);
    for (Field field : fields) {
        doc.add(field);
    }
    addDocument(doc);
    Point upperleft = ctx.makePoint(-122.88, 48.54);
    Point lowerright = ctx.makePoint(-122.82, 48.62);
    Query query = strategy.makeQuery(new SpatialArgs(SpatialOperation.Intersects, ctx.makeRectangle(upperleft, lowerright)));
    commit();
    TopDocs search = indexSearcher.search(query, 10);
    ScoreDoc[] scoreDocs = search.scoreDocs;
    for (ScoreDoc scoreDoc : scoreDocs) {
        System.out.println(indexSearcher.doc(scoreDoc.doc));
    }
    assertEquals(1, search.totalHits);
}
Also used : SpatialArgs(org.apache.lucene.spatial.query.SpatialArgs) Shape(org.locationtech.spatial4j.shape.Shape) Query(org.apache.lucene.search.Query) Point(org.locationtech.spatial4j.shape.Point) Document(org.apache.lucene.document.Document) ScoreDoc(org.apache.lucene.search.ScoreDoc) TopDocs(org.apache.lucene.search.TopDocs) Field(org.apache.lucene.document.Field) TextField(org.apache.lucene.document.TextField) TextField(org.apache.lucene.document.TextField) TermQueryPrefixTreeStrategy(org.apache.lucene.spatial.prefix.TermQueryPrefixTreeStrategy) Test(org.junit.Test)

Aggregations

Point (org.locationtech.spatial4j.shape.Point)71 Test (org.junit.Test)21 Shape (org.locationtech.spatial4j.shape.Shape)15 Query (org.apache.lucene.search.Query)9 SpatialArgs (org.apache.lucene.spatial.query.SpatialArgs)9 Rectangle (org.locationtech.spatial4j.shape.Rectangle)9 ArrayList (java.util.ArrayList)7 Field (org.apache.lucene.document.Field)6 PointImpl (org.locationtech.spatial4j.shape.impl.PointImpl)6 BooleanQuery (org.apache.lucene.search.BooleanQuery)5 TopDocs (org.apache.lucene.search.TopDocs)5 IOException (java.io.IOException)4 SpatialContext (org.locationtech.spatial4j.context.SpatialContext)4 Document (org.apache.lucene.document.Document)3 StoredField (org.apache.lucene.document.StoredField)3 IndexReader (org.apache.lucene.index.IndexReader)3 IndexSearcher (org.apache.lucene.search.IndexSearcher)3 ScoreDoc (org.apache.lucene.search.ScoreDoc)3 Cell (org.apache.lucene.spatial.prefix.tree.Cell)3 CellIterator (org.apache.lucene.spatial.prefix.tree.CellIterator)3