2012-09-15 17 views
12

He visto tantas funciones pero resulta que solo funciona para MySQL o Postgresql. Quiero la lógica equivalente para PHP. Estoy haciendo algunas comparaciones, como si tuviera estos datos que se estaban produciendo cuando se crearon.Cómo comprobar si algunas coordenadas caen en otro radio de coordenadas usando PHP solamente

Lat: 56.130366 
Long: -106.34677099999 

Más adelante, quiero comprobar si esta coordenadas caerán dentro de un radio de otras coordenadas y luego devuelve verdadero, de lo contrario falso.

Lat: 57.223366 
Long: -106.34675644699 
radius: 100000 (meters) 

¡Gracias de antemano!

+1

Google "Haversine fórmula" o "fórmula Vincenty" para trabajar a cabo la distancia entre dos latitud/longitud posiciones –

Respuesta

28

Gracias por la ayuda. A continuación se muestra una función de ejemplo que toma dos conjuntos de coordenadas de longitud y latitud y devuelve la distancia entre los dos.

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; 
} 

$distance = getDistance(56.130366, -106.34677099999, 57.223366, -106.34675644699); 
if($distance < 100) { 
    echo "Within 100 kilometer radius"; 
} else { 
    echo "Outside 100 kilometer radius"; 
} 
+2

[El equivalente, pero en Javascript] (https://gist.github.com/moshmage/2ae02baa14d10bd6092424dcef5a1186) porque pasé demasiado tiempo buscando esto. – MoshMage

6

Debe usar Haversine formula para calcular la distancia entre dos puntos. Usted tiene un PHP version here.

Luego solo marque distance < 100000.

+0

buenos códigos que tienes ahí. Pero la distancia es realmente en metros o kilómetros? –

+0

Depende del radio de la tierra. Si usa 6371 como en el código que he vinculado, son los kilómetros :) –

+0

Vi algunos algoritmos usando 6367 como el radio de la Tierra, pero la mayoría de ellos son 6371 ¿realmente importa o no? de todos modos, gracias :) –

1

Esto debería ayudar,

$lat_origin = 56.130366; 
$long_origin = -106.34677099999; 

$lat_dest = 57.223366; 
$long_dest = -106.34675644699; 

$radius  = 3958;  # Earth's radius (miles, convert to meters) 
$deg_per_rad = 57.29578; # Number of degrees/radian (for conversion) 

$distance = ($radius * pi() * sqrt(
      ($lat_origin - $lat_dest) 
      * ($lat_origin - $lat_dest) 
      + cos($lat_origin/$deg_per_rad) # Convert these to 
      * cos($lat_dest/$deg_per_rad) # radians for cos() 
      * ($long_origin - $long_dest) 
      * ($long_origin - $long_dest) 
    )/180); 
1
// Vincenty formula to calculate great circle distance between 2 locations 
//  expressed as Lat/Long in KM 

function VincentyDistance($lat1,$lat2,$lon1,$lon2){ 
    $a = 6378137 - 21 * sin(lat); 
    $b = 6356752.3142; 
    $f = 1/298.257223563; 

    $p1_lat = $lat1/57.29577951; 
    $p2_lat = $lat2/57.29577951; 
    $p1_lon = $lon1/57.29577951; 
    $p2_lon = $lon2/57.29577951; 

    $L = $p2_lon - $p1_lon; 

    $U1 = atan((1-$f) * tan($p1_lat)); 
    $U2 = atan((1-$f) * tan($p2_lat)); 

    $sinU1 = sin($U1); 
    $cosU1 = cos($U1); 
    $sinU2 = sin($U2); 
    $cosU2 = cos($U2); 

    $lambda = $L; 
    $lambdaP = 2*PI; 
    $iterLimit = 20; 

    while(abs($lambda-$lambdaP) > 1e-12 && $iterLimit>0) { 
     $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); 
     $alpha = asin($cosU1 * $cosU2 * $sinLambda/$sinSigma); 
     $cosSqAlpha = cos($alpha) * cos($alpha); 
     $cos2SigmaM = $cosSigma - 2*$sinU1*$sinU2/$cosSqAlpha; 
     $C = $f/16*$cosSqAlpha*(4+$f*(4-3*$cosSqAlpha)); 
     $lambdaP = $lambda; 
     $lambda = $L + (1-$C) * $f * sin($alpha) * ($sigma + $C*$sinSigma*($cos2SigmaM+$C*$cosSigma*(-1+2*$cos2SigmaM*$cos2SigmaM))); 
    } 

    $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); 
    return $s/1000; 
} 


echo VincentyDistance($lat1,$lat2,$lon1,$lon2); 
Cuestiones relacionadas