Obtener lat / long dado el punto actual, la distancia y el rodamiento

Dado un punto existente en lat / long, distancia en (en KM) y rumbo (en grados convertidos a radianes), me gustaría calcular el nuevo lat / long. Este sitio aparece una y otra vez, pero no puedo conseguir que la fórmula funcione para mí.

Las fórmulas que se han tomado del enlace anterior son:

lat2 = asin(sin(lat1)*cos(d/R) + cos(lat1)*sin(d/R)*cos(θ)) lon2 = lon1 + atan2(sin(θ)*sin(d/R)*cos(lat1), cos(d/R)−sin(lat1)*sin(lat2)) 

La fórmula anterior es para MSExcel donde:

 asin = arc sin() d = distance (in any unit) R = Radius of the earth (in the same unit as above) and hence d/r = is the angular distance (in radians) atan2(a,b) = arc tan(b/a) θ is the bearing (in radians, clockwise from north); 

Aquí está el código que tengo en Python.

 import math R = 6378.1 #Radius of the Earth brng = 1.57 #Bearing is 90 degrees converted to radians. d = 15 #Distance in km #lat2 52.20444 - the lat result I'm hoping for #lon2 0.36056 - the long result I'm hoping for. lat1 = 52.20472 * (math.pi * 180) #Current lat point converted to radians lon1 = 0.14056 * (math.pi * 180) #Current long point converted to radians lat2 = math.asin( math.sin(lat1)*math.cos(d/R) + math.cos(lat1)*math.sin(d/R)*math.cos(brng)) lon2 = lon1 + math.atan2(math.sin(brng)*math.sin(d/R)*math.cos(lat1), math.cos(d/R)-math.sin(lat1)*math.sin(lat2)) print(lat2) print(lon2) 

yo obtengo

 lat2 = 0.472492248844 lon2 = 79.4821662373 

Related of "Obtener lat / long dado el punto actual, la distancia y el rodamiento"

Necesario para convertir las respuestas de radianes a grados. Código de trabajo a continuación:

 import math R = 6378.1 #Radius of the Earth brng = 1.57 #Bearing is 90 degrees converted to radians. d = 15 #Distance in km #lat2 52.20444 - the lat result I'm hoping for #lon2 0.36056 - the long result I'm hoping for. lat1 = math.radians(52.20472) #Current lat point converted to radians lon1 = math.radians(0.14056) #Current long point converted to radians lat2 = math.asin( math.sin(lat1)*math.cos(d/R) + math.cos(lat1)*math.sin(d/R)*math.cos(brng)) lon2 = lon1 + math.atan2(math.sin(brng)*math.sin(d/R)*math.cos(lat1), math.cos(d/R)-math.sin(lat1)*math.sin(lat2)) lat2 = math.degrees(lat2) lon2 = math.degrees(lon2) print(lat2) print(lon2) 

La biblioteca Geopy soporta esto:

 import geopy from geopy.distance import VincentyDistance # given: lat1, lon1, b = bearing in degrees, d = distance in kilometers origin = geopy.Point(lat1, lon1) destination = VincentyDistance(kilometers=d).destination(origin, b) lat2, lon2 = destination.latitude, destination.longitude 

Encontrado a través de https://stackoverflow.com/a/4531227/37610

Puede ser un poco tarde para responder, pero después de probar las otras respuestas, parece que no funcionan correctamente. Aquí hay un código PHP que usamos para nuestro sistema. Trabajando en todas direcciones.

Código PHP:

lat1 = latitud del punto de inicio en grados

long1 = longitud del punto de inicio en grados

d = distancia en KM

ángulo = rodamiento en grados

 function get_gps_distance($lat1,$long1,$d,$angle) { # Earth Radious in KM $R = 6378.14; # Degree to Radian $latitude1 = $lat1 * (M_PI/180); $longitude1 = $long1 * (M_PI/180); $brng = $angle * (M_PI/180); $latitude2 = asin(sin($latitude1)*cos($d/$R) + cos($latitude1)*sin($d/$R)*cos($brng)); $longitude2 = $longitude1 + atan2(sin($brng)*sin($d/$R)*cos($latitude1),cos($d/$R)-sin($latitude1)*sin($latitude2)); # back to degrees $latitude2 = $latitude2 * (180/M_PI); $longitude2 = $longitude2 * (180/M_PI); # 6 decimal for Leaflet and other system compatibility $lat2 = round ($latitude2,6); $long2 = round ($longitude2,6); // Push in array and get back $tab[0] = $lat2; $tab[1] = $long2; return $tab; } 

Esta pregunta es conocida como el problema directo en el estudio de la geodesia .

Esta es, de hecho, una pregunta muy popular y una causa constante de confusión. La razón es que la mayoría de las personas está buscando una respuesta simple y directa. Pero no hay ninguno, porque la mayoría de las personas que hacen esta pregunta no proporcionan suficiente información, simplemente porque no son conscientes de que:

  1. La Tierra no es una esfera perfecta, ya que está aplanada / comprimida por sus polos
  2. Debido a que (1) la tierra no tiene un radio constante, R Ver aqui
  3. La Tierra no es perfectamente lisa (variaciones de altitud) etc.
  4. Debido al movimiento de la placa tectónica, la posición lat / lon de un punto geográfico puede cambiar varios milímetros (al menos), cada año.

Por lo tanto, se utilizan muchos supuestos diferentes en los diversos modelos geométricos que se aplican de manera diferente, dependiendo de la precisión necesaria. Entonces, para responder a la pregunta, debe considerar qué precisión le gustaría obtener su resultado.

Algunos ejemplos:

  • Solo estoy buscando una ubicación aproximada a los pocos kilómetros más cercanos para distancias pequeñas ( < 100 km) en latitudes entre 0 y 0-70 deg N | S. (La tierra es ~ modelo plano.)
  • Quiero una respuesta que sea buena en cualquier parte del mundo, pero solo precisa unos pocos metros.
  • Quiero un posicionamiento súper preciso que sea válido hasta escalas atómicas de nanometers [nm].
  • Quiero respuestas que sean muy rápidas y fáciles de calcular y no computacionalmente intensivas.

Así que puedes tener muchas opciones en qué algoritmo usar. Además, cada lenguaje de progtwigción tiene su propia implementación o “paquete” multiplicado por la cantidad de modelos y las necesidades específicas de los desarrolladores de modelos. Para todos los propósitos prácticos aquí, vale la pena ignorar cualquier otro lenguaje aparte de javascript , ya que se parece mucho al pseudocódigo por su naturaleza. Por lo tanto, se puede convertir fácilmente a cualquier otro idioma, con cambios mínimos.

Entonces los principales modelos son:

  • Euclidian/Flat earth model : bueno para distancias muy cortas de menos de 10 km
  • Spherical model : bueno para grandes distancias longitudinales, pero con una pequeña diferencia latitudinal. Modelo popular:
    • Haversine : precisión del metro en escalas [km], código muy simple.
  • Ellipsoidal models : los más precisos en cualquier lat / lon y distancia, pero sigue siendo una aproximación numérica que depende de la precisión que necesite. Algunos modelos populares son:
    • Lambert : ~ 10 metros de precisión sobre 1000 de km .
    • Paul D. Thomas : aproximación de Andoyer-Lambert
    • Vincenty : milímetro de precisión y eficiencia computacional.
    • Kerney : precisión nanométrica

Referencias:

lon1 y lat1 en grados

brng = rodamiento en radianes

d = distancia en km

R = radio de la Tierra en km

 lat2 = math.degrees((d/R) * math.cos(brng)) + lat1 long2 = math.degrees((d/(R*math.sin(math.radians(lat2)))) * math.sin(brng)) + long1 

Implementé tu algoritmo y el mío en PHP y lo comparé. Esta versión se ejecutó en aproximadamente el 50% del tiempo. Los resultados generados fueron idénticos, por lo que parece ser matemáticamente equivalente.

No probé el código de Python anterior, así que podría haber errores de syntax.

Manera rápida usando geopy

 from geopy import distance #distance.distance(unit=15).destination((lat,lon),bering) #Exemples distance.distance(nautical=15).destination((-24,-42),90) distance.distance(miles=15).destination((-24,-42),90) distance.distance(kilometers=15).destination((-24,-42),90) 

También tarde, pero para aquellos que puedan encontrar esto, obtendrás resultados más precisos utilizando la biblioteca de biblioteca geográfica . Consulte las descripciones de problemas geodésicos y los ejemplos de JavaScript para obtener una introducción fácil a cómo usar para responder la pregunta del tema, así como a muchas otras. Implementaciones en una variedad de lenguajes incluyendo Python. Mucho mejor que codificar el tuyo si te importa la precisión; mejor que VincentyDistance en la recomendación anterior de “usar una biblioteca”. Como dice la documentación: “El énfasis está en devolver resultados precisos con errores cercanos al redondeo (alrededor de 5 a 15 nanómetros)”.

Simplemente intercambie los valores en la función atan2 (y, x). No atan2 (x, y)!

Porté la respuesta de Brad a la respuesta de vanilla JS, sin dependencia de los mapas de Bing

https://jsfiddle.net/kodisha/8a3hcjtd/

 // ---------------------------------------- // Calculate new Lat/Lng from original points // on a distance and bearing (angle) // ---------------------------------------- let llFromDistance = function(latitude, longitude, distance, bearing) { // taken from: https://stackoverflow.com/a/46410871/13549 // distance in KM, bearing in degrees const R = 6378.1; // Radius of the Earth const brng = bearing * Math.PI / 180; // Convert bearing to radian let lat = latitude * Math.PI / 180; // Current coords to radians let lon = longitude * Math.PI / 180; // Do the math magic lat = Math.asin(Math.sin(lat) * Math.cos(distance / R) + Math.cos(lat) * Math.sin(distance / R) * Math.cos(brng)); lon += Math.atan2(Math.sin(brng) * Math.sin(distance / R) * Math.cos(lat), Math.cos(distance / R) - Math.sin(lat) * Math.sin(lat)); // Coords back to degrees and return return [(lat * 180 / Math.PI), (lon * 180 / Math.PI)]; } let pointsOnMapCircle = function(latitude, longitude, distance, numPoints) { const points = []; for (let i = 0; i <= numPoints - 1; i++) { const bearing = Math.round((360 / numPoints) * i); console.log(bearing, i); const newPoints = llFromDistance(latitude, longitude, distance, bearing); points.push(newPoints); } return points; } const points = pointsOnMapCircle(41.890242042122836, 12.492358982563019, 0.2, 8); let geoJSON = { "type": "FeatureCollection", "features": [] }; points.forEach((p) => { geoJSON.features.push({ "type": "Feature", "properties": {}, "geometry": { "type": "Point", "coordinates": [ p[1], p[0] ] } }); }); document.getElementById('res').innerHTML = JSON.stringify(geoJSON, true, 2); 

Además, agregué la exportación de geoJSON, así que simplemente puedes pegar el geoJSON resultante en http://geojson.io/#map=17/41.89017/12.49171 y ver los resultados al instante.

Resultado: Captura de pantalla de GeoJSON

Porté el Python a Javascript. Esto devuelve un objeto de Location Bing Maps, puedes cambiarlo a lo que quieras.

 getLocationXDistanceFromLocation: function(latitude, longitude, distance, bearing) { // distance in KM, bearing in degrees var R = 6378.1, // Radius of the Earth brng = Math.radians(bearing) // Convert bearing to radian lat = Math.radians(latitude), // Current coords to radians lon = Math.radians(longitude); // Do the math magic lat = Math.asin(Math.sin(lat) * Math.cos(distance / R) + Math.cos(lat) * Math.sin(distance / R) * Math.cos(brng)); lon += Math.atan2(Math.sin(brng) * Math.sin(distance / R) * Math.cos(lat), Math.cos(distance/R)-Math.sin(lat)*Math.sin(lat)); // Coords back to degrees and return return new Microsoft.Maps.Location(Math.degrees(lat), Math.degrees(lon)); }, 

Aquí hay una versión de PHP basada en el formulario de Ed Williams Aviation. Módulo se maneja un poco diferente en PHP. Esto funciona para mi

 function get_new_waypoint ( $lat, $lon, $radial, $magvar, $range ) { // $range in nm. // $radial is heading to or bearing from // $magvar for local area. $range = $range * pi() /(180*60); $radial = $radial - $magvar ; if ( $radial < 1 ) { $radial = 360 + $radial - $magvar; } $radial = deg2rad($radial); $tmp_lat = deg2rad($lat); $tmp_lon = deg2rad($lon); $new_lat = asin(sin($tmp_lat)* cos($range) + cos($tmp_lat) * sin($range) * cos($radial)); $new_lat = rad2deg($new_lat); $new_lon = $tmp_lon - asin(sin($radial) * sin($range)/cos($new_lat))+ pi() % 2 * pi() - pi(); $new_lon = rad2deg($new_lon); return $new_lat." ".$new_lon; } 

Pasé la respuesta de @David M a java si alguien quería esto … Obtengo un resultado ligeramente diferente de 52.20462299620793, 0.360433887489931

  double R = 6378.1; //Radius of the Earth double brng = 1.57; //Bearing is 90 degrees converted to radians. double d = 15; //Distance in km double lat2 = 52.20444; // - the lat result I'm hoping for double lon2 = 0.36056; // - the long result I'm hoping for. double lat1 = Math.toRadians(52.20472); //Current lat point converted to radians double lon1 = Math.toRadians(0.14056); //Current long point converted to radians lat2 = Math.asin( Math.sin(lat1)*Math.cos(d/R) + Math.cos(lat1)*Math.sin(d/R)*Math.cos(brng)); lon2 = lon1 + Math.atan2(Math.sin(brng)*Math.sin(d/R)*Math.cos(lat1), Math.cos(d/R)-Math.sin(lat1)*Math.sin(lat2)); lat2 = Math.toDegrees(lat2); lon2 = Math.toDegrees(lon2); System.out.println(lat2 + ", " + lon2);