use of org.apache.lucene.spatial3d.geom.GeoPoint in project lucene-solr by apache.
the class Geo3DUtil method fromPath.
/**
* Convert input parameters to a path.
* @param pathLatitudes latitude values for points of the path: must be within standard +/-90 coordinate bounds.
* @param pathLongitudes longitude values for points of the path: must be within standard +/-180 coordinate bounds.
* @param pathWidthMeters width of the path in meters.
* @return the path.
*/
static GeoPath fromPath(final double[] pathLatitudes, final double[] pathLongitudes, final double pathWidthMeters) {
if (pathLatitudes.length != pathLongitudes.length) {
throw new IllegalArgumentException("same number of latitudes and longitudes required");
}
final GeoPoint[] points = new GeoPoint[pathLatitudes.length];
for (int i = 0; i < pathLatitudes.length; i++) {
final double latitude = pathLatitudes[i];
final double longitude = pathLongitudes[i];
GeoUtils.checkLatitude(latitude);
GeoUtils.checkLongitude(longitude);
points[i] = new GeoPoint(PlanetModel.WGS84, fromDegrees(latitude), fromDegrees(longitude));
}
return GeoPathFactory.makeGeoPath(PlanetModel.WGS84, fromMeters(pathWidthMeters), points);
}
use of org.apache.lucene.spatial3d.geom.GeoPoint in project lucene-solr by apache.
the class TestGeo3DPoint method testComplexPolygons.
public void testComplexPolygons() {
final PlanetModel pm = PlanetModel.WGS84;
// Pick a random pole
final GeoPoint randomPole = new GeoPoint(pm, toRadians(GeoTestUtil.nextLatitude()), toRadians(GeoTestUtil.nextLongitude()));
int iters = atLeast(100);
for (int i = 0; i < iters; i++) {
// Create a polygon that's less than 180 degrees
final Polygon clockWise = makePoly(pm, randomPole, true, true);
}
iters = atLeast(100);
for (int i = 0; i < iters; i++) {
// Create a polygon that's greater than 180 degrees
final Polygon counterClockWise = makePoly(pm, randomPole, false, true);
}
}
use of org.apache.lucene.spatial3d.geom.GeoPoint in project lucene-solr by apache.
the class TestGeo3DPoint method testGeo3DRelations.
/** Tests consistency of GeoArea.getRelationship vs GeoShape.isWithin */
public void testGeo3DRelations() throws Exception {
int numDocs = atLeast(1000);
if (VERBOSE) {
System.out.println("TEST: " + numDocs + " docs");
}
GeoPoint[] docs = new GeoPoint[numDocs];
GeoPoint[] unquantizedDocs = new GeoPoint[numDocs];
for (int docID = 0; docID < numDocs; docID++) {
unquantizedDocs[docID] = new GeoPoint(PlanetModel.WGS84, toRadians(GeoTestUtil.nextLatitude()), toRadians(GeoTestUtil.nextLongitude()));
docs[docID] = quantize(unquantizedDocs[docID]);
if (VERBOSE) {
System.out.println(" doc=" + docID + ": " + docs[docID] + "; unquantized: " + unquantizedDocs[docID]);
}
}
int iters = atLeast(10);
int recurseDepth = RandomNumbers.randomIntBetween(random(), 5, 15);
iters = atLeast(50);
for (int iter = 0; iter < iters; iter++) {
GeoShape shape = randomShape();
StringWriter sw = new StringWriter();
PrintWriter log = new PrintWriter(sw, true);
if (VERBOSE) {
log.println("TEST: iter=" + iter + " shape=" + shape);
}
XYZBounds bounds = new XYZBounds();
shape.getBounds(bounds);
// Start with the root cell that fully contains the shape:
Cell root = new Cell(null, encodeValueLenient(bounds.getMinimumX()), encodeValueLenient(bounds.getMaximumX()), encodeValueLenient(bounds.getMinimumY()), encodeValueLenient(bounds.getMaximumY()), encodeValueLenient(bounds.getMinimumZ()), encodeValueLenient(bounds.getMaximumZ()), 0);
if (VERBOSE) {
log.println(" root cell: " + root);
}
// make sure the root cell (XYZBounds) does in fact contain all points that the shape contains
{
boolean fail = false;
for (int docID = 0; docID < numDocs; docID++) {
if (root.contains(docs[docID]) == false) {
boolean expected = shape.isWithin(unquantizedDocs[docID]);
if (expected) {
log.println(" doc=" + docID + " is contained by shape but is outside the returned XYZBounds");
log.println(" unquantized=" + unquantizedDocs[docID]);
log.println(" quantized=" + docs[docID]);
fail = true;
}
}
}
if (fail) {
log.println(" shape=" + shape);
log.println(" bounds=" + bounds);
System.out.print(sw.toString());
fail("invalid bounds for shape=" + shape);
}
}
List<Cell> queue = new ArrayList<>();
queue.add(root);
Set<Integer> hits = new HashSet<>();
while (queue.size() > 0) {
Cell cell = queue.get(queue.size() - 1);
queue.remove(queue.size() - 1);
if (VERBOSE) {
log.println(" cycle: " + cell + " queue.size()=" + queue.size());
}
if (random().nextInt(10) == 7 || cell.splitCount > recurseDepth) {
if (VERBOSE) {
log.println(" leaf");
}
// Leaf cell: brute force check all docs that fall within this cell:
for (int docID = 0; docID < numDocs; docID++) {
GeoPoint point = docs[docID];
GeoPoint mappedPoint = unquantizedDocs[docID];
boolean pointWithinShape = shape.isWithin(point);
boolean mappedPointWithinShape = shape.isWithin(mappedPoint);
if (cell.contains(point)) {
if (mappedPointWithinShape) {
if (VERBOSE) {
log.println(" check doc=" + docID + ": match! Actual quantized point within: " + pointWithinShape);
}
hits.add(docID);
} else {
if (VERBOSE) {
log.println(" check doc=" + docID + ": no match. Quantized point within: " + pointWithinShape);
}
}
}
}
} else {
GeoArea xyzSolid = GeoAreaFactory.makeGeoArea(PlanetModel.WGS84, Geo3DUtil.decodeValueFloor(cell.xMinEnc), Geo3DUtil.decodeValueCeil(cell.xMaxEnc), Geo3DUtil.decodeValueFloor(cell.yMinEnc), Geo3DUtil.decodeValueCeil(cell.yMaxEnc), Geo3DUtil.decodeValueFloor(cell.zMinEnc), Geo3DUtil.decodeValueCeil(cell.zMaxEnc));
if (VERBOSE) {
log.println(" minx=" + Geo3DUtil.decodeValueFloor(cell.xMinEnc) + " maxx=" + Geo3DUtil.decodeValueCeil(cell.xMaxEnc) + " miny=" + Geo3DUtil.decodeValueFloor(cell.yMinEnc) + " maxy=" + Geo3DUtil.decodeValueCeil(cell.yMaxEnc) + " minz=" + Geo3DUtil.decodeValueFloor(cell.zMinEnc) + " maxz=" + Geo3DUtil.decodeValueCeil(cell.zMaxEnc));
}
switch(xyzSolid.getRelationship(shape)) {
case GeoArea.CONTAINS:
// Shape fully contains the cell: blindly add all docs in this cell:
if (VERBOSE) {
log.println(" GeoArea.CONTAINS: now addAll");
}
for (int docID = 0; docID < numDocs; docID++) {
if (cell.contains(docs[docID])) {
if (VERBOSE) {
log.println(" addAll doc=" + docID);
}
hits.add(docID);
}
}
continue;
case GeoArea.OVERLAPS:
if (VERBOSE) {
log.println(" GeoArea.OVERLAPS: keep splitting");
}
//log.println(" crosses1");
break;
case GeoArea.WITHIN:
if (VERBOSE) {
log.println(" GeoArea.WITHIN: keep splitting");
}
//log.println(" crosses2");
break;
case GeoArea.DISJOINT:
//log.println(" outside");
if (VERBOSE) {
log.println(" GeoArea.DISJOINT: drop this cell");
for (int docID = 0; docID < numDocs; docID++) {
if (cell.contains(docs[docID])) {
log.println(" skip doc=" + docID);
}
}
}
continue;
default:
assert false;
}
// Randomly split:
switch(random().nextInt(3)) {
case 0:
// Split on X:
{
int splitValue = RandomNumbers.randomIntBetween(random(), cell.xMinEnc, cell.xMaxEnc);
if (VERBOSE) {
log.println(" now split on x=" + splitValue);
}
Cell cell1 = new Cell(cell, cell.xMinEnc, splitValue, cell.yMinEnc, cell.yMaxEnc, cell.zMinEnc, cell.zMaxEnc, cell.splitCount + 1);
Cell cell2 = new Cell(cell, splitValue, cell.xMaxEnc, cell.yMinEnc, cell.yMaxEnc, cell.zMinEnc, cell.zMaxEnc, cell.splitCount + 1);
if (VERBOSE) {
log.println(" split cell1: " + cell1);
log.println(" split cell2: " + cell2);
}
queue.add(cell1);
queue.add(cell2);
}
break;
case 1:
// Split on Y:
{
int splitValue = RandomNumbers.randomIntBetween(random(), cell.yMinEnc, cell.yMaxEnc);
if (VERBOSE) {
log.println(" now split on y=" + splitValue);
}
Cell cell1 = new Cell(cell, cell.xMinEnc, cell.xMaxEnc, cell.yMinEnc, splitValue, cell.zMinEnc, cell.zMaxEnc, cell.splitCount + 1);
Cell cell2 = new Cell(cell, cell.xMinEnc, cell.xMaxEnc, splitValue, cell.yMaxEnc, cell.zMinEnc, cell.zMaxEnc, cell.splitCount + 1);
if (VERBOSE) {
log.println(" split cell1: " + cell1);
log.println(" split cell2: " + cell2);
}
queue.add(cell1);
queue.add(cell2);
}
break;
case 2:
// Split on Z:
{
int splitValue = RandomNumbers.randomIntBetween(random(), cell.zMinEnc, cell.zMaxEnc);
if (VERBOSE) {
log.println(" now split on z=" + splitValue);
}
Cell cell1 = new Cell(cell, cell.xMinEnc, cell.xMaxEnc, cell.yMinEnc, cell.yMaxEnc, cell.zMinEnc, splitValue, cell.splitCount + 1);
Cell cell2 = new Cell(cell, cell.xMinEnc, cell.xMaxEnc, cell.yMinEnc, cell.yMaxEnc, splitValue, cell.zMaxEnc, cell.splitCount + 1);
if (VERBOSE) {
log.println(" split cell1: " + cell1);
log.println(" split cell2: " + cell2);
}
queue.add(cell1);
queue.add(cell2);
}
break;
}
}
}
if (VERBOSE) {
log.println(" " + hits.size() + " hits");
}
// Done matching, now verify:
boolean fail = false;
for (int docID = 0; docID < numDocs; docID++) {
GeoPoint point = docs[docID];
GeoPoint mappedPoint = unquantizedDocs[docID];
boolean expected = shape.isWithin(mappedPoint);
boolean actual = hits.contains(docID);
if (actual != expected) {
if (actual) {
log.println("doc=" + docID + " should not have matched but did");
} else {
log.println("doc=" + docID + " should match but did not");
}
log.println(" point=" + point);
log.println(" mappedPoint=" + mappedPoint);
fail = true;
}
}
if (fail) {
System.out.print(sw.toString());
fail("invalid hits for shape=" + shape);
}
}
}
use of org.apache.lucene.spatial3d.geom.GeoPoint in project lucene-solr by apache.
the class TestGeo3DPoint method explain.
public static String explain(String fieldName, GeoShape shape, GeoPoint targetDocPoint, GeoPoint scaledDocPoint, IndexReader reader, int docID) throws Exception {
final XYZBounds bounds = new XYZBounds();
shape.getBounds(bounds);
// First find the leaf reader that owns this doc:
int subIndex = ReaderUtil.subIndex(docID, reader.leaves());
LeafReader leafReader = reader.leaves().get(subIndex).reader();
StringBuilder b = new StringBuilder();
b.append("target is in leaf " + leafReader + " of full reader " + reader + "\n");
DocIdSetBuilder hits = new DocIdSetBuilder(leafReader.maxDoc());
ExplainingVisitor visitor = new ExplainingVisitor(shape, targetDocPoint, scaledDocPoint, new PointInShapeIntersectVisitor(hits, shape, bounds), docID - reader.leaves().get(subIndex).docBase, 3, Integer.BYTES, b);
// Do first phase, where we just figure out the "path" that leads to the target docID:
leafReader.getPointValues(fieldName).intersect(visitor);
// Do second phase, where we we see how the wrapped visitor responded along that path:
visitor.startSecondPhase();
leafReader.getPointValues(fieldName).intersect(visitor);
return b.toString();
}
use of org.apache.lucene.spatial3d.geom.GeoPoint in project lucene-solr by apache.
the class TestGeo3DPoint method testEncodeDecodeIsStable.
public void testEncodeDecodeIsStable() throws Exception {
int iters = atLeast(1000);
for (int iter = 0; iter < iters; iter++) {
double lat = GeoTestUtil.nextLatitude();
double lon = GeoTestUtil.nextLongitude();
GeoPoint point = new GeoPoint(PlanetModel.WGS84, toRadians(lat), toRadians(lon));
// encode point
GeoPoint pointEnc = new GeoPoint(Geo3DUtil.decodeValue(Geo3DUtil.encodeValue(point.x)), Geo3DUtil.decodeValue(Geo3DUtil.encodeValue(point.y)), Geo3DUtil.decodeValue(Geo3DUtil.encodeValue(point.z)));
// encode it again (double encode)
GeoPoint pointEnc2 = new GeoPoint(Geo3DUtil.decodeValue(Geo3DUtil.encodeValue(pointEnc.x)), Geo3DUtil.decodeValue(Geo3DUtil.encodeValue(pointEnc.y)), Geo3DUtil.decodeValue(Geo3DUtil.encodeValue(pointEnc.z)));
//System.out.println("TEST " + iter + ":\n point =" + point + "\n pointEnc =" + pointEnc + "\n pointEnc2=" + pointEnc2);
assertEquals(pointEnc.x, pointEnc2.x, 0.0);
assertEquals(pointEnc.y, pointEnc2.y, 0.0);
assertEquals(pointEnc.z, pointEnc2.z, 0.0);
}
}
Aggregations