Draw "Draw Ferns Programmatically" in Python-No Recursion + Generator Version-

I was finally able to participate in "Drawing ferns programmatically"!

Created based on @ noc06140728's code. Thank you very much.

change point

Output result

fern.png

code


# coding: utf-8
import random

N = 1000000

WIDTH = 500
HEIGHT = 500

fern = [
    [1.0, [+0.836, +0.044, 0.0, -0.044, +0.836, 0.169]],
    [0.3, [-0.141, +0.302, 0.0, +0.302, +0.0141,0.127]],
    [0.3, [+0.141, -0.302, 0.0, +0.302, +0.141, 0.169]],
    [0.3, [0.0, 0.0, 0.0, 0.0, 0.175337, 0.0]],
]

p_table = []


def W(n,v):
    c = fern[n][1]
    return (c[0] * v[0] + c[1] * v[1] + c[2], c[3] * v[0] + c[4] * v[1] + c[5])
 

# Python 2.7 to itertools.Since there is no accumulate, it is simplified by borrowing from the following
# http://docs.python.jp/3.3/library/itertools.html#itertools.accumulate 
def accumulate(iterable):
    it = iter(iterable)
    total = next(it)
    yield total
    for e in it:
        total = total + e
        yield total

        
def g(v, n):
    it = 0
    while it < n:
        it += 1
        yield v
        r = random.random()
        for i, p in enumerate(p_table):
            if r < p:
                v = W(i,v)
                break;
                
                
if __name__ == '__main__':
    #Smooth the value of probability
    p_total = sum(f[0] for f in fern)
    p_table = [a/p_total for a in accumulate([f[0] for f in fern])]
    
    #A buffer that stores the trajectory of points
    acc = [0] * 3 * WIDTH * HEIGHT
    #First point
    v = (0.0, 0.0)
    acc_max = 1
    for p in g(v, N):
        x, y = (int((p[0] + 0.5) * WIDTH), HEIGHT - int(p[1] * HEIGHT))
        if x >=0 and x < WIDTH and y >= 0 and y < HEIGHT:
            acc_index = x + y * HEIGHT
            acc[acc_index] += 1
            if acc[acc_index] > acc_max:
                acc_max = acc[acc_index] 
    
    from math import pow
    from PIL import Image
    im = Image.new("RGB", (WIDTH, HEIGHT), (255, 255, 255))
    pix = im.load()
    
    for i in xrange(WIDTH * HEIGHT):
        #if acc[i]:
        #Lift in the dark
        d = int(pow(float(acc[i]) / float(acc_max),1.0/15.0) * 255.0)
        pix[i % WIDTH, i / WIDTH] = (0, d, 0)
            
    im.show()

Summary

was fun!

Recommended Posts

Draw "Draw Ferns Programmatically" in Python-No Recursion + Generator Version-
Draw "Draw Ferns Programmatically" in Python
Output "Draw ferns programmatically" to the drawing process in Python