-
Notifications
You must be signed in to change notification settings - Fork 3
/
algo.py
80 lines (63 loc) · 2.4 KB
/
algo.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
from __future__ import division
import math
import itertools
SPACING = 2
def iter_to_runs(visibles, pixels):
cur_val = 6666666
start_idx = None
out = []
for i, val in enumerate(itertools.chain(visibles, [None])):
if cur_val != val:
if cur_val is True:
# we just ended a run of "True" values
out.append((pixels[start_idx], pixels[i - 1]))
cur_val = val
start_idx = i
return out
def generate_line_segments(radius, center):
"""Generate radii of a circle that are a fixed width apart on the circle.
Args:
radius: radius of the circle, in pixels
center: center of the circle (x, y) as tuple
Returns:
iterator of points (center, point on circle)
"""
ang_step = SPACING / radius # angle step in radians
ang = 0
while ang < 2 * math.pi:
ang += ang_step
yield (center, (center[0] + radius * math.cos(ang), center[1] + radius * math.sin(ang)))
def generate_visible(tower_height, heightmap):
"""Trace a ray and determine if a region is viewable.
Args:
tower_height: the elevation in meters above sea level of your antenna
heightmap: an enumerable of heights in a given direction
Returns:
an enumerable of True/False for visibility
"""
min_angle = -10000
for i, height in enumerate(heightmap):
if tower_height - height == 0:
angle_to_point = 0
elif tower_height > height:
angle_to_point = math.atan(i / (tower_height - height))
else:
angle_to_point = math.atan((height - tower_height) / i) + math.pi / 2
if angle_to_point >= min_angle:
min_angle = angle_to_point
yield True
else:
yield False
if __name__ == '__main__':
assert iter_to_runs([False, False, True, True, False, True, False, True, True]) == [(2, 3), (5, 5), (7, 8)]
assert iter_to_runs([True]) == [(0, 0)]
assert iter_to_runs([True, True, True, True, False, True, True]) == [(0, 3), (5, 6)]
import matplotlib.pyplot as plt
heightmap = [math.sin(x/15.0) * x for x in xrange(360)]
tower_height = 100.0 # foots above MSL
filt = ray(tower_height, heightmap)
fhm = [h if fl else 0 for (h, fl) in zip(heightmap, filt)]
plt.scatter(range(len(heightmap)), fhm)
plt.scatter([0], [tower_height], color='red')
plt.plot(heightmap)
plt.show()