2013-02-07 10 views
16

Ich möchte diese Formel mit PHP verwenden. Ich habe eine Datenbank mit einigen Werten von Längen- und Breitengrad gespeichert.Haversine Formel mit PHP

Ich möchte mit einem bestimmten Wert von Breite und Länge in der Eingabe alle Entfernungen (in km) von diesem Punkt mit jedem Punkt in der Datenbank finden. Dazu habe ich die Formel auf Googlemaps api:

(6371 * acos(cos(radians(37)) * cos(radians(lat)) * cos(radians(lng) - radians(-122)) + sin(radians(37)) * sin(radians(lat)))) 

Natürlich mit, dass in PHP ich Radiant ersetzt mit deg2rad .Der 37 Werte, -122 meine Werte eingegeben werden und lat, lng sind meine Werte in die Datenbank.

Unten ist mein Code. Das Problem ist, dass etwas nicht stimmt, aber ich verstehe nicht was. Der Wert der Entfernung ist natürlich falsch.

//values of latitude and longitute in input (Rome - eur, IT) 
$center_lat = "41.8350"; 
$center_lng = "12.470"; 

//connection to database. it works 
(..) 

//to take each value in the database: 
    $query = "SELECT * FROM Dati"; 
    $result = mysql_query($query); 
    while ($row = @mysql_fetch_assoc($result)){ 
     $lat=$row['Lat']); 
     $lng=$row['Lng']); 
    $distance =(6371 * acos((cos(deg2rad($center_lat))) * (cos(deg2rad($lat))) * (cos(deg2rad($lng) - deg2rad($center_lng)))+ ((sin(deg2rad($center_lat))) * (sin(deg2rad($lat)))))); 
    } 

Für Werte zum Beispiel: $ lat = 41,9133741000 $ lng = 12,5203944000

Ich habe die Ausgabe von Abstand = "4826,9341106926"

+0

folgen Ihre Klammern –

Antwort

43

Die Formel, die Sie verwendet haben, scheint die arccosine anstelle der hairsine Formel zu sein. Die hairsine-Formel ist in der Tat geeigneter, um den Abstand auf einer Kugel zu berechnen, da sie nicht anfällig für Rundungsfehler mit antipodischen Punkten ist.

/** 
* Calculates the great-circle distance between two points, with 
* the Haversine formula. 
* @param float $latitudeFrom Latitude of start point in [deg decimal] 
* @param float $longitudeFrom Longitude of start point in [deg decimal] 
* @param float $latitudeTo Latitude of target point in [deg decimal] 
* @param float $longitudeTo Longitude of target point in [deg decimal] 
* @param float $earthRadius Mean earth radius in [m] 
* @return float Distance between points in [m] (same as earthRadius) 
*/ 
function haversineGreatCircleDistance(
    $latitudeFrom, $longitudeFrom, $latitudeTo, $longitudeTo, $earthRadius = 6371000) 
{ 
    // convert from degrees to radians 
    $latFrom = deg2rad($latitudeFrom); 
    $lonFrom = deg2rad($longitudeFrom); 
    $latTo = deg2rad($latitudeTo); 
    $lonTo = deg2rad($longitudeTo); 

    $latDelta = $latTo - $latFrom; 
    $lonDelta = $lonTo - $lonFrom; 

    $angle = 2 * asin(sqrt(pow(sin($latDelta/2), 2) + 
    cos($latFrom) * cos($latTo) * pow(sin($lonDelta/2), 2))); 
    return $angle * $earthRadius; 
} 

P.S. Ich konnte keinen Fehler in Ihrem Code finden, also ist es nur ein Tippfehler, den Sie geschrieben haben $lat= 41.9133741000 $lat= 12.5203944000? Vielleicht haben Sie gerade mit $ lat = 12.5203944000 und $ long = 0 gerechnet, weil Sie Ihre $ lat Variable überschrieben haben.

Edit:

den Code getestet und es ergab ein richtiges Ergebnis:

$center_lat = 41.8350; 
$center_lng = 12.470; 
$lat = 41.9133741000; 
$lng = 12.5203944000; 

// test with your arccosine formula 
$distance =(6371 * acos((cos(deg2rad($center_lat))) * (cos(deg2rad($lat))) * (cos(deg2rad($lng) - deg2rad($center_lng)))+ ((sin(deg2rad($center_lat))) * (sin(deg2rad($lat)))))); 
print($distance); // prints 9.662174538188 

// test with my haversine formula 
$distance = haversineGreatCircleDistance($center_lat, $center_lng, $lat, $lng, 6371); 
print($distance); // prints 9.6621745381693 
+0

Entschuldigung, ja, es ist nur ein Fehler im Test der Frage, natürlich in dem Code, den ich verwendet $ Lat und $ lng –

+0

Ich nahm die Formel [hier] (https://developers.google.com/maps/articles/ phpsqlsearch_v3? hl = es # findnearsql). mit Ihrer Funktion habe ich (mit dem gleichen Eingang oben) den Ausgang von "4826934.1106926". Warum? –

+0

@ user1938352 - Haben Sie versucht, die Variable als Zahl anstelle einer Zeichenfolge zu deklarieren? Ihr Beispiel verwendet '$ center_lat =" 41.8350 ";' wo es '$ center_lat = 41.8350;' sein sollte, analysiert es vielleicht das '.' als Tausendertrennzeichen abhängig von Ihren Gebietsschemaeinstellungen. – martinstoeckli

1

von this link:

function getDistance($latitude1, $longitude1, $latitude2, $longitude2) { 
    $earth_radius = 6371; 

    $dLat = deg2rad($latitude2 - $latitude1); 
    $dLon = deg2rad($longitude2 - $longitude1); 

    $a = sin($dLat/2) * sin($dLat/2) + cos(deg2rad($latitude1)) * cos(deg2rad($latitude2)) * sin($dLon/2) * sin($dLon/2); 
    $c = 2 * asin(sqrt($a)); 
    $d = $earth_radius * $c; 

    return $d; 
} 

Wie Sie sehen können, gibt es viele Unterschiede zwischen Ihrem Code. Ich weiß nicht, ob Sie einen anderen Ansatz für die Formel haben oder vielleicht ein Schritt bei der Konvertierung zu PHP schief ging, aber die obige Formel sollte funktionieren.

+0

dieses Gebens prüfen ich die gleiche Ausgabe meiner Methode, so denke ich, dass das Problem in den Werten der Eingabe ist. Aber wo ist der Fehler? –

1

I berechnen Entfernungen gerade innerhalb von Abfragen, die folgende gespeicherte Prozedur:

CREATE FUNCTION GEODIST (lat1 DOUBLE, lon1 DOUBLE, lat2 DOUBLE, lon2 DOUBLE) 
    RETURNS DOUBLE 
    DETERMINISTIC 
     BEGIN 
      DECLARE dist DOUBLE; 
      SET dist = round(acos(cos(radians(lat1))*cos(radians(lon1))*cos(radians(lat2))*cos(radians(lon2)) + cos(radians(lat1))*sin(radians(lon1))*cos(radians(lat2))*sin(radians(lon2)) + sin(radians(lat1))*sin(radians(lat2))) * 6378.8, 1); 
      RETURN dist; 
     END| 

Sie einfach die oben als SQL-Anweisung ausführen aus phpMyAdmin die Prozedur zu erstellen. Beachten Sie die Endung |, und wählen Sie in Ihrem SQL-Eingabefenster die Option | als Limiter signieren.

Dann in einer Abfrage, es so nennen:

$sql = " 
SELECT `locations`.`name`, GEODIST(`locations`.`lat`, `locations`.`lon`, " . $lat_to_calculate . ", " . $lon_to_calculate . ") AS `distance` 
FROM `locations` "; 

ich dies fand viel schneller zu sein, als es in PHP Berechnung nachdem die Abfrage ausgeführt wurde.

+0

Übrigens berechnet dies die Entfernung in Metern, also könnte man sie durch 1000 teilen oder irgendwie umrechnen, um KM zu berechnen. – CyberBrain

2
public function getDistanceBetweenTwoPoints($point1 , $point2){ 
    // array of lat-long i.e $point1 = [lat,long] 
    $earthRadius = 6371; // earth radius in km 
    $point1Lat = $point1[0]; 
    $point2Lat =$point2[0]; 
    $deltaLat = deg2rad($point2Lat - $point1Lat); 
    $point1Long =$point1[1]; 
    $point2Long =$point2[1]; 
    $deltaLong = deg2rad($point2Long - $point1Long); 
    $a = sin($deltaLat/2) * sin($deltaLat/2) + cos(deg2rad($point1Lat)) * cos(deg2rad($point2Lat)) * sin($deltaLong/2) * sin($deltaLong/2); 
    $c = 2 * atan2(sqrt($a), sqrt(1-$a)); 

    $distance = $earthRadius * $c; 
    return $distance; // in km 
} 
0

ich die Klasse von haversign machen, die die statische fuction mit getDistance die vier paramters mit und Rückkehr die Entfernung vom Standort des Botes

class HaverSign { 

    public static function getDistance($latitude1, $longitude1, $latitude2, $longitude2) { 
     $earth_radius = 6371; 

     $dLat = deg2rad($latitude2 - $latitude1); 
     $dLon = deg2rad($longitude2 - $longitude1); 

     $a = sin($dLat/2) * sin($dLat/2) + cos(deg2rad($latitude1)) * cos(deg2rad($latitude2)) * sin($dLon/2) * sin($dLon/2); 
     $c = 2 * asin(sqrt($a)); 
     $d = $earth_radius * $c; 

     return $d; 
} 
} 

oben Klasse wird im Stammverzeichnis und das Stammverzeichnis enthält Klassen Ordner Rufen Sie diese mithilfe der folgenden Art und Weise in jeder PHP-Seite

include "../classes/HaverSign.php"; 
$haversign=new HaverSign(); 

$lat=18.5204; 
$lon=73.8567; 

$lat1=18.5404; 
$lon1=73.8167; 

$dist = $haversign->getDistance($lat,$lon,$lat1,$lon1); 
echo $dist; 

Ausgang ist gespeichert, wie

4.7676529976827