var t = db.get_s2nearcomplex t.drop() t.ensureIndex({geo: "2dsphere"}) /* Short names for math operations */ Random.setRandomSeed(); var random = Random.rand; var PI = Math.PI; var asin = Math.asin; var sin = Math.sin; var cos = Math.cos; var atan2 = Math.atan2 var originGeo = {type: "Point", coordinates: [20.0, 20.0]}; // Center point for all tests. var origin = { name: "origin", geo: originGeo } /* * Convenience function for checking that coordinates match. threshold let's you * specify how accurate equals should be. */ function coordinateEqual(first, second, threshold){ threshold = threshold || 0.001 first = first['geo']['coordinates'] second = second['geo']['coordinates'] if(Math.abs(first[0] - second[0]) <= threshold){ if(Math.abs(first[1] - second[1]) <= threshold){ return true; } } return false; } /* * Creates `count` random and uniformly distributed points centered around `origin` * no points will be closer to origin than minDist, and no points will be further * than maxDist. Points will be inserted into the global `t` collection, and will * be returned. * based on this algorithm: http://williams.best.vwh.net/avform.htm#LL */ function uniformPoints(origin, count, minDist, maxDist){ var i; var lng = origin['geo']['coordinates'][0]; var lat = origin['geo']['coordinates'][1]; var distances = []; var points = []; for(i=0; i < count; i++){ distances.push((random() * (maxDist - minDist)) + minDist); } distances.sort(); while(points.length < count){ var angle = random() * 2 * PI; var distance = distances[points.length]; var pointLat = asin((sin(lat) * cos(distance)) + (cos(lat) * sin(distance) * cos(angle))); var pointDLng = atan2(sin(angle) * sin(distance) * cos(lat), cos(distance) - sin(lat) * sin(pointLat)); var pointLng = ((lng - pointDLng + PI) % 2*PI) - PI; // Latitude must be [-90, 90] var newLat = lat + pointLat; if (newLat > 90) newLat -= 180; if (newLat < -90) newLat += 180; // Longitude must be [-180, 180] var newLng = lng + pointLng; if (newLng > 180) newLng -= 360; if (newLng < -180) newLng += 360; var newPoint = { geo: { type: "Point", //coordinates: [lng + pointLng, lat + pointLat] coordinates: [newLng, newLat] } }; points.push(newPoint); } for(i=0; i < points.length; i++){ t.insert(points[i]); assert(!db.getLastError()); } return points; } /* * Creates a random uniform field as above, excepting for `numberOfHoles` gaps that * have `sizeOfHoles` points missing centered around a random point. */ function uniformPointsWithGaps(origin, count, minDist, maxDist, numberOfHoles, sizeOfHoles){ var points = uniformPoints(origin, count, minDist, maxDist); var i; for(i=0; i