Algoritmo para compensar una latitud / longitud por una cierta cantidad de metros


108

Estoy buscando un algoritmo que cuando se le da un par de latitud y longitud y una traducción vectorial en metros en coordenadas cartesianas (x, y) me daría una nueva coordenada. Algo así como un Haversine inverso. También podría trabajar con una transformación de distancia y rumbo, pero esto probablemente sería más lento y no tan preciso. Idealmente, el algoritmo debería ser rápido ya que estoy trabajando en un sistema embebido. La precisión no es crítica, dentro de 10 metros sería bueno.


¿Entonces estarías bien modelando la tierra como una esfera?
oscuro

1
Sí, eso estaría bien, ya que espero compensaciones de <1 km.
Thomas O

Respuestas:


107

Si sus desplazamientos no son demasiado grandes (menos de unos pocos kilómetros) y no está justo en los polos, use la estimación rápida y sucia de que 111,111 metros (111,111 km) en la dirección y es 1 grado (de latitud) y 111,111 * cos (latitud) metros en la dirección x es 1 grado (de longitud).


3
@Thomas: En realidad, puedes estar muy cerca de los polos. Verifiqué con un cálculo UTM usando desplazamientos iguales de x e y de 1400 m (por lo que el desplazamiento total es de 2 km). Los resultados son buenos a 8.6 metros o mejor. La peor latitud (para esta dirección y cantidad de desplazamiento) es de 81 grados: la aproximación en realidad se vuelve más precisa a medida que avanza hacia el norte y su error permanece por debajo de 10 metros hasta que supere los 89.6 grados.
whuber

6060
Por cierto, estos números mágicos de 111,111 son fáciles de recordar al conocer algo de historia: los franceses originalmente definieron el medidor de modo que 10 ^ 7 metros serían la distancia a lo largo del meridiano de París desde el ecuador hasta el polo norte. Por lo tanto, 10 ^ 7/90 = 111,111.1 metros equivale a un grado de latitud dentro de las capacidades de los topógrafos franceses hace dos siglos.
whuber

3
Entonces, con la fórmula si quisiera moverme + 100m en la dirección y desde, por ejemplo, 10.0 N, 10.0 E, ¿agregaría 100/111111? Si se mueve en la dirección x + 100m, ¿sería 100 ÷ (111,111 × (cos 10))? Solo asegurándome de que tengo esto bien.
Thomas O

55
@Thomas Sí, eso es correcto. Observe cómo la segunda fórmula expande el desplazamiento aparente de x (en virtud de dividir por un número menor que 1) como debería, porque un grado de longitud se reduce a medida que avanza hacia los polos desde el ecuador. El único problema potencial es asegurarse de que usted y su plataforma de software estén de acuerdo en lo que significa "cos": ¡es mejor interpretar cos (10) como el coseno de 10 grados , no 10 radianes! (Si no, 10 grados = 10 * pi / 180 radianes ilustran la conversión simple). En este punto, el código ofrecido por @haakon_d debería tener todo el sentido para usted.
whuber

77
Alguien intentó editar esta respuesta para reemplazar "metros" por "km". Probablemente estaban leyendo la coma "," en el sentido europeo de un punto decimal. Sigo la convención estadounidense (que creo que también es la convención de publicaciones internacionales) de usar una coma para separar cadenas de dígitos largos en grupos de tres y un punto decimal "." en lugar de la coma. (Este uso se muestra claramente en comentarios anteriores). Para evitar cualquier ambigüedad, he editado la respuesta para mostrar claramente lo que significan la coma y el punto.
whuber

56

Como dice Liedman en su respuesta, las fórmulas de aviación de Williams son una fuente inestimable, y para mantener la precisión dentro de los 10 metros para desplazamientos de hasta 1 km, es probable que necesite usar el más complejo de estos.

Pero si está dispuesto a aceptar errores por encima de 10 m para puntos con un desplazamiento de más de aproximadamente 200 m, puede usar un cálculo simplificado de tierra plana. Creo que los errores seguirán siendo inferiores a 50 m para compensaciones de hasta 1 km.

 //Position, decimal degrees
 lat = 51.0
 lon = 0.0

 //Earth’s radius, sphere
 R=6378137

 //offsets in meters
 dn = 100
 de = 100

 //Coordinate offsets in radians
 dLat = dn/R
 dLon = de/(R*Cos(Pi*lat/180))

 //OffsetPosition, decimal degrees
 latO = lat + dLat * 180/Pi
 lonO = lon + dLon * 180/Pi 

Esto debería devolver:

 latO = 51,00089832
 lonO = 0,001427437

77
Solo quiero señalar que esto es idéntico a la respuesta que proporcioné, excepto que usted ha reemplazado mi valor de 111,111 metros por grado por 111,319.5. Su valor es ligeramente mejor en latitudes altas, pero un poco peor en las latitudes más bajas (de 0 a aproximadamente 40 grados). Cualquiera de los valores cumple con los requisitos de precisión establecidos.
whuber

1
+1 por proporcionar código. Tenga en cuenta que es más preciso de lo que sospecha (el error suele ser inferior a 5 m en 2000 m).
whuber

1
Me preguntaba si debería agregar un comentario en mi respuesta de que esta es una solución idéntica a la suya, excepto por el valor de R, pero lo omití debido a la brevedad. Cuando se trata de precisión, tiene razón siempre que no agregue ningún error de rotación al sistema. Usando compensaciones medidas en un sistema de coordenadas local proyectado, los errores de rotación pueden crecer bastante.
haakon_d

1
Ese es un punto excelente: hemos asumido implícitamente que el desplazamiento x está al menos cerca del verdadero este-oeste y el desplazamiento y está cerca del norte-sur. De lo contrario, tienen que convertirse en desplazamientos EW y NS equivalentes (no solo "este" y "norte") antes de calcular sus equivalentes lat-lon.
whuber

El parámetro de distancia d de las ecuaciones del Formulario de aviación está en radianes, por ejemplo (distancia / radio de la tierra).
user1089933

23

Me parece que el Formulario de Aviación, aquí es ideal para este tipo de fórmulas y algoritmos. Para su problema, consulte el "lat / long radial y distancia dados": aquí

Tenga en cuenta que este algoritmo puede ser demasiado complejo para su uso, si desea mantener bajo el uso de funciones de trigonometría, etc.


Gracias por esto, se ve ideal. Aunque no puedo entender si la distancia es en metros o alguna otra medida.
Thomas O

2

Puede tener sentido proyectar el punto primero. Podrías hacer algo como este pseudocódigo:

falt_coordinate = latlon_to_utm(original_koordinate)
new_flat_coordinate = flat_coordinate + (x,y)
result_coordinate = utm_to_latlon(new_flat_coordinate)

donde (x, y) es el desplazamiento deseado.

No necesita usar utm, cualquier sistema de coordenadas planas, que tenga sentido en su área servirá.

¿Con qué software estás trabajando?