Cálculo de coordenadas dado un cojinete y una distancia
-
22-08-2019 - |
Pregunta
Estoy teniendo problemas para implementar la función descrita aquí aquí .
Esta es mi aplicación Java:
private static double[] pointRadialDistance(double lat1, double lon1,
double radianBearing, double radialDistance) {
double lat = Math.asin(Math.sin(lat1)*Math.cos(radialDistance)+Math.cos(lat1)
*Math.sin(radialDistance)*Math.cos(radianBearing));
double lon;
if(Math.cos(lat) == 0) { // Endpoint a pole
lon=lon1;
}
else {
lon = ((lon1-Math.asin(Math.sin(radianBearing)*Math.sin(radialDistance)/Math.cos(lat))
+Math.PI) % (2*Math.PI)) - Math.PI;
}
return (new double[]{lat, lon});
}
convierto el cojinete grados a radianes y convertir la distancia (km) en una distancia radianes antes de llamar a la función -. Por lo que no es el problema
Sin embargo, cuando las coordenadas de entrada, tales como: lat = 49,25705; lon = -123,140259; con un cojinete de 225 (sur-oeste) y una distancia de 1 km
Me sale este regresó: Lat: -1.0085434360125864 lon: -3,7595299668539504
Su obviamente no es correcta, puede alguien ver lo que estoy haciendo mal?
Gracias
Solución
Parece que estos son los temas en su código:
- Es necesario para convertir
lat1
ylon1
a radianes antes de llamar a su función. - Es posible que se aumenta de escala
radialDistance
incorrectamente. - Comprobación de un número de coma flotante por la igualdad es peligroso. Dos números que son iguales después de aritmética exacta podría no ser exactamente igual después de la aritmética de punto flotante. Por lo tanto es más seguro que
abs(x-y) < threshold
x == y
para probar dos números de punto flotante yx
y
por la igualdad. - Pienso que desea convertir
lat
ylon
de radianes a grados.
Aquí está mi aplicación de su código en Python:
#!/usr/bin/env python
from math import asin,cos,pi,sin
rEarth = 6371.01 # Earth's average radius in km
epsilon = 0.000001 # threshold for floating-point equality
def deg2rad(angle):
return angle*pi/180
def rad2deg(angle):
return angle*180/pi
def pointRadialDistance(lat1, lon1, bearing, distance):
"""
Return final coordinates (lat2,lon2) [in degrees] given initial coordinates
(lat1,lon1) [in degrees] and a bearing [in degrees] and distance [in km]
"""
rlat1 = deg2rad(lat1)
rlon1 = deg2rad(lon1)
rbearing = deg2rad(bearing)
rdistance = distance / rEarth # normalize linear distance to radian angle
rlat = asin( sin(rlat1) * cos(rdistance) + cos(rlat1) * sin(rdistance) * cos(rbearing) )
if cos(rlat) == 0 or abs(cos(rlat)) < epsilon: # Endpoint a pole
rlon=rlon1
else:
rlon = ( (rlon1 - asin( sin(rbearing)* sin(rdistance) / cos(rlat) ) + pi ) % (2*pi) ) - pi
lat = rad2deg(rlat)
lon = rad2deg(rlon)
return (lat, lon)
def main():
print "lat1 \t lon1 \t\t bear \t dist \t\t lat2 \t\t lon2"
testcases = []
testcases.append((0,0,0,1))
testcases.append((0,0,90,1))
testcases.append((0,0,0,100))
testcases.append((0,0,90,100))
testcases.append((49.25705,-123.140259,225,1))
testcases.append((49.25705,-123.140259,225,100))
testcases.append((49.25705,-123.140259,225,1000))
for lat1, lon1, bear, dist in testcases:
(lat,lon) = pointRadialDistance(lat1,lon1,bear,dist)
print "%6.2f \t %6.2f \t %4.1f \t %6.1f \t %6.2f \t %6.2f" % (lat1,lon1,bear,dist,lat,lon)
if __name__ == "__main__":
main()
Aquí está la salida:
lat1 lon1 bear dist lat2 lon2
0.00 0.00 0.0 1.0 0.01 0.00
0.00 0.00 90.0 1.0 0.00 -0.01
0.00 0.00 0.0 100.0 0.90 0.00
0.00 0.00 90.0 100.0 0.00 -0.90
49.26 -123.14 225.0 1.0 49.25 -123.13
49.26 -123.14 225.0 100.0 48.62 -122.18
49.26 -123.14 225.0 1000.0 42.55 -114.51
Otros consejos
Creo que hay un problema en el algoritmo proporcionado en el mensaje 5.
Funciona, pero sólo para la latitud, de la longitud no es un problema debido a la señal.
Los datos hablan por sí solos:
49,26 -123,14 225,0 1,0 49,25 -123,13
Si se parte de -123,14 ° y vaya hacia el oeste usted debe tener algo lejos en el oeste. Aquí vamos de nuevo en el ESTE (-123,13)!
la fórmula debe incluye alguna parte:
degreeBearing = ((360-degreeBearing)% 360)
antes de la conversión en radianes.
Cuando implementé esto, mis latitudes resultantes eran correctas, pero las longitudes estaban equivocados. Por ejemplo, el punto de partida: 36.9460678N 9.434807E, Teniendo 45.03334, 15,0083313 kilometros Distancia El resultado fue 37.0412865N 9.315302E Eso es más al oeste que mi punto de partida, en lugar de hacia el este. De hecho, es como si el porte era 315.03334 grados.
Más Web búsqueda me llevó a: http: //www.movable- type.co.uk/scripts/latlong.html El código de longitud es mostrar a continuación (en C # con todo en radianes)
if ((Math.Cos(rLat2) == 0) || (Math.Abs(Math.Cos(rLat2)) < EPSILON))
{
rLon2 = rLon1;
}
else
{
rLon2 = rLon1 + Math.Atan2(Math.Sin(rBearing) * Math.Sin(rDistance) * Math.Cos(rLat1), Math.Cos(rDistance) - Math.Sin(rLat1) * Math.Sin(rLat2));
}
Esto parece funcionar bien para mí. Esperamos que sea útil.
Gracias por su código Python Traté de su puesta en marcha en mi caso de uso donde yo estoy tratando de encontrar la lon lat de un punto entre otros dos a una distancia determinada desde el primer punto lo que es muy similare a su código appart que mi rodamiento se calcula dinámicamente
punto de inicio (lat1) lon1 / lat1 = 55.625541, -21.142463
punto final (Lat2) Lon2 / Lat2 = 55.625792, -22.142248
mi resultado debe ser un punto entre estos dos en lon3 / Lat3 unfortunetly consigo lon3 / Lat3 = 0.0267695450609,0.0223553243666
pensé que esto podría haber una diferencia en lon lat pero sin cuando agrego o sub que no es bueno
Cualquier consejo sería realmente grande Gracias
aquí está mi aplicación
distancia = 0,001 epsilon = 0.000001
cálculo de rodamiento dinámicamente
y = math.sin(distance) * math.cos(lat2);
x = math.cos(lat1)*math.sin(lat2) - math.sin(lat1)*math.cos(lat2)*math.cos(distance);
bearing = math.atan2(y, x)
calcular lon3 Lat3 dinámica
rlat1 = (lat1 * 180) / math.pi
rlon1 = (lon1 * 180) / math.pi
rbearing = (bearing * 180) / math.pi
rdistance = distance / R # normalize linear distance to radian angle
rlat = math.asin( math.sin(rlat1) * math.cos(rdistance) + math.cos(rlat1) * math.sin(rdistance) * math.cos(rbearing) )
if math.cos(rlat) == 0 or abs(math.cos(rlat)) < epsilon: # Endpoint a pole
rlon=rlon1
else:
rlon = ( (rlon1 + math.asin( math.sin(rbearing)* math.sin(rdistance) / math.cos(rlat) ) + math.pi ) % (2*math.pi) ) - math.pi
lat3 = (rlat * math.pi)/ 180
lon3 = (rlon * math.pi)/ 180
Todo está funcionando según lo previsto, pero el problema es que tus cuentas asume que la Tierra es una esfera cuando en realidad se aproxima a un elipsoide.
Una rápida búsqueda de su motor de búsqueda favorito para 'Vincenty Fórmula' se espera que resulte útil.