はじめに
フラクタルを再帰処理で描画できるという話を聞いて、面白そうだったので、自然界にある再帰で描けそうなものを題材にお絵かきしてみました。
木
import pygame
import math
import random
pygame.init()
win = pygame.display.set_mode((750, 650))
win.fill((255, 255, 255))
def drawTree(a, b, pos, deepness):
if deepness:
branch1 = random.randint(1,15)
branch2 = random.randint(1,15)
c = a + int(math.cos(math.radians(pos)) * deepness * branch1)
d = b + int(math.sin(math.radians(pos)) * deepness * branch2)
pygame.draw.line(win, (128,64,0), (a, b), (c, d), int(1.3**deepness))
drawTree(c, d, pos - 20, deepness - 1)
drawTree(c, d, pos + 20, deepness - 1)
else:
pygame.draw.circle(win,(0,192,0),(a,b),random.randint(1, 4),0)
drawTree(370, 650, -90, 10)
pygame.display.flip()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
この記事のコードを拝借して、色とか枝の太さとかを調整しました
雪の結晶
import pygame
import math
pygame.init()
win = pygame.display.set_mode((750, 650))
win.fill((255, 255, 255))
def drawKochLine(start, end, depth):
if depth == 0:
pygame.draw.line(win, (0, 0, 255), start, end, 2)
return
x1, y1 = start
x5, y5 = end
x2 = x1 + (x5 - x1) / 3
y2 = y1 + (y5 - y1) / 3
x4 = x1 + (x5 - x1) * 2 / 3
y4 = y1 + (y5 - y1) * 2 / 3
angle = math.radians(60)
x3 = (x2 + x4) / 2 - (y4 - y2) * math.tan(angle)
y3 = (y2 + y4) / 2 + (x4 - x2) * math.tan(angle)
drawKochLine((x1, y1), (x2, y2), depth - 1)
drawKochLine((x2, y2), (x3, y3), depth - 1)
drawKochLine((x3, y3), (x4, y4), depth - 1)
drawKochLine((x4, y4), (x5, y5), depth - 1)
def drawHexagon(center, size, depth):
x, y = center
points = []
for i in range(6):
angle = math.radians(60 * i)
px = x + size * math.cos(angle)
py = y + size * math.sin(angle)
points.append((px, py))
for i in range(6):
drawKochLine(points[i], points[(i+1) % 6], depth)
drawHexagon((375, 325), 150, 4)
pygame.display.flip()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
コッホ曲線をベースに、六角形を取り入れてくれという曖昧な指示で、AIが割と上手に書いてくれました
アンモナイト
import pygame
import math
pygame.init()
win = pygame.display.set_mode((750, 650))
win.fill((248, 240, 216))
# フィボナッチ数列の生成
def fibonacci(n = None):
a, b = 1, 1
if n is None:
while True:
yield a
a, b = b, a + b
for _ in range(n):
yield a
a, b = b, a + b
def drawFibonacciSpiral(start, num_steps):
prev_x, prev_y = start
fib_sequence = fibonacci()
directions = [(-1, 1), (1, 1), (1, -1), (-1, -1)] # 左下→右下→右上→左上
angles = [(math.radians(90), math.radians(180)),
(math.radians(180), math.radians(270)),
(math.radians(270), math.radians(0)),
(math.radians(0), math.radians(90))] # 始点と終点の角度
center_directions = [(0, 1), (1, 0), (0, -1), (-1, 0)] #始点から見た中心の方向
for i in range(num_steps):
step = i % 4
fib = next(fib_sequence)
dx, dy = directions[step]
x_next = prev_x + fib * dx
y_next = prev_y + fib * dy
# 円弧の中心位置を調整
center_x = prev_x + fib * center_directions[step][0]
center_y = prev_y + fib * center_directions[step][1]
radius = fib
# 扇形を描画(開始角度と終了角度の調整)
s_angle, e_angle = angles[step]
rect = (center_x - radius, center_y - radius, radius * 2, radius * 2)
# 始点と終点を曲線で結ぶ
pygame.draw.arc(win, (150, 75, 0), rect, s_angle, e_angle, 1)
prev_x, prev_y = x_next, y_next
drawFibonacciSpiral((375, 325), 13)
pygame.display.flip()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
アンモナイトというか、アンモナイトの貝殻の螺旋なんですが、フィボナッチ数列で表せるので書いてみました。弧線を書く時の長さを90度分じゃなくて一周にすると変なバラみたいなのが書けます
最後に
ここまで読んで下さりありがとうございました。単純に面白そうって理由だけでやってみましたが、再帰の練習とか、頭の体操にはちょうどいい題材だと思いました。特に木とか、自分で書くよりも、よっぽどうまく書けますね。逆に言えば、自分で書くときも再帰処理を意識して書けばいいってことでしょうか。