openlayers – Difference Between ol.proj.getPointResolution() and ol.sphere.getDistance()

distanceopenlayers

Is there anyone who can explain the difference between ol.proj.getPointResolution() and ol.sphere.getDistance()?

I have tested it, and ol.sphere.getDistance() is a little bit shorter than ol.proj.getPointResolution().
In addition, I corrected the lengths by elevations with the Pythagoras.
Below an GPX example file.

Why is with "sphere" shortener? "sphere" calculate with a radius and not the direct distance, logical there must be greater. ???
The same difference exists everywhere on the map, also much further north, eg in Europe.

Only getLength(): 1322.334212854104

getLength() with pythagorean(): 1322.4583239930157

ol.proj.getPointResolution(): 1322.3120192140298

ol.proj.getPointResolution() with pythagorean(): 1322.436132435775

ol.sphere.getDistance(): 1320.834204523846

ol.sphere.getDistance() with pythagorean(): 1320.9584565960345

GPX Example (near equador) from brouter.de

<?xml version="1.0" encoding="UTF-8"?>
<!-- track-length = 1323 filtered ascend = 0 plain-ascend = -1 cost=4036 energy=.0kwh time=9.9m -->
<gpx 
 xmlns="http://www.topografix.com/GPX/1/1" 
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd" 
 creator="BRouter-1.4.11" version="1.1">
 <trk>
  <name>brouter_trekking_0</name>
  <trkseg>
   <trkpt lon="11.487967" lat="0.332443"><ele>319.0</ele></trkpt>
   <trkpt lon="11.488969" lat="0.332369"><ele>318.0</ele></trkpt>
   <trkpt lon="11.494446" lat="0.331905"><ele>309.0</ele></trkpt>
   <trkpt lon="11.499806" lat="0.331473"><ele>317.0</ele></trkpt>
  </trkseg>
 </trk>
</gpx>

Example what i mean:

enter image description here

1) is simple length() between two coords. (longest).
2) the earth is round, but a direct distance is "through" the earth. (shortest).
3) the earth is round and the distance is on the earths surface. (best).

TEST:

Result (single-calculation sum, in meter):

Near Equator short distance (4 points), manually set elevation (350,100,0,300):

brouter (inside GPX file) = 1323

ol.proj.getPointResolution() = 1322.3120192140298
ol.proj.getPointResolution() + pythagorean() = 1563.4324417597672

ol.sphere.getDistance() = 1320.834204523846
ol.sphere.getDistance() + pythagorean() = 1562.1085409935195

distVincenty() = 1322.2532472090315
distVincenty() + pythagorean() = 1563.379164847775


Near Equator long distance, 440 meter elevation range (min,max):

brouter (inside GPX file) = 385356

ol.proj.getPointResolution() = 384026.1115163949
ol.proj.getPointResolution() + pythagorean() = 384353.99178101047

ol.sphere.getDistance() = 383596.9242847851
ol.sphere.getDistance() + pythagorean() = 383925.16964882094

distVincenty() = 383079.99691655475
distVincenty() + pythagorean() = 383408.65056785266


Europe near Pyrenees long distance, 430 meter elevation range (min,max):

brouter (inside GPX file) = 144047

ol.proj.getPointResolution() = 142398.39352352163
ol.proj.getPointResolution() + pythagorean() = 142514.5599121801

ol.sphere.getDistance() = 142239.2492071166
ol.sphere.getDistance() + pythagorean() = 142355.53984053037

distVincenty() = 142463.4265797505
distVincenty() + pythagorean() = 142579.5329685958


Fazit: The joke is, the first was i notice, that the ol.proj.getPointResolution() is shorter than brouter. Than i test ol.sphere.getDistance(), and this was more shorter. Last i test distVincenty(), and this was once shorter and some longer than the other (Equator shorter, Europe longer), but shorter as brouter. Logical would be for me, though the ol.proj.getPointResolution() was the shortest and the distVincenty() was the longest. Does anyone have an explanation for that?

Best Answer

Sphere gives the shortest distance on a spherical planet. What appears to be a straight line on a flat map isn't the shortest distance that an aircraft would fly, especially over long distances such as London to Tokyo

enter image description here

distVincenty = function(p1, p2) {
    var ct = {
        a: 6378137,
        b: 6356752.3142,
        f: 1/298.257223563
    };
    var a = ct.a, b = ct.b, f = ct.f;

    var L = (p2.lon - p1.lon) * Math.PI/180;
    var U1 = Math.atan((1-f) * Math.tan(p1.lat*Math.PI/180));
    var U2 = Math.atan((1-f) * Math.tan(p2.lat*Math.PI/180));
    var sinU1 = Math.sin(U1), cosU1 = Math.cos(U1);
    var sinU2 = Math.sin(U2), cosU2 = Math.cos(U2);
    var lambda = L, lambdaP = 2*Math.PI;
    var iterLimit = 20;
    while (Math.abs(lambda-lambdaP) > 1e-12 && --iterLimit>0) {
        var sinLambda = Math.sin(lambda), cosLambda = Math.cos(lambda);
        var sinSigma = Math.sqrt((cosU2*sinLambda) * (cosU2*sinLambda) +
        (cosU1*sinU2-sinU1*cosU2*cosLambda) * (cosU1*sinU2-sinU1*cosU2*cosLambda));
        if (sinSigma==0) {
            return 0;  // co-incident points
        }
        var cosSigma = sinU1*sinU2 + cosU1*cosU2*cosLambda;
        var sigma = Math.atan2(sinSigma, cosSigma);
        var alpha = Math.asin(cosU1 * cosU2 * sinLambda / sinSigma);
        var cosSqAlpha = Math.cos(alpha) * Math.cos(alpha);
        var cos2SigmaM = cosSigma - 2*sinU1*sinU2/cosSqAlpha;
        var C = f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha));
        lambdaP = lambda;
        lambda = L + (1-C) * f * Math.sin(alpha) *
        (sigma + C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)));
    }
    if (iterLimit==0) {
        return NaN;  // formula failed to converge
    }
    var uSq = cosSqAlpha * (a*a - b*b) / (b*b);
    var A = 1 + uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq)));
    var B = uSq/1024 * (256+uSq*(-128+uSq*(74-47*uSq)));
    var deltaSigma = B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)-
        B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM)));
    var s = b*A*(sigma-deltaSigma);
    var d = s.toFixed(3)/1000; // round to 1mm precision
    return d;
};