我有一条经度和纬度为两点的线
答:3.222895,101.719751
B:3.227511,101.724318
和1点
C:3.224972,101.722932
如何计算C点与A点和B点之间的最小距离? 如果您也可以提供计算和Objective-c代码将会很方便。距离约为89米(使用Google地球中的标尺)。
答案 0 :(得分:12)
感谢mimi和这篇伟大的文章http://www.movable-type.co.uk/scripts/latlong.html,但他们没有全面了解。这是一个细节。所有这些点都是使用Google地球使用地标标记位置来收集的。确保在首选项中将lat / long设置为十进制度数。
lat A = 3.222895
lon A = 101.719751
lat B = 3.222895
lon B = 101.719751
lat C = 3.224972
lon C = 101.722932
Earth radius, R = 6371
<强> 1。首先,您必须找到从A到C和A到B的轴承。
轴承公式
bearingAC = atan2( sin(Δλ)*cos(φ₂), cos(φ₁)*sin(φ₂) − sin(φ₁)*cos(φ₂)*cos(Δλ) )
bearingAB = atan2( sin(Δλ)*cos(φ₂), cos(φ₁)*sin(φ₂) − sin(φ₁)*cos(φ₂)*cos(Δλ) )
φ是纬度,λ是经度,R是地球半径
<强> 2。使用球面的余弦定律找到A到C的距离
distanceAC = acos( sin(φ₁)*sin(φ₂) + cos(φ₁)*cos(φ₂)*cos(Δλ) )*R
第3。查找跨轨距离
distance = asin(sin(distanceAC/ R) * sin(bearingAC − bearing AB)) * R
Objective-C代码
double lat1 = 3.227511;
double lon1 = 101.724318;
double lat2 = 3.222895;
double lon2 = 101.719751;
double lat3 = 3.224972;
double lon3 = 101.722932;
double y = sin(lon3 - lon1) * cos(lat3);
double x = cos(lat1) * sin(lat3) - sin(lat1) * cos(lat3) * cos(lat3 - lat1);
double bearing1 = radiansToDegrees(atan2(y, x));
bearing1 = 360 - ((bearing1 + 360) % 360);
double y2 = sin(lon2 - lon1) * cos(lat2);
double x2 = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(lat2 - lat1);
double bearing2 = radiansToDegrees(atan2(y2, x2));
bearing2 = 360 - ((bearing2 + 360) % 360);
double lat1Rads = degreesToRadians(lat1);
double lat3Rads = degreesToRadians(lat3);
double dLon = degreesToRadians(lon3 - lon1);
double distanceAC = acos(sin(lat1Rads) * sin(lat3Rads)+cos(lat1Rads)*cos(lat3Rads)*cos(dLon)) * 6371;
double min_distance = fabs(asin(sin(distanceAC/6371)*sin(degreesToRadians(bearing1)-degreesToRadians(bearing2))) * 6371);
NSLog(@"bearing 1: %g", bearing1);
NSLog(@"bearing 2: %g", bearing2);
NSLog(@"distance AC: %g", distanceAC);
NSLog(@"min distance: %g", min_distance);
实际上有一个库。你可以在https://github.com/100grams/CoreLocationUtils
找到它答案 1 :(得分:3)
计算每个的方位:C到A,C到B:
var y = Math.sin(dLon) * Math.cos(lat2);
var x = Math.cos(lat1)*Math.sin(lat2) -
Math.sin(lat1)*Math.cos(lat2)*Math.cos(dLon);
var brng = Math.atan2(y, x).toDeg();
dLon = lon2-lon1;
计算跨轨距离:
var dXt = Math.asin(Math.sin(distance_CB/R)*Math.sin(bearing_CA-bearing_CB)) * R;
R是地球的半径,dXt是您想要计算的最小距离。
答案 2 :(得分:1)
执行此计算的代码发布在here。 这实现了椭球测地线的精确解决方案。 对于基本的测地线计算,您可以使用 GeographicLib或这些算法到C的端口,包含在PROJ.4版本4.9.0中。此C接口记录为here。
以下是编译和运行intercept.cpp的结果:
$ echo 3.222895 101.719751 3.227511 101.724318 3.224972 101.722932 | ./intercept
Initial guess 3.225203 101.7220345
Increment 0.0003349040566247297 0.0003313413822354505
Increment -4.440892098500626e-16 0
Increment 0 0
...
Final result 3.225537904056624 101.7223658413822
Azimuth to A1 -135.1593040635131
Azimuth to A2 44.84069593652217
Azimuth to B1 134.8406959363608
距离线路为88.743米:
$ echo 3.224972 101.722932 3.225537904056624 101.7223658413822 | GeodSolve -i
-45.15927221 -45.15930407 88.743
答案 3 :(得分:1)
见帖子: https://stackoverflow.com/a/33343505/4083623
对于几千米的距离,我会简化从球到平面的问题。 然后,问题非常简单,因为可以使用简单的三角形计算:
我们有A点和B点,并寻找到AB线的距离X.然后:
Location a;
Location b;
Location x;
double ax = a.distanceTo(x);
double alfa = (Math.abs(a.bearingTo(b) - a.bearingTo(x))) / 180
* Math.PI;
double distance = Math.sin(alfa) * ax;
答案 4 :(得分:0)
如果你知道如何计算两点的距离,得到每两点之间的距离,你得到AB,AC和BC。您想知道C点和AB线之间的最近距离。
首先得到P
的值P=(AB+BC+AC)/2
使用P,你需要得到S
S=SQRT((P(P-AC)(P-AB)(P-AC))
SQRT表示平方根。
然后你得到了你想要的东西2*S/AB