-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpenrhomb.py
executable file
·101 lines (77 loc) · 2.46 KB
/
penrhomb.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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# Reference: https://preshing.com/20110831/penrose-tiling-explained/
import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.collections as mplc
import matplotlib.patheffects as mplpe
import matplotlib.style as mplstyle
import math
import cmath
from collections import deque
# Colors
COLOR1 = '#ffc300'
COLOR2 = '#c70039'
LINE_COLOR = 'black'
# Parameters
iterations = 5
save = True
print(f'Iterations: {iterations}')
phi = (1 + math.sqrt(5)) / 2
def get_color(ty):
return COLOR2 if ty else COLOR1
def subdiv(tris: deque):
for i in range(len(tris)):
(ty, a, b, c) = tris.popleft()
if ty == 0:
p = a + (b - a) / phi
tris.extend([(0, c, p, b), (1, p, c, a)])
elif ty == 1:
q = b + (a - b) / phi
r = b + (c - b) / phi
tris.extend([(1, r, c, a), (1, q, r, b), (0, r, q, a)])
# Initial setup
base_tris = []
# Triangle fan
for i in range(10):
b = cmath.rect(1, (2*i - 1) * math.pi / 10)
c = cmath.rect(1, (2*i + 1) * math.pi / 10)
if i % 2 == 0:
b, c = c, b
base_tris.append((0, 0j, b, c))
# Iteration
tris = deque(base_tris)
for i in range(iterations):
subdiv(tris)
fig = plt.figure()
base_tri_verts = []
for ty, a, b, c in base_tris:
base_tri_verts.append(((a.real, a.imag), (b.real, b.imag), (c.real, c.imag)))
tri_verts = []
line_segs = []
for ty, a, b, c in tris:
if ty == 0:
tri_verts.append(((a.real, a.imag), (b.real, b.imag), (c.real, c.imag)))
line_segs.append(((b.real, b.imag), (a.real, a.imag), (c.real, c.imag)))
# Remove duplicate lines
print(f'108 degree triangle count: {len(tri_verts)}')
print(f'36 degree triangle count: {len(tris) - len(tri_verts)}')
print(f'Line count: {len(line_segs)}')
lw = 10 / phi ** iterations
if not save:
exit()
qual = 15
base_tri_c = mplc.PolyCollection(base_tri_verts, color=COLOR2, linewidth=lw)
tri_c = mplc.PolyCollection(tri_verts, color=COLOR1, linewidth=lw )
line_c = mplc.LineCollection(line_segs, color=LINE_COLOR, linewidth=lw, path_effects=[mplpe.Stroke(capstyle='round')])
ax = fig.add_subplot()
ax.add_collection(base_tri_c)
ax.add_collection(tri_c)
ax.add_collection(line_c)
plt.axis('off')
plt.xlim([-1.0, 1.0])
plt.ylim([-1.0, 1.0])
ax.set_aspect('equal')
# Save graph
filename = f'penrose-{iterations}.png'
mplstyle.use('fast')
plt.savefig(filename, dpi=max(300, qual * phi ** iterations))
print(f'Saved to {filename}')