boostorg / boostorg/geometry

Karney gives often wrong results

Open
#1,465 0 comments 0 reactions 0 assignees View on GitHub
bug
Dominant language
C++
Stars
517
Forks
232
PR merge metrics
No merged PRs in 30d

Description

The Karney formula *(inside Boost.Geometry)* gives often **very wrong** results.

(In GeographicLib, the results are different - and correct)

It fails in several cases:

* Results: negative distances
* Output ≈ D_antipodal (~20003 km) for pairs that are nowhere near antipodal
* Off by exactly one quarter-meridian (~10001 km) for near-meridional polar-transit pairs
* ~25% relative error on short (~km-scale) pairs entirely above 45° latitude

The bug is not limited to edge cases — case 7 in the repro is a 6.5 km pair near Rotterdam (both endpoints at ~51° N) where our version of Karney returns 8009 m instead of 6520 m.

Minimal reproduction scenario:

```
#include
#include

#include

namespace bg = boost::geometry;

using latlon_point = bg::model::point>;

struct distance_pair
{
latlon_point first;
latlon_point second;
double geodesic_distance{0};
};

int main()
{
using stype = bg::srs::spheroid;

std::vector pairs;
pairs.push_back({{0.0, 0.0}, {2.0, 0.0}, 222638.98}); // OK

pairs.push_back({{0.0, 41.306061250198}, {100.88904290879072632, -52.570275453324655475}, 14174344.4466144}); // source: GeodTest.dat line 78768
pairs.push_back({{0.0, 25.7158673231}, {32.9180106939834239, -66.243826410425021118}, 10569765.894952}); // source: GeodTest.dat line 78769
pairs.push_back({{0.0, 58.256371249077}, {22.784150207906535006, 28.739702371452295937}, 3721028.7556286}); // source: GeodTest.dat line 78770
pairs.push_back({{0.0, 17.812015912354}, {179.998636794719653263, 45.432345524206019945}, 13000761.9422694}); // source: GeodTest.dat line 349760
pairs.push_back({{0.0, 64.858589732434}, { 0.002464379937107867, -50.63203940688252426}, 12806725.1078506}); // source: GeodTest.dat line 349762

pairs.push_back({{4.19132,51.1189}, {4.1005,51.106}, 6520.61}); // source: local random test

bg::strategy::distance::karney karney{};
bg::strategy::distance::vincenty vincenty{};

for (auto const& item : pairs)
{
auto const k = bg::distance(item.first, item.second, karney);
auto const v = bg::distance(item.first, item.second, vincenty);
std::cout << "Karney: " << std::setprecision(10) << std::setw(12) << k
<< " Vincenty: " << std::setw(12) << v
<< " expected: " << std::setw(12) << item.geodesic_distance
<< std::endl;
}

return 0;
}

```

Giving:

```
Karney: 222638.9816 Vincenty: 222638.9816 expected: 222638.98
Karney: -5587.447352 Vincenty: 14174344.45 expected: 14174344.45
Karney: -3120.426059 Vincenty: 10569765.89 expected: 10569765.89
Karney: 19988085.62 Vincenty: 3721028.756 expected: 3721028.756
Karney: 20001692.52 Vincenty: 13000761.94 expected: 13000761.94
Karney: 2829433.304 Vincenty: 12806725.11 expected: 12806725.11
Karney: 8008.921612 Vincenty: 6519.839481 expected: 6520.61
```

Vincenty is not perfect. But Karney should be perfect and give identical results to the version in GeographicLib. However, it is so often off that it is a mystery what is the exact cause, and why it is not reported before...

This came from the investigation of #1461

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.