static S2Point coordToPoint(double lng, double lat) { // Note that it's (lat, lng) for S2 but (lng, lat) for MongoDB. S2LatLng ll = S2LatLng::FromDegrees(lat, lng).Normalized(); if (!ll.is_valid()) { stringstream ss; ss << "coords invalid after normalization, lng = " << lng << " lat = " << lat << endl; uasserted(17125, ss.str()); } return ll.ToPoint(); }
// function computes distance between two non-null points // function computes distance using Haversine formula static double getDistance(const GeographyPointValue &point1, const GeographyPointValue &point2) { assert(!point1.isNull()); assert(!point2.isNull()); const S2LatLng latLng1 = S2LatLng(point1.toS2Point()).Normalized(); const S2LatLng latLng2 = S2LatLng(point2.toS2Point()).Normalized(); S1Angle distance = latLng1.GetDistance(latLng2); return distance.radians() * SPHERICAL_EARTH_MEAN_RADIUS_M; }
static S2Point coordToPoint(double lng, double lat) { // We don't rely on drem to clean up non-sane points. We just don't let them become // spherical. verify(isValidLngLat(lng, lat)); // Note that it's (lat, lng) for S2 but (lng, lat) for MongoDB. S2LatLng ll = S2LatLng::FromDegrees(lat, lng).Normalized(); // This shouldn't happen since we should only have valid lng/lats. if (!ll.is_valid()) { stringstream ss; ss << "coords invalid after normalization, lng = " << lng << " lat = " << lat << endl; uasserted(17125, ss.str()); } return ll.ToPoint(); }
static Status coordToPoint(double lng, double lat, S2Point* out) { // We don't rely on drem to clean up non-sane points. We just don't let them become // spherical. if (!isValidLngLat(lng, lat)) return BAD_VALUE("longitude/latitude is out of bounds, lng: " << lng << " lat: " << lat); // Note that it's (lat, lng) for S2 but (lng, lat) for MongoDB. S2LatLng ll = S2LatLng::FromDegrees(lat, lng).Normalized(); // This shouldn't happen since we should only have valid lng/lats. if (!ll.is_valid()) { stringstream ss; ss << "coords invalid after normalization, lng = " << lng << " lat = " << lat << endl; uasserted(17125, ss.str()); } *out = ll.ToPoint(); return Status::OK(); }
template<> NValue NValue::call<FUNC_VOLT_DISTANCE_POINT_POINT>(const std::vector<NValue>& arguments) { assert(arguments[0].getValueType() == VALUE_TYPE_POINT); assert(arguments[1].getValueType() == VALUE_TYPE_POINT); if (arguments[0].isNull() || arguments[1].isNull()) { return NValue::getNullValue(VALUE_TYPE_DOUBLE); } // compute distance using Haversine formula // alternate to this is just obtain 2 s2points and compute S1Angle between them // and use that as distance. // S2 test uses S2LatLng for computing distances const S2LatLng latLng1 = S2LatLng(arguments[0].getGeographyPointValue().toS2Point()).Normalized(); const S2LatLng latLng2 = S2LatLng(arguments[1].getGeographyPointValue().toS2Point()).Normalized(); S1Angle distance = latLng1.GetDistance(latLng2); NValue retVal(VALUE_TYPE_DOUBLE); // distance is in radians, so convert it to meters retVal.getDouble() = distance.radians() * SPHERICAL_EARTH_MEAN_RADIUS_M; return retVal; }