Sierpinski, you say? Fine, I'll fill up this square.
@ addtest
def sfc_sierpinski (self):
delta = {
# quarters
'u': (2, 1), 'd': (2, 3),
'l': (1, 2), 'r': (3, 2),
# halves
"UR": (1, 0), "UL": (0, 0),
"DL": (0, 1), "DR": (1, 1)
}
reduce = {
"UR": "drul", "UL": "ruld",
"DL": "uldr", "DR": "ldru"
}
terminal = {
key: tuple (delta [ch] for ch in val)
for key, val in reduce.items ()
}
expand = {
"UR": ("UR", "DR", "UR", "UL"),
"UL": ("UL", "UR", "UL", "DL"),
"DL": ("DL", "UL", "DL", "DR"),
"DR": ("DR", "DL", "DR", "UR")
}
places = {
"UR": ("DL", "DR", "UR", "UL"),
"UL": ("DR", "UR", "UL", "DL"),
"DL": ("UR", "UL", "DL", "DR"),
"DR": ("UL", "DL", "DR", "UR")
}
wind = {
key: tuple (delta [x] for x in val)
for key, val in places.items ()
}
size = 512
draw = self.makedraw (size, size)
Tests.sfc_sierpinski_work (
draw, expand, wind, terminal,
0, 0, size, "UR", 5)
return draw
@ staticmethod
def sfc_sierpinski_work (draw, expand, wind, terminal, x, y, size, var, level):
ps = Tests.sfc_sierpinski_points (
expand, wind, terminal, x, y, size, var, level)
pit = iter (ps)
p0 = p = next (pit)
for q in pit:
draw.line (p [0], p [1], q [0], q [1])
p = q
draw.line (p [0], p [1], p0 [0], p0 [1])
@ staticmethod
def sfc_sierpinski_points (expand, wind, terminal, x, y, size, var, level):
if level == 0:
s14 = size // 4
delta = terminal [var]
return [(x + dx * s14, y + dy * s14) for dx, dy in delta]
symbols = expand [var]
delta = wind [var]
level -= 1
s12 = size // 2
l = [
Tests.sfc_sierpinski_points (
expand, wind, terminal,
x + d [0] * s12, y + d [1] * s12,
s12, sym, level
) for d, sym in zip (delta, symbols)
]
l0 = l [0]
l1 = l [1:]
half = (4 ** level) * 2
l0it = iter (l0)
return itertools.chain (
itertools.islice (l0it, half),
itertools.chain.from_iterable (l1),
l0it
)