▶ L-system
프랙탈을 통해, 간단한 규칙을 이용해서 복잡한 시스템을 만들 수 있다.
'선 그리기'를 기본으로 작동하는 L시스템을 만들어보자.
1. matplotlib를 사용하여 선 그리기
%matplotlib inline
import matplotlib.pyplot as plt
plt.style.use('bmh') # 색 설정
plt.plot(
[0, 1, 2], # X 값
[0, 1, 0] # Y 값
)
plt.xlabel('x')
plt.ylabel('y');
def plot_coords(coords, bare_plot=False):
if bare_plot:
plt.axis('off')
# .set_aspect('equal', 'eatalim')은 가로세로 비율을 동일하게 설정해준다.
plt.axes().set_aspect('equal', 'datalim')
# 각각의 x, y 좌표
X, Y = zip(*coords)
# 그림 그리기
plt.plot(X, Y);
plot_coords([
(0, 0),
(1, 0),
(2, 1),
(3, 1),
(2, 0)
])
nan = float('nan')
plot_coords([
(0, 0),
(1, 1),
(nan, nan),
(1, 0),
(2, 1)
])
2. 거북이 그래픽
x좌표, y 좌표, 각도
이렇게 3가지를 입력하면, 거북이는 이동하면서 그림을 그리게 된다.
'F' | move forward one unit and trace the path with a line. 앞으로 이동하면서, 선의 경로를 그린다 |
'f' | move forward one unit but don't draw anything. 앞으로 이동하지만, 선의 경로를 그리지는 않는다 |
'-' | rotate counter-clockwise but don't move. 반시계방향으로 회전하는데 움직이지는 않는다 |
'+' | rotate clockwise but don't move. 시계방향으로 회전하는데 움직이지는 않는다 |
%matplotlib inline
import matplotlib.pyplot as plt
plt.style.use('bmh') # Use some nicer default colors
from math import pi, sin, cos
DEGREES_TO_RADIANS = pi / 180
def turtle_to_coords(turtle_program, turn_amount=45):
# 거북이가 (0,0)으로 시작하고 위쪽을 향해있다.
state = (0.0, 0.0, 90.0)
# 거북이가 가는 경로
yield (0.0, 0.0)
for command in turtle_program:
x, y, angle = state
if command in 'Ff': # 거북이를 앞으로 움직인다
state = (x - cos(angle * DEGREES_TO_RADIANS),
y + sin(angle * DEGREES_TO_RADIANS),
angle)
if command == 'f':
yield (float('nan'), float('nan'))
yield (state[0], state[1])
elif command == '+': # 움직이지 않고 거북이를 시계방향으로 돌린다
state = (x, y, angle + turn_amount)
elif command == '-': # 움직이지 않고, 거북이를 반시계 방향으로 돌린다
state = (x, y, angle - turn_amount)
plot_coords(turtle_to_coords('FfF++FfF++FfF++FfF'))
3. 거북이 그래픽의 예시
%matplotlib inline
import matplotlib.pyplot as plt
plt.style.use('bmh') # Use some nicer default colors
from math import pi, sin, cos
DEGREES_TO_RADIANS = pi / 180
def turtle_to_coords(turtle_program, turn_amount=45):
# 거북이가 (0,0)으로 시작하고 위쪽을 향해있다.
state = (0.0, 0.0, 90.0)
# 거북이가 가는 경로
yield (0.0, 0.0)
for command in turtle_program:
x, y, angle = state
if command in 'Ff': # 거북이를 앞으로 움직인다
state = (x - cos(angle * DEGREES_TO_RADIANS),
y + sin(angle * DEGREES_TO_RADIANS),
angle)
if command == 'f':
yield (float('nan'), float('nan'))
yield (state[0], state[1])
elif command == '+': # 움직이지 않고 거북이를 시계방향으로 돌린다
state = (x, y, angle + turn_amount)
elif command == '-': # 움직이지 않고, 거북이를 반시계 방향으로 돌린다
state = (x, y, angle - turn_amount)
plot_coords(turtle_to_coords('F-F+F+F+f+F+F+F-F'))
%matplotlib inline
import matplotlib.pyplot as plt
plt.style.use('bmh') # Use some nicer default colors
from math import isnan
def print_coords(coords):
for (x, y) in coords:
if isnan(x):
print('<gap>')
else:
print('({:.2f}, {:.2f})'.format(x, y))
print_coords(turtle_to_coords('F-F+F+F+f+F+F+F-F'))
(0.00, 0.00)
(-0.00, 1.00)
(-0.71, 1.71)
(-0.71, 2.71)
(-0.00, 3.41)
# <gap>
(1.00, 3.41)
(1.71, 2.71)
(1.71, 1.71)
(1.00, 1.00)
(1.00, -0.00)
plot_coords(turtle_to_coords('F-F+F+F+f+F+F+F-F', 65))
거북이 그래픽에서 회전도 잘 된다.
* 참고
https://nb.paulbutler.org/l-systems/
'Game AI & Unity > L-system algorithm' 카테고리의 다른 글
[L-system]Fractal Generation with L-Systems ③ (0) | 2024.04.12 |
---|---|
[L-system]Fractal Generation with L-Systems ② (0) | 2024.04.12 |
[Plants and Python][prac10] 함수와 프랙탈 4 (0) | 2024.03.29 |
[Plants and Python][prac9] 함수와 프랙탈 3 (0) | 2024.03.29 |
[Plants and Python][prac8] 함수와 프랙탈 2 (0) | 2024.03.29 |