Calculando a distância entre dois pontos através da latitude e longitude
https://www.lucasmantuan.com.br
https://github.com/lucasmantuan
https://www.linkedin.com/in/lucasmantuan
O objetivo deste tutorial é calcular a distância entre determinados pontos e a centroide de diversas cidades, e com isso estabelecer a quais cidades aqueles pontos pertencem.
Podemos utilizar algumas abordagens diferentes para o cálculo da distância através da latitude e longitude. Entretanto, como estes cálculos geralmente envolvem uma alta complexidade, faremos um primeiro filtro, com uma precisão mais baixa e baseado em uma região menor, para então fazer o cálculo preciso da distância levando em consideração a curvatura da Terra.
Bounding Box
Neste método criamos uma área retangular de extensão D (em km) ao redor do ponto central, depois podemos verificar se as coordenadas do ponto estão dentro dessa área.
- Primeiro convertemos a distância D (em km) em graus de latitude e longitude. Onde 1 grau de latitude é aproximadamente 111 \text{ km } e 1 grau de longitude é aproximadamente 111 \text{ km } \times cos(\phi_{central}).
- Em seguida usamos as variações calculadas para definir os limites da caixa em torno do ponto central.
- Finalizamos verificando se o ponto está dentro desta caixa.
- Por exemplo, se desejarmos calcular se a cidade de Santa Terezinha do Itaipu (-25.4447825, -54.4091065) está a 10 km de distância da cidade de Foz do Iguaçu (-25.5513318, -54.4578273) fazemos os seguintes cálculos:
- Abaixo o exemplo de como implementar as fórmulas no Python:
import math
D = 10
lat_central = -25.5513318
lon_central = -54.4578273
lat_ponto = -25.4447825
lon_ponto = -54.4091065
delta_phi = D / 111
delta_lambda = D / (111 * math.cos(math.radians(lat_central)))
phi_min = lat_central - delta_phi
phi_max = lat_central + delta_phi
lambda_min = lon_central - delta_lambda
lambda_max = lon_central + delta_lambda
dentro_da_caixa = (phi_min <= lat_ponto <= phi_max) and (lambda_min <= lon_ponto <= lambda_max)
print(dentro_da_caixa)
Bounding Circle
Este método consiste em determinar se um ponto está dentro de um círculo de raio R (em km) ao redor de um ponto central. Podemos calcular a distância aproximada entre o ponto central e o ponto em questão usando uma fórmula simplificada (uma adaptação do Teorema de Pitágoras), adequada para pequenas distância.
- Primeiro calculamos a diferença em latitude e longitude em relação ao ponto central e em seguida convertemos a latitude central para radianos, o que nos ajuda a criar um círculo com o raio desejado ao redor do ponto central.
- Finalizamos calculando a distância aproximada entre o ponto central e o ponto e verificando se a distância é menor ou igual ao raio (R) desejado.
- Por exemplo, se desejarmos calcular se a cidade de Santa Terezinha do Itaipu (-25.4447825, -54.4091065) está a 10 km de distância da cidade de Foz do Iguaçu (-25.5513318, -54.4578273) fazemos os seguintes cálculos:
- Abaixo o exemplo de como implementar as fórmulas no Python.
import math
R = 10
lat_central = -25.5513318
lon_central = -54.4578273
lat_ponto = -25.4447825
lon_ponto = -54.4091065
delta_phi_ponto = lat_ponto - lat_central
delta_lambda_ponto = lon_ponto - lon_central
phi_central_rad = lat_central * math.pi / 180
distancia = 111 * math.sqrt((delta_phi_ponto)**2 + (delta_lambda_ponto * math.cos(phi_central_rad))**2)
dentro_do_circulo = distancia <= R
print(dentro_do_circulo)
Em seguida, podemos utilizar algum outro método para um cálculo mais preciso da distância entre os pontos. Dentre as abordagens existentes temos a fórmula de Haversine, ideal para distâncias curtas e moderadas, a fórmula da Lei dos Cossenos Esférico, com precisão similar a de Haversine, mas, mais simples e direta de implementar, o algoritmo de Great Circle Distance, um pouco mais precisa que as anteriores para distâncias longas e a fórmula de Vincenty, sendo precisa em qualquer distância.
Como em nosso exemplo o cálculo exige uma precisão baixa, de menos de 1000 km, utilizaremos a fórmula da Lei dos Cossenos Esféricos e de Haversine
Lei dos Cossenos Esféricos
Esta fórmula é uma generalização da Lei dos Cossenos aplicada a esferas, utilizada para calcular distância entre dois pontos na superfície de uma esfera. Sua fórmula é:
Onde:
- d é a distância entre os dois pontos.
- r é o raio da Terra (aproximadamente 6.371 km)
- \phi_1 e \phi_2 são as latitudes dos dois pontos (em radianos)
- \lambda_1 e \lambda_2 são as longitudes dos dois pontos (em radianos)
- \Delta \lambda é a diferença entre as longitudes dos dois pontos
Vamos continuar em nosso exemplo fazendo o cálculo entre a cidade de Santa Terezinha do Itaipu (-25.4447825, -54.4091065) e Foz do Iguaçu (-25.5513318, -54.4578273):
- Começamos convertendo as coordenadas em radianos:
- Para depois calcular a diferença de longitude:
- E por último, aplicar a Lei dos Cossenos Esféricos:
- Abaixo o exemplo de como implementar as fórmulas no Python:
import math
r = 6371
lat1 = -25.4447825
lon1 = -54.4091065
lat2 = -25.5513318
lon2 = -54.4578273
phi1 = math.radians(lat1)
lambda1 = math.radians(lon1)
phi2 = math.radians(lat2)
lambda2 = math.radians(lon2)
delta_lambda = lambda2 - lambda1
d = r * math.acos(math.sin(phi1) * math.sin(phi2) + math.cos(phi1) * math.cos(phi2) * math.cos(delta_lambda))
print(d)
Haversine
Esta fórmula considera a Terra como uma esfera e fornece a distância ao longo da superfície, levando em consideração a sua curvatura. Sua fórmula é:
Onde:
- d é a distância entre os dois pontos.
- r é o raio da Terra (aproximadamente 6.371 km)
- \phi_1 e \phi_2 são as latitudes dos dois pontos (em radianos)
- \lambda_1 e \lambda_2 são as longitudes dos dois pontos (em radianos)
- \Delta \phi é a diferença entre as latitudes dos dois pontos
- \Delta \lambda é a diferença entre as longitudes dos dois pontos
Vamos, também neste exemplo fazer o cálculo entre a cidade de Santa Terezinha do Itaipu (-25.4447825, -54.4091065) e Foz do Iguaçu (-25.5513318, -54.4578273):
- Começamos convertendo as coordenadas em radianos:
- Para depois calculamos a diferença de latitude e longitude:
- E por último, aplicar a fórmula de Haversine:
- Abaixo o exemplo de como implementar os cálculos em Python.
import math
r = 6371
lat1 = -25.4447825
lon1 = -54.4091065
lat2 = -25.5513318
lon2 = -54.4578273
phi1 = math.radians(lat1)
lambda1 = math.radians(lon1)
phi2 = math.radians(lat2)
lambda2 = math.radians(lon2)
delta_phi = phi2 - phi1
delta_lambda = lambda2 - lambda1
a = math.sin(delta_phi / 2)**2 + math.cos(phi1) * math.cos(phi2) * math.sin(delta_lambda / 2)**2
c = 2 * math.asin(math.sqrt(a))
d = r * c
print(d)
Well-known Text e Well-known Binary
Para encerrar, é importante falar um pouco sobre 2 formatos utilizados para representar dados geométricos. O Well-known Text (WKT) que é uma notação textual que descreve formas geométricas usando coordenadas sendo amplamente utilizado em bancos de dados geoespaciais e em sistemas de informação geográficas (GIS) e o Well-known Binary (WKB) que é a representação binária equivalente de dados geométricos, utilizado para armazenamento e transferência de forma mais compacta e eficiente. Ambos os formatos são definidos pelo Open Geospatial Consortium (OGC) e são compatíveis com diversas ferramentas e bibliotecas geoespaciais.