I have written a simple Python script that generates n-flakes using matplotlib.
Wikipedia article on N-flake.
I wrote two functions, one function generates pentaflake, the other generates hexaflake, I adapted my code from some turtle example code, I understand the mathematics, but I am not sure about the performance.
Pentaflake, five iterations:
Hexaflake, six iterations:
Code
import math
import matplotlib.pyplot as plt
import random
from functools import lru_cache
from matplotlib.collections import PolyCollection
from PIL import Image
@lru_cache(maxsize=None)
def cos(d): return math.cos(math.radians(d))
@lru_cache(maxsize=None)
def sin(d): return math.sin(math.radians(d))
@lru_cache(maxsize=None)
def tan(d): return math.tan(math.radians(d))
def pentagon(x, y, r, direction):
return [(x + r * cos(direction+i*72), y + r * sin(direction+i*72)) for i in range(5)]
def pentaflake(n):
pentagons = []
ratio = (1+2*cos(36))
def worker(x, y, r, direction, n):
if not n:
pentagons.append(pentagon(x,y,r,direction))
return
r2 = r/ratio
d = 2*r2*cos(36)
for _ in range(5):
x2,y2 = x+d*cos(direction),y+d*sin(direction)
worker(x2,y2,r2,direction,n-1)
direction += 72
worker(x,y,r2,direction+180,n-1)
worker(0, 0, 2, 90, n)
return pentagons
def hexagon(x, y, r):
return [(x + r * cos(90+i*60), y + r * sin(90+i*60)) for i in range(6)]
def hexaflake(n):
hexagons = []
def worker(x, y, r, n):
if n==0:
hexagons.append(hexagon(x,y,r))
return
r2 = r/3
for i in range(6):
x2,y2 = x+r*cos(90+i*60)*2/3,y+r*sin(90+i*60)*2/3
worker(x2,y2,r2,n-1)
worker(x,y,r2,n-1)
worker(0, 0, 2, n)
return hexagons
def plot_nflake(iterations, width=1920, height=1080, lw=0, color='#4d0dff', alpha=1, show=True, method=pentaflake):
assert method in (pentaflake, hexaflake)
polygons = method(iterations)
fig = plt.figure(figsize=(width/100, height/100), dpi=100, facecolor='black')
ax = fig.add_subplot(111)
ax.set_axis_off()
if not color:
color = '#'+random.randbytes(3).hex()
ax.add_collection(PolyCollection(polygons, facecolors=color, lw=lw, alpha=alpha))
plt.axis('scaled')
fig.subplots_adjust(left=0, bottom=0, right=1, top=1, wspace=0, hspace=0)
fig.canvas.draw()
image = Image.frombytes(
'RGB', fig.canvas.get_width_height(), fig.canvas.tostring_rgb())
if not show:
plt.close(fig)
else:
plt.show()
return image
How do I improve the performance of this script?
Probably irrelevant, but I made these two images by editing the example pictures:
pentagon
andhexagon
? That would be a good place to start. \$\endgroup\$