Return-Path: X-Original-To: apmail-lucene-commits-archive@www.apache.org Delivered-To: apmail-lucene-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 8A4BC199AE for ; Tue, 8 Mar 2016 01:19:46 +0000 (UTC) Received: (qmail 91920 invoked by uid 500); 8 Mar 2016 01:19:44 -0000 Mailing-List: contact commits-help@lucene.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@lucene.apache.org Delivered-To: mailing list commits@lucene.apache.org Received: (qmail 90628 invoked by uid 99); 8 Mar 2016 01:19:43 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 08 Mar 2016 01:19:43 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 08CEADFE61; Tue, 8 Mar 2016 01:19:43 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: dsmiley@apache.org To: commits@lucene.apache.org Date: Tue, 08 Mar 2016 01:19:59 -0000 Message-Id: <9eedcf6d6de94375bf4485d2955dfb99@git.apache.org> In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [18/32] lucene-solr git commit: LUCENE-7056: Geo3D package re-org (cherry picked from commit 3a31a8c) http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/0a1951be/lucene/spatial3d/src/test/org/apache/lucene/geo3d/PlaneTest.java ---------------------------------------------------------------------- diff --git a/lucene/spatial3d/src/test/org/apache/lucene/geo3d/PlaneTest.java b/lucene/spatial3d/src/test/org/apache/lucene/geo3d/PlaneTest.java deleted file mode 100644 index 2ac3856..0000000 --- a/lucene/spatial3d/src/test/org/apache/lucene/geo3d/PlaneTest.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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.geo3d; - -import org.junit.Test; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -/** - * Test basic plane functionality. - */ -public class PlaneTest { - - - @Test - public void testIdenticalPlanes() { - final GeoPoint p = new GeoPoint(PlanetModel.SPHERE, 0.123, -0.456); - final Plane plane1 = new Plane(p, 0.0); - final Plane plane2 = new Plane(p, 0.0); - assertTrue(plane1.isNumericallyIdentical(plane2)); - final Plane plane3 = new Plane(p, 0.1); - assertFalse(plane1.isNumericallyIdentical(plane3)); - final Vector v1 = new Vector(0.1, -0.732, 0.9); - final double constant = 0.432; - final Vector v2 = new Vector(v1.x * constant, v1.y * constant, v1.z * constant); - final Plane p1 = new Plane(v1, 0.2); - final Plane p2 = new Plane(v2, 0.2 * constant); - assertTrue(p1.isNumericallyIdentical(p2)); - } - - @Test - public void testInterpolation() { - // [X=0.35168818443386646, Y=-0.19637966197066342, Z=0.9152870857244183], - // [X=0.5003343189532654, Y=0.522128543226148, Z=0.6906861469771293], - - final GeoPoint start = new GeoPoint(0.35168818443386646, -0.19637966197066342, 0.9152870857244183); - final GeoPoint end = new GeoPoint(0.5003343189532654, 0.522128543226148, 0.6906861469771293); - - // [A=-0.6135342247741855, B=0.21504338363863665, C=0.28188192383666794, D=0.0, side=-1.0] internal? false; - final Plane p = new Plane(-0.6135342247741855, 0.21504338363863665, 0.28188192383666794, 0.0); - - final GeoPoint[] points = p.interpolate(start, end, new double[]{0.25, 0.50, 0.75}); - - for (GeoPoint point : points) { - assertTrue(p.evaluateIsZero(point)); - } - } -} - http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/0a1951be/lucene/spatial3d/src/test/org/apache/lucene/geo3d/TestGeo3DPoint.java ---------------------------------------------------------------------- diff --git a/lucene/spatial3d/src/test/org/apache/lucene/geo3d/TestGeo3DPoint.java b/lucene/spatial3d/src/test/org/apache/lucene/geo3d/TestGeo3DPoint.java deleted file mode 100644 index 17a4075..0000000 --- a/lucene/spatial3d/src/test/org/apache/lucene/geo3d/TestGeo3DPoint.java +++ /dev/null @@ -1,801 +0,0 @@ -/* - * 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.geo3d; - -import java.io.IOException; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.atomic.AtomicBoolean; - -import org.apache.lucene.codecs.Codec; -import org.apache.lucene.codecs.FilterCodec; -import org.apache.lucene.codecs.PointsFormat; -import org.apache.lucene.codecs.PointsReader; -import org.apache.lucene.codecs.PointsWriter; -import org.apache.lucene.codecs.lucene60.Lucene60PointsReader; -import org.apache.lucene.codecs.lucene60.Lucene60PointsWriter; -import org.apache.lucene.document.Document; -import org.apache.lucene.document.Field; -import org.apache.lucene.document.NumericDocValuesField; -import org.apache.lucene.index.DirectoryReader; -import org.apache.lucene.index.IndexReader; -import org.apache.lucene.index.IndexWriter; -import org.apache.lucene.index.IndexWriterConfig; -import org.apache.lucene.index.LeafReaderContext; -import org.apache.lucene.index.MultiDocValues; -import org.apache.lucene.index.NumericDocValues; -import org.apache.lucene.index.SegmentReadState; -import org.apache.lucene.index.SegmentWriteState; -import org.apache.lucene.index.Term; -import org.apache.lucene.search.IndexSearcher; -import org.apache.lucene.search.Query; -import org.apache.lucene.search.SimpleCollector; -import org.apache.lucene.store.Directory; -import org.apache.lucene.store.MockDirectoryWrapper; -import org.apache.lucene.util.FixedBitSet; -import org.apache.lucene.util.IOUtils; -import org.apache.lucene.util.LuceneTestCase; -import org.apache.lucene.util.TestUtil; -import org.junit.BeforeClass; - -import com.carrotsearch.randomizedtesting.generators.RandomInts; - -public class TestGeo3DPoint extends LuceneTestCase { - - private static boolean smallBBox; - - @BeforeClass - public static void beforeClass() { - smallBBox = random().nextBoolean(); - if (VERBOSE) { - System.err.println("TEST: smallBBox=" + smallBBox); - } - } - - private static Codec getCodec() { - if (Codec.getDefault().getName().equals("Lucene60")) { - int maxPointsInLeafNode = TestUtil.nextInt(random(), 16, 2048); - double maxMBSortInHeap = 3.0 + (3*random().nextDouble()); - if (VERBOSE) { - System.out.println("TEST: using Lucene60PointsFormat with maxPointsInLeafNode=" + maxPointsInLeafNode + " and maxMBSortInHeap=" + maxMBSortInHeap); - } - - return new FilterCodec("Lucene60", Codec.getDefault()) { - @Override - public PointsFormat pointsFormat() { - return new PointsFormat() { - @Override - public PointsWriter fieldsWriter(SegmentWriteState writeState) throws IOException { - return new Lucene60PointsWriter(writeState, maxPointsInLeafNode, maxMBSortInHeap); - } - - @Override - public PointsReader fieldsReader(SegmentReadState readState) throws IOException { - return new Lucene60PointsReader(readState); - } - }; - } - }; - } else { - return Codec.getDefault(); - } - } - - public void testBasic() throws Exception { - Directory dir = getDirectory(); - IndexWriterConfig iwc = newIndexWriterConfig(); - iwc.setCodec(getCodec()); - IndexWriter w = new IndexWriter(dir, iwc); - Document doc = new Document(); - doc.add(new Geo3DPoint("field", toRadians(50.7345267), toRadians(-97.5303555))); - w.addDocument(doc); - IndexReader r = DirectoryReader.open(w); - // We can't wrap with "exotic" readers because the query must see the BKD3DDVFormat: - IndexSearcher s = newSearcher(r, false); - assertEquals(1, s.search(Geo3DPoint.newShapeQuery("field", - GeoCircleFactory.makeGeoCircle(PlanetModel.WGS84, toRadians(50), toRadians(-97), Math.PI/180.)), 1).totalHits); - w.close(); - r.close(); - dir.close(); - } - - private static double toRadians(double degrees) { - return Math.PI*(degrees/360.0); - } - - private static PlanetModel getPlanetModel() { - if (random().nextBoolean()) { - // Use one of the earth models: - if (random().nextBoolean()) { - return PlanetModel.WGS84; - } else { - return PlanetModel.SPHERE; - } - } else { - // Make a randomly squashed planet: - double oblateness = random().nextDouble() * 0.5 - 0.25; - return new PlanetModel(1.0 + oblateness, 1.0 - oblateness); - } - } - - private static class Cell { - static int nextCellID; - - final Cell parent; - final int cellID; - final int xMinEnc, xMaxEnc; - final int yMinEnc, yMaxEnc; - final int zMinEnc, zMaxEnc; - final int splitCount; - - public Cell(Cell parent, - int xMinEnc, int xMaxEnc, - int yMinEnc, int yMaxEnc, - int zMinEnc, int zMaxEnc, - int splitCount) { - this.parent = parent; - this.xMinEnc = xMinEnc; - this.xMaxEnc = xMaxEnc; - this.yMinEnc = yMinEnc; - this.yMaxEnc = yMaxEnc; - this.zMinEnc = zMinEnc; - this.zMaxEnc = zMaxEnc; - this.cellID = nextCellID++; - this.splitCount = splitCount; - } - - /** Returns true if the quantized point lies within this cell, inclusive on all bounds. */ - public boolean contains(double planetMax, GeoPoint point) { - int docX = Geo3DUtil.encodeValue(planetMax, point.x); - int docY = Geo3DUtil.encodeValue(planetMax, point.y); - int docZ = Geo3DUtil.encodeValue(planetMax, point.z); - - return docX >= xMinEnc && docX <= xMaxEnc && - docY >= yMinEnc && docY <= yMaxEnc && - docZ >= zMinEnc && docZ <= zMaxEnc; - } - - @Override - public String toString() { - return "cell=" + cellID + (parent == null ? "" : " parentCellID=" + parent.cellID) + " x: " + xMinEnc + " TO " + xMaxEnc + ", y: " + yMinEnc + " TO " + yMaxEnc + ", z: " + zMinEnc + " TO " + zMaxEnc + ", splits: " + splitCount; - } - } - - private static GeoPoint quantize(double planetMax, GeoPoint point) { - return new GeoPoint(Geo3DUtil.decodeValueCenter(planetMax, Geo3DUtil.encodeValue(planetMax, point.x)), - Geo3DUtil.decodeValueCenter(planetMax, Geo3DUtil.encodeValue(planetMax, point.y)), - Geo3DUtil.decodeValueCenter(planetMax, Geo3DUtil.encodeValue(planetMax, point.z))); - } - - /** Tests consistency of GeoArea.getRelationship vs GeoShape.isWithin */ - public void testGeo3DRelations() throws Exception { - - PlanetModel planetModel = getPlanetModel(); - - int numDocs = atLeast(1000); - if (VERBOSE) { - System.out.println("TEST: " + numDocs + " docs"); - } - - GeoPoint[] docs = new GeoPoint[numDocs]; - for(int docID=0;docID queue = new ArrayList<>(); - queue.add(root); - Set 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 0 && x < 3 && haveRealDoc) { - int oldDocID; - while (true) { - oldDocID = random().nextInt(docID); - if (Double.isNaN(lats[oldDocID]) == false) { - break; - } - } - - if (x == 0) { - // Identical lat to old point - lats[docID] = lats[oldDocID]; - lons[docID] = toRadians(randomLon()); - if (VERBOSE) { - System.err.println(" doc=" + docID + " lat=" + lats[docID] + " lon=" + lons[docID] + " (same lat as doc=" + oldDocID + ")"); - } - } else if (x == 1) { - // Identical lon to old point - lats[docID] = toRadians(randomLat()); - lons[docID] = lons[oldDocID]; - if (VERBOSE) { - System.err.println(" doc=" + docID + " lat=" + lats[docID] + " lon=" + lons[docID] + " (same lon as doc=" + oldDocID + ")"); - } - } else { - assert x == 2; - // Fully identical point: - lats[docID] = lats[oldDocID]; - lons[docID] = lons[oldDocID]; - if (VERBOSE) { - System.err.println(" doc=" + docID + " lat=" + lats[docID] + " lon=" + lons[docID] + " (same lat/lon as doc=" + oldDocID + ")"); - } - } - } else { - lats[docID] = toRadians(randomLat()); - lons[docID] = toRadians(randomLon()); - haveRealDoc = true; - if (VERBOSE) { - System.err.println(" doc=" + docID + " lat=" + lats[docID] + " lon=" + lons[docID]); - } - } - } - - verify(lats, lons); - } - - private static double randomLat() { - if (smallBBox) { - return 2.0 * (random().nextDouble()-0.5); - } else { - return -90 + 180.0 * random().nextDouble(); - } - } - - private static double randomLon() { - if (smallBBox) { - return 2.0 * (random().nextDouble()-0.5); - } else { - return -180 + 360.0 * random().nextDouble(); - } - } - - // Poached from Geo3dRptTest.randomShape: - private static GeoShape randomShape(PlanetModel planetModel) { - while (true) { - final int shapeType = random().nextInt(4); - switch (shapeType) { - case 0: { - // Polygons - final int vertexCount = random().nextInt(3) + 3; - final List geoPoints = new ArrayList<>(); - while (geoPoints.size() < vertexCount) { - final GeoPoint gPt = new GeoPoint(planetModel, toRadians(randomLat()), toRadians(randomLon())); - geoPoints.add(gPt); - } - final int convexPointIndex = random().nextInt(vertexCount); //If we get this wrong, hopefully we get IllegalArgumentException - try { - return GeoPolygonFactory.makeGeoPolygon(planetModel, geoPoints, convexPointIndex); - } catch (IllegalArgumentException e) { - // This is what happens when we create a shape that is invalid. Although it is conceivable that there are cases where - // the exception is thrown incorrectly, we aren't going to be able to do that in this random test. - continue; - } - } - - case 1: { - // Circles - - double lat = toRadians(randomLat()); - double lon = toRadians(randomLon()); - - double angle; - if (smallBBox) { - angle = random().nextDouble() * Math.PI/360.0; - } else { - angle = random().nextDouble() * Math.PI/2.0; - } - - try { - return GeoCircleFactory.makeGeoCircle(planetModel, lat, lon, angle); - } catch (IllegalArgumentException iae) { - // angle is too small; try again: - continue; - } - } - - case 2: { - // Rectangles - double lat0 = toRadians(randomLat()); - double lat1 = toRadians(randomLat()); - if (lat1 < lat0) { - double x = lat0; - lat0 = lat1; - lat1 = x; - } - double lon0 = toRadians(randomLon()); - double lon1 = toRadians(randomLon()); - if (lon1 < lon0) { - double x = lon0; - lon0 = lon1; - lon1 = x; - } - - return GeoBBoxFactory.makeGeoBBox(planetModel, lat1, lat0, lon0, lon1); - } - - case 3: { - // Paths - final int pointCount = random().nextInt(5) + 1; - final double width = toRadians(random().nextInt(89)+1); - try { - final GeoPath path = new GeoPath(planetModel, width); - for (int i = 0; i < pointCount; i++) { - path.addPoint(toRadians(randomLat()), toRadians(randomLon())); - } - path.done(); - return path; - } catch (IllegalArgumentException e) { - // This is what happens when we create a shape that is invalid. Although it is conceivable that there are cases where - // the exception is thrown incorrectly, we aren't going to be able to do that in this random test. - continue; - } - } - - default: - throw new IllegalStateException("Unexpected shape type"); - } - } - } - - private static void verify(double[] lats, double[] lons) throws Exception { - IndexWriterConfig iwc = newIndexWriterConfig(); - - // Else we can get O(N^2) merging: - int mbd = iwc.getMaxBufferedDocs(); - if (mbd != -1 && mbd < lats.length/100) { - iwc.setMaxBufferedDocs(lats.length/100); - } - iwc.setCodec(getCodec()); - Directory dir; - if (lats.length > 100000) { - dir = newFSDirectory(createTempDir("TestBKDTree")); - } else { - dir = getDirectory(); - } - Set deleted = new HashSet<>(); - // RandomIndexWriter is too slow here: - IndexWriter w = new IndexWriter(dir, iwc); - for(int id=0;id 0 && random().nextInt(100) == 42) { - int idToDelete = random().nextInt(id); - w.deleteDocuments(new Term("id", ""+idToDelete)); - deleted.add(idToDelete); - if (VERBOSE) { - System.err.println(" delete id=" + idToDelete); - } - } - } - if (random().nextBoolean()) { - w.forceMerge(1); - } - final IndexReader r = DirectoryReader.open(w); - w.close(); - - // We can't wrap with "exotic" readers because the geo3d query must see the Geo3DDVFormat: - IndexSearcher s = newSearcher(r, false); - - int numThreads = TestUtil.nextInt(random(), 2, 5); - - List threads = new ArrayList<>(); - final int iters = atLeast(100); - - final CountDownLatch startingGun = new CountDownLatch(1); - final AtomicBoolean failed = new AtomicBoolean(); - - for(int i=0;i", point.toString()); - } - - public void testShapeQueryToString() { - assertEquals("PointInGeo3DShapeQuery: field=point: Shape: GeoStandardCircle: {planetmodel=PlanetModel.WGS84, center=[lat=0.3861041107739683, lon=0.06780373760536706], radius=0.1(5.729577951308232)}", - Geo3DPoint.newShapeQuery("point", GeoCircleFactory.makeGeoCircle(PlanetModel.WGS84, toRadians(44.244272), toRadians(7.769736), 0.1)).toString()); - } - - private static Directory getDirectory() { - return newDirectory(); - } -} http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/0a1951be/lucene/spatial3d/src/test/org/apache/lucene/geo3d/XYZSolidTest.java ---------------------------------------------------------------------- diff --git a/lucene/spatial3d/src/test/org/apache/lucene/geo3d/XYZSolidTest.java b/lucene/spatial3d/src/test/org/apache/lucene/geo3d/XYZSolidTest.java deleted file mode 100644 index 876a525..0000000 --- a/lucene/spatial3d/src/test/org/apache/lucene/geo3d/XYZSolidTest.java +++ /dev/null @@ -1,220 +0,0 @@ -/* - * 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.geo3d; - -import org.apache.lucene.util.LuceneTestCase; -import org.junit.Test; - -public class XYZSolidTest extends LuceneTestCase { - - @Test - public void testNonDegenerateRelationships() { - XYZSolid s; - GeoShape shape; - // Something bigger than the world - s = new StandardXYZSolid(PlanetModel.SPHERE, -2.0, 2.0, -2.0, 2.0, -2.0, 2.0); - // Any shape, except whole world, should be within. - shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1); - assertEquals(GeoArea.WITHIN, s.getRelationship(shape)); - shape = new GeoWorld(PlanetModel.SPHERE); - // An XYZSolid represents a surface shape, which when larger than the world is in fact - // the entire world, so it should overlap the world. - assertEquals(GeoArea.OVERLAPS, s.getRelationship(shape)); - - // Something overlapping the world on only one side - s = new StandardXYZSolid(PlanetModel.SPHERE, -2.0, 0.0, -2.0, 2.0, -2.0, 2.0); - // Some things should be disjoint... - shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1); - assertEquals(GeoArea.DISJOINT, s.getRelationship(shape)); - // And, some things should be within... - shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, Math.PI, 0.1); - assertEquals(GeoArea.WITHIN, s.getRelationship(shape)); - // And, some things should overlap. - shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, Math.PI * 0.5, 0.1); - assertEquals(GeoArea.OVERLAPS, s.getRelationship(shape)); - - // Partial world should be contained by GeoWorld object... - shape = new GeoWorld(PlanetModel.SPHERE); - assertEquals(GeoArea.CONTAINS, s.getRelationship(shape)); - - // Something inside the world - s = new StandardXYZSolid(PlanetModel.SPHERE, -0.1, 0.1, -0.1, 0.1, -0.1, 0.1); - // All shapes should be disjoint - shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1); - assertEquals(GeoArea.DISJOINT, s.getRelationship(shape)); - shape = new GeoWorld(PlanetModel.SPHERE); - assertEquals(GeoArea.DISJOINT, s.getRelationship(shape)); - - } - - @Test - public void testDegenerateRelationships() { - GeoArea solid; - GeoShape shape; - - // Basic test of the factory method - non-degenerate - solid = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE, -2.0, 2.0, -2.0, 2.0, -2.0, 2.0); - // Any shape, except whole world, should be within. - shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1); - assertEquals(GeoArea.WITHIN, solid.getRelationship(shape)); - shape = new GeoWorld(PlanetModel.SPHERE); - // An XYZSolid represents a surface shape, which when larger than the world is in fact - // the entire world, so it should overlap the world. - assertEquals(GeoArea.OVERLAPS, solid.getRelationship(shape)); - - // Build a degenerate point, not on sphere - solid = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); - // disjoint with everything? - shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1); - assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape)); - shape = new GeoWorld(PlanetModel.SPHERE); - assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape)); - - // Build a degenerate point that IS on the sphere - solid = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0); - // inside everything that it touches? - shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1); - assertEquals(GeoArea.CONTAINS, solid.getRelationship(shape)); - shape = new GeoWorld(PlanetModel.SPHERE); - assertEquals(GeoArea.CONTAINS, solid.getRelationship(shape)); - shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, Math.PI, 0.1); - assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape)); - - // Build a shape degenerate in (x,y), which has no points on sphere - solid = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE, 0.0, 0.0, 0.0, 0.0, -0.1, 0.1); - // disjoint with everything? - shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1); - assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape)); - shape = new GeoWorld(PlanetModel.SPHERE); - assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape)); - - // Build a shape degenerate in (x,y) which has one point on sphere - solid = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE, 0.0, 0.0, 0.0, 0.0, -0.1, 1.1); - // inside everything that it touches? - shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1); - assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape)); - shape = new GeoWorld(PlanetModel.SPHERE); - assertEquals(GeoArea.CONTAINS, solid.getRelationship(shape)); - shape = new GeoStandardCircle(PlanetModel.SPHERE, Math.PI * 0.5, 0.0, 0.1); - assertEquals(GeoArea.CONTAINS, solid.getRelationship(shape)); - shape = new GeoStandardCircle(PlanetModel.SPHERE, -Math.PI * 0.5, 0.0, 0.1); - assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape)); - - // Build a shape degenerate in (x,y) which has two points on sphere - solid = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE, 0.0, 0.0, 0.0, 0.0, -1.1, 1.1); - // inside everything that it touches? - shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1); - assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape)); - shape = new GeoWorld(PlanetModel.SPHERE); - assertEquals(GeoArea.CONTAINS, solid.getRelationship(shape)); - shape = new GeoStandardCircle(PlanetModel.SPHERE, Math.PI * 0.5, 0.0, 0.1); - assertEquals(GeoArea.OVERLAPS, solid.getRelationship(shape)); - shape = new GeoStandardCircle(PlanetModel.SPHERE, -Math.PI * 0.5, 0.0, 0.1); - assertEquals(GeoArea.OVERLAPS, solid.getRelationship(shape)); - - // Build a shape degenerate in (x,z), which has no points on sphere - solid = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE, 0.0, 0.0, -0.1, 0.1, 0.0, 0.0); - // disjoint with everything? - shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1); - assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape)); - shape = new GeoWorld(PlanetModel.SPHERE); - assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape)); - - // Build a shape degenerate in (x,z) which has one point on sphere - solid = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE, 0.0, 0.0, -0.1, 1.1, 0.0, 0.0); - // inside everything that it touches? - shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1); - assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape)); - shape = new GeoWorld(PlanetModel.SPHERE); - assertEquals(GeoArea.CONTAINS, solid.getRelationship(shape)); - shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, Math.PI * 0.5, 0.1); - assertEquals(GeoArea.CONTAINS, solid.getRelationship(shape)); - shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, -Math.PI * 0.5, 0.1); - assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape)); - - // Build a shape degenerate in (x,y) which has two points on sphere - solid = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE, 0.0, 0.0, -1.1, 1.1, 0.0, 0.0); - // inside everything that it touches? - shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1); - assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape)); - shape = new GeoWorld(PlanetModel.SPHERE); - assertEquals(GeoArea.CONTAINS, solid.getRelationship(shape)); - shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, Math.PI * 0.5, 0.1); - assertEquals(GeoArea.OVERLAPS, solid.getRelationship(shape)); - shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, -Math.PI * 0.5, 0.1); - assertEquals(GeoArea.OVERLAPS, solid.getRelationship(shape)); - - // MHL for y-z check - - // Build a shape that is degenerate in x, which has zero points intersecting sphere - solid = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE, 0.0, 0.0, -0.1, 0.1, -0.1, 0.1); - // disjoint with everything? - shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1); - assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape)); - shape = new GeoWorld(PlanetModel.SPHERE); - assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape)); - - // Build a shape that is degenerate in x, which has zero points intersecting sphere, second variation - solid = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE, 0.0, 0.0, -0.1, 0.1, 1.1, 1.2); - // disjoint with everything? - shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1); - assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape)); - shape = new GeoWorld(PlanetModel.SPHERE); - assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape)); - - // Build a shape that is disjoint in X but intersects sphere in a complete circle - solid = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE, 0.0, 0.0, -1.1, 1.1, -1.1, 1.1); - // inside everything that it touches? - shape = new GeoWorld(PlanetModel.SPHERE); - assertEquals(GeoArea.CONTAINS, solid.getRelationship(shape)); - shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1); - assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape)); - shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, Math.PI, 0.1); - assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape)); - shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, Math.PI * 0.5, 0.1); - assertEquals(GeoArea.OVERLAPS, solid.getRelationship(shape)); - shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, -Math.PI * 0.5, 0.1); - assertEquals(GeoArea.OVERLAPS, solid.getRelationship(shape)); - shape = new GeoStandardCircle(PlanetModel.SPHERE, Math.PI * 0.5, 0.0, 0.1); - assertEquals(GeoArea.OVERLAPS, solid.getRelationship(shape)); - shape = new GeoStandardCircle(PlanetModel.SPHERE, -Math.PI * 0.5, 0.0, 0.1); - assertEquals(GeoArea.OVERLAPS, solid.getRelationship(shape)); - - // Build a shape that is disjoint in X but intersects sphere in a half circle in Y - solid = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE, 0.0, 0.0, 0.0, 1.1, -1.1, 1.1); - // inside everything that it touches? - shape = new GeoWorld(PlanetModel.SPHERE); - assertEquals(GeoArea.CONTAINS, solid.getRelationship(shape)); - shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1); - assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape)); - shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, Math.PI, 0.1); - assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape)); - shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, Math.PI * 0.5, 0.1); - assertEquals(GeoArea.OVERLAPS, solid.getRelationship(shape)); - shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, -Math.PI * 0.5, 0.1); - assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape)); - shape = new GeoStandardCircle(PlanetModel.SPHERE, Math.PI * 0.5, 0.0, 0.1); - assertEquals(GeoArea.OVERLAPS, solid.getRelationship(shape)); - shape = new GeoStandardCircle(PlanetModel.SPHERE, -Math.PI * 0.5, 0.0, 0.1); - assertEquals(GeoArea.OVERLAPS, solid.getRelationship(shape)); - - // MHL for degenerate Y - // MHL for degenerate Z - - } - -} http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/0a1951be/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/TestGeo3DPoint.java ---------------------------------------------------------------------- diff --git a/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/TestGeo3DPoint.java b/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/TestGeo3DPoint.java new file mode 100644 index 0000000..a4d8ed1 --- /dev/null +++ b/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/TestGeo3DPoint.java @@ -0,0 +1,810 @@ +/* + * 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.spatial3d; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.apache.lucene.codecs.Codec; +import org.apache.lucene.codecs.FilterCodec; +import org.apache.lucene.codecs.PointsFormat; +import org.apache.lucene.codecs.PointsReader; +import org.apache.lucene.codecs.PointsWriter; +import org.apache.lucene.codecs.lucene60.Lucene60PointsReader; +import org.apache.lucene.codecs.lucene60.Lucene60PointsWriter; +import org.apache.lucene.document.Document; +import org.apache.lucene.document.Field; +import org.apache.lucene.document.NumericDocValuesField; +import org.apache.lucene.spatial3d.geom.GeoArea; +import org.apache.lucene.spatial3d.geom.GeoAreaFactory; +import org.apache.lucene.spatial3d.geom.GeoBBoxFactory; +import org.apache.lucene.spatial3d.geom.GeoCircleFactory; +import org.apache.lucene.spatial3d.geom.GeoPath; +import org.apache.lucene.spatial3d.geom.GeoPoint; +import org.apache.lucene.spatial3d.geom.GeoPolygonFactory; +import org.apache.lucene.spatial3d.geom.GeoShape; +import org.apache.lucene.spatial3d.geom.PlanetModel; +import org.apache.lucene.spatial3d.geom.XYZBounds; +import org.apache.lucene.index.DirectoryReader; +import org.apache.lucene.index.IndexReader; +import org.apache.lucene.index.IndexWriter; +import org.apache.lucene.index.IndexWriterConfig; +import org.apache.lucene.index.LeafReaderContext; +import org.apache.lucene.index.MultiDocValues; +import org.apache.lucene.index.NumericDocValues; +import org.apache.lucene.index.SegmentReadState; +import org.apache.lucene.index.SegmentWriteState; +import org.apache.lucene.index.Term; +import org.apache.lucene.search.IndexSearcher; +import org.apache.lucene.search.Query; +import org.apache.lucene.search.SimpleCollector; +import org.apache.lucene.store.Directory; +import org.apache.lucene.util.FixedBitSet; +import org.apache.lucene.util.IOUtils; +import org.apache.lucene.util.LuceneTestCase; +import org.apache.lucene.util.TestUtil; +import org.junit.BeforeClass; + +import com.carrotsearch.randomizedtesting.generators.RandomInts; + +public class TestGeo3DPoint extends LuceneTestCase { + + private static boolean smallBBox; + + @BeforeClass + public static void beforeClass() { + smallBBox = random().nextBoolean(); + if (VERBOSE) { + System.err.println("TEST: smallBBox=" + smallBBox); + } + } + + private static Codec getCodec() { + if (Codec.getDefault().getName().equals("Lucene60")) { + int maxPointsInLeafNode = TestUtil.nextInt(random(), 16, 2048); + double maxMBSortInHeap = 3.0 + (3*random().nextDouble()); + if (VERBOSE) { + System.out.println("TEST: using Lucene60PointsFormat with maxPointsInLeafNode=" + maxPointsInLeafNode + " and maxMBSortInHeap=" + maxMBSortInHeap); + } + + return new FilterCodec("Lucene60", Codec.getDefault()) { + @Override + public PointsFormat pointsFormat() { + return new PointsFormat() { + @Override + public PointsWriter fieldsWriter(SegmentWriteState writeState) throws IOException { + return new Lucene60PointsWriter(writeState, maxPointsInLeafNode, maxMBSortInHeap); + } + + @Override + public PointsReader fieldsReader(SegmentReadState readState) throws IOException { + return new Lucene60PointsReader(readState); + } + }; + } + }; + } else { + return Codec.getDefault(); + } + } + + public void testBasic() throws Exception { + Directory dir = getDirectory(); + IndexWriterConfig iwc = newIndexWriterConfig(); + iwc.setCodec(getCodec()); + IndexWriter w = new IndexWriter(dir, iwc); + Document doc = new Document(); + doc.add(new Geo3DPoint("field", toRadians(50.7345267), toRadians(-97.5303555))); + w.addDocument(doc); + IndexReader r = DirectoryReader.open(w); + // We can't wrap with "exotic" readers because the query must see the BKD3DDVFormat: + IndexSearcher s = newSearcher(r, false); + assertEquals(1, s.search(Geo3DPoint.newShapeQuery("field", + GeoCircleFactory.makeGeoCircle(PlanetModel.WGS84, toRadians(50), toRadians(-97), Math.PI/180.)), 1).totalHits); + w.close(); + r.close(); + dir.close(); + } + + private static double toRadians(double degrees) { + return Math.PI*(degrees/360.0); + } + + private static PlanetModel getPlanetModel() { + if (random().nextBoolean()) { + // Use one of the earth models: + if (random().nextBoolean()) { + return PlanetModel.WGS84; + } else { + return PlanetModel.SPHERE; + } + } else { + // Make a randomly squashed planet: + double oblateness = random().nextDouble() * 0.5 - 0.25; + return new PlanetModel(1.0 + oblateness, 1.0 - oblateness); + } + } + + private static class Cell { + static int nextCellID; + + final Cell parent; + final int cellID; + final int xMinEnc, xMaxEnc; + final int yMinEnc, yMaxEnc; + final int zMinEnc, zMaxEnc; + final int splitCount; + + public Cell(Cell parent, + int xMinEnc, int xMaxEnc, + int yMinEnc, int yMaxEnc, + int zMinEnc, int zMaxEnc, + int splitCount) { + this.parent = parent; + this.xMinEnc = xMinEnc; + this.xMaxEnc = xMaxEnc; + this.yMinEnc = yMinEnc; + this.yMaxEnc = yMaxEnc; + this.zMinEnc = zMinEnc; + this.zMaxEnc = zMaxEnc; + this.cellID = nextCellID++; + this.splitCount = splitCount; + } + + /** Returns true if the quantized point lies within this cell, inclusive on all bounds. */ + public boolean contains(double planetMax, GeoPoint point) { + int docX = Geo3DUtil.encodeValue(planetMax, point.x); + int docY = Geo3DUtil.encodeValue(planetMax, point.y); + int docZ = Geo3DUtil.encodeValue(planetMax, point.z); + + return docX >= xMinEnc && docX <= xMaxEnc && + docY >= yMinEnc && docY <= yMaxEnc && + docZ >= zMinEnc && docZ <= zMaxEnc; + } + + @Override + public String toString() { + return "cell=" + cellID + (parent == null ? "" : " parentCellID=" + parent.cellID) + " x: " + xMinEnc + " TO " + xMaxEnc + ", y: " + yMinEnc + " TO " + yMaxEnc + ", z: " + zMinEnc + " TO " + zMaxEnc + ", splits: " + splitCount; + } + } + + private static GeoPoint quantize(double planetMax, GeoPoint point) { + return new GeoPoint(Geo3DUtil.decodeValueCenter(planetMax, Geo3DUtil.encodeValue(planetMax, point.x)), + Geo3DUtil.decodeValueCenter(planetMax, Geo3DUtil.encodeValue(planetMax, point.y)), + Geo3DUtil.decodeValueCenter(planetMax, Geo3DUtil.encodeValue(planetMax, point.z))); + } + + /** Tests consistency of GeoArea.getRelationship vs GeoShape.isWithin */ + public void testGeo3DRelations() throws Exception { + + PlanetModel planetModel = getPlanetModel(); + + int numDocs = atLeast(1000); + if (VERBOSE) { + System.out.println("TEST: " + numDocs + " docs"); + } + + GeoPoint[] docs = new GeoPoint[numDocs]; + for(int docID=0;docID queue = new ArrayList<>(); + queue.add(root); + Set 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 0 && x < 3 && haveRealDoc) { + int oldDocID; + while (true) { + oldDocID = random().nextInt(docID); + if (Double.isNaN(lats[oldDocID]) == false) { + break; + } + } + + if (x == 0) { + // Identical lat to old point + lats[docID] = lats[oldDocID]; + lons[docID] = toRadians(randomLon()); + if (VERBOSE) { + System.err.println(" doc=" + docID + " lat=" + lats[docID] + " lon=" + lons[docID] + " (same lat as doc=" + oldDocID + ")"); + } + } else if (x == 1) { + // Identical lon to old point + lats[docID] = toRadians(randomLat()); + lons[docID] = lons[oldDocID]; + if (VERBOSE) { + System.err.println(" doc=" + docID + " lat=" + lats[docID] + " lon=" + lons[docID] + " (same lon as doc=" + oldDocID + ")"); + } + } else { + assert x == 2; + // Fully identical point: + lats[docID] = lats[oldDocID]; + lons[docID] = lons[oldDocID]; + if (VERBOSE) { + System.err.println(" doc=" + docID + " lat=" + lats[docID] + " lon=" + lons[docID] + " (same lat/lon as doc=" + oldDocID + ")"); + } + } + } else { + lats[docID] = toRadians(randomLat()); + lons[docID] = toRadians(randomLon()); + haveRealDoc = true; + if (VERBOSE) { + System.err.println(" doc=" + docID + " lat=" + lats[docID] + " lon=" + lons[docID]); + } + } + } + + verify(lats, lons); + } + + private static double randomLat() { + if (smallBBox) { + return 2.0 * (random().nextDouble()-0.5); + } else { + return -90 + 180.0 * random().nextDouble(); + } + } + + private static double randomLon() { + if (smallBBox) { + return 2.0 * (random().nextDouble()-0.5); + } else { + return -180 + 360.0 * random().nextDouble(); + } + } + + // Poached from Geo3dRptTest.randomShape: + private static GeoShape randomShape(PlanetModel planetModel) { + while (true) { + final int shapeType = random().nextInt(4); + switch (shapeType) { + case 0: { + // Polygons + final int vertexCount = random().nextInt(3) + 3; + final List geoPoints = new ArrayList<>(); + while (geoPoints.size() < vertexCount) { + final GeoPoint gPt = new GeoPoint(planetModel, toRadians(randomLat()), toRadians(randomLon())); + geoPoints.add(gPt); + } + final int convexPointIndex = random().nextInt(vertexCount); //If we get this wrong, hopefully we get IllegalArgumentException + try { + return GeoPolygonFactory.makeGeoPolygon(planetModel, geoPoints, convexPointIndex); + } catch (IllegalArgumentException e) { + // This is what happens when we create a shape that is invalid. Although it is conceivable that there are cases where + // the exception is thrown incorrectly, we aren't going to be able to do that in this random test. + continue; + } + } + + case 1: { + // Circles + + double lat = toRadians(randomLat()); + double lon = toRadians(randomLon()); + + double angle; + if (smallBBox) { + angle = random().nextDouble() * Math.PI/360.0; + } else { + angle = random().nextDouble() * Math.PI/2.0; + } + + try { + return GeoCircleFactory.makeGeoCircle(planetModel, lat, lon, angle); + } catch (IllegalArgumentException iae) { + // angle is too small; try again: + continue; + } + } + + case 2: { + // Rectangles + double lat0 = toRadians(randomLat()); + double lat1 = toRadians(randomLat()); + if (lat1 < lat0) { + double x = lat0; + lat0 = lat1; + lat1 = x; + } + double lon0 = toRadians(randomLon()); + double lon1 = toRadians(randomLon()); + if (lon1 < lon0) { + double x = lon0; + lon0 = lon1; + lon1 = x; + } + + return GeoBBoxFactory.makeGeoBBox(planetModel, lat1, lat0, lon0, lon1); + } + + case 3: { + // Paths + final int pointCount = random().nextInt(5) + 1; + final double width = toRadians(random().nextInt(89)+1); + try { + final GeoPath path = new GeoPath(planetModel, width); + for (int i = 0; i < pointCount; i++) { + path.addPoint(toRadians(randomLat()), toRadians(randomLon())); + } + path.done(); + return path; + } catch (IllegalArgumentException e) { + // This is what happens when we create a shape that is invalid. Although it is conceivable that there are cases where + // the exception is thrown incorrectly, we aren't going to be able to do that in this random test. + continue; + } + } + + default: + throw new IllegalStateException("Unexpected shape type"); + } + } + } + + private static void verify(double[] lats, double[] lons) throws Exception { + IndexWriterConfig iwc = newIndexWriterConfig(); + + // Else we can get O(N^2) merging: + int mbd = iwc.getMaxBufferedDocs(); + if (mbd != -1 && mbd < lats.length/100) { + iwc.setMaxBufferedDocs(lats.length/100); + } + iwc.setCodec(getCodec()); + Directory dir; + if (lats.length > 100000) { + dir = newFSDirectory(createTempDir("TestBKDTree")); + } else { + dir = getDirectory(); + } + Set deleted = new HashSet<>(); + // RandomIndexWriter is too slow here: + IndexWriter w = new IndexWriter(dir, iwc); + for(int id=0;id 0 && random().nextInt(100) == 42) { + int idToDelete = random().nextInt(id); + w.deleteDocuments(new Term("id", ""+idToDelete)); + deleted.add(idToDelete); + if (VERBOSE) { + System.err.println(" delete id=" + idToDelete); + } + } + } + if (random().nextBoolean()) { + w.forceMerge(1); + } + final IndexReader r = DirectoryReader.open(w); + w.close(); + + // We can't wrap with "exotic" readers because the geo3d query must see the Geo3DDVFormat: + IndexSearcher s = newSearcher(r, false); + + int numThreads = TestUtil.nextInt(random(), 2, 5); + + List threads = new ArrayList<>(); + final int iters = atLeast(100); + + final CountDownLatch startingGun = new CountDownLatch(1); + final AtomicBoolean failed = new AtomicBoolean(); + + for(int i=0;i", point.toString()); + } + + public void testShapeQueryToString() { + assertEquals("PointInGeo3DShapeQuery: field=point: Shape: GeoStandardCircle: {planetmodel=PlanetModel.WGS84, center=[lat=0.3861041107739683, lon=0.06780373760536706], radius=0.1(5.729577951308232)}", + Geo3DPoint.newShapeQuery("point", GeoCircleFactory.makeGeoCircle(PlanetModel.WGS84, toRadians(44.244272), toRadians(7.769736), 0.1)).toString()); + } + + private static Directory getDirectory() { + return newDirectory(); + } +}