我是python的新手。但是我有一个艰巨的任务: 我有带GPS坐标的CSV文件和1个带参考轨迹(坐标点)的文件,它们代表了车辆的轨迹。
所以任务是对所有点计算到参考轨迹的垂直距离,并定义该点在参考轨迹的哪一公里
我试图用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
因此,我期望的输出是计算到直线轨迹的距离,以及该点在轨迹的特定公里数内。
我很高兴听到任何想法,因为我确实陷在这个问题中
答案 0 :(得分:0)
在这么小的距离(例如2.5公里的路程)的情况下,您可能可以使用平面近似值并使用非常简单的方法:对于距离,您可以使用公式来计算三角形的高度,例如与semiperimeter合作。然后,您仍然必须计算该点是否在给定的线段中(在其上构建的垂直带的一部分),在这里您可以使用向量的标量(点)的projection property。>
因此对于线段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
计算两个相邻点之间的“旅行位置”。
然后对示例数据进行一些解析:
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坐标)。