纬度,经度中点与线之间的最小距离

时间:2013-11-27 01:22:06

标签: objective-c xcode map distance latitude-longitude

我有一条经度和纬度为两点的线 答:3.222895,101.719751
B:3.227511,101.724318

和1点
C:3.224972,101.722932

如何计算C点与A点和B点之间的最小距离? 如果您也可以提供计算和Objective-c代码将会很方便。距离约为89米(使用Google地球中的标尺)。

5 个答案:

答案 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