69 lines
2.7 KiB
Python
69 lines
2.7 KiB
Python
import re,math,heapq,collections,sys,json
|
|
sys.path.insert(0, __file__.rsplit("/", 1)[0])
|
|
from adturns import load
|
|
def angle(N,p,b,c):
|
|
v1=(N[b]["x"]-N[p]["x"],N[b]["z"]-N[p]["z"]); v2=(N[c]["x"]-N[b]["x"],N[c]["z"]-N[b]["z"])
|
|
l1=math.hypot(*v1); l2=math.hypot(*v2)
|
|
if l1<1e-6 or l2<1e-6: return 0.0
|
|
return math.degrees(math.acos(max(-1,min(1,(v1[0]*v2[0]+v1[1]*v2[1])/(l1*l2)))))
|
|
def speed(a):
|
|
for lim,sp in ((3,50),(5,38),(8,27),(12,20),(15,13),(20,10),(30,7)):
|
|
if a<lim: return sp
|
|
return 4
|
|
def is_reverse(N,p,b,c):
|
|
return (b not in N[c]["inc"]) or (b in N[c]["inc"] and p not in N[b]["inc"])
|
|
def transit(N):
|
|
T={}
|
|
for b,n in N.items():
|
|
for p in n["inc"]:
|
|
if p not in N: continue
|
|
T[(p,b)]=[c for c in n["out"] if c in N and (angle(N,p,b,c)<=80 or is_reverse(N,p,b,c))]
|
|
return T
|
|
def dijkstra(N,T,start):
|
|
# tilstand = (forrige, node); returnerer bedste forgænger-tilstand pr node
|
|
dist={};pre={};best={}
|
|
h=[]
|
|
for c in N[start]["out"]:
|
|
if c not in N: continue
|
|
d=math.hypot(N[c]["x"]-N[start]["x"],N[c]["z"]-N[start]["z"])/(50/3.6)*(20 if N[c]["fl"]&1 else 1)
|
|
s=(start,c); dist[s]=d; pre[s]=None; heapq.heappush(h,(d,s))
|
|
while h:
|
|
d,s=heapq.heappop(h)
|
|
if d>dist.get(s,1e18): continue
|
|
p,b=s
|
|
if b not in best or d<dist[best[b]]: best[b]=s
|
|
# AD: efter en bakforbindelse (p ikke i b.incoming) findes ingen transitMapping -> alle udgange er tilladt
|
|
for c in T.get(s,N[b]["out"]):
|
|
a=angle(N,p,b,c); l=math.hypot(N[c]["x"]-N[b]["x"],N[c]["z"]-N[b]["z"])
|
|
nd=d+l/(speed(a)/3.6)*(20 if N[c]["fl"]&1 else 1)
|
|
ns=(b,c)
|
|
if nd<dist.get(ns,1e18): dist[ns]=nd; pre[ns]=s; heapq.heappush(h,(nd,ns))
|
|
return best,pre
|
|
def path_turns(N,best,pre,target):
|
|
s=best.get(target); turns=[]
|
|
seq=[]
|
|
while s: seq.append(s); s=pre[s]
|
|
seq.reverse()
|
|
for i in range(1,len(seq)):
|
|
p,b=seq[i-1]; _,c=seq[i]
|
|
turns.append((p,b,c))
|
|
return turns
|
|
if __name__=="__main__":
|
|
s,N,_=load(sys.argv[1])
|
|
mm=[(int(float(i)),n,g) for i,n,g in re.findall(r"<mm\d+>\s*<id>([\d.]+)</id>\s*<name>([^<]*)</name>\s*<group>([^<]*)</group>",s)]
|
|
T=transit(N)
|
|
ids=[m[0] for m in mm if m[0] in N]
|
|
sharp=collections.Counter(); rev=0
|
|
for k,st in enumerate(ids):
|
|
best,pre=dijkstra(N,T,st)
|
|
for tg in ids:
|
|
if tg==st or tg not in best: continue
|
|
for (p,b,c) in path_turns(N,best,pre,tg):
|
|
a=angle(N,p,b,c)
|
|
if a>45:
|
|
if is_reverse(N,p,b,c): rev+=1; continue
|
|
sharp[(p,b,c)]+=1
|
|
json.dump([[p,b,c,n,round(angle(N,p,b,c),1)] for (p,b,c),n in sharp.items()],open(sys.argv[2],"w"))
|
|
print("markører",len(ids),"forskellige skarpe sving på ruter:",len(sharp),"bakke-sving sprunget over:",rev)
|
|
print(collections.Counter(int(angle(N,*k)//5*5) for k in sharp))
|