حساب الإحداثيات بالنظر إلى الاتجاه والمسافة
-
22-08-2019 - |
سؤال
أواجه مشكلات في تنفيذ الوظيفة الموضحة هنا هنا.
هذا هو تطبيق 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});
}
أقوم بتحويل محمل الدرجة إلى راديان وتحويل المسافة (كم) إلى مسافة راديان قبل استدعاء الوظيفة - لذلك ليست هذه هي المشكلة.
ومع ذلك، عندما أقوم بإدخال الإحداثيات مثل:خطوط العرض = 49.25705؛خط الطول = -123.140259؛بإتجاه 225 (جنوب غرب) ومسافة 1 كم
أحصل على هذا عاد:خطوط العرض:-1.0085434360125864 LON:-3.7595299668539504
من الواضح أن هذا ليس صحيحًا، هل يمكن لأي شخص أن يرى الخطأ الذي أفعله؟
شكرًا
المحلول
يبدو أن هذه هي المشكلات الموجودة في التعليمات البرمجية الخاصة بك:
- تحتاج إلى تحويل
lat1
وlon1
إلى راديان قبل استدعاء وظيفتك. - ربما تقوم بالتحجيم
radialDistance
بشكل غير صحيح. - يعد اختبار رقم الفاصلة العائمة للمساواة أمرًا خطيرًا.قد لا يكون الرقمان المتساويان بعد الحساب الدقيق متساويين تمامًا بعد حساب الفاصلة العائمة.هكذا
abs(x-y) < threshold
أكثر أمانا منx == y
لاختبار رقمين الفاصلة العائمةx
وy
من أجل المساواة. - أعتقد أنك تريد التحويل
lat
وlon
من راديان إلى درجات.
هذا هو تنفيذ التعليمات البرمجية الخاصة بك في بايثون:
#!/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()
هنا هو الإخراج:
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
نصائح أخرى
وفي الأساس، يبدو أن مشكلتك هي أنك تمر خطوط الطول والعرض وتحمل كما درجة بدلا من راديان. محاولة ضمان ان كنت دائما يمر راديان إلى وظيفة الخاص بك ومعرفة ما تحصل عليه العودة.
وPS: انظر قضايا مماثلة ناقش هنا و <لأ href = " https://stackoverflow.com/questions/695065/geoalgorithm-for-finding-coordinates-of-point-from-a-known-location-by-distance-a">here .
وأعتقد أن هناك مشكلة في خوارزمية المقدمة في رسالة 5.
وكان يعمل ولكن فقط لخطوط العرض والطول للوجود مشكلة بسبب علامة.
والبيانات تتحدث عن نفسها:
<اقتباس فقرة>49.26 -123.14 225.0 1.0 49.25 -123.13
اقتباس فقرة>إذا كنت تبدأ من على -123.14 ° و تذهب WEST يجب أن يكون لديك شيء FAR في WEST. هنا نذهب مرة أخرى على EAST (-123.13)!
وتتضمن الصيغة ينبغي مكان ما:
<اقتباس فقرة>وdegreeBearing = ((360 degreeBearing)٪ 360)
اقتباس فقرة>وقبل التحويل راديان.
وعندما تنفذ هذه، كانت لي خطوط العرض مما أدى الصحيحة ولكن كانت الطول الخطأ. على سبيل المثال نقطة انطلاق: 36.9460678N 9.434807E، وإذ تضع 45.03334، المسافة 15.0083313km وكانت النتيجة 37.0412865N 9.315302E هذا إلى الغرب من نقطة البداية بالنسبة لي، وليس مزيدا من الشرق. في واقع الأمر كما لو كان تأثير 315،03334 درجة.
والمزيد من البحث على شبكة الإنترنت قادني إلى: HTTP: //www.movable- type.co.uk/scripts/latlong.html رمز العرض هو إظهار أدناه (في C # مع كل شيء في راديان)
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));
}
ويبدو أن هذا العمل غرامة بالنسبة لي. نأمل أن تكون مفيدة.
والشكر لرمز الثعبان الخاص بك حاولت وضع هذا الامر في حال استخدامي حيث أحاول العثور على خط الطول خطوط الطول نقطة في بين اثنين آخرين على مسافة مجموعة من النقطة الأولى حتى انها سميلر تماما إلى التعليمات البرمجية APPART أن بلدي تحمل يحسب حيوي
وstartpoint (lat1) lon1 / lat1 = 55.625541، -21.142463
ونقطة النهاية (lat2) lon2 / lat2 = 55.625792، -22.142248
ويجب أن يكون نتيجة بلدي نقطة بين هذين في lon3 / lat3 لكن لسوء الحظ أحصل lon3 / lat3 = 0.0267695450609،0.0223553243666
وأعتقد أن هذا قد يكون الفرق في خط الطول خطوط الطول ولكن لا عندما أضيف أو دون ذلك انها ليست جيدة
وأن أي نصيحة تكون كبيرة حقا بفضل
وهنا تنفيذ بلدي
وبعد = 0.001 إبسيلون = 0.000001
حساب تحمل حيوي
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)
حساب lon3 lat3 حيوي
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
وكل شيء يعمل على النحو المنشود، ولكن المشكلة هي أن الرياضيات الخاص تفترض الأرض ليكون المجال عندما تكون في واقع الأمر يقترب من الإهليلجي.
وسوف الجر السريع لمحرك البحث المفضلة لديك ل"الفورمولا Vincenty" يثبت نأمل مفيدة.