Calculando distâncias com PHP
Neste artigo vamos ver como é possível calcular a distância entre duas coordenadas utilizando PHP. Existem várias formas de fazer este cálculo, neste artigo vamos focar num método chamado fórmula de Harvesine.
A fórmula de Haversine é equação utilizada em navegação, fornecendo distância entre 2 pontos de uma esfera, a partir de suas latitudes e longitudes. Esta fórmula é um caso especial de uma fórmula mais geral de trigonometria esférica, a lei dos haversines, que relaciona os lados e ângulos de um triângulo contido em uma superfície esférica.
Devemos ter em mente que a Terra não é uma esfera perfeita, ela é ligeiramente achatada nos polos. Por causa disso, o raio de nosso planeta é variável. Na região do Equador o radio possui o valor de 6378 km, mas nos pólos o seu valor é de 6357 km. Como você deve ter percebido, os valores aumentam a medida que nos aproximamos dos pólos.
Para facilitar o nosso cálculo, vamos considerar que o raio da Terra é de 6371 km.
As etapas que precisamos seguir para fazer este complexo cálculo são as seguintes:
1 - Converter as latitudes e longitudes de origem em destino em radianos.
2 - Com as latitudes que serão utilizadas devidamente convertidas em radianos, multiplicar o coseno da latitude de origem com o coseno da latitude de destino e depois com o coseno da diferença entre longitude de destino - longitude de origem.
3 - Pegar este resultado e somar com o resultado do seno da latitude de origem multiplicado pelo seno da latitude de destino.
4 - Vamos retornar o inverso do cosseno deste resultado.
5 - Para concluir, vamos multiplicar o resultado desta operação por 6371, que é o valor que vamos utilizar como raio da Terra em kilometros.
O resultado desta operação será em kilômetros.
Para nos ajudar em nossa implementação da fórmula de Harvesine, vamos precisar utilizar as seguintes funções do PHP.
* Acos - Retorna o arco cosseno de um número informado em radianos. Arco cosseno é a função inversa de cosseno
* Cos - Retorna o cosseno de um número informado em radianos. O cosseno é a razão entre a medida do cateto oposto sobre o valor da hipotenusa.
* Deg2rad - Converte um número em graus para radianos. O radiano é a razão entre o comprimento de um arco e o seu raio.
* Sin - Retorna o seno de um número informado em radianos. O seno é a razão entre o cateto oposto e a hipotenusa de um triângulo retângulos
Vamos implementar nossa fórmula no PHP. No exemplo a seguir, as coordenadas de origem se referem a cidade de Adamantina e as coordenadas de destino se referem a cidade de Presidente Prudente. Ambas as cidades ficam no estado de São Paulo.
Origem - Adamantina
Latitude: -21.682
Longitude: -51.0737
Destino - Presidente Prudente
Latitude: -22.1207
Longitude: -51.3925
$lat1 = "-21.682";
$lat2 = "-22.1207";
$lon1 = "-51.0737";
$lon2 = "-51.3925";
$lat1 = deg2rad($lat1);
$lat2 = deg2rad($lat2);
$lon1 = deg2rad($lon1);
$lon2 = deg2rad($lon2);
$distancia = (6371 * acos(cos($lat1) * cos($lat2) * cos($lon2 - $lon1) + sin($lat1) * sin($lat2)));
$distancia = number_format($distancia, 2, ".", "");
echo $distancia;
Perceba que ao implementar este cálculo, utilizamos a função number_format para retornar o resultado em kilometros com duas casas decimais.
O resultado da operação foi 58.83 kilometros, que é a distância que separa as cidades de Adamantina e Presidente Prudente.
Agora que temos a distância entre as duas cidades, temos um outro problema para resolver. Perceba que se estamos na cidade de Adamantina e queremos ir para a cidade de Presidente Prudente, precisamos de mais uma informação além da distância. É necessário saber para qual direção ir. Não temos como saber se a cidade fica ao norte ou ao sul por exemplo.
Para nos ajudar com isso, podemos fazer o seguinte cálculo:
1 - Converter as coordenadas em radianos.
2 - Calcular a diferença entre as coordenadas longitudinais
3 - Calcular a tangente da seguinte operação: Metade da latitude de destino mais a soma de PI dividido por quatro.
4 - Calcular a tangente da seguinte operação: Metade da latitude de origem mais a soma de PI dividido por quatro.
5 - Extrair o log da divisão entre os itens 3 e 4 (latitudes)
6 - Se o resultado do cálculo 2 (longitudes) for maior que a constante PI, recalcular da seguinte forma: (2 * pi() - cálculo das longitudes) * -1
7 - Calcular a tangente inversa dos resultados obtidos para as latitudes e longitudes e converter o resultado em graus.
7 - Com base neste resultado, somar 360 e retornar o resto da divisão por 360.
O resultado desta operação vai ser em graus.
Para nos ajudar, vamos precisar utilizar as seguintes funções do PHP:
* Abs - Retorna o valor absoluto (positivo) de um número.
* Atan2 - Calcula a tangente inversa entre dois números, seu retorno é um número em radianos.
* Log - Retorna o logaritmo natural de um número.
* Pi - Retorna o valor da constante de Pi, é uma proporção numérica definida pela relação entre o perímetro de uma circunferência e seu diâmetro.
* Rad2deg - Converte um valor em radianos para um valor em graus.
* Round - Arredonda um número, se o número de digitos decimais de precisão não for informado se utiliza o valor zero.
* Tan - Retorna a tangente de um número informado em radianos. Tangente é a razão entre o cateto oposto e o cateto adjacente.
Nossa implementação do cálculo da direção e dos pontos cardeais ficaria da seguinte forma:
$lat1 = "-21.682";
$lat2 = "-22.1207";
$lon1 = "-51.0737";
$lon2 = "-51.3925";
$dLon = deg2rad($lon2) - deg2rad($lon1);
$dPhi = log(tan(deg2rad($lat2) / 2 + pi() / 4) / tan(deg2rad($lat1) / 2 + pi() / 4));
if(abs($dLon) > pi()) {
if($dLon > 0) {
$dLon = (2 * pi() - $dLon) * -1;
} else {
$dLon = 2 * pi() + $dLon;
}
}
$direcao = (rad2deg(atan2($dLon, $dPhi)) + 360) % 360;
$pontos_cardeais = array("N", "NE", "E", "SE", "S", "SW", "W", "NW", "N");
echo "Direção:" . $direcao;
echo (" * ");
echo $pontos_cardeais[round($direcao/45)];
Desta forma, descobrimos que a cidade de Presidente Prudente fica a 213 graus da cidade de Adamantina, ou seja, ela fica ao Sudoeste da cidade de Adamantina.
Veja que em nosso array de pontos cardeais nós inserimos os pontos cardeais e os pontos colaterais, que são aqueles que ficam entre os pontos cardeais. Como a circurferência possui 360 graus, dividimos o resultado em graus da direção por 45. Dividir a circunferência por 45 vai dar 8, que é o número de pontos cardeais e colaterais.
Com base na última operação, podemos descobrir que a cidade de Presidente Prudente fica ao sudoeste da cidade de Adamantina.
Encerramento
Este artigo mostrou como calcular a distância entre duas coordenadas com PHP.
Se você deseja se aprofundar neste assunto e ver como fazer isso utilizando um banco de dados SQL eu recomendo muito a leitura do artigo a seguir: