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);
}
}
}
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);
}
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);
}
}
}
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);
}
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);
}
Aggregations