blob: 80bda53ac0c91ff1b57e3dda405563600ee7f929 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.lucene.spatial.composite;
import java.io.IOException;
import org.apache.lucene.spatial.prefix.RandomSpatialOpStrategyTestCase;
import org.apache.lucene.spatial.prefix.RecursivePrefixTreeStrategy;
import org.apache.lucene.spatial.prefix.tree.GeohashPrefixTree;
import org.apache.lucene.spatial.prefix.tree.QuadPrefixTree;
import org.apache.lucene.spatial.prefix.tree.SpatialPrefixTree;
import org.apache.lucene.spatial.query.SpatialOperation;
import org.apache.lucene.spatial.serialized.SerializedDVStrategy;
import org.junit.Test;
import org.locationtech.spatial4j.context.SpatialContext;
import org.locationtech.spatial4j.context.SpatialContextFactory;
import org.locationtech.spatial4j.shape.Point;
import org.locationtech.spatial4j.shape.Rectangle;
import org.locationtech.spatial4j.shape.Shape;
import org.locationtech.spatial4j.shape.impl.RectangleImpl;
import static com.carrotsearch.randomizedtesting.RandomizedTest.randomBoolean;
import static com.carrotsearch.randomizedtesting.RandomizedTest.randomDouble;
import static com.carrotsearch.randomizedtesting.RandomizedTest.randomIntBetween;
public class CompositeStrategyTest extends RandomSpatialOpStrategyTestCase {
private SpatialPrefixTree grid;
private RecursivePrefixTreeStrategy rptStrategy;
private void setupQuadGrid(int maxLevels) {
//non-geospatial makes this test a little easier (in gridSnap), and using boundary values 2^X raises
// the prospect of edge conditions we want to test, plus makes for simpler numbers (no decimals).
SpatialContextFactory factory = new SpatialContextFactory();
factory.geo = false;
factory.worldBounds = new RectangleImpl(0, 256, -128, 128, null);
this.ctx = factory.newSpatialContext();
//A fairly shallow grid
if (maxLevels == -1)
maxLevels = randomIntBetween(1, 8);//max 64k cells (4^8), also 256*256
this.grid = new QuadPrefixTree(ctx, maxLevels);
this.rptStrategy = newRPT();
}
private void setupGeohashGrid(int maxLevels) {
this.ctx = SpatialContext.GEO;
//A fairly shallow grid
if (maxLevels == -1)
maxLevels = randomIntBetween(1, 3);//max 16k cells (32^3)
this.grid = new GeohashPrefixTree(ctx, maxLevels);
this.rptStrategy = newRPT();
}
protected RecursivePrefixTreeStrategy newRPT() {
final RecursivePrefixTreeStrategy rpt = new RecursivePrefixTreeStrategy(this.grid,
getClass().getSimpleName() + "_rpt");
rpt.setDistErrPct(0.10);//not too many cells
return rpt;
}
@Test
public void testOperations() throws IOException {
//setup
if (randomBoolean()) {
setupQuadGrid(-1);
} else {
setupGeohashGrid(-1);
}
SerializedDVStrategy serializedDVStrategy = new SerializedDVStrategy(ctx, getClass().getSimpleName() + "_sdv");
this.strategy = new CompositeSpatialStrategy("composite_" + getClass().getSimpleName(),
rptStrategy, serializedDVStrategy);
//Do it!
for (SpatialOperation pred : SpatialOperation.values()) {
if (pred == SpatialOperation.BBoxIntersects || pred == SpatialOperation.BBoxWithin) {
continue;
}
if (pred == SpatialOperation.IsDisjointTo) {//TODO
continue;
}
testOperationRandomShapes(pred);
deleteAll();
commit();
}
}
@Override
protected Shape randomIndexedShape() {
return randomShape();
}
@Override
protected Shape randomQueryShape() {
return randomShape();
}
private Shape randomShape() {
return random().nextBoolean() ? randomCircle() : randomRectangle();
}
//TODO move up
private Shape randomCircle() {
final Point point = randomPoint();
//TODO pick using gaussian
double radius;
if (ctx.isGeo()) {
radius = randomDouble() * 100;
} else {
//find distance to closest edge
final Rectangle worldBounds = ctx.getWorldBounds();
double maxRad = point.getX() - worldBounds.getMinX();
maxRad = Math.min(maxRad, worldBounds.getMaxX() - point.getX());
maxRad = Math.min(maxRad, point.getY() - worldBounds.getMinY());
maxRad = Math.min(maxRad, worldBounds.getMaxY() - point.getY());
radius = randomDouble() * maxRad;
}
return ctx.makeCircle(point, radius);
}
}