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 km e 1 grau de longitude é aproximadamente 111 km ×cos(ϕcentral).
Δϕ=111DΔλ=111×cos(ϕcentral)D
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.
ϕmin≤ϕponto≤ϕmaxλmin≤λponto≤λmax
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:
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.
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:
Δϕponto=−25.5513318−(−25.4447825)=−0.1065493Δλponto=−54.4578273−(−54.4091065)=−0.0487208ϕcentralrad=−25.5513318×180π≈−0.445955Dista^ncia≈111×(−0.1065493)2+(−0.0487208×cos(−0.445955))2≈111×0.0113528+(−0.0487208×0.902199)2≈111×0.01328492≈12.79389 km
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 é:
ϕ1 e ϕ2 são as latitudes dos dois pontos (em radianos)
λ1 e λ2 são as longitudes dos dois pontos (em radianos)
Δλ é 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:
ϕ1=−25.4447825×180π≈−0.444095 rad λ1=−54.4091065×180π≈−0.949618 rad ϕ2=−25.5513318×180π≈−0.445955 rad λ2=−54.4578273×180π≈−0.950468 rad
Para depois calcular a diferença de longitude:
Δλ=−0.950468−(−0.949618)≈−0.00085 rad
E por último, aplicar a Lei dos Cossenos Esféricos:
ϕ1 e ϕ2 são as latitudes dos dois pontos (em radianos)
λ1 e λ2 são as longitudes dos dois pontos (em radianos)
Δϕ é a diferença entre as latitudes dos dois pontos
Δλ é 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:
ϕ1=−25.4447825×180π≈−0.444095 rad λ1=−54.4091065×180π≈−0.949618 rad ϕ2=−25.5513318×180π≈−0.445955 rad λ2=−54.4578273×180π≈−0.950468 rad
Para depois calculamos a diferença de latitude e longitude:
Δϕ=−0.445955−(−0.444095)≈−0.00186 rad Δλ=−0.950468−(−0.949618)≈−0.00085 rad
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.