Le calcul de coordonnées donné un palier et d'une distance
-
22-08-2019 - |
Question
Je rencontre des problèmes de mise en œuvre de la fonction décrite ici .
Ceci est mon implémentation 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});
}
je convertir le roulement de degrés en radians et convertir la distance (km) en une distance de radians avant d'appeler la fonction -. Si ce n'est pas le problème
Cependant, quand je coordonnées d'entrée, tels que: lat = 49,25705; lon = -123,140259; avec un palier de 225 (sud-ouest) et d'une distance de 1 km
Je reçois ce retour: lat: -1,0085434360125864 LON: -3,7595299668539504
Son évidemment pas correct, peut-on voir ce que je fais mal?
Merci
La solution
Il semble que ce sont les problèmes dans votre code:
- Vous devez convertir
lat1
etlon1
en radians avant d'appeler votre fonction. - Vous pouvez être mise à l'échelle
radialDistance
de manière incorrecte. - Test d'un nombre à virgule flottante pour l'égalité est dangereux. Deux chiffres qui sont égaux après l'arithmétique exacte pourraient ne pas être exactement égale après l'arithmétique à virgule flottante. Ainsi
abs(x-y) < threshold
est plus sûr quex == y
pour tester deux nombres à virgule flottantex
ety
pour l'égalité. - Je pense que vous voulez convertir
lat
etlon
de radians en degrés.
Voici mon implémentation de votre code 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()
Voici la sortie:
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
Autres conseils
Fondamentalement, il semble que votre problème est que vous passez la latitude, la longitude et portant en degrés plutôt que radians. Essayez d'assurer que vous êtes toujours de passage radians à votre fonction et voir ce que vous obtenez en retour.
PS: voir des problèmes similaires abordés et here .
Je pense qu'il ya un problème dans l'algorithme fourni dans le message 5.
Il fonctionne, mais seulement pour la latitude, la longitude il y a un problème à cause du signe.
Les données parlent d'eux-mêmes:
49,26 -123,14 -123,13 49,25 225,0 1,0
Si vous partez de -123,14 ° et allez vers l'ouest, vous devriez avoir quelque chose de bien dans l'Ouest. nous allons revenir ici sur l'EST (-123,13)!
La formule devrait comprend quelque part:
degreeBearing = ((360-degreeBearing)% 360)
avant radian convertion.
Quand je mis en œuvre, mes latitudes résultantes étaient correctes, mais les longitudes ont eu tort. Par exemple le point de départ: 36.9460678N 9.434807E, Ayant 45,03334, Distance 15,0083313 km Le résultat a été 37.0412865N 9.315302E C'est plus à l'ouest que mon point de départ, plutôt que plus à l'est. En fait, il est comme si le roulement 315.03334 degrés.
Plus de recherche web m'a conduit à: http: //www.movable- type.co.uk/scripts/latlong.html Le code de longitude est montrer ci-dessous (en C # avec tout en radians)
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));
}
Cela semble fonctionner très bien pour moi. Espérons que c'est utile.
Merci pour votre code python J'ai essayé de le mettre dans mon cas d'utilisation où je suis en train de trouver le lat lon d'un point entre les deux autres à une distance de jeu du premier point il est donc tout à fait similare à votre code appart que mon palier est calculée dynamiquement
startpoint (LAT1) LON1 / lat1 = 55,625541, -21,142463
point d'extrémité (LAT2) Lon2 / lat2 = 55,625792, -22,142248
mon résultat devrait être un point entre ces deux à lon3 / LAT3 unfortunetly Je reçois lon3 / LAT3 = 0.0267695450609,0.0223553243666
Je pensais que cela pourrait être une différence de latitude, mais pas lon quand j'ajouter ou sous ce n'est pas bon
tout conseil serait vraiment génial Merci
voici mon implémentation
distance = 0,001 epsilon = 0.000001
calculé le palier dynamique
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)
LAT3 lon3 calculé dynamiquement
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
Tout fonctionne comme prévu, mais le problème est que vos mathématiques suppose la Terre est une sphère alors qu'en réalité il se rapproche d'un ellipsoïde.
Un chalut rapide de votre moteur de recherche privilégié pour « Vincenty Formula », nous l'espérons se révéler utile.