summaryrefslogtreecommitdiff
path: root/jstests/core/index/geo/geo_center_sphere2.js
diff options
context:
space:
mode:
Diffstat (limited to 'jstests/core/index/geo/geo_center_sphere2.js')
-rw-r--r--jstests/core/index/geo/geo_center_sphere2.js158
1 files changed, 158 insertions, 0 deletions
diff --git a/jstests/core/index/geo/geo_center_sphere2.js b/jstests/core/index/geo/geo_center_sphere2.js
new file mode 100644
index 00000000000..1c59850d841
--- /dev/null
+++ b/jstests/core/index/geo/geo_center_sphere2.js
@@ -0,0 +1,158 @@
+// @tags: [
+// requires_getmore,
+// ]
+
+//
+// Tests the error handling of spherical queries
+// along with multi-location documents.
+// This is necessary since the error handling must manage
+// multiple documents, and so requires simultaneous testing.
+//
+
+load("jstests/libs/geo_math.js");
+
+function computexscandist(y, maxDistDegrees) {
+ return maxDistDegrees /
+ Math.min(Math.cos(deg2rad(Math.min(89.0, y + maxDistDegrees))),
+ Math.cos(deg2rad(Math.max(-89.0, y - maxDistDegrees))));
+}
+
+function pointIsOK(startPoint, radius) {
+ yscandist = rad2deg(radius) + 0.01;
+ xscandist = computexscandist(startPoint[1], yscandist);
+ return (startPoint[0] + xscandist < 180) && (startPoint[0] - xscandist > -180) &&
+ (startPoint[1] + yscandist < 90) && (startPoint[1] - yscandist > -90);
+}
+
+var numTests = 30;
+
+for (var test = 0; test < numTests; test++) {
+ Random.srand(1337 + test);
+
+ var radius = 5000 * Random.rand(); // km
+ radius = radius / 6378.1; // radians; earth radius from geoconstants.h
+ var numDocs = Math.floor(400 * Random.rand());
+ // TODO: Wrapping uses the error value to figure out what would overlap...
+ var bits = Math.floor(5 + Random.rand() * 28);
+ var maxPointsPerDoc = 50;
+
+ var t = db.sphere;
+
+ var randomPoint = function() {
+ return [Random.rand() * 360 - 180, Random.rand() * 180 - 90];
+ };
+
+ // Get a start point that doesn't require wrapping
+ // TODO: Are we a bit too aggressive with wrapping issues?
+ var startPoint;
+ var ex = null;
+ do {
+ t.drop();
+ startPoint = randomPoint();
+ t.createIndex({loc: "2d"}, {bits: bits});
+ } while (!pointIsOK(startPoint, radius));
+
+ var pointsIn = 0;
+ var pointsOut = 0;
+ var docsIn = 0;
+ var docsOut = 0;
+ var totalPoints = 0;
+
+ var bulk = t.initializeUnorderedBulkOp();
+ for (var i = 0; i < numDocs; i++) {
+ var numPoints = Math.floor(Random.rand() * maxPointsPerDoc + 1);
+ var docIn = false;
+ var multiPoint = [];
+
+ totalPoints += numPoints;
+
+ for (var p = 0; p < numPoints; p++) {
+ var point = randomPoint();
+ multiPoint.push(point);
+
+ if (Geo.sphereDistance(startPoint, point) <= radius) {
+ pointsIn++;
+ docIn = true;
+ } else {
+ pointsOut++;
+ }
+ }
+
+ bulk.insert({loc: multiPoint});
+
+ if (docIn)
+ docsIn++;
+ else
+ docsOut++;
+ }
+
+ printjson({
+ test: test,
+ radius: radius,
+ bits: bits,
+ numDocs: numDocs,
+ pointsIn: pointsIn,
+ docsIn: docsIn,
+ pointsOut: pointsOut,
+ docsOut: docsOut
+ });
+
+ assert.commandWorked(bulk.execute());
+ assert.eq(docsIn + docsOut, numDocs);
+ assert.eq(pointsIn + pointsOut, totalPoints);
+
+ // $centerSphere
+ assert.eq(docsIn, t.find({loc: {$within: {$centerSphere: [startPoint, radius]}}}).count());
+
+ // $nearSphere
+ var cursor = t.find({loc: {$nearSphere: startPoint, $maxDistance: radius}});
+ var results = cursor.limit(2 * pointsIn).toArray();
+
+ assert.eq(docsIn, results.length);
+
+ var distance = 0;
+ for (var i = 0; i < results.length; i++) {
+ var minNewDistance = radius + 1;
+ for (var j = 0; j < results[i].loc.length; j++) {
+ var newDistance = Geo.sphereDistance(startPoint, results[i].loc[j]);
+ if (newDistance < minNewDistance && newDistance >= distance) {
+ minNewDistance = newDistance;
+ }
+ }
+
+ // print( "Dist from : " + results[i].loc[j] + " to " + startPoint + " is "
+ // + minNewDistance + " vs " + radius )
+
+ assert.lte(minNewDistance, radius);
+ assert.gte(minNewDistance, distance);
+ distance = minNewDistance;
+ }
+
+ // Test $geoNear.
+ results = t.aggregate({
+ $geoNear: {
+ near: startPoint,
+ distanceField: "dis",
+ maxDistance: radius,
+ spherical: true,
+ }
+ }).toArray();
+ assert.eq(docsIn, results.length, tojson(results));
+
+ var distance = 0;
+ for (var i = 0; i < results.length; i++) {
+ var retDistance = results[i].dis;
+
+ var distInObj = false;
+ for (var j = 0; j < results[i].loc.length && distInObj == false; j++) {
+ var newDistance = Geo.sphereDistance(startPoint, results[i].loc[j]);
+ distInObj =
+ (newDistance >= retDistance - 0.0001 && newDistance <= retDistance + 0.0001);
+ }
+
+ assert(distInObj);
+ assert.lte(retDistance, radius);
+ assert.gte(retDistance, distance);
+ distance = retDistance;
+ }
+}