Distancia entre dos puntos georeferenciados (PHP y MySQL)

http://www.iuttu.com/2011/05/distancia-entre-dos-puntos-georeferenciados-php-mysql/

Con el uso de APIs de mapas como Google Maps y la -cada día más- posibilidad de georeferenciación del contenido, es posible que en algún momento necesitemos calcular la distancia entre dos puntos georeferenciados.

Sin más explicaciones físicas, escribimos la función en PHP:

function distancia($punto1, $punto2){
    	$km = 111.302;
    	$coo1 = explode(',',$punto1);
    	$coo2 = explode(',',$punto2);
    	return floor(acos(sin((double)$coo1[0]) * sin((double)$coo2[0]) + (cos((double)$coo1[0]) * cos((double)$coo2[0]) * cos((double)$coo1[1] - (double)$coo2[1]))) * (double)$km);
    }

No vamos a entrar en demasiados detalles de la función, nos tenemos que creer la fórmula creada por nuestros amigos físicos, pero sí os explicaremos que hemos dado a la variable $km es la distancia en kilómetros que abarca un grado de circunferencia del planeta tierra (por tanto los habitantes de otros mundos tendréis que ajustar este valor).

Tambien és posible que guardemos en base de datos una lista de “elementos” georeferenciados (con latitud y longitud). En nuestro caso almacenamos la latitud y longitud en una misma columna de tipo varchar(255), pero se podía guardar en dos columnas diferentes o en una columna de tipo POINT.

Para nuestra llamada hemos creado una función strSplit que nos ayudará a dividir la cadena de latitud/longitud en cada valor:

CREATE

FUNCTION `strSplit`(x varchar(255), delim varchar(12), pos int)
  RETURNS varchar(255) CHARSET latin1
DETERMINISTIC
BEGIN
   RETURN replace(substring(substring_index(x, delim, pos),
      length(substring_index(x, delim, pos - 1)) + 1), delim, '');

-- end the stored function code block
END$$

La condición del WHERE de la consulta que devolvería todos los puntos a una distancia menor o igual que $distancia quedaría de la siguiente manera:

WHERE ACOS(
	SIN(strSplit(coordenadas,',',1)) * SIN($latitud) +
	COS(strSplit(coordenadas,',',1)) * COS($latitud) * COS(strSplit(coordenadas,',',2) - ($longitud))
      ) * 111.302 <= $distancia

Linkografía:
– En GeoNames se puede descargar varias bases de datos de información georeferenciada del planeta
Fórmula Haversine del cálculo de distancias geográficas