所以基本上,我试图标记一些GPS点是否非常靠近道路。
我有经纬度坐标的向量,当与向量中的后续/前行连接时,它们会形成代表道路的线(以matplotlib图形表示为颜色) 我也有简单的地理位置(经纬度)(描绘为黑色的matplotlib散点图)
我想标记一个点是否在道路附近(例如,在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]
如何解决这个问题?我想不出一种解决方法,但是在查看情节时似乎很简单...有没有可以帮助您的库?
答案 0 :(得分:2)
我假设您正在使用地球的球形模型。然后,我想您所说的“直线”实际上是大圆的圆弧段(球形几何形状的直线)。换句话说,您在球面上具有经纬度坐标p1
的一个点[lat1, lon1]
,在球面上具有经纬度坐标p2
的另一个点[lat2, lon2]
。穿过p1
和p2
的球面上的“直线”是指球体与穿过球心的平面相交而获得的唯一圆(称为大圆)球体和两个点p1
和p2
。然后,您所说的“线”是该大圆上的两个圆弧中较小的一个,以两个点p1
和p2
为界。
您要计算的距离(以弧度为单位)可以是从具有经纬度坐标p
的第三个点[lat, lon]
到由两个点{{1 }}和p1
。所述距离应该是从穿过p2
的大圆到垂直于p
和p1
的大圆的弧的弧长。该垂直大圆是由球体与垂直于p2
和p1
大圆的平面的平面相交并通过点p2
和中心确定的圆的范围。如果垂直大圆与大圆弧p
的交点是弧段p1 p2
内的点h
,则大圆弧{{1} }是搜寻距离。但是,如果p1 p2
在圆弧p h
之外,则搜寻距离为h
或p1 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的测量也应该工作。
您选择所需的功能,球形的或近似于欧几里得的。后者可能更快。您可以选择删除平方根并计算平方的距离,以使处理速度更快。
我急着写了这个,所以可能有些不准确。