[英]Find the distance between points and line and achieve the projection distance that the point takes in a line
我是python的新手。 但是对于我来说,我面临着一项艰巨的任务:我有一个带有GPS坐标的CSV文件和一个带有代表车辆轨迹的参考轨迹(坐标点)的文件。
因此,任务是对所有点计算到参考轨迹的垂直距离并定义该点在参考轨迹的哪一公里内
我试图用QGIS解决它,但问题是数据太多,QGIS一直崩溃。 我正在使用距离矩阵。
因此,参考轨迹数据如下所示:
datetime lon_deg lat_deg ki1ometers
0 27.03.2018 15:07 14.34559621 48.28282695 0
1 27.03.2018 15:07 14.34539589 48.283579 0.08492765648897423
2 27.03.2018 15:08 14.34509878 48.28437137 0.17573647034625345
3 27.03.2018 15:08 14.34476681 48.28520735 0.2718837851891085
4 27.03.2018 15:09 14.34440297 48.28607467 0.372012272777317
5 27.03.2018 15:10 14.34355387 48.28785601 0.5798125761498747
6 27.03.2018 15:10 14.34312139 48.28876254 0.6855708866782635
7 27.03.2018 15:11 14.34267986 48.28966368 0.7909635418697577
8 27.03.2018 15:11 14.34235909 48.29057934 0.895509507334529
9 27.03.2018 15:12 14.34193015 48.29147634 1.000178064181187
10 27.03.2018 15:12 14.34158939 48.2923968 1.1055875957864745
11 27.03.2018 15:13 14.34125444 48.29332421 1.2116463089787737
12 27.03.2018 15:13 14.34084938 48.29424082 1.31788253222638
13 27.03.2018 15:14 14.34041673 48.29515665 1.4246295164890292
14 27.03.2018 15:14 14.34001362 48.29608703 1.532295241219843
15 27.03.2018 15:15 14.33959522 48.29702238 1.6408091272201002
16 27.03.2018 15:15 14.33917898 48.29796904 1.7504838454702525
17 27.03.2018 15:16 14.33875624 48.29892358 1.8611345768980705
18 27.03.2018 15:16 14.33832484 48.29988211 1.9723928345544686
19 27.03.2018 15:17 14.337844699999998 48.30083163 2.083788039109954
20 27.03.2018 15:17 14.33733187 48.30177414 2.1952441083077696
21 27.03.2018 15:18 14.33680756 48.30271439 2.3067561380904458
22 27.03.2018 15:18 14.33637327 48.30366977 2.4177398933361665
23 27.03.2018 15:19 14.33579109 48.30456609 2.5263104564169723
以及我需要在参考轨迹上计算距离和位置的数据:
datetime lon_deg lat_deg
2018-01-29 00:00:00.000 13.535165989333333 48.58077572716667
29.01.2018 0:00 13.535166009 48.580775726166664
2018-01-29 00:00:01.000 13.535165977166667 48.580775749
29.01.2018 0:00 13.5351658175 48.58077575
2018-01-29 00:00:02.000 13.535165976833333 48.58077567466667
29.01.2018 0:00 13.535165988166666 48.58077563316667
2018-01-29 00:00:03.000 13.535165978333334 48.580775599
29.01.2018 0:00 13.535166127833334 48.5807756575
2018-01-29 00:00:04.000 13.535166430833334 48.5807757935
29.01.2018 0:00 13.535166510166666 48.580775819
2018-01-29 00:00:05.000 13.5351665845 48.5807758835
29.01.2018 0:00 13.5351665215 48.580775906
2018-01-29 00:00:06.000 13.535166549166666 48.58077594583333
29.01.2018 0:00 13.535166521333334 48.58077594466667
2018-01-29 00:00:07.000 13.535166487 48.580775927666664
29.01.2018 0:00 13.5351670905 48.58077611433333
2018-01-29 00:00:08.000 13.5351669075 48.5807760195
29.01.2018 0:00 13.535166444166666 48.580775919
因此,我期望的输出是计算的到直线轨迹的距离以及该点在轨迹的特定公里数内。
我很高兴听到任何想法,因为我确实陷入了这个问题
在这么小的距离(例如2.5公里的路程)的情况下,您可能可以使用平面近似值并使用非常简单的方法:对于距离,您可以使用公式来计算三角形的高度,例如使用半周长的公式。 然后,您仍然必须计算该点是否在给定的线段中(在其上构建的垂直带的一部分),在此处可以使用矢量的标量(点)乘积的投影属性 。
因此,对于线段AB和点C(所有点都是元组/列表),您将需要以下内容:
pdist=lambda A,B:((A[0]-B[0])**2+(A[1]-B[1])**2)**(1/2)
def dist(A,B,C):
c=pdist(A,B)
rat=((C[0]-A[0])*(B[0]-A[0])+(C[1]-A[1])*(B[1]-A[1]))/c/c
if rat<0 or rat>1:
return None,None
a=pdist(B,C)
b=pdist(A,C)
s=(a+b+c)/2
alt=2*(s*(s-a)*(s-b)*(s-c))**(1/2)/c
return alt,rat
如果C的垂直基点在AB外部,或者垂直距离(C到AB段的距离)的元组和0 ... 1之间的比率(可以用作计算“行程位置”的权重) None,None
则返回None,None
在两个相邻点之间。
然后对示例数据进行一些解析:
import re
rawtour='''0 27.03.2018 15:07 14.34559621 48.28282695 0
1 27.03.2018 15:07 14.34539589 48.283579 0.08492765648897423
2 27.03.2018 15:08 14.34509878 48.28437137 0.17573647034625345
3 27.03.2018 15:08 14.34476681 48.28520735 0.2718837851891085
4 27.03.2018 15:09 14.34440297 48.28607467 0.372012272777317
5 27.03.2018 15:10 14.34355387 48.28785601 0.5798125761498747
6 27.03.2018 15:10 14.34312139 48.28876254 0.6855708866782635
7 27.03.2018 15:11 14.34267986 48.28966368 0.7909635418697577
8 27.03.2018 15:11 14.34235909 48.29057934 0.895509507334529
9 27.03.2018 15:12 14.34193015 48.29147634 1.000178064181187
10 27.03.2018 15:12 14.34158939 48.2923968 1.1055875957864745
11 27.03.2018 15:13 14.34125444 48.29332421 1.2116463089787737
12 27.03.2018 15:13 14.34084938 48.29424082 1.31788253222638
13 27.03.2018 15:14 14.34041673 48.29515665 1.4246295164890292
14 27.03.2018 15:14 14.34001362 48.29608703 1.532295241219843
15 27.03.2018 15:15 14.33959522 48.29702238 1.6408091272201002
16 27.03.2018 15:15 14.33917898 48.29796904 1.7504838454702525
17 27.03.2018 15:16 14.33875624 48.29892358 1.8611345768980705
18 27.03.2018 15:16 14.33832484 48.29988211 1.9723928345544686
19 27.03.2018 15:17 14.337844699999998 48.30083163 2.083788039109954
20 27.03.2018 15:17 14.33733187 48.30177414 2.1952441083077696
21 27.03.2018 15:18 14.33680756 48.30271439 2.3067561380904458
22 27.03.2018 15:18 14.33637327 48.30366977 2.4177398933361665
23 27.03.2018 15:19 14.33579109 48.30456609 2.5263104564169723 '''
tour=list(map(lambda line:list(map(lambda x:float(x),re.match(r'[^\s]+\s+[^\s]+\s+[^\s]+\s+([\d\.]+)\s+([\d\.]+)\s+([\d\.]+)\s*',line).groups())),rawtour.split('\n')))
rawmarks='''2018-01-29 00:00:00.000 13.535165989333333 48.58077572716667
29.01.2018 0:00 13.535166009 48.580775726166664
2018-01-29 00:00:01.000 13.535165977166667 48.580775749
29.01.2018 0:00 13.5351658175 48.58077575
2018-01-29 00:00:02.000 13.535165976833333 48.58077567466667
29.01.2018 0:00 13.535165988166666 48.58077563316667
2018-01-29 00:00:03.000 13.535165978333334 48.580775599
29.01.2018 0:00 13.535166127833334 48.5807756575
2018-01-29 00:00:04.000 13.535166430833334 48.5807757935
29.01.2018 0:00 13.535166510166666 48.580775819
2018-01-29 00:00:05.000 13.5351665845 48.5807758835
29.01.2018 0:00 13.5351665215 48.580775906
2018-01-29 00:00:06.000 13.535166549166666 48.58077594583333
29.01.2018 0:00 13.535166521333334 48.58077594466667
2018-01-29 00:00:07.000 13.535166487 48.580775927666664
29.01.2018 0:00 13.5351670905 48.58077611433333
2018-01-29 00:00:08.000 13.5351669075 48.5807760195
29.01.2018 0:00 13.535166444166666 48.580775919'''
marks=list(map(lambda line:list(map(lambda x:float(x),re.match(r'[^\s]+\s+[^\s]+\s+([\d\.]+)\s+([\d\.]+)\s*',line).groups())),rawmarks.split('\n')))
并且[[dist(A,B,C) for A,B in zip(tour,tour[1:])] for C in marks]
生成距离矩阵,在这种情况下,由于两个坐标集是距离太远与线段上构建的垂直窄带有关。 经度约为48度时,一度经度约为111公里/秒。 整个示例游览仅2.5公里长。
为了加快速度,可以在pdist
上使用https://docs.python.org/3/library/functools.html#functools.lru_cache,也可以将c
-s(游览段的长度)明确计算并存储在某处,则/c/c
师可以推迟和temprat<0 or temprat>c**2
可以在可使用if
,其中c**2
可以预先计算过。 当我注意到距离问题时,我只是失去了动力。
但是,图像的下部用于说明不能将点到点的距离用作替换,并且它甚至也不能真正地“驱动”正交计算,因为红色点是与蓝色最接近的角点。一个并不意味着一个区段不可能更近,红色的甚至不是那个区段的终点。
为了使它与纬度坐标一起工作,存在许多令人毛骨悚然的公式,我现在不敢为您选择一个。 https://en.wikipedia.org/wiki/Geographical_distance可能是一个很好的起点。 您可以依靠的一种捷径是您的轨迹包含以km-s为单位的距离,因此您可以将线段中某个点的行程距离作为其端点处行程距离的加权总和来计算(而不是直接从经纬度计算距离) -lon坐标)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.