Nota editorial: Este post fazia parte de uma versão antiga do meu blog e foi republicado aqui como forma de preservar o histórico do que já escrevi. Mantive a essência do conteúdo original, com ajustes pontuais apenas quando necessário.
Utilizando geometria esférica, escrevi um exemplo de código em PHP de como calcular a distância entre dois pontos em uma esfera como o nosso planeta Terra. Neste exemplo utilizei o PHP, mas poderia ser escrito em qualquer outra linguagem de programação.
Sabemos que o raio da Terra, em média, tem aproximadamente 6371.005076123 km’s, e isso será importante para usarmos no nosso exemplo. Logo abaixo explico um pouco sobre a fórmula utilizada.
O que é a Fórmula de Haversine?
A fórmula de Haversine é o método mais popular e numericamente estável para calcular a distância entre dois pontos na superfície de uma esfera (como a Terra) a partir de suas coordenadas de latitude e longitude.
Ela usa o conceito de haversine (half-versine), que é uma função trigonométrica definida como:
Fórmula Matemática Completa
Dadas duas coordenadas:
- Ponto 1:
- Ponto 2:
A distância é calculada assim:
Onde:
-
- = raio da esfera (Terra ≈ 6371 km)
Código em PHP
Eu criei uma classe em PHP para um exemplo mais próximo a uma implementação real:
<?php
/**
* Cálculo entre dois pontos GPS
*/
class GeoDistance
{
const RADIUS = 6371.005076123; // raio da Terra em km
private float $latitudeFrom;
private float $longitudeFrom;
private float $latitudeTo;
private float $longitudeTo;
/**
* Gps constructor
*
* Exemplos:
* new GeoDistance(-12.9927866, -38.4544938, -25.4356954, -49.2832619)
*/
public function __construct(float $latitudeFrom, float $longitudeFrom, float $latitudeTo, float $longitudeTo)
{
$this->setFrom($latitudeFrom, $longitudeFrom);
$this->setTo($latitudeTo, $longitudeTo);
}
/**
* Calcula a distância entre dois pontos GPS.
*/
public function calculate($returnIn = 'km', $decimalDigits = 2): float
{
$p1Lat = $this->getLatitudeFrom() * pi() / 180.0;
$p1Lng = $this->getLongitudeFrom() * pi() / 180.0;
$p2Lat = $this->getLatitudeTo() * pi() / 180.0;
$p2Lng = $this->getLongitudeTo() * pi() / 180.0;
$dLat = $p2Lat - $p1Lat;
$dLng = $p2Lng - $p1Lng;
$angles = sin($dLat / 2) * sin($dLat / 2) + cos($p1Lat) * cos($p2Lat) * sin($dLng / 2) * sin($dLng / 2);
$arcCos = 2 * atan2(sqrt($angles), sqrt(1 - $angles));
$distance = self::RADIUS * $arcCos;
if ($returnIn == 'm') {
$distance = $distance * 1000;
}
return round($distance, $decimalDigits);
}
/**
* Define a latitude e longitude de origem
*/
public function setFrom(float $latitude, float $longitude): self
{
$this->latitudeFrom = $latitude;
$this->longitudeFrom = $longitude;
return $this;
}
/**
* Define a latitude e longitude de destino
*/
public function setTo(float $latitude, float $longitude): self
{
$this->latitudeTo = $latitude;
$this->longitudeTo = $longitude;
return $this;
}
public function getLatitudeFrom(): float
{
return $this->latitudeFrom;
}
public function getLongitudeFrom(): float
{
return $this->longitudeFrom;
}
public function getLatitudeTo(): float
{
return $this->latitudeTo;
}
public function getLongitudeTo(): float
{
return $this->longitudeTo;
}
}
Exemplo de uso:
<?php
$gps = new GeoDistance(-23.061599, -47.224603, -23.615940, -46.622572);
echo $gps->calculate() . ' km';
Espero ter ajudado em algo!
Caso você queira o mesmo exemplo escrito em alguma outra linguagem ou tenha alguma dúvida, deixe nos comentários.
Abraços!