Margin-Auto: Entfernung zwischen zwei Punkten auf der Erdoberfläche

Hi,

ich bin auf der Suche nach einem Codebeispiel, mittels dessen sich die Entfernung zwischen zwei Punkten auf der Erdoberfläche berechnen lässt. Zu den Punkten liegen die (Kugel-)Koordinaten vor, also bspw. 52.5145° östl. Breite/13.3501° nördl. Länge.

Ich habe bereits das hier gefunden und nach Perl übersetzt. Das liefert mir jedoch (mit zunehmender Entfernung) abweichende Werte. (Verglichen mit der Entfernungsmessung bspw. in GoogleEarth oder dem hier)

Kann da jemand helfen?

TIA

Margin-Auto

  1. Hallo Margin-Auto,

    Kann da jemand helfen?

    Schau mal in der FAQ von OpenGeoDB.

    Mit freundlichem Gruß
    Micha

    1. Hi,

      Schau mal in der FAQ von OpenGeoDB.

      Danke für den Hinweis. Ich habs jetzt so gemacht:

        
      sub distance{  
       my ($lat1,$long1,$lat2,$long2) = @_;  
        
       $lat1=torad($lat1);  
       $long1=torad($long1);  
       $lat2=torad($lat2);  
       $long2=torad($long2);  
        
       my $a = sin($lat1) * sin($lat2);  
       my $b = cos($lat1) * cos($lat2) * cos($long2 - $long1);  
       my $c = acos($a + $b);  
       return 6380000 * $c;  
      }  
        
      sub torad{  
       return $_[0]*(3.14159265 / 180);  
      }  
        
      sub acos{  
       return atan2(sqrt(1-$_[0]*$_[0]), $_[0]);  
      }  
      
      

      Weicht zwar immer noch von Google Earth ab, ist aber wesentlich genauer als der erste Versuch. Wenn jemand noch was Besseres weiss....

      Margin-Auto

      1. Hallo,

        Weicht zwar immer noch von Google Earth ab, ist aber wesentlich genauer als der erste Versuch. Wenn jemand noch was Besseres weiss....

        schau' Dir mal die von Norbert in diesem Archivposting verlinkte Klasse zur Abstandsberechnung an.
        Vielleicht ist die ja besser.

        Freundliche Grüße

        Vinzenz

        1. Hi,

          schau' Dir mal die von Norbert in diesem Archivposting verlinkte Klasse zur Abstandsberechnung an.
          Vielleicht ist die ja besser.

          Danke für den Hinweis, aber auch das ist nicht viel genauer. Für die (willkürlich gewählten) Punkte

          6.703656°E 48.248512°N
          7.557858°E 48.251641°N

          komme ich mittels der verlinkten PHP-Klasse auf 95,303 km Entfernung, mit der Formel aus openGeoDB auf 95,117. Google Earth behauptet jedoch 63,25 km, was mir auch plausibel erscheint.

          Ratlose Grüße

          Margin-Auto

          1. Hallo,

            schau' Dir mal die von Norbert in diesem Archivposting verlinkte Klasse zur Abstandsberechnung an.

            Danke für den Hinweis, aber auch das ist nicht viel genauer. Für die (willkürlich gewählten) Punkte

            6.703656°E 48.248512°N
            7.557858°E 48.251641°N

            komme ich mittels der verlinkten PHP-Klasse auf 95,303 km Entfernung, mit der Formel aus openGeoDB auf 95,117. Google Earth behauptet jedoch 63,25 km, was mir auch plausibel erscheint.

            tja, ich hab' sie auch nicht selbst durchgetestet :-)

            Eine schnelle Abschätzung: Unterschied in der Nordkoordinate vernachlässigt, da nur ca. 10 Bogensekunden und somit noch kein Kilometer. Geoid-Korrektur vernachlässigt, da Abstände gering, damit komme ich auf 63,2 Kilometer. Passt und ähnlich wirst Du es abgeschätzt haben.

            Freundliche Grüße

            Vinzenz

          2. Hallo

            schau' Dir mal die von Norbert in diesem Archivposting verlinkte Klasse zur Abstandsberechnung an.
            Vielleicht ist die ja besser.

            Danke für den Hinweis, aber auch das ist nicht viel genauer. Für die (willkürlich gewählten) Punkte

            6.730656°E 48.248512°N
            7.557858°E 48.251641°N

            komme ich mittels der verlinkten PHP-Klasse auf 95,303 km Entfernung,

            dann wendest Du die Klasse falsch an.
            Es geht nur um die Klasse, nicht Norberts restlichen Code. Dort baut er nämlich Fehler ein, die ich in einem Folgeposting seziert habe - leider ohne eine Antwort zu bekommen :-(

            mit der Formel aus openGeoDB auf 95,117. Google Earth behauptet jedoch 63,25 km, was mir auch plausibel erscheint.

            Mir liefert die Klasse bei den von Dir angegebenen Daten 63,05 km, was ebenfalls plausibel ist :-)

            Die Differenz von 200 Metern halte ich für vernachlässigbar.

            Freundliche Grüße

            Vinzenz

            1. Hi,

              dann wendest Du die Klasse falsch an.
              Es geht nur um die Klasse, nicht Norberts restlichen Code. Dort baut er nämlich Fehler ein, die ich in einem Folgeposting seziert habe - leider ohne eine Antwort zu bekommen :-(

              Ich habe die Klasse folgendermaßen nach Perl übersetzt:

                
              sub luftlinie{  
               my ($lat1,$long1,$lat2,$long2) = @_;  
                
               $lat1=torad($lat1);  
               $long1=torad($long1);  
               $lat2=torad($lat2);  
               $long2=torad($long2);  
                
               my $phi1 = ellipsoid($lat1);  
               my $phi2 = ellipsoid($lat2);  
                
               my $zw1 = sin($phi1) * sin($phi2);  
               my $zw2 = cos($phi1) * cos($phi2);  
               my $zw3 = cos($long2 - $long1);  
                
               return 6371 * acos($zw1 + $zw2 * $zw3);  
              }  
              sub torad{  
               return $_[0]*(3.14159265 / 180);  
              }  
                
              sub tan{return (sin($_[0])/cos($_[0]))}  
                
              sub acos{return atan2(sqrt(1-$_[0]*$_[0]), $_[0]);}  
                
              sub ellipsoid{  
               return 298.2 * tan($_[0] / 297.2);  
              }  
              
              

              Ich kann da keinen sinngemäßen Unterschied zum Original erkennen. Wo liegt mein Denkfehler? Für die Umwandlung ins Bogenmaß habe ich meine eigene Funktion verwendet, da ich nicht verstehe, warum er ein seiner Funktion

                
              function get_BogMss($sc)  
               {return ((doubleval($sc) / 3600) * M_PI / 180);  
                }  
              
              

              den Wert durch 3600 teilt. Verwende ich diese Funktion, kommt noch größerer Blödsinn raus.

              Margin-Auto

              1. Hallo

                Ich kann da keinen sinngemäßen Unterschied zum Original erkennen.

                  
                 my ($lat1,$long1,$lat2,$long2) = @_;  
                  
                 $lat1=torad($lat1);  
                 $long1=torad($long1);  
                 $lat2=torad($lat2);  
                 $long2=torad($long2);  
                  
                 my $phi1 = ellipsoid($lat1);  
                 my $phi2 = ellipsoid($lat2);  
                
                

                Wo liegt mein Denkfehler?

                Du musst ellipsoid auf die Länge und nicht auf die Breite anwenden. Da liegt der Hase im Pfeffer.

                Für die Umwandlung ins Bogenmaß habe ich meine eigene Funktion verwendet, da ich nicht verstehe, warum er ein seiner Funktion

                function get_BogMss($sc)
                {return ((doubleval($sc) / 3600) * M_PI / 180);
                  }

                
                >   
                > den Wert durch 3600 teilt. Verwende ich diese Funktion, kommt noch größerer Blödsinn raus.  
                  
                Weil, wie es in der Dokumentation der Klasse steht, die Übergabewerte als Gradsekunden betrachtet werden, was man aus dem Namen des Funktionsparameters ablesen kann. Es gibt gewisse Dinge, die ich an Perl nicht mag, zum Beispiel solche subs wie Deine to\_rad. Ich mag benannte Parameter :-)  
                  
                Ich bin in Perl nicht so geübt, aber Du setzt die Funktion atan2 voraus und schreibst Dir Deine eigene Tangens und Arcuscosinus-Funktion. Ich kann mir nicht vorstellen, dass diese in Perl nicht eingebaut sein sollten.  
                  
                Wie wäre es mit [Math::Trig](http://perldoc.perl.org/Math/Trig.html)?  
                  
                  
                Freundliche Grüße  
                  
                Vinzenz
                
                1. Hi,

                  Du musst ellipsoid auf die Länge und nicht auf die Breite anwenden. Da liegt der Hase im Pfeffer.

                  Warum?
                  In der Klasse heisst es:

                  function luftlinie($strt, $ziel) // array($nord, $ost)
                  $phi[0] = $this->ellipsoid($this->get_BogMss($strt[0]));
                  $phi[1] = $this->ellipsoid($this->get_BogMss($ziel[0]));

                  Die nördliche Breite ist also das jeweils erste Element des Arrays, und das wird dann mit $strt[0] bzw. $ziel[0] auch dem Ellipsoid vorgeworfen. (Blöd, dass die Parameter nicht benannt sind ;-) )

                  Ich bin in Perl nicht so geübt, aber Du setzt die Funktion atan2 voraus und schreibst Dir Deine eigene Tangens und Arcuscosinus-Funktion. Ich kann mir nicht vorstellen, dass diese in Perl nicht eingebaut sein sollten.

                  tan und acos sind in Perl ohne zusätzliche Module nicht vorhanden. Und da das Vorhandensein bzw. die Nachinstallation einzelner Module bei meinem Homepage-Hoster (wo das Skript mal landen soll) immer eine kritische Sache ist, schreibe ich mir solche Sachen gerne selbst. Zumal es ja nur recht einfache Einzeiler sind.

                  Margin-Auto

      2. Hallo Margin-Auto,

        Weicht zwar immer noch von Google Earth ab

        ... die ggf. auf einem Referenzellipsoid (WGS84) rechnen.

        Mit freundlichem Gruß
        Micha