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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20231258/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 04:21:16  来源:igfitidea点击:

Minimum distance between a point and a line in latitude, longitude

objective-cxcodemapdistancelatitude-longitude

提问by Azam

I have a line with two points in latitude and longitude
A: 3.222895, 101.719751
B: 3.227511, 101.724318

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

and 1 point
C: 3.224972, 101.722932

和 1 点
C: 3.224972, 101.722932

How can I calculate minimum distance between point C and a line consists of point A and B? It will be convenient if you can provide the calculation and objective-c code too. The distance is around 89 meters (using ruler in Google Earth).

如何计算点 C 和由点 A 和 B 组成的线之间的最小距离?如果你也提供计算和objective-c代码会很方便。距离约为 89 米(使用 Google 地球中的标尺)。

回答by Azam

Thanks to mimi and this great article http://www.movable-type.co.uk/scripts/latlong.htmlbut they don't give the whole picture. Here is a detail one. All this points are collected using Google Earth using Placemark to mark the locations. Make sure lat/long are set to decimal degrees in Preferences.

感谢 mimi 和这篇很棒的文章http://www.movable-type.co.uk/scripts/latlong.html但他们没有给出全貌。这是一个细节。所有这些点都是使用 Google Earth 收集的,使用 Placemark 来标记位置。确保在首选项中将纬度/经度设置为十进制度数。

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. First you have to find the bearing from A to C and A to B.
Bearing formula

1.首先你要找到从A到C和A到B的
轴承轴承公式

bearingAC = atan2( sin(Δλ)*cos(φ?), cos(φ?)*sin(φ?) ? sin(φ?)*cos(φ?)*cos(Δλ) )  
bearingAB = atan2( sin(Δλ)*cos(φ?), cos(φ?)*sin(φ?) ? sin(φ?)*cos(φ?)*cos(Δλ) ) 

φ is latitude, λ is longitude, R is earth radius

φ是纬度,λ是经度,R是地球半径

2. Find A to C distance using spherical law of cosines

2. 使用余弦球定律求 A 到 C 的距离

distanceAC = acos( sin(φ?)*sin(φ?) + cos(φ?)*cos(φ?)*cos(Δλ) )*R

3. Find cross-track distance

3. 查找交叉轨道距离

distance = asin(sin(distanceAC/ R) * sin(bearingAC ? bearing AB)) * R

Objective-C code

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);

Actually there's a library for this. You can find it here https://github.com/100grams/CoreLocationUtils

实际上有一个图书馆。你可以在这里找到它https://github.com/100grams/CoreLocationUtils

回答by Azam

Calculate bearing for each: C to A , and C to B:

计算每个方位: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;

dLon=lon2-lon1;

Calculate cross-track distance:

计算交叉轨道距离:

var dXt = Math.asin(Math.sin(distance_CB/R)*Math.sin(bearing_CA-bearing_CB)) * R;

R is the radius of earth, dXt is the minimum distance you wanted to calculate.

R 是地球的半径,dXt 是您要计算的最小距离。

回答by cffk

Code to carry out this calculation is posted at here. This implements an accurate solution in terms of ellipsoidal geodesics. For the basic geodesic calculations, you can use GeographicLibor the port of these algorithms to C which are included in version 4.9.0 of PROJ.4. This C interface is documented here.

执行此计算的代码发布在此处。这在椭球测地线方面实现了准确的解决方案。对于基本的测地线计算,您可以使用 GeographicLib或这些算法到 C 的端口,这些算法包含在 PROJ.4 的4.9.0版本中。此 C 接口记录在此处

Here's the result of compiling and running intercept.cpp:

下面是编译和运行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

Distance to line is 88.743m:

到线的距离是 88.743m:

$ echo 3.224972 101.722932 3.225537904056624 101.7223658413822 | GeodSolve -i
-45.15927221 -45.15930407 88.743

回答by Martin Koubek

See post here: https://stackoverflow.com/a/33343505/4083623

请参阅此处的帖子:https: //stackoverflow.com/a/33343505/4083623

For distance up to a few thousands meters I would simplify the issue from sphere to plane. Then, the issue is pretty simply as a easy triangle calculation can be used:

对于长达几千米的距离,我会简化从球体到平面的问题。然后,问题很简单,因为可以使用简单的三角形计算:

We have points A and B and look for a distance X to line AB. Then:

我们有点 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;

回答by David Lin

If you know how to calculate the distance of two points, get the distances between each two points, you get AB, AC, and BC. You want to know the closest distance between point C and line AB.

如果你知道如何计算两点的距离,得到每两个点之间的距离,你就会得到 AB、AC 和 BC。您想知道点 C 和线 AB 之间的最近距离。

First get the value of P

首先得到P的值

P=(AB+BC+AC)/2

Using P, you need to get S

使用P,你需要得到S

S=SQRT((P(P-AC)(P-AB)(P-AC)) 

SQRT means square root. Then you get what you want by

SQRT 表示平方根。然后你得到你想要的

2*S/AB