summaryrefslogtreecommitdiff
path: root/db/geo
diff options
context:
space:
mode:
authorgregs <greg@10gen.com>2011-05-06 10:22:08 -0400
committergregs <greg@10gen.com>2011-05-06 13:31:26 -0400
commitaa13edaae8449d76d16d3931428c6bd922cbb81f (patch)
tree229178cdfa416c175f0f49196a9e1746a22ada83 /db/geo
parentbe124009c226d122979fb11623dc3f98aaa1c3be (diff)
downloadmongo-aa13edaae8449d76d16d3931428c6bd922cbb81f.tar.gz
check spherical earth query bounds SERVER-2980
Diffstat (limited to 'db/geo')
-rw-r--r--db/geo/2d.cpp31
-rw-r--r--db/geo/core.h6
2 files changed, 27 insertions, 10 deletions
diff --git a/db/geo/2d.cpp b/db/geo/2d.cpp
index 2404bf6df8a..a2c864aff5e 100644
--- a/db/geo/2d.cpp
+++ b/db/geo/2d.cpp
@@ -1599,12 +1599,14 @@ namespace mongo {
double approxDistance( const GeoHash& h ) {
double approxDistance = -1;
+ Point p( _g, h );
switch (_type) {
case GEO_PLAIN:
- approxDistance = _near.distance( Point( _g, h ) );
+ approxDistance = _near.distance( p );
break;
case GEO_SPHERE:
- approxDistance = spheredist_deg( _near, Point( _g, h ) );
+ checkEarthBounds( p );
+ approxDistance = spheredist_deg( _near, p );
break;
default: assert( false );
}
@@ -1636,14 +1638,17 @@ namespace mongo {
double exactDistance = -1;
bool exactWithin = false;
+ Point p( loc );
+
// Get the appropriate distance for the type
switch ( _type ) {
case GEO_PLAIN:
- exactDistance = _near.distance( Point( loc ) );
- exactWithin = _near.distanceWithin( Point( loc ), _maxDistance );
+ exactDistance = _near.distance( p );
+ exactWithin = _near.distanceWithin( p, _maxDistance );
break;
case GEO_SPHERE:
- exactDistance = spheredist_deg( _near, Point( loc ) );
+ checkEarthBounds( p );
+ exactDistance = spheredist_deg( _near, p );
exactWithin = ( exactDistance <= _maxDistance );
break;
default: assert( false );
@@ -1723,6 +1728,7 @@ namespace mongo {
_scanDistance = maxDistance + _spec->_error;
}
else if (type == GEO_SPHERE) {
+ checkEarthBounds( startPt );
// TODO: consider splitting into x and y scan distances
_scanDistance = computeXScanDistance( startPt._y, rad2deg( _maxDistance ) + _spec->_error );
}
@@ -1927,6 +1933,7 @@ namespace mongo {
// Same, but compute maxDistance using spherical transform
uassert(13461, "Spherical MaxDistance > PI. Are you sure you are using radians?", _maxDistance < M_PI);
+ checkEarthBounds( _startPt );
_type = GEO_SPHERE;
_yScanDistance = rad2deg( _maxDistance ) + _g->_error;
@@ -1973,10 +1980,13 @@ namespace mongo {
d = _g->distance( _start , h );
error = _g->_error;
break;
- case GEO_SPHERE:
- d = spheredist_deg( _startPt, Point( _g, h ) );
+ case GEO_SPHERE: {
+ Point p( _g, h );
+ checkEarthBounds( p );
+ d = spheredist_deg( _startPt, p );
error = _g->_errorSphere;
break;
+ }
default: assert( false );
}
@@ -1991,17 +2001,19 @@ namespace mongo {
GEODEBUG( "Inexact distance : " << d << " vs " << _maxDistance << " from " << ( *i ).toString() << " due to error " << error );
+ Point p( *i );
// Exact distance checks.
switch (_type) {
case GEO_PLAIN: {
- if( _startPt.distanceWithin( Point( *i ), _maxDistance ) ) return true;
+ if( _startPt.distanceWithin( p, _maxDistance ) ) return true;
break;
}
case GEO_SPHERE:
// Ignore all locations not hashed to the key's hash, since spherical calcs are
// more expensive.
if( _g->_hash( *i ) != h ) break;
- if( spheredist_deg( _startPt , Point( *i ) ) <= _maxDistance ) return true;
+ checkEarthBounds( p );
+ if( spheredist_deg( _startPt , p ) <= _maxDistance ) return true;
break;
default: assert( false );
}
@@ -2373,7 +2385,6 @@ namespace mongo {
if ( cmdObj["spherical"].trueValue() )
type = GEO_SPHERE;
- // We're returning exact distances, so don't evaluate lazily.
GeoSearch gs( g , n , numWanted , filter , maxDistance , type );
if ( cmdObj["start"].type() == String) {
diff --git a/db/geo/core.h b/db/geo/core.h
index 684b6e49b4a..109495066c0 100644
--- a/db/geo/core.h
+++ b/db/geo/core.h
@@ -454,6 +454,12 @@ namespace mongo {
extern const double EARTH_RADIUS_KM;
extern const double EARTH_RADIUS_MILES;
+ // Technically lat/long bounds, not really tied to earth radius.
+ inline void checkEarthBounds( Point p ) {
+ uassert( 14808, str::stream() << "point " << p.toString() << " must be in earth-like bounds of long : [-180, 180), lat : [-90, 90] ",
+ p._x >= -180 && p._x < 180 && p._y >= -90 && p._y <= 90 );
+ }
+
inline double deg2rad(double deg) { return deg * (M_PI/180); }
inline double rad2deg(double rad) { return rad * (180/M_PI); }