В случае таких небольших расстояний (например, расстояние в 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
Возвращает None,None
, еслиПерпендикулярная базовая точка для C находится за пределами AB, или кортеж перпендикулярного расстояния (от C до сегмента AB) и отношения между 0 ... 1, которое вы можете использовать в качестве веса для расчета "положения путешествия" между двумя соседними точками.
Затем выполняется анализ данных вашего примера:
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]
создает матрицу расстояний, которая в этом случае совершенно пуста, так как два набора координат слишком далеко связаны сузкие перпендикулярные полосы построены на отрезках линии.Один градус долготы составляет около 111 км-с на широте ~ 48 градусов.В то время как длина всего примера составляет всего 2,5 км.
Для ускорения объекта можно использовать https://docs.python.org/3/library/functools.html#functools.lru_cache на pdist
или c
-s (длина сегментов тура) может быть явно предварительно вычислен и сохранен где-то, деление /c/c
может быть отложено, а temprat<0 or temprat>c**2
может быть использовано в if
, где c**2
также может быть рассчитано заранее.Просто я потерял мотивацию, когда заметил проблему с расстоянием.
Думаю, вам также придется проверять расстояния между точками.Посмотрите на верхнюю часть рисунка: синяя точка находится за пределами серых прямоугольников (конечно, они бесконечны и простираются в обоих направлениях, я просто ограничил их для лучшего наглядности), но оказывается внутри красной, поэтому ортогональнойПодход только на расстоянии сказал бы, что самый правый отрезок был ближайшим к рассматриваемой точке, в то время как при взгляде на расстояния между точками можно найти зеленую точку как ближайшую точку.
Однако нижняя часть изображения предназначена для иллюстрации того, что расстояния от точки до точки не могут быть использованы в качестве замены, и она также не может даже «управлять» ортогональными вычислениями, поскольку красная точка является ближайшей угловой точкой ксиний не означает, что сегмент не может быть ближе, а красный - даже не конечная точка этого сегмента.
Для того, чтобы заставить его работать с широтными координатами, существует множество жутких формул, я быНе смей выбирать один для тебя на данный момент.https://en.wikipedia.org/wiki/Geographical_distance может быть хорошей отправной точкой.Одним из ярлыков, на который вы можете положиться, является то, что ваши траектории содержат расстояния в км-с, поэтому вы можете рассчитать расстояние в пути для точки в сегменте как взвешенную сумму расстояний в пути в его конечных точках (вместо того, чтобы вычислять расстояния непосредственно от широты).координаты)