comparison safe.py @ 23:1670a33e3e6d

from markup
author Henry Thompson <ht@markup.co.uk>
date Sat, 29 May 2021 11:07:34 +0100
parents
children 6df2f6dcc809
comparison
equal deleted inserted replaced
5:bd1db1ed4c25 23:1670a33e3e6d
1 #!/usr/bin/python3
2 '''Find a safe landing space (i.e. in air, not above lava) near a cluster'''
3 import sys, math
4
5 from util import *
6 from bisect import insort
7
8 def usage():
9 print("""Usage: safe.py [-d n] [filename]
10 n is maximum distance of landing to some point in the cluster, default is 10.
11
12 Feed stdin with lines from the output of cluster.py, having produced
13 air.tsv with the same settings as the cluster input, and lava.tsv
14 with a lower-bound on Y of 0""")
15
16 n=10.0
17 if len(sys.argv)>1:
18 if sys.argv[1]=='-d':
19 sys.argv.pop()
20 n=float(sys.argv.pop(1))
21
22 if len(sys.argv)>1:
23 infile=open(sys.argv.pop(1))
24 else:
25 infile=sys.stdin
26
27 class Block:
28 '''Shared by Air and Lava,
29 holds points and columns.
30 Columns are dictionaries indexed by (x,z) coords,
31 value is upward-ordered list of pairs, closed intervals of y'''
32 def __init__(self,filename):
33 with open(filename,'r') as file:
34 self.readHeaders(file)
35 self.readPoints(file)
36
37 cc=self.columns={}
38 tc={}
39 for p in self.points:
40 k=(p[0],p[2])
41 y=p[1]
42 try:
43 yy=tc[k]
44 insort(yy,y)
45 except KeyError:
46 tc[k]=[y]
47 # convert to lists of intervals
48 for k,yy in tc.items():
49 tyy=[yy]
50 ii=[]
51 while True:
52 clean=True
53 for j,yy in enumerate(tyy):
54 if len(yy)==1+(yy[-1]-yy[0]):
55 ii.append((yy[0],yy[-1]))
56 else:
57 clean=False
58 for i in range(len(yy)-1):
59 if yy[i]+1!=yy[i+1]:
60 ii+=(yy[0],yy[i])
61 tyy=[yy[i+1:]]+tyy[j+1:]
62 break
63 if clean:
64 break
65 self.columns[k]=set(ii) # so we can merge later
66
67 def readPoints(self,file):
68 file.readline()
69 self.points=[[float(i) for i in l.split('\t')[2].split(',')] for l in file]
70
71 Block.readHeaders=readHeaders # from util
72
73 class Air(Block):
74 pass
75
76 A=Air('air.tsv')
77
78 class Lava(Block):
79 pass
80
81 L=Lava('lava.tsv')
82
83 def d(p1,p2):
84 dx=p1[0]-p2[0]
85 dz=p1[1]-p2[1]
86 dy=p1[2]-p2[2]
87 return math.sqrt((dx*dx)+(dy*dy)+(dz*dz))
88
89 def safety(p):
90 ka=[((a[0],a[2]),d(a,p)) for a in A.points if d(a,p)<=n]
91 return [(k,A.columns[k[0]],L.columns[k[0]]) for k in ka if k[0] in L.columns]
92
93 readHeaders(sys.modules['__main__'],infile,False)
94 for l in infile:
95 c=eval(l)
96 ss=[]
97 hits={}
98 misses=[]
99 for p in c:
100 ss=safety(p)
101 if ss:
102 for (k,a,l) in ss:
103 try:
104 (aa,ll)=hits[k]
105 aa.update(a)
106 ll.update(l)
107 except KeyError:
108 hits[k]=(a,l)
109 else:
110 misses.append(p)
111 print(c)
112 if hits:
113 print(' %s nearby landing columns'%len(hits))
114 for k in sorted(hits.keys(),key=lambda k:k[1]):
115 aa,ll=hits[k]
116 print("%s@%0.1f: %s %s"%(k[0],k[1],sorted(list(aa)),sorted(list(ll))))
117 else:
118 print(' No nearby landing zones')
119
120 if infile!=sys.stdin:
121 infile.close()