How TackTracker Calculates Distance

Distance underpins much of what TackTracker shows you: how far a boat has sailed, its speed, the length of each leg, and Navigation Rally results. This page explains how the default distance calculation works and how accurate it is.

It also gives every constant and formula needed to reproduce the calculation in your own software, with worked examples to check your results against.

Overview

By default, TackTracker uses the haversine formula, which gives the "great circle" distance between two points on a sphere. TackTracker adds two refinements to the basic Haversine formula:

  1. A flat-earth shortcut for short distances. For distances up to about 50 km, TackTracker uses an equirectangular projection. The small patch of sphere around the line segment is projected onto a flat plane, and the distance is measured on that plane. This is simpler and faster than haversine, and over short distances the error from flattening the surface is vanishingly small.
  2. A local earth radius in the direction of travel. The Earth is not a perfect sphere, so its radius of curvature depends on where you are and which way you are heading. TackTracker uses Euler's theorem to calculate that local radius for every line segment. This is far more accurate than using a single average radius, such as 6,371 km, which can be wrong by more than half a percent.

Together, these keep the result within 0.001% of the exact distance on the WGS-84 ellipsoid, for segments up to 500 km. That is 1 cm per kilometre. We believe this algorithm provides the best balance of accuracy and performance for typical sailing applications.

Other calculation methods used by TackTracker
  • Karney TackTracker offers the Karney method as an advanced option. Karney computes the exact shortest distance on the WGS-84 ellipsoid, to within a fraction of a millimetre at any distance. However, it is about 25 times slower than the default method and this will slow TackTracker down - and you will see longer event load times. You can select the Karney option in Settings.
  • Legacy The legacy method is the original approach used by TackTracker, using an equirectangular projection and a fixed radius value. It is fast but far less accurate than the current default method. TackTracker will still use the Legacy method when opening an older race, to preserve previously published results. You can switch to the new default method by re-saving the race.

The TackTracker desktop player adds a message to the lower left corner of the map to advise when an alternative distance method is in use.

The default calculation, step by step

If you would like to reproduce TackTracker's results, this is a step by step description of the algorithm.

The inputs are two position coordinates in decimal degrees on WGS-84 from (φ1, λ1) to (φ2, λ2), where φ is latitude and λ is longitude. The result is in metres.

1. Constants
SymbolValueMeaning
a6378137.0 mWGS-84 equatorial radius
f1 / 298.257223563WGS-84 flattening
f (2 − f) = 0.0066943799901413165First eccentricity squared
DEG0.017453292519943295Radians per degree, π / 180
2. Differences and Mean Latitude
Δφ = |φ2 − φ1|
Δλ = |λ2 − λ1|, and if Δλ > 180 then Δλ = 360 − Δλ
φm = (φ1 + φ2) / 2

The wrap on Δλ handles segments that cross the 180° meridian. Convert angles to radians before any trigonometry.

3. Radii of Curvature at the Mean Latitude

M, the meridian radius, is the Earth's radius of curvature for travel north or south. N, the prime vertical radius, is its radius for travel east or west.

W = 1 − e² sin²(φm)
M = a (1 − e²) / W3/2
N = a / √W
4. Direction of Travel

Resolve the line segment into north and east components, in metres. Their ratio gives the direction of travel, α, without computing α itself.

northing = Δφ · M              (Δφ in radians)
easting  = Δλ · cos(φm) · N      (Δλ in radians)

cos²α = northing² / (northing² + easting²)
sin²α = easting²  / (northing² + easting²)

If both components are zero, the two positions are the same and the distance is zero.

5. Radius in the Direction of Travel

Euler's theorem gives the radius of curvature in any direction:

R = 1 / (cos²α / M + sin²α / N)

R equals M for travel due north or south, and N for travel due east or west. In any other direction it lies between the two.

6. Choose the Formula
span² = Δφ² + (Δλ · cos(φm))²      (Δφ and Δλ in degrees)

span² ≤ 0.45²   use the equirectangular formula
span² > 0.45²   use the haversine formula

A span of 0.45° is about 50 km. Below it, the flat-earth formula is as accurate as haversine, and faster. The test uses the whole span, so a diagonal segment switches formula at the same length as a north-south segment.

7a. Equirectangular Formula, for Segments up to About 50 km
x = Δλ · cos(φm)        (Δλ in radians)
y = φ2 − φ1              (radians)
distance = R · √(x² + y²)
7b. Haversine Formula, for Longer Segments
h = sin²((φ2 − φ1) / 2) + cos φ1 · cos φ2 · sin²(Δλ / 2)
distance = R · 2 · atan2(√h, √(1 − h))

The atan2 form stays accurate for very long segments, where the more common arcsine form loses precision.

Reference Implementation

This is the complete calculation in C-style pseudocode. It performs the arithmetic in the same order as TackTracker's own code, so an implementation using standard double-precision arithmetic will reproduce the worked examples below.

const double a   = 6378137.0;
const double f   = 1.0 / 298.257223563;
const double e2  = f * (2.0 - f);
const double DEG = 0.017453292519943295;   // pi / 180

double distance(double lat1, double lon1, double lat2, double lon2)
{
    // 2. Differences and mean latitude
    double dLat = abs(lat2 - lat1);
    double dLon = abs(lon2 - lon1);
    if (dLon > 180.0) dLon = 360.0 - dLon;
    double phim = ((lat1 + lat2) * 0.5) * DEG;

    // 3. Radii of curvature
    double s = sin(phim);
    double w = 1.0 - e2 * s * s;
    double M = a * (1.0 - e2) / (w * sqrt(w));
    double N = a / sqrt(w);

    // 4. Direction of travel
    double northing = (dLat * DEG) * M;
    double easting  = (dLon * DEG) * cos(phim) * N;
    double sum = northing * northing + easting * easting;
    if (sum == 0.0) return 0.0;
    double cos2 = (northing * northing) / sum;
    double sin2 = (easting * easting) / sum;

    // 5. Radius in the direction of travel
    double R = 1.0 / ((cos2 / M) + (sin2 / N));

    // 6. Choose the formula
    double spanX = dLon * cos(phim);
    if (dLat * dLat + spanX * spanX <= 0.45 * 0.45)
    {
        // 7a. Equirectangular
        double x = (dLon * DEG) * cos(phim);
        double y = (lat2 - lat1) * DEG;
        return R * sqrt(x * x + y * y);
    }

    // 7b. Haversine
    double sp = sin(((lat2 - lat1) * DEG) * 0.5);
    double sl = sin((dLon * DEG) * 0.5);
    double h  = sp * sp + cos(lat1 * DEG) * cos(lat2 * DEG) * (sl * sl);
    return R * (2.0 * atan2(sqrt(h), sqrt(1.0 - h)));
}

Worked Examples

Use these segments to check an implementation. The values are given to full double precision.

SegmentFromToFormulaDistance
A. Sydney Harbour-33.8500, 151.2500-33.8488, 151.2514Equirectangular185.75315091018112 m
B. Offshore run-33.8500, 151.2500-33.7200, 151.4200Equirectangular21350.004072398544 m
C. Coastal passage-33.8500, 151.2500-32.9300, 151.7800Haversine113328.56675719352 m
D. Across 180°-17.7000, 179.9500-17.6900, -179.9600Equirectangular9611.63652076639 m
E. On the equator0.0000, 150.00000.0010, 150.0010Equirectangular156.90435678766934 m

Intermediate values, for tracking down a difference:

LegMNcos²αRspan²
A6355228.8847292526384771.0736919760.5134634972345436369568.0130041880.000002791886026243269
B6355162.4139044086384748.8136765330.45614314068843456371219.0828995410.0368634613005486
C6354756.098907436384612.7419123640.81067469337703656360387.2689720491.0422241996339714
D6341321.2361661836380110.2394580780.0132592749999463586379592.821372280.007451676992154509
E6335439.3272976646378137.0000016260.496641606593702666356859.862249210.0000019999999999333956

Maths libraries differ slightly in how they round sine and cosine and cause small differences in your results.

How Accurate Is It?

These are the worst errors against the exact distance on the WGS-84 ellipsoid, computed with Karney's algorithm. They are taken over all directions of travel, at latitudes from the equator to 60°.

Leg lengthWorst errorAs a percentage
10 m0.1 mm0.00056%
100 m0.6 mm0.00056%
1 km6 mm0.00056%
10 km57 mm0.00057%
50 km0.47 m0.00093%
100 km0.56 m0.00056%
1000 km20.6 m0.0021%

The error peaks on legs just under 50 km, where the flat-earth formula is about to hand over to haversine. It drops again beyond that, and grows once more on legs of many hundreds of kilometres.

The worked examples above fall well within these limits. Leg C, for instance, is 187 mm longer than the exact distance over 113 km.

For comparison, a GPS fix is typically accurate to a few metres. Over the distances sailed in a race, the calculation adds far less error than the GPS itself.

Further Reading