Estoy trabajando en la implementación del formato binario móvil OSM para datos de mapas, y debido a que utiliza un delta de 16 bits para cada punto a lo largo de un camino, no puede representar un camino si hay una gran distancia entre dos puntos.
La solución documentada es inyectar nuevos puntos en el camino, para mantener la brecha más pequeña.
Aquí está la sección relevante de mi 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
}
No estoy seguro de cómo calcular la posición de nuevos puntos en el camino? ¿Asumo que necesita ser un gran círculo?
Los puntos lo suficientemente separados como para causar este problema son raros, pero cuando suceden, generalmente es un límite político o similar, que tiende a ser bastante largo y debe representarse con precisión.
openstreetmap
mobile
spherical-geometry
mathematics
Abhi Beckert
fuente
fuente
Respuestas:
La mejor precisión se obtiene con modelos elipsoidales. En aras de la simplicidad, debe evitarlos cuando tenga que codificar distancias usted mismo. Pagamos un precio: dado que el aplanamiento de la Tierra es de aproximadamente 1/300, el uso de un modelo puramente esférico puede potencialmente introducir un error de distancia relativa de hasta 1/300 para rutas muy largas: alrededor de 3000 partes por millón. Vale la pena explorarlo.
Primero, la fórmula esférica : simplemente convierta (lat, lon) a coordenadas cartesianas, promedie los dos puntos cartesianos, luego convierta el promedio nuevamente a coordenadas esféricas. Aquí está el pseudocódigo:
(La aritmética para
midpoint
implica una suma vectorial y una división escalar de esa suma, por lo que realmente oculta tres sumas y tres divisiones).Ese es el punto medio en geometría esférica. El cálculo requiere dos cosenos, dos senos, una raíz cuadrada, dos arcotangentes y algo de multiplicación y suma: razonablemente rápido y fácil. No habrá problemas cerca de los polos o cruzando el meridiano + -180. El resultado será indefinido cuando los dos puntos son diametralmente opuestos.
Una forma de medir el error es calcular la mayor distancia recorrida a través del punto medio en comparación con la distancia entre los puntos originales. Si el aumento es pequeño en comparación con la distancia original, tenemos poco de qué quejarnos. He calculado estos errores utilizando la distancia elipsoidal precisa para el elipsoide WGS84. Como ejemplo típico de los resultados, aquí hay una gráfica de errores relativos cuando uno de los puntos finales se fija en (lat, lon) = (45, 0):
Los contornos están en una escala logarítmica (base 10): los contornos -6 muestran puntos donde el error relativo es 10 ^ (- 6); es decir, una parte por millón (ppm). Los contornos -5 (apenas visibles cerca (-45, 180), el punto diametralmente opuesto) son 10 ppm. Los -7, -8, etc. son fracciones de ppm: muy precisos.
Evidentemente, mientras no estemos tratando de calcular puntos medios de dos puntos que son casi diametralmente opuestos, lo haremos bien. (Recuerde, el cálculo es perfectamente correcto para la esfera; estos errores se deben al aplanamiento de la esfera).
Dado que la precisión de 16 bits es de aproximadamente 16 ppm (un registro de base 10 igual a -4.8), parece correcto usar la fórmula esférica para encontrar puntos medios siempre que los dos puntos estén a más de un grado de distancia de ser diametralmente opuestos.
¿Qué pasa con la fórmula lineal más simple? Para estudiar esto, comparemos la distancia entre el punto medio lineal (obtenido promediando las dos latitudes y las dos longitudes) con el punto medio esférico, en relación con la distancia entre los dos puntos finales. La siguiente figura fija un punto final en (45, 180) y explora una región relativamente pequeña a su alrededor.
La mayoría de estos contornos (logaritmos de base 10 una vez más) están cerca de -2: eso es una parte por cien (1%) de error. Para las direcciones norte-sur no hay error, pero para todas las demás direcciones el error es inaceptable para muchas aplicaciones .
Para ver si la aproximación lineal se vuelve correcta, acerquémonos a ese mapa anterior por un factor de 10. Ahora tiene un grado de ancho (50 millas en esta latitud) y medio grado de ancho (35 millas): estamos mirando a la escala de una gran ciudad o una pequeña ciudad y sus suburbios.
Ahora los contornos están alrededor de -3 a -4: eso es de 100 a 1000 partes por millón (0.01% a 0.1%). Bastante crudo y apenas perceptible en una pantalla de computadora de alta resolución si se mira de cerca.
Mirando hacia atrás, es evidente que la fórmula esférica un poco más complicada, pero aún fácilmente implementable, logra una mayor precisión en todo el mundo que la fórmula lineal simple incluso en ubicaciones cercanas. (Estoy bromeando un poco, porque he usado dos formas diferentes de medir errores, por lo que no son directamente comparables).
La línea de fondo:
- La fórmula lineal colocará mal el punto medio por un error relativo de 0.01% a 0.1% a escala de ciudad; en áreas más grandes, la colocación incorrecta puede ser muy incorrecta (1% en hasta cientos de%).
La fórmula esférica es absolutamente correcta para un modelo de tierra esférica. En comparación con la fórmula elipsoidal más precisa, aún debería funcionar bien, excepto por los puntos que son casi diametralmente opuestos.
fuente
Su solución funciona para distancias pequeñas, pero no funcionará para distancias más grandes. La forma más fácil de ver por qué es mirar el siguiente mapa (tomado de aquí ):
Es un mapa mundial en proyección equirectangular: las longitudes y latitudes se proyectan linealmente en los ejes X e Y. Sus matemáticas pueden ser representadas por el rectángulo azul . Sin embargo, la diagonal azul no representa la "línea" más corta entre dos puntos en la superficie de la Tierra. Lo que necesitas es un gran círculo (representado por una curva negra ).
Aunque está utilizando C ++, le recomiendo echar un vistazo a la Biblioteca de Geodesia C # de Mike Gavaghan , es de código abierto y el código es de alta calidad, debería ser capaz de descubrir cómo hacer el cálculo a lo largo del gran círculo. También puede echar un vistazo a las fórmulas de Vincenty si está interesado en las matemáticas detrás del cálculo.
fuente
Las matemáticas lineales simples parecen funcionar bien:
Estoy insertando recursivamente puntos nuevos a la mitad en cada sección del camino que es demasiado grande, hasta que todos sean lo suficientemente pequeños.
No estoy seguro de si se necesitan matemáticas más complejas para distancias más grandes (¿alguien puede confirmar esto por mí?), Pero funciona bien en este caso (unos 5 km):
fuente