LoginSignup
5
5

More than 5 years have passed since last update.

「プログラムでシダを描画する」をPythonで描画する - 再帰なし+ジェネレータ版 -

Posted at

「プログラムでシダを描画する」にようやく参加できた!

@noc06140728 さんのコードをベースに作成しました。ありがとうございます。

変更点

  • 再帰をなくしてジェネレータだけを使用
  • 画像に濃淡を持たせた
  • 関数をパラメータを各々ひとまとめにした

出力結果

fern.png

コード


# 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 には itertools.accumulate がないので以下から借用して簡略化
# 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__':
    # 確率の値ををならす
    p_total = sum(f[0] for f in fern)
    p_table = [a/p_total for a in accumulate([f[0] for f in fern])]

    # 点の軌跡を溜めておくバッファ
    acc = [0] * 3 * WIDTH * HEIGHT
    # 最初の点
    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]:
        # 暗いところを持ち上げる
        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()

まとめ

楽しかった!

5
5
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5