online metros longitud latitud geograficas formatos entre distancia coordenadas calcular geolocation geospatial distance geography

geolocation - longitud - Coordenadas geoespaciales y distancia en kilómetros



latitud y longitud (5)

Esta es una continuación de esta pregunta .

Me parece estar atrapado en esto. Básicamente, necesito poder convertir hacia adelante y hacia atrás para referirme a coordenadas en el sistema de grados estándar O al medir una distancia al norte desde el polo sur a lo largo de la línea de fecha internacional, y luego una distancia hacia el este a partir de ese punto en la fecha línea. Para hacer esto (así como algunas cosas más generales de medición de distancia), tengo un método para determinar la distancia entre dos puntos lat / lon, y otro método que toma un punto lat / lon, un rumbo y una distancia, y regresa el punto lat / lon al final de ese curso.

Aquí están los dos métodos estáticos que he definido:

/* Takes two lon/lat pairs and returns the distance between them in kilometers. */ public static double distance (double lat1, double lon1, double lat2, double lon2) { double theta = toRadians(lon1-lon2); lat1 = toRadians(lat1); lon1 = toRadians(lon1); lat2 = toRadians(lat2); lon2 = toRadians(lon2); double dist = sin(lat1)*sin(lat2) + cos(lat1)*cos(lat2)*cos(theta); dist = toDegrees(acos(dist)) * 60 * 1.1515 * 1.609344 * 1000; return dist; } /* endOfCourse takes a lat/lon pair, a heading (in degrees clockwise from north), and a distance (in kilometers), and returns * the lat/lon pair that would be reached by traveling that distance in that direction from the given point. */ public static double[] endOfCourse (double lat1, double lon1, double tc, double dist) { double pi = Math.PI; lat1 = toRadians(lat1); lon1 = toRadians(lon1); tc = toRadians(tc); double dist_radians = toRadians(dist / (60 * 1.1515 * 1.609344 * 1000)); double lat = asin(sin(lat1) * cos(dist_radians) + cos(lat1) * sin(dist_radians) * cos(tc)); double dlon = atan2(sin(tc) * sin(dist_radians) * cos(lat1), cos(dist_radians) - sin(lat1) * sin(lat)); double lon = ((lon1-dlon + pi) % (2*pi)) - pi; double[] endPoint = new double[2]; endPoint[0] = lat; endPoint[1] = lon; return endPoint; }

Y aquí está la función que estoy usando para probarlo:

public static void main(String args[]) throws java.io.IOException, java.io.FileNotFoundException { double distNorth = distance(0.0, 0.0, 72.0, 0.0); double distEast = distance(72.0, 0.0, 72.0, 31.5); double lat1 = endOfCourse(0.0, 0.0, 0.0, distNorth)[0]; double lon1 = endOfCourse(lat1, 0.0, 90.0, distEast)[1]; System.out.println("end at: " + lat1 + " / " + lon1); return; }

Los valores "end at" deben ser aprox. 72.0 / 31.5. Pero en cambio estoy obteniendo aproximadamente 1.25 / 0.021.

Supongo que debo estar perdiendo algo estúpido, olvidar convertir unidades en algún lugar, o algo ... ¡Cualquier ayuda sería muy apreciada!

ACTUALIZACIÓN 1:

Escribí (correctamente) la función de distancia para devolver los metros, pero escribí kilómetros en los comentarios por error ... lo cual, por supuesto, me confundió cuando volví al tema hoy. De todos modos, ahora está arreglado, y arreglé el error de factorización en el método endOfCourse, y también me di cuenta de que había olvidado convertir a grados de radianes en ese método también. De todos modos: mientras parece que ahora estoy obteniendo el número de latitud correcto (71.99 ...), el número de longitud está muy lejos (obtengo 3.54 en vez de 11.5).

ACTUALIZACIÓN 2: Tuve un error tipográfico en la prueba, como se menciona a continuación. Ahora está arreglado en el código. Sin embargo, el número de longitud sigue siendo incorrecto: ahora recibo -11.34 en vez de 11.5. Creo que debe haber algo mal con estas líneas:

double dlon = atan2(sin(tc) * sin(dist_radians) * cos(lat1), cos(dist_radians) - sin(lat1) * sin(lat)); double lon = ((lon1-dlon + pi) % (2*pi)) - pi;


Echa un vistazo a http://www.movable-type.co.uk/scripts/latlong.html

Ese sitio tiene muchas fórmulas diferentes y un código Javascript que debería ayudarte. Lo traduje con éxito tanto a C # como a UDF de SQL Server y los utilizo en todas partes.

Por ejemplo, Javascript para calcular la distancia:

var R = 6371; // km var φ1 = lat1.toRadians(); var φ2 = lat2.toRadians(); var Δφ = (lat2-lat1).toRadians(); var Δλ = (lon2-lon1).toRadians(); var a = Math.sin(Δφ/2) * Math.sin(Δφ/2) + Math.cos(φ1) * Math.cos(φ2) * Math.sin(Δλ/2) * Math.sin(Δλ/2); var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); var d = R * c;

¡Disfrutar!


En cuanto a su pregunta actualizada: ¿No debería

double lon1 = endOfCourse(lat1, 0.0, 90.0, distEast)[0];

ser

double lon1 = endOfCourse(lat1, 0.0, 90.0, distEast)[1];


Descubrí el gran problema con estas fórmulas, aparte de los errores de implementación mencionados en las otras respuestas y actualizaciones.

El gran problema era este: el método Distancia (para calcular la distancia entre dos puntos) estaba calculando distancias de círculo máximo. Lo cual, por supuesto, tiene sentido: ese es el camino más corto entre los dos puntos. Sin embargo , la distancia del gran círculo entre dos puntos que se encuentran en el mismo paralelo (línea de latitud) NO es la misma que la distancia entre esos dos puntos cuando se viaja directamente a lo largo de la línea de latitud, a menos que estés en el ecuador.

Entonces: las funciones están funcionando correctamente; sin embargo, el sistema de coordenadas alternativo que propuse en la pregunta original requiere que miremos solo la distancia al norte a lo largo del IDL seguido de la distancia al este a lo largo del paralelo en la latitud resultante. ¡Y calcular la distancia a lo largo de un paralelo específico es bastante diferente de calcular la distancia a lo largo de un gran círculo!

De todos modos, ahí lo tienes.


Tienes un caso serio de los números mágicos en el código. La expresion:

(60 * 1.1515 * 1.609344 * 1000)

aparece dos veces, pero no hay mucha explicación de eso. Con algo de ayuda: 1.609344 es el número de kilómetros en una milla; 60 es la cantidad de minutos en un grado; 1000 es la cantidad de metros en un kilómetro; y 1.1515 es el número de millas terrestres en una milla náutica (gracias, DanM). Una milla náutica es la longitud de un minuto de latitud en el ecuador.

Supongo que estás usando un modelo esférico de tierra, en lugar de una tierra esferoidal. El álgebra no es lo suficientemente complejo como para ser esferoidal.

La primera fórmula, la conversión entre dos pares de latitud y longitud, es impar. Necesita delta-lat (Δλ) y delta-lon (Δφ) para ordenar la respuesta. Además, la distancia entre los pares:

(60° N, 30° W), (60° N, 60° W) (60° N, 60° W), (60° N, 90° W)

debería ser el mismo, pero estoy bastante seguro de que tu código produce respuestas diferentes.

Por lo tanto, creo que debe volver a sus materiales de referencia de trigonometría esférica y ver qué está haciendo mal. (Me tomaría un tiempo encontrar mi libro sobre el tema, necesitaría ser desempaquetado desde cualquier casilla).

[ ... el tiempo pasa ... desempacando ... ]

Dado un triángulo esférico con ángulos A , B , C en los vértices y lados a , b , c opuestos a esos vértices (es decir, el lado a es de B a C , etc.), la Fórmula Coseno es:

cos a = cos b . cos c + sin b . sin c . cos A

Aplicando esto al problema, podemos llamar a los dos puntos dados B y C , y creamos un triángulo esférico derecho con un ángulo recto en A.

Arte ASCII en su peor momento:

+ C /| / | a / | b / | / | / | B +------+ A c

El lado c es igual a la diferencia en longitud; el lado b es igual a la diferencia en latitud; el ángulo A es 90 °, entonces cos A = 0. Por lo tanto, creo que una ecuación para a es:

cos a = cos Δλ . cos Δφ + sin Δλ . sin Δφ . cos 90° a = arccos (cos Δλ . cos Δφ)

El ángulo a en radianes se convierte a una distancia multiplicando por el radio de la Tierra. Alternativamente, dado a en grados (y fracciones de grado), entonces hay 60 millas náuticas a un grado, por lo tanto, 60 * 1.1515 millas terrestres y 60 * 1.1515 * 1.609344 kilómetros hasta un grado. A menos que quiera la distancia en metros, no veo la necesidad del factor de 1000.

Paul Tomblin señala el Formulario de Aviación v1.44 como una fuente de la ecuación, y de hecho, está allí, junto con una versión numéricamente más estable para cuando la diferencia de posición es pequeña.

Yendo a la trigonometría básica, también sabemos que:

cos (A - B) = cos A . cos B + sin A . sin B

Aplicando eso dos veces en la ecuación que di podría terminar en la fórmula en el Formulario de Aviación.

(Mi referencia: "Astronomía: Principios y práctica, cuarta edición" por AE Roy y D Clarke (2003); mi copia es la primera edición de 1977, Adam Hilger, ISBN 0-85274-346-7.)

NB Check out (Google) ''define:'' milla náutica ''''; parece que una milla náutica ahora es 1852 m (1.852 km) por definición. El multiplicador 1.1515 corresponde a la antigua definición de la milla náutica como aproximadamente 6080 pies. Usando bc con una escala de 10, obtengo:

(1852/(3*0.3048))/1760 1.1507794480

El factor que funciona para usted depende de cuál es su base.

Mirando el segundo problema desde los primeros principios, tenemos una configuración ligeramente diferente, y necesitamos la ''otra'' ecuación de trigonometría esférica, la fórmula sinusoidal:

sin A sin B sin C ----- = ----- = ----- sin a sin b sin c

Adaptando el diagrama anterior:

+ C /| / | a / | b | / | |X/ | |/ | B +------+ A c

Se le da el punto inicial B , el ángulo X = 90º - B, la longitud (ángulo) a , y el ángulo A = 90 °. Lo que buscas es b (el delta en latitud) y c (el delta en longitud).

Entonces tenemos:

sin a sin b ----- = ---- sin A sin B

O

sin a . sin B sin b = ------------- sin A

O, dado que A = 90 °, sen A = 1, y sen B = sen (90 ° - X) = cos X:

sin b = sin a . cos X

Eso significa que convertirás la distancia recorrida en un ángulo a , tomarás el seno de eso, multiplicarás por el coseno de la dirección del rumbo y tomarás el arco del resultado.

Dado a , b (solo calculado) y A y B , podemos aplicar la fórmula del coseno para obtener c . Tenga en cuenta que no podemos simplemente volver a aplicar la fórmula sinusoidal para obtener c ya que no tenemos el valor de C y, debido a que estamos jugando con trigonometría esférica, no hay una regla conveniente que C = 90 ° - B (la suma de los ángulos en un triángulo esférico puede ser mayor que 180 °, considere un triángulo esférico equilátero con todos los ángulos iguales a 90 °, que es perfectamente factible).


Tu conversión entre km y radianes es incorrecta. Una milla náutica es 1/60 de un grado, por lo que suponiendo que 1.15 ... es su conversión de millas a millas náuticas, y 1.6 ... es su conversión de km a millas terrestres,

nm = km / (1.1515 * 1.609344); deg = nm / 60; rad = toRadians(deg);

En otras palabras, creo que estás por un factor de 1000.