Probleme bei Umsetzung der Semiversus Formel

preko

Erfahrenes Mitglied
Hi,

ich habe die Semiversus Formel (s. JPG-Datei im Anhang), die ich für eine Berechnung in PHP "übersetzen" muss, allerdings schier daran verzweifle.

Ich habe mir folgendes vorgestellt (wobei ich weiss, dass es fehlerhaft ist, daher bitte ich ja dringendst um Hilfe) - zumindest müsste es sinngemäß so in etwa umgesetzt werden:
Code:
d = 2arcsin(sqrt(((sin^2*(($phi_2-$phi_1)/2))+cos($phi_1)*cos($phi_2)*(sin^2*(($lambda_2-$lambda_1)/2))))

Der Code, den ich bisher habe sieht im Prinzip so aus:
PHP:
<?php
include("class.inc.php");

//Koordinaten Ort Nr. 1 LAT (Breitengrad)
$phi_1 = '50.93895982764574';

//Koordinaten Ort Nr. 1 LONG (Laengengrad)
$phi_2 = '6.9577789306640625';

//Koordinaten Ort Nr. 2 LAT (Breitengrad)
$lambda_1 = '51.22279768927183';

//Koordinaten Ort Nr. 2 LONG (Laengengrad)
$lambda_2 = '6.785430908203125';

//Erdradius 6378.137 km
$erdradius = '6378.137';

// Hier soll die o. g. Formel erscheinen
$d = 2arcsin(sqrt(((sin^2*(($phi_2-$phi_1)/2))+cos($phi_1)*cos($phi_2)*(sin^2*(($lambda_2-$lambda_1)/2))));

// Oberflaechenentfernung
$entfernung = $erdradius*$d;

echo "Entfernung: ".$entfernung." km";
?>

Hat jemand (bitte) die rettende Lösung - hänge jetzt schon den ganzen Nachmittag dran?


Beste Grüße,
preko
 

Anhänge

  • Semiversus_Formel.jpg
    Semiversus_Formel.jpg
    9,5 KB · Aufrufe: 180
Hi,

wenn ich die Formel richtig lese:

PHP:
$d = 2 * asin(
   sqrt(
      pow(sin(($phi_2-$phi_1)/2), 2)
      + cos($phi_1)*cos($phi_2)
   )
   * pow(sin(($lambda_2-$lambda_1)/2), 2)
);

Die Zeilenumbrüche und Einrückungen sind natürlich nur gegen Augenkrebs.

LG
 
@ kuddeldaddeldu:

Super, die Umsetzung ist, soweit ich es beurteilen kann absolut richtig, allerdings habe ich einen Fehler gemacht bei der Grafik. Die Wurzel war - aus welchen Gründen auch immer - nicht richtig dargestellt. Ich habe die korrigierte Grafik in den Anhang gepackt.

Ich habe mich auch an die Umsetzung/Änderung der Formel gemacht, allerdings kann das Ergebnis nicht richtig sein, da es viel zu hoch ausfällt:
PHP:
$d = 2 * asin( 
   sqrt( 
      (
        pow(sin(($phi_2-$phi_1)/2), 2) 
        + cos($phi_1)*cos($phi_2)
      )
      * pow(sin(($lambda_2-$lambda_1)/2), 2) 
   )  
);
Gibt es vielleicht eine Idee dazu?


Beste Grüße,
preko

Sorry, Anhang fehlte im Eifer des Gefechts. :eek:

Wird hiermit nachgeliefert. :)
 

Anhänge

  • Semiversus_Formel.jpg
    Semiversus_Formel.jpg
    9,6 KB · Aufrufe: 85
Hi,

eigentlich hast Du die Klammern gemäß der Formel gesetzt. Kann es sein, dass die Formel noch nicht stimmt? Hier unter Punkt 2 z.B. fehlen die Klammern, die Du da im Code noch eingefügt hast.

Das sähe dann so aus:
PHP:
$d = 2 * asin( 
   sqrt( 
        pow(sin(($phi_2-$phi_1)/2), 2) 
        + cos($phi_1) * cos($phi_2) * pow(sin(($lambda_2-$lambda_1)/2), 2) 
   )  
);

LG

EDIT//

Übrigens sind die Phi-Platzhalter die Lat-Werte und die Lambda-Platzhalter die Lon-Werte. Demnach müssten Deine Variablen eigentlich so gefüllt werden:

PHP:
//Koordinaten Ort Nr. 1 LAT (Breitengrad)
$phi_1 = '50.93895982764574';

//Koordinaten Ort Nr. 1 LONG (Laengengrad)
$lambda_1 = '6.9577789306640625';

//Koordinaten Ort Nr. 2 LAT (Breitengrad)
$phi_2 = '51.22279768927183';

//Koordinaten Ort Nr. 2 LONG (Laengengrad)
$lambda_2 = '6.785430908203125';
 
Zuletzt bearbeitet:
Wie bereits geschrieben - in meinem Link bekommst du die Formel auf Seite 3 geliefert - musst nur noch auf deine Bedürfnisse umbauen.

Eine andere Möglichkeit ist die Funktion getDistance aus der gmapper-Klasse zu verwenden.

Wie du siehst erwartet die Funktion getDistance ein (Mehrdimensionales) Array mit den Koordinaten des Startortes und des Zielortes. Mit dieser Funktion kannst du auch die Distanz über mehrere Punkte ausgeben. Einfach das Array um die weiteren Punkte erweitern.

PHP:
function getDistance($koord)
    {
        if (!is_array($koord))
        {
            return false;
        }

        $ent = 0;
        $welt = 6378.137; // Erdradius, ca. Angabe

        foreach($koord as $key => $fetch)
        {
            if (isset($koord[$key + 1]))
            {
                $erste_breite = $koord[$key][0]; // lat
                $erste_laenge = $koord[$key][1]; // lon
                $erste_breite_rad = deg2rad($erste_breite);
                $erste_laenge_rad = deg2rad($erste_laenge);

                $zweite_breite = $koord[$key + 1][0]; // lat
                $zweite_laenge = $koord[$key + 1][1]; // lon
                $zweite_breite_rad = deg2rad($zweite_breite);
                $zweite_laenge_rad = deg2rad($zweite_laenge);

                $dis = acos(
                    (sin($erste_breite_rad) * sin($zweite_breite_rad)) +
                    (cos($erste_breite_rad) * cos($zweite_breite_rad) *
                        cos($zweite_laenge_rad - $erste_laenge_rad))) * $welt;

                $ent = $ent + $dis;
            }
        }
        $entfernung = $ent * 1000;
        return round($entfernung, 0);
    }
 
Zuletzt bearbeitet:
@ dwex:

herzlichen Dank für den Lösungsweg - das war´s was ich gebraucht habe. Ich habe mir erlaubt einige Anpassungen vorzunehmen, wie das nachfolgende Listing zeigt.

Hier die Datenbankstruktur:
SQL:
CREATE TABLE IF NOT EXISTS `ts_geocoding` (
  `id` bigint(255) NOT NULL auto_increment,
  `postalcode` varchar(10) collate utf8_unicode_ci NOT NULL,
  `lat` varchar(20) collate utf8_unicode_ci NOT NULL,
  `long` varchar(20) collate utf8_unicode_ci NOT NULL,
  `city` varchar(30) collate utf8_unicode_ci NOT NULL,
  `city_int` varchar(50) collate utf8_unicode_ci NOT NULL,
  `country_short` varchar(5) collate utf8_unicode_ci NOT NULL,
  PRIMARY KEY  (`id`),
  KEY `city` (`city`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;

Und hier die relevanten Codezeilen:
PHP:
<?php
include("db_access.php");

// Die Zahl PI als Variable
$pi = '3.1415926535';

// Koordinaten des Ortes 
$ort = "K&ouml;ln"; 
$ursprungsbreite = 50.9407; 
$ursprungslaenge = 6.9599; 

// max. Km-Entfernung von Startort 
$entf = '100'; 

echo "<p>Folgende grössere Orte liegen im Radius von $entf km um $ort:</p>"; 

// Berechnungsvariablen Teil 1
$alpha = 180*$entf/(6378137/1000*$pi); 
$geo1 = $ursprungsbreite-$alpha; 
$geo2 = $ursprungsbreite+$alpha; 
$geo3 = $ursprungslaenge-$alpha; 
$geo4 = $ursprungslaenge+$alpha;
$a = $ursprungsbreite/180*$pi; 
$b = $ursprungslaenge/180*$pi; 

// Zählervariable
$z = 1; 

// Datenbankzugriff und Query
    $db = @mysql_connect($host1,$user,$password)
        or die ("Verbindung mit Datenbankserver fehlgeschlagen!");
    @mysql_select_db($database,$db)
        or die ("Verbindung mit Datenbank fehlgeschlagen!");
    $sql_query = ("SELECT 
								* 
						FROM 
								`db_geocoding` 
						WHERE 
								(`lat` >= '$geo1') 
						AND 
								(`lat` <= '$geo2') 
						AND 
								(`long` >= '$geo3') 
						AND 
								(`long` <= '$geo4')
						AND
						 	    (`city_int` != '$ort')
					"); 
    $result = mysql_query($sql_query);
	while( $row = mysql_fetch_array($result,MYSQL_ASSOC) ) {

		// Berechnungsvariablen Teil 2	
		$c = $row['lat']; 
		$d = $row['long']; 
		$c = $c/180*$pi; 
		$d = $d/180*$pi; 

		$e = sin($a)*sin($c); 
		$f = cos($a)*cos($c)*cos($d-$b); 
		$g = acos($e + $f); 
		$h = $g * 6378.137; 
		$ausgabe = sprintf("%01.2f", $h);
			if($ausgabe > $entf) { 
					continue; 
				} 
		$ausgabe = str_replace(".", ",", $ausgabe); 

		echo "$z - Nach <strong>".$row['city_int']."</strong> sind es $ausgabe km.<br><hr />"; 
		$z++; 
	} 
?>


Beste Grüße,
preko
 
Zuletzt bearbeitet von einem Moderator:
Es freut mich, dass ich dir weiterhelfen konnte.
Ich würde mich über eine Bewertung meines Beitrages sehr freuen.
 

Neue Beiträge

Zurück