make - Fórmula Haversine con php
php google maps example (5)
Calculo las distancias directamente dentro de las consultas, utilizando el siguiente procedimiento almacenado:
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|
Simplemente ejecute lo anterior como una declaración SQl desde phpMyAdmin para crear el procedimiento. Solo note el final |, entonces en su ventana de entrada de SQL, elija para el | firmar como limitador.
Luego, en una consulta, llámalo así:
$sql = "
SELECT `locations`.`name`, GEODIST(`locations`.`lat`, `locations`.`lon`, " . $lat_to_calculate . ", " . $lon_to_calculate . ") AS `distance`
FROM `locations` ";
Descubrí que esto es mucho más rápido que calcularlo en PHP después de ejecutar la consulta.
Quiero usar esta fórmula con php. Tengo una base de datos con algunos valores de latitud y longitud guardados.
Quiero encontrar, con un cierto valor de latitud y longitud en la entrada, todas las distancias (en km) desde este punto con cada punto de la base de datos. Para hacer esto, usé la fórmula en googlemaps api:
( 6371 * acos( cos( radians(37) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(-122) ) + sin( radians(37) ) * sin( radians( lat ) ) ) )
Por supuesto, usando php reemplazé los radianes con deg2rad
. Los valores 37, -122 son mis valores de entrada y lat, lng son mis valores en la base de datos.
Abajo hay mi código. El problema es que hay algo mal pero no entiendo qué. El valor de la distancia es, por supuesto, incorrecto.
//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))))) );
}
Para valores, por ejemplo: $ lat = 41.9133741000 $ lng = 12.5203944000
Tengo la salida de la distancia = "4826.9341106926"
Estoy haciendo la clase de diseño que tiene la función estática getDistance teniendo los cuatro parámetros y devuelve la distancia desde los puntos de ubicación del bot
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;
}
}
la clase anterior se almacena en el directorio raíz y el directorio raíz contiene clases carpeta Llame a esto utilizando la siguiente forma en cualquier página php
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;
La salida es como sigue
4.7676529976827
La fórmula que usaste , parece ser la arccosina en lugar de la fórmula de haversina . La fórmula de haversine es más apropiada para calcular la distancia en una esfera, ya que no es propensa a errores de redondeo con puntos antípodas.
/**
* 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;
}
PS No pude encontrar un error en su código, ¿es solo un error tipográfico que escribió $lat= 41.9133741000 $lat= 12.5203944000
? Tal vez acaba de calcular con $ lat = 12.5203944000 y $ long = 0 porque sobrescribió su variable $ lat.
Editar:
Probó el código y devolvió un resultado correcto:
$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
desde este enlace :
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;
}
Como puede ver, hay muchas diferencias entre esto como su código. No sé si tiene un enfoque diferente de la fórmula o tal vez algún paso al convertir a PHP salió mal, pero la fórmula anterior debería funcionar.
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
}