Estou trabalhando na implementação do formato OSM Mobile Binary para dados de mapa e, como usa um delta de 16 bits para cada ponto ao longo do caminho, não pode representar um caminho se houver uma grande distância entre dois pontos.
A solução documentada é injetar novos pontos no caminho, para manter a diferença menor.
Aqui está a seção relevante do meu código:
// calculate the distance between this point and the previous point,
// multiplied by 1,000,000 so it can be represented as an integer.
int32_t realNodeLatDelta = ((point.latitude - lastPoint.latitude) * 1000000);
int32_t realNodeLonDelta = ((point.longitude - lastPoint.longitude) * 1000000);
// cast as a 16 bit int (reduces filesize by about half)
int16_t nodeLatDelta = realNodeLatDiff;
int16_t nodeLonDelta = realNodeLonDiff;
// check if the cast caused corruption
if (realNodeLatDelta != nodeLatDelta || realNodeLatDelta != nodeLatDelta) {
// if this point is reached, we need to add new points in the way,
// which can be represented in a 16 bit delta
}
Não sei como calcular a posição de novos pontos ao longo do caminho? Presumo que precisa ser um grande círculo?
Pontos distantes o suficiente para causar esse problema são raros, mas quando ocorrem, geralmente é um limite político ou similar, que costuma ser bastante longo e precisa ser representado com precisão.
openstreetmap
mobile
spherical-geometry
mathematics
Abhi Beckert
fonte
fonte
Respostas:
A melhor precisão é obtida nos modelos elipsoidais. No interesse da simplicidade, você deseja evitar aqueles quando precisa codificar as distâncias. Pagamos um preço: dado que o achatamento da Terra é de cerca de 1/300, o uso de um modelo puramente esférico pode potencialmente introduzir um erro de distância relativa de até 1/300 para rotas muito longas: cerca de 3000 partes por milhão. Vale a pena explorar.
Primeiro, a fórmula esférica : basta converter (lat, lon) em coordenadas cartesianas, calcular a média dos dois pontos cartesianos e depois converter a média de volta em coordenadas esféricas. Aqui está o pseudocódigo:
(A aritmética para
midpoint
envolve uma soma vetorial e uma divisão escalar dessa soma, portanto, está realmente escondendo três somas e três divisões.)Esse é o ponto médio da geometria esférica. O cálculo requer dois cossenos, dois senos, uma raiz quadrada, dois arco-tangentes e alguma multiplicação e adição: razoavelmente rápido e fácil. Não haverá problemas perto dos pólos ou cruzando o meridiano + -180. O resultado será indefinido quando os dois pontos forem diametralmente opostos.
Uma maneira de medir o erro é calcular o aumento da distância percorrida pelo ponto médio em comparação com a distância entre os pontos originais. Se o aumento for pequeno comparado à distância original, temos pouco a reclamar. Eu calculei esses erros usando a distância elipsoidal precisa para o elipsóide WGS84. Como um exemplo típico dos resultados, aqui está um gráfico de erros relativos quando um dos pontos de extremidade é fixado em (lat, lon) = (45, 0):
Os contornos estão em uma escala logarítmica (base 10): os contornos -6 mostram pontos onde o erro relativo é 10 ^ (- 6); isto é, uma parte por milhão (ppm). Os contornos -5 (quase invisíveis perto de (-45, 180), o ponto diametralmente oposto) são 10 ppm. Os -7, -8 etc. são frações de um ppm: altamente precisos.
Evidentemente, enquanto não estivermos tentando calcular pontos médios de dois pontos que são quase diametralmente opostos, faremos bem. (Lembre-se de que o cálculo está perfeitamente correto para a esfera; esses erros se devem ao achatamento da esfera.)
Dado que a precisão de 16 bits é de cerca de 16 ppm (um log de base 10 igual a -4,8), parece aceitável usar a fórmula esférica para encontrar pontos médios, desde que os dois pontos estejam a mais de um grau de diametralmente opostos.
E a fórmula linear mais simples? Para estudar isso, vamos comparar a distância entre o ponto médio linear (obtido pela média das duas latitudes e duas longitudes) com o ponto médio esférico, em relação à distância entre os dois pontos finais. A figura a seguir fixa um ponto final em (45, 180) e explora uma região relativamente pequena ao seu redor.
A maioria desses contornos (logaritmos da base 10 mais uma vez) está perto de -2: isso é um erro de uma parte por cem (1%). Para as direções norte-sul, não há erro, mas para todas as outras direções, o erro é inaceitável para muitas aplicações .
Para verificar se a aproximação linear está correta, vamos ampliar o mapa anterior por um fator de 10. Agora ele tem um grau de largura (80 quilômetros a essa latitude) e meio grau de diâmetro (35 quilômetros): estamos olhando na escala de uma cidade grande ou de uma cidade pequena e seus subúrbios.
Agora, os contornos estão entre -3 e -4: são 100 a 1000 partes por milhão (0,01% a 0,1%). Bastante grosseiro e quase imperceptível em uma tela de computador de alta resolução, se você olhar com atenção.
Olhando para trás, é aparente que a fórmula esférica um pouco mais complicada - mas ainda facilmente implementável - alcança maior precisão em todo o mundo do que a fórmula linear simples, mesmo em locais próximos. (Estou enganando um pouco, porque usei duas maneiras diferentes de medir erros, para que não sejam diretamente comparáveis.)
A linha inferior:
- A fórmula linear irá posicionar incorretamente o ponto médio por um erro relativo de 0,01% a 0,1% na escala da cidade; em áreas maiores, o posicionamento incorreto pode estar totalmente errado (1% em até centenas de%).
--A fórmula esférica é absolutamente correta para um modelo de terra esférico. Comparado à fórmula elipsóide mais precisa, ela ainda deve se sair bem, exceto por pontos quase diametralmente opostos.
fonte
Sua solução funciona para pequenas distâncias, mas não para maiores. A maneira mais fácil de entender por que é olhar para o mapa a seguir (extraído daqui ):
É um mapa-múndi em projeção equiretangular - longitudes e latitudes são simplesmente projetadas linearmente nos eixos X e Y. Sua matemática pode ser representada pelo retângulo azul . No entanto, a diagonal azul não representa a menor "linha" entre dois pontos na superfície da Terra. O que você precisa é de um grande círculo (representado pela curva preta ).
Embora você esteja usando C ++, eu recomendo dar uma olhada na C # Geodesy Library de Mike Gavaghan , é de código aberto e de código de alta qualidade, você deve descobrir como fazer o cálculo ao longo do grande círculo. Você também pode dar uma olhada nas fórmulas de Vincenty se estiver interessado em matemática por trás do cálculo.
fonte
A matemática linear simples parece funcionar bem:
Estou inserindo recursivamente metade dos novos pontos em cada seção do caminho, que é muito grande, até que todos sejam pequenos o suficiente.
Não tenho certeza se é necessária uma matemática mais complexa para distâncias maiores (alguém pode confirmar isso para mim?), Mas funciona bem nessa (cerca de 5 km):
fonte