如何计算一组线和一个点之间的(最小)距离?

时间:2019-05-31 23:29:54

标签: python pandas numpy math distance

所以基本上,我试图标记一些GPS点是否非常靠近道路。

我有经纬度坐标的向量,当与向量中的后续/前行连接时,它们会形成代表道路的线(以matplotlib图形表示为颜色) 我也有简单的地理位置(经纬度)(描绘为黑色的matplotlib散点图) two muppets

我想标记一个点是否在道路附近(例如,在0.001弧度距离之内)-为此,我想可能需要计算一个点与这组向量的最接近距离。

#example vector 1
[[-84.3146272, 33.7741084], [-84.3145183, 33.7741196]]
#example vector 2
[[-84.4043106, 33.7700542], [-84.4045421, 33.770055]]

#example point to predict wether it will be near one of these two lines
[-84.31106, 33.73887]

如何解决这个问题?我想不出一种解决方法,但是在查看情节时似乎很简单...有没有可以帮助您的库?

1 个答案:

答案 0 :(得分:2)

我假设您正在使用地球的球形模型。然后,我想您所说的“直线”实际上是大圆的圆弧段(球形几何形状的直线)。换句话说,您在球面上具有经纬度坐标p1的一个点[lat1, lon1],在球面上具有经纬度坐标p2的另一个点[lat2, lon2] 。穿过p1p2的球面上的“直线”是指球体与穿过球心的平面相交而获得的唯一圆(称为大圆)球体和两个点p1p2。然后,您所说的“线”是该大圆上的两个圆弧中较小的一个,以两个点p1p2为界。

您要计算的距离(以弧度为单位)可以是从具有经纬度坐标p的第三个点[lat, lon]到由两个点{{1 }}和p1。所述距离应该是从穿过p2的大圆到垂直于pp1的大圆的弧的弧长。该垂直大圆是由球体与垂直于p2p1大圆的平面的平面相交并通过点p2和中心确定的圆的范围。如果垂直大圆与大圆弧p的交点是弧段p1 p2内的点h,则大圆弧{{1} }是搜寻距离。但是,如果p1 p2在圆弧p h之外,则搜寻距离为hp1 p2中较小的一个。

以下是一些Matlab代码,用于计算点与弧间隔之间的最短距离:

p p1

您可以对形成道路的一系列弧间隔进行迭代,并选择到弧间隔的最小距离。

根据此计算,该点到第一个“向量1”的距离为 p p2弧度,到第二个“向量2”的距离为 lat_lon = [lat, lon]; lat_lon1 = [lat1, lon1]; lat_lon2 = [lat2, lon2]; function dist = dist_point_2_road(lat_lon, lat_lon1, lat_lon2) % you may have to convert lat-long angles from degrees to radians % First, convert from lat-long coordinates to 3D coordinates of points on the unit % sphere. Since Earth's radius cancels out in our computations, we simply assume it % is R = 1 lat = lat_lon(1); lon = lat_lon(2); lat1 = lat_lon1(1); lon1 = lat_lon1(2); lat2 = lat_lon2(1); lon2 = lat_lon2(2); p1 = [ cosd(lat1)*cosd(lon1), cosd(lat1)*sind(lon1), sind(lat1) ]; %cosd = cos(degrees) p2 = [ cosd(lat2)*cosd(lon2), cosd(lat2)*sind(lon2), sind(lat2) ]; %sind = sin(degrees) p = [ cosd(lat)*cosd(lon), cosd(lat)*sind(lon), sind(lat) ]; % n12 is the unit vector perpendicular to the plane of the great circle % determined by the points p1 and p2 n12 = cross(p1, p2); n12 = n12 / sqrt(dot(n12, n12)); sin_of_dist = dot(p, n12); % sine of the angle that equals arc-distance % from point p to the great arc p1 p2 dist = pi/2 - acos(abs(sin_of_dist)); % acos = arccos, abs() = absolute value % dist is the shortest distance in radians from p to the % great circle determined by the points p1 and p2 n1 = cross(p1, p); n1 = n1 / sqrt(dot(n1, n1)); % unit normal vector perpendicular to the great-arc determined by p and p1 n2 = cross(p, p2); n2 = n1 / sqrt(dot(n2, n2)); % unit normal vector perpendicular to the great-arc determined by p and p2 if dot(n12, n1) < 0 % if the angle of spherical triangle p p1 p2 at vertex p1 is obtuse dist = acos(dot(p, p1)); % the shortest distance is p p1 elseif dot(n12, n2) < 0 % if the angle of spherical triangle p p1 p2 at vertex p2 is obtuse dist = acos(dot(p, p2)); % the shortest distance is p p2 end % the function returns the appropriate dist as output end 弧度。该点最接近向量1内的一个点,但是对于向量2来说,它最接近圆弧间隔的一端之一。

编辑。现在,如果要使用Euculdiean(平坦)近似,而忽略地球曲率,则可能需要将经纬度坐标转换为Euclidean平坦近似坐标。为了避免任何地图特定的坐标,可以尝试针对经度坐标绘制纬度。在赤道周围也许可以,但是越靠近极点,这些坐标在表示距离数据时越不准确。这是因为靠近两极,沿固定纬度的距离比沿固定经度的距离短得多。这就是为什么我们需要纠正这一差异。这可以通过在球体上使用经纬度坐标的黎曼度量来完成,也可以仅通过查看球体上给定点附近的经度和纬度圆的3D几何来完成。

0.0000615970599633145

注释::后一个函数计算距离,但是只计算0.00162840939265068可能同样方便,避免了平方根lat_lon = [lat, lon]; lat_lon1 = [lat1, lon1]; lat_lon2 = [lat2, lon2]; %center of approximate Euclidean coordinate system is point p % with lat_long coordinates and the scaling coefficient of longitude, % which equalizes longitude and latitude distance at point p, is a = cosd(lat_long(1)); function x = convert_2_Eucl(lat_long1, lat_long, a) x = [lat_long1(1) - lat_long(1), a*(lat_long1(2) - lat_long(2))]; end % convert from lat-long to approximate Euclidean coordinates x1 = convert_2_Eucl(lat_long1, lat_long, a); x2 = convert_2_Eucl(lat_long2, lat_long, a); function dist = dist_point_2_road(x1, x2) dist = dot(x1, x1) * dot(x2 - x1, x2 - x1) - dot(x1, x2 - x1)^2 ; dist = sqrt( dist / ( dot(x2 - x1, x2 - x1)^2) ); % dist is the distance from the point p, which has Eucl coordinates [0,0] % to the straight Euclidean interval x1 x2 representing the interval p1 p2 if dot(x1, x2 - x1) > 0 dist = sqrt( dot(x1, x1) ); elseif dot(x2, x1 - x2) > 0 dist = sqrt( dot(x2, x2) ); end end 的计算以加快速度表演。关于dist ^ 2的测量也应该工作。

您选择所需的功能,球形的或近似于欧几里得的。后者可能更快。您可以选择删除平方根并计算平方的距离,以使处理速度更快。

我急着写了这个,所以可能有些不准确。