On Fri, Sep 19, 2008 at 03:42:11AM +0200, Florian Heer wrote:

Bei einigen (ca. 20%) der Tracks, stimmen die Werte aber nicht (Fehler weit über 1%),
Fehler von 1% würde ich bei Deiner Formel durchaus erwarten. Nimm Vincenty's Algorithmus, der ist besser. Gibts auf [1] in JavaScript, meine Übersetzungen in C und Python habe ich angehängt. Lizenz ist LGPL.


[1] http://www.movable-type.co.uk/scripts/latlong-vincenty.html

CU Sascha

--
http://sascha.silbe.org/
http://www.infra-silbe.de/
# arch-tag: 413a3fa1-5a89-41f2-a905-0ad78cdd0267
from math import *

#############################################################################
##
## Copyright (C) 2002-2008 Chris Veness -- http://www.movable-type.co.uk/scripts/latlong-vincenty.html
## Copyright (C) 2007-2008 Sascha Silbe -- http://sascha.silbe.org/
##
## This file may be distributed and/or modified under the terms of the
## GNU Lesser General Public License version 2 as published by the Free
## Software Foundation and appearing in the file COPYING.LESSER included in
## the packaging of this file.
##
#############################################################################

# source of algorithm:
#       Vincenty direct formula - T Vincenty, "Direct and Inverse Solutions of Geodesics on the
#       Ellipsoid with application of nested equations", Survey Review, vol XXII no 176, 1975
#       http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf
#
# based on JavaScript implementation by Chris Veness, available at
# http://www.movable-type.co.uk/scripts/latlong-vincenty-direct.html
# Python implementation by Sascha Silbe
#
# License for original JavaScript implementation:
# JavaScript functions are shown below. You are welcome to re-use these scripts [without any warranty express or implied]
# provided you retain my copyright notice and when possible a link to my website (under a LGPL license). If you have any
# queries or find any problems, please contact me.
# (C) 2002-2008 Chris Veness


# WGS-84 ellipsiod
a = 6378137.
b = 6356752.3142
f = 1/298.257223563

def distance(p1, p2) :
  p1Lat = p1[0]*pi/180
  p1Lon = p1[1]*pi/180
  p2Lat = p2[0]*pi/180
  p2Lon = p2[1]*pi/180
  L = p2Lon - p1Lon
  U1 = atan((1-f) * tan(p1Lat))
  U2 = atan((1-f) * tan(p2Lat))
  sinU1 = sin(U1)
  cosU1 = cos(U1)
  sinU2 = sin(U2)
  cosU2 = cos(U2)
  Lambda = L
  LambdaP = 2*pi
  iterLimit = 20

  while ((fabs(Lambda-LambdaP) > 1e-12) and iterLimit) :
    iterLimit -= 1
    sinLambda = sin(Lambda)
    cosLambda = cos(Lambda)
    sinSigma = sqrt((cosU2*sinLambda) * (cosU2*sinLambda) +
      (cosU1*sinU2-sinU1*cosU2*cosLambda) * (cosU1*sinU2-sinU1*cosU2*cosLambda))

    if (sinSigma==0) :
      return 0, 0  # co-incident points

    cosSigma = sinU1*sinU2 + cosU1*cosU2*cosLambda
    sigma = atan2(sinSigma, cosSigma)
    sinAlpha = cosU1 * cosU2 * sinLambda / sinSigma
    cosSqAlpha = 1 - sinAlpha*sinAlpha
    if (cosSqAlpha == 0) :
      cos2SigmaM = 0  # equatorial line: cosSqAlpha=0 (Rule 6)
    else :
      cos2SigmaM = cosSigma - 2*sinU1*sinU2/cosSqAlpha

    C = f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha))
    LambdaP = Lambda
    Lambda = L + (1-C) * f * sinAlpha * (sigma + C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)))

  if (iterLimit==0) :
    # formula failed to converge
    return None, None

  uSq = cosSqAlpha * (a*a - b*b) / (b*b)
  A = 1 + uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq)))
  B = uSq/1024 * (256+uSq*(-128+uSq*(74-47*uSq)))
  deltaSigma = B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)-B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM)))
  s = b*A*(sigma-deltaSigma)
  # initial bearing
  bearing = atan2(cosU2*sinLambda, cosU1*sinU2 - sinU1*cosU2*cosLambda)*180/pi
  # final bearing
  # bearing = atan2(cosU1*sinLambda, -sinU1*cosU2 + cosU1*sinU2*cosLambda)*180/pi

  while (bearing < 0) :
    bearing += 360

  return s, bearing


def destination(origin, bearing, distance) :
  lat1, lon1 = origin
  s = float(distance)
  alpha1 = bearing*pi/180
  sinAlpha1 = sin(alpha1)
  cosAlpha1 = cos(alpha1)

  tanU1 = (1-f) * tan(lat1*pi/180)
  cosU1 = 1. / sqrt((1 + tanU1*tanU1))
  sinU1 = tanU1*cosU1
  sigma1 = atan2(tanU1, cosAlpha1)
  sinAlpha = cosU1 * sinAlpha1
  cosSqAlpha = 1 - sinAlpha*sinAlpha
  uSq = cosSqAlpha * (a*a - b*b) / (b*b)
  A = 1 + uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq)))
  B = uSq/1024 * (256+uSq*(-128+uSq*(74-47*uSq)))

  sigma = s / (b*A)
  sigmaP = 2*pi
  while (abs(sigma-sigmaP) > 1e-12) :
    cos2SigmaM = cos(2*sigma1 + sigma)
    sinSigma = sin(sigma)
    cosSigma = cos(sigma)
    deltaSigma = B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)-B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM)))
    sigmaP = sigma
    sigma = s / (b*A) + deltaSigma

  tmp = sinU1*sinSigma - cosU1*cosSigma*cosAlpha1
  lat2 = atan2(sinU1*cosSigma + cosU1*sinSigma*cosAlpha1, (1-f)*sqrt(sinAlpha*sinAlpha + tmp*tmp))
  Lambda = atan2(sinSigma*sinAlpha1, cosU1*cosSigma - sinU1*sinSigma*cosAlpha1)
  C = f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha))
  L = Lambda - (1-C) * f * sinAlpha * (sigma + C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)))

#  revAz = atan2(sinAlpha, -tmp)  # final bearing
  lat2D = lat2*180/pi
  lon2D = lon1+L*180/pi

  while (lat2D > 90) :
    lat2D -= 180

  while (lat2D < -90) :
    lat2D += 180

  while (lon2D > 180) :
    lon2D -= 360

  while (lon2D < -180) :
    lon2D += 360

  return (lat2D, lon2D)

// arch-tag: a7d2a3ab-1c56-4ef5-9edd-0c4f1a5de4dd
// #############################################################################
// ##
// ## Copyright (C) 2002-2008 Chris Veness -- http://www.movable-type.co.uk/scripts/latlong-vincenty.html
// ## Copyright (C) 2007-2008 Sascha Silbe -- http://sascha.silbe.org/
// ##
// ## This file may be distributed and/or modified under the terms of the
// ## GNU Lesser General Public License version 2 as published by the Free
// ## Software Foundation and appearing in the file COPYING.LESSER included in
// ## the packaging of this file.
// ##
// #############################################################################
#include <math.h>
#include <stdint.h>
#include "vincenty.h"

#ifndef M_PI
// M_PI was removed in C99 :-/
#define M_PI 3.14159265358979323846264338327
#endif

static double const a = 6378137., b = 6356752.3142,  f = 1/298.257223563;  // WGS-84 ellipsiod

double distance(double _p1Lon, double _p1Lat, double _p2Lon, double _p2Lat, double *bearing)
{
  const double p1Lat = _p1Lat*M_PI/180;
  const double p1Lon = _p1Lon*M_PI/180;
  const double p2Lat = _p2Lat*M_PI/180;
  const double p2Lon = _p2Lon*M_PI/180;
  const double L = p2Lon - p1Lon;
  const double U1 = atan((1-f) * tan(p1Lat));
  const double U2 = atan((1-f) * tan(p2Lat));
  const double sinU1 = sin(U1), cosU1 = cos(U1);
  const double sinU2 = sin(U2), cosU2 = cos(U2);
  double lambda = L, lambdaP = 2*M_PI;
  uint8_t iterLimit = 20;
  double sinLambda = 0., cosLambda = 0., sinSigma = 0., cosSigma = 0., sigma = 0., sinAlpha, cosSqAlpha = 0.;
  double cos2SigmaM = 0., C;
  double uSq, A, B, deltaSigma, s;

  while ((fabs(lambda-lambdaP) > 1e-12) && --iterLimit)
  {
    sinLambda = sin(lambda);
    cosLambda = cos(lambda);
    sinSigma = sqrt((cosU2*sinLambda) * (cosU2*sinLambda) +
      (cosU1*sinU2-sinU1*cosU2*cosLambda) * (cosU1*sinU2-sinU1*cosU2*cosLambda));

    if (sinSigma==0) return 0;  // co-incident points

    cosSigma = sinU1*sinU2 + cosU1*cosU2*cosLambda;
    sigma = atan2(sinSigma, cosSigma);
    sinAlpha = cosU1 * cosU2 * sinLambda / sinSigma;
    cosSqAlpha = 1 - sinAlpha*sinAlpha;
    cos2SigmaM = cosSigma - 2*sinU1*sinU2/cosSqAlpha;

    if (isnan(cos2SigmaM))
      cos2SigmaM = 0;  // equatorial line: cosSqAlpha=0 (§6)

    C = f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha));
    lambdaP = lambda;
    lambda = L + (1-C) * f * sinAlpha *
      (sigma + C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)));
  }

  if (iterLimit==0) return NAN;  // formula failed to converge

  uSq = cosSqAlpha * (a*a - b*b) / (b*b);
  A = 1 + uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq)));
  B = uSq/1024 * (256+uSq*(-128+uSq*(74-47*uSq)));
  deltaSigma = B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)-
    B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM)));
  s = b*A*(sigma-deltaSigma);
  if (bearing)
  // initial bearing
    *bearing = atan2(cosU2*sinLambda, cosU1*sinU2 - sinU1*cosU2*cosLambda)*180/M_PI;
  // final bearing
  //  *bearing = atan2(cosU1*sinLambda, -sinU1*cosU2 + cosU1*sinU2*cosLambda)*180/M_PI;

  return s;
}

void destination(double originLon, double originLat, double bearing, double distance, double *destLon, double *destLat)
{
  double lat1, lon1, s, alpha1, sinAlpha1, cosAlpha1;
  double tanU1, cosU1, sinU1, sigma1, sinAlpha, cosSqAlpha = 0., uSq, A, B, sigma, sigmaP;
  double cos2SigmaM = 0., sinSigma = 0., cosSigma = 0., deltaSigma, tmp, lat2, Lambda, C, L, lat2D, lon2D;

  lat1 = originLat;
  lon1 = originLon;
  s = distance;
  alpha1 = bearing*M_PI/180;
  sinAlpha1 = sin(alpha1);
  cosAlpha1 = cos(alpha1);

  tanU1 = (1-f) * tan(lat1*M_PI/180);
  cosU1 = 1. / sqrt((1 + tanU1*tanU1));
  sinU1 = tanU1*cosU1;
  sigma1 = atan2(tanU1, cosAlpha1);
  sinAlpha = cosU1 * sinAlpha1;
  cosSqAlpha = 1 - sinAlpha*sinAlpha;
  uSq = cosSqAlpha * (a*a - b*b) / (b*b);
  A = 1 + uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq)));
  B = uSq/1024 * (256+uSq*(-128+uSq*(74-47*uSq)));

  sigma = s / (b*A);
  sigmaP = 2*M_PI;
  while (fabs(sigma-sigmaP) > 1e-12)
  {
    cos2SigmaM = cos(2*sigma1 + sigma);
    sinSigma = sin(sigma);
    cosSigma = cos(sigma);
    deltaSigma = B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)-B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM)));
    sigmaP = sigma;
    sigma = s / (b*A) + deltaSigma;
  }

  tmp = sinU1*sinSigma - cosU1*cosSigma*cosAlpha1;
  lat2 = atan2(sinU1*cosSigma + cosU1*sinSigma*cosAlpha1, (1-f)*sqrt(sinAlpha*sinAlpha + tmp*tmp));
  Lambda = atan2(sinSigma*sinAlpha1, cosU1*cosSigma - sinU1*sinSigma*cosAlpha1);
  C = f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha));
  L = Lambda - (1-C) * f * sinAlpha * (sigma + C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)));

//  revAz = atan2(sinAlpha, -tmp)  # final bearing
  lat2D = lat2*180/M_PI;
  lon2D = lon1+L*180/M_PI;

  while (lat2D > 90)
    lat2D = lat2D - 180;

  while (lat2D < -90)
    lat2D = lat2D + 180;

  while (lon2D > 180)
    lon2D = lon2D - 360;

  while (lon2D < -180)
    lon2D = lon2D + 360;

  *destLon = lon2D;
  *destLat = lat2D;
}
// arch-tag: 0ad91b8e-ebf5-45ae-850f-541cb4fa3cc0
// #############################################################################
// ##
// ## Copyright (C) 2008 Sascha Silbe -- http://sascha.silbe.org/
// ##
// ## This file may be distributed and/or modified under the terms of the
// ## GNU Lesser General Public License version 2 as published by the Free
// ## Software Foundation and appearing in the file COPYING.LESSER included in
// ## the packaging of this file.
// ##
// #############################################################################
#ifndef __VINCENTY_H__
#define __VINCENTY_H__

double distance(double p1Lon, double p1Lat, double p2Lon, double p2Lat, double *bearing);
void destination(double originLon, double originLat, double bearing, double distance, double *destLon, double *destLat);

#endif

Attachment: signature.asc
Description: Digital signature

_______________________________________________
Talk-de mailing list
[email protected]
http://lists.openstreetmap.org/listinfo/talk-de

Antwort per Email an