Uploaded image for project: 'Core Server'
  1. Core Server
  2. SERVER-22001

geoNear spherical returning incorrect distance

    • Type: Icon: Bug Bug
    • Resolution: Done
    • Priority: Icon: Major - P3 Major - P3
    • None
    • Affects Version/s: 3.0.6
    • Component/s: Geo
    • None
    • ALL
    • Hide
      > db.createCollection("circleTest")
      > db.circleTest.insert("loc":{"type":"Point", "coordinates":[-24,40]})
      > db.circleTest.createIndex({"loc":"2dsphere"})
      > db.runCommand({geoNear:"circleTest",near:[-25,40],spherical:true,distanceMultiplier:6378.1})
      
      Show
      > db.createCollection("circleTest") > db.circleTest.insert("loc":{"type":"Point", "coordinates":[-24,40]}) > db.circleTest.createIndex({"loc":"2dsphere"}) > db.runCommand({geoNear:"circleTest",near:[-25,40],spherical:true,distanceMultiplier:6378.1})
    • Repl F (01/29/16), Query 10 (02/22/16)

      Result:

      {
      	"dis" : 85.27473543648324,
      	"obj" : {
      		"_id" : ObjectId("567a6af8f2f0548bc9a9a4f2"),
      		"loc" : {
      			"type" : "Point",
      			"coordinates" : [
      				-24,
      				40
      			]
      		}
      	}
      },
      

      These are the distances using different formulas:
      "n-vector" : 111.2,
      "haversine" : 111.2,
      "vincenty" : 110.77,

      Problem:
      https://github.com/mongodb/mongo/blob/master/src/mongo/db/geo/shapes.cpp
      double spheredist_rad(const Point& p1, const Point& p2) {

      Looking at https://en.wikipedia.org/wiki/N-vector the below is wrong
      double cross_prod = (cosy1 * cosx1 * cosy2 * cosx2) + (cosy1 * sinx1 * cosy2 * sinx2) + (siny1 * siny2);

      Shoulg be:
      double cross_prod = (cosy1 * cosx1 * cosy2 * cosx2) + (cosx1 * siny1 * cosx2 * siny2) + (sinx1 * sinx2);

      //Example https://ideone.com/8nhK37
          #include <iostream>
          #include <math.h>
          using namespace std;
           
          struct Point {
              Point();
              Point(double x, double y);
              std::string toString() const;
           
              double x;
              double y;
          };
          Point::Point() : x(0), y(0) {}
          Point::Point(double x, double y) : x(x), y(y) {}
           
          double spheredist_rad(const Point& p1, const Point& p2) {
              double sinx1(sin(p1.x)), cosx1(cos(p1.x));
              double siny1(sin(p1.y)), cosy1(cos(p1.y));
              double sinx2(sin(p2.x)), cosx2(cos(p2.x));
              double siny2(sin(p2.y)), cosy2(cos(p2.y));
           
              double cross_prod = (cosy1 * cosx1 * cosy2 * cosx2) + (cosy1 * sinx1 * cosy2 * sinx2) + (siny1 * siny2);
           
              double cross_prod2 = (cosy1 * cosx1 * cosy2 * cosx2) + (cosx1 * siny1 * cosx2 * siny2) + (sinx1 * sinx2);
           
          	cout << (acos(cross_prod) * 6378.1) << endl;
          	cout << (acos(cross_prod2) * 6378.1)<< endl;
          }
           
          int main() {
          	Point p1 = Point(-25 * M_PI / 180, 40 * M_PI / 180);
          	Point p2 = Point(-24 * M_PI / 180, 40 * M_PI / 180);
           
          	spheredist_rad(p1, p2);
           
          	return 0;
          }
      

            Assignee:
            david.storch@mongodb.com David Storch
            Reporter:
            sean_rand Sean
            Votes:
            0 Vote for this issue
            Watchers:
            11 Start watching this issue

              Created:
              Updated:
              Resolved: