Skip to content

Commit 4e66586

Browse files
committed
SERVER-21869 Avoid wrapping of spherical queries in geo_full.js
1 parent d4a23dd commit 4e66586

File tree

1 file changed

+28
-9
lines changed

1 file changed

+28
-9
lines changed

jstests/noPassthrough/geo_full.js

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -109,9 +109,27 @@ var randDataType = function() {
109109
function deg2rad(arg) { return arg * Math.PI / 180.0; }
110110
function rad2deg(arg) { return arg * 180.0 / Math.PI; }
111111

112-
function computexscandist(y, maxDistDegrees) {
113-
return maxDistDegrees / Math.min(Math.cos(deg2rad(Math.min(89.0, y + maxDistDegrees))),
114-
Math.cos(deg2rad(Math.max(-89.0, y - maxDistDegrees))));
112+
function computexscandist(latDegrees, maxDistDegrees) {
113+
// See s2cap.cc
114+
//
115+
// Compute the range of longitudes covered by the cap. We use the law
116+
// of sines for spherical triangles. Consider the triangle ABC where
117+
// A is the north pole, B is the center of the cap, and C is the point
118+
// of tangency between the cap boundary and a line of longitude. Then
119+
// C is a right angle, and letting a,b,c denote the sides opposite A,B,C,
120+
// we have sin(a)/sin(A) = sin(c)/sin(C), or sin(A) = sin(a)/sin(c).
121+
// Here "a" is the cap angle, and "c" is the colatitude (90 degrees
122+
// minus the latitude). This formula also works for negative latitudes.
123+
//
124+
// Angle A is the difference of longitudes of B and C.
125+
var sin_c = Math.cos(deg2rad(latDegrees));
126+
var sin_a = Math.sin(deg2rad(maxDistDegrees));
127+
if (sin_a > sin_c) {
128+
// Double floating number error, return invalid distance
129+
return 180;
130+
}
131+
var angleA = Math.asin(sin_a / sin_c);
132+
return rad2deg(angleA);
115133
}
116134

117135
function errorMarginForPoint(env) {
@@ -124,12 +142,13 @@ function errorMarginForPoint(env) {
124142

125143
function pointIsOK(startPoint, radius, env) {
126144
var error = errorMarginForPoint(env);
127-
yscandist = rad2deg(radius) + error;
128-
xscandist = computexscandist(startPoint[1], yscandist);
129-
return (startPoint[0] + xscandist < 180)
130-
&& (startPoint[0] - xscandist > -180)
131-
&& (startPoint[1] + yscandist < 90)
132-
&& (startPoint[1] - yscandist > -90);
145+
var distDegrees = rad2deg(radius) + error;
146+
// Cap should not include the South/North Pole.
147+
if ((startPoint[1] + distDegrees > 90) || (startPoint[1] - distDegrees < -90)) {
148+
return false;
149+
}
150+
var xscandist = computexscandist(startPoint[1], distDegrees);
151+
return (startPoint[0] + xscandist < 180) && (startPoint[0] - xscandist > -180);
133152
}
134153

135154
var randQuery = function( env ) {

0 commit comments

Comments
 (0)