Files
fs25-adsmartpickup/tools/ad-smooth/adroutes.py
T

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))