5
\$\begingroup\$

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:

enter image description here

Hexaflake, six iterations:

enter image description here


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:

enter image description here

enter image description here

\$\endgroup\$
1
  • \$\begingroup\$ Have you made an attempt at vectorising pentagon and hexagon? That would be a good place to start. \$\endgroup\$
    – Reinderien
    Jun 6 at 13:00

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.