@@ -109,9 +109,27 @@ var randDataType = function() {
109109function deg2rad ( arg ) { return arg * Math . PI / 180.0 ; }
110110function 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
117135function errorMarginForPoint ( env ) {
@@ -124,12 +142,13 @@ function errorMarginForPoint(env) {
124142
125143function 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
135154var randQuery = function ( env ) {
0 commit comments