Game AI & Unity/L-system algorithm
[Plants and Python][prac7] 함수와 프랙탈 1
bay07
2024. 3. 29. 09:28
#1 plot_coords 함수
#1
import matplotlib.pyplot as plt
%matplotlib inline
nan = float('nan')
def plot_coords(coords, lw=0.5, bare_plot=True):
if bare_plot:
# Turns off the axis markers.
plt.axis('off')
# Ensures equal aspect ratio.
plt.axes().set_aspect('equal', 'datalim')
# Converts a list of coordinates into
# lists of X and Y values, respectively.
X, Y = zip(*coords)
# Draws the plot.
plt.plot(X, Y, lw=lw, c='k')
import matplotlib.pyplot as plt | Matplotlib 파이썬에서 데이터 시각화를 위한 라이브러리 주로 그래프나 플롯을 그리는 데 사용된다 |
%matplotlib inline | 그래프나 플롯을 출력할 때, 그림을 인라인으로 표시하도록 지정한다. 이 코드가 없으면, 별도의 창에서 출력이 됨 |
nan = float('nan') | 파이썬의 내장함수인 float()를 사용하여 NaN(Not a Number)을 나타내는 값을 만든다. |
plot_coords(coords, lw=0.5, bare_plot=True) | 주어진 좌표를 사용하여 그림을 그리기 coords : (x, y) 좌표 쌍의 리스트 lw : 선의 너비를 지정 bare_plot : True로 설정하면 축과 눈금이 없는 순수한 그림을 만든다 |
plt.axis('off') | 축 표시를 끈다 |
plt.axes().set_aspect('equal', 'datalim') | 동일한 가로 및 세로 비율을 표시함 |
X, Y = zip(*coords) | 주어진 좌표를 X 및 Y 값의 리스트로 분리 |
plt.plot(X, Y, lw=lw, c='k') | 주어진 X 및 Y 값으로 선을 그린다 lw : 선의 너비 c : 선의 색상 |
#2 plot_coords 함수
#2
from math import pi, sin, cos
DEGREES_TO_RADIANS = pi / 180
def turtle_to_coords(turtle_program, turn_amount=45):
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)
turtle_to_coords(turtle_program, turn_amount=45) | 주어진 터틀 프로그램에 따라 터틀의 이동 경로를 생성하고, 이를 좌표로 반환한다. turtle_program : 터틀 프로그램 문자열, 터틀의 동작을 나타낸다 turn_amount : 터틀이 회전하는 각도 |
state = (0.0, 0.0, 90.0) | 거북이의 초기 상태를 설정 (x, y) 좌표 + 거북이의 방향을 나타내는 각도 초기 상태에서 거북이는 (0, 0) 위치에 있다. 각도가 90도 이므로, 위를 향하고 있다 |
yield (0.0, 0.0) | 초기 위치를 반환 거북이의 경로를 그리기 위한 출발점으로 사용된다. |
for command in turtle_program | 주어진 거북이 프로그램을 한 글자씩 반복한다 |
if command in 'Ff | 거북이가 앞으로 이동하는 명령일 경우를 처리한다. 'F' : 전진 'f' : 전진하지만 선을 그리지 않음 |
state = (x - cos(angle * DEGREES_TO_RADIANS), y + sin(angle * DEGREES_TO_RADIANS), angle) | 거북이를 이동시키고 새로운 위치를 업데이트함 거북이의 각도에 따라 삼각함수를 사용하여 새로운 위치를 계산한다 |
yield (float('nan'), float('nan')) | 'f' 명령을 만나면 선을 그리지 않고 이동하므로, 이동 후 선을 끊는다 |
yield (state[0], state[1]) | 거북이의 새로운 위치를 반환한다. 이 위치는 선분을 그리는데 사용됨 |
'+' | 거북이의 방향을 시계 방향으로 회전시킨다 |
'-' | 거북이의 방향을 반시계 방향으로 회전시킨다 |
#3 print_coords
#3
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))
from math import isnan | math 모듈에서 isnan 함수를 가져온다 |
def print_coords(coords) | 주어진 좌표를 처리하여 출력한다. 만약 x 좌표가 NaN이면 <gap>을 출력함 |
for (x, y) in coords | 어진 좌표를 반복한다. 각 좌표는 (x, y) 쌍으로 구성됨 |
if isnan(x) | x 좌표가 NaN인지 확인한다 NaN : 거북이가 선분을 그리지 않고 이동한 경우 |
print('({:.2f}, {:.2f})'.format(x, y)) | 좌표를 소수점 아래 2자리까지 출력 |
▷ data code 1
더보기
axiom = 'F-F-F-F'
production_rules = {'F':'F+FF-FF-F-F+F+FF-F-F+F+FF+FF-F'}
iterations = 2
angle = 90
axiom = '-F'
production_rules = {'F':'F+F-F-F+F'}
iterations = 4
angle = 90
axiom = 'F+F+F+F'
production_rules = {'F':'F+f-FF+F+FF+Ff+FF-f+FF-F-FF-Ff-FFF', 'f':'ffffff'}
iterations = 2
angle = 90
axiom = 'F-F-F-F'
production_rules = {'F':'FF-F-F-F-F-F+F'}
iterations = 4
angle = 90
axiom = 'F-F-F-F'
production_rules = {'F':'FF-F-F-F-FF'}
iterations = 4
angle = 90
axiom = 'F-F-F-F'
production_rules = {'F':'FF-F+F-F-FF'}
iterations = 3
angle = 90
axiom = 'F-F-F-F'
production_rules = {'F':'FF-F--F-F'}
iterations = 4
angle = 90
axiom = 'F-F-F-F'
production_rules = {'F':'F-FF--F-F'}
iterations = 5
angle = 90
axiom = 'F-F-F-F'
production_rules = {'F':'F-F+F-F-F'}
iterations = 4
angle = 90
▷ data code 2
더보기
axiom = 'L'
production_rules = {'L':'L+R+', 'R':'-L-R'}
iterations = 10
angle = 90
axiom = 'R'
production_rules = {'L':'R+L+R', 'R':'L-R-L'}
iterations = 6
angle = 60
axiom = 'L'
production_rules = {'L':'L+R++R-L--LL-R+', 'R':'-L+RR++R+L--L-R'}
iterations = 4
angle = 60
axiom = '-R'
production_rules = {'L':'LL-R-R+L+L-R-RL+R+LLR-L+R+LL+R-LR-R-L+L+RR-',
'R':'+LL-R-R+L+LR+L-RR-L-R+LRR-L-RL+L+R-R-L+L+RR'}
iterations = 2
angle = 90
▷ 전체 코드
더보기
import matplotlib.pyplot as plt
%matplotlib inline
nan = float('nan')
#1
def plot_coords(coords, lw=0.5, bare_plot=True):
if bare_plot:
# Turns off the axis markers.
plt.axis('off')
# Ensures equal aspect ratio.
plt.axes().set_aspect('equal', 'datalim')
# Converts a list of coordinates into
# lists of X and Y values, respectively.
X, Y = zip(*coords)
# Draws the plot.
plt.plot(X, Y, lw=lw, c='k')
#2
from math import pi, sin, cos
DEGREES_TO_RADIANS = pi / 180
def turtle_to_coords(turtle_program, turn_amount=45):
# The state variable tracks the current location and angle of the turtle.
# The turtle starts at (0, 0) facing up (90 degrees).
state = (0.0, 0.0, 90.0)
# Throughout the turtle's journey, we "yield" its location. These coordinate
# pairs become the path that plot_coords draws.
yield (0.0, 0.0)
# Loop over the program, one character at a time.
for command in turtle_program:
x, y, angle = state
# Move turtle forward
if command in 'Ff':
state = (x - cos(angle * DEGREES_TO_RADIANS),
y + sin(angle * DEGREES_TO_RADIANS),
angle)
if command == 'f':
# Insert a break in the path so that
# this line segment isn't drawn.
yield (float('nan'), float('nan'))
yield (state[0], state[1])
# Turn turtle clockwise without moving
elif command == '+':
state = (x, y, angle + turn_amount)
# Turn turtle counter-clockwise without moving
elif command == '-':
state = (x, y, angle - turn_amount)
# Note: We silently ignore unknown commands
#3
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))
#4
def transform_sequence(sequence, transformations):
return ''.join(transformations.get(c, c) for c in sequence)
#5
def transform_multiple(sequence, transformations, iterations):
for _ in range(iterations):
sequence = transform_sequence(sequence, transformations)
return sequence
#6
def branching_turtle_to_coords(turtle_program, turn_amount=45):
saved_states = list()
state = (0, 0, 90)
yield (0, 0)
for command in turtle_program:
x, y, angle = state
# Move forward (matches a-j and A-J)
if command.lower() in 'abcdefghijklmnopqrstuvwxyz':
state = (x - cos(angle * DEGREES_TO_RADIANS),
y + sin(angle * DEGREES_TO_RADIANS),
angle)
# Add a break in the line if command matches a-j
if command.islower():
yield (float('nan'), float('nan'))
yield (state[0], state[1])
# Turn clockwise
elif command == '+':
state = (x, y, angle + turn_amount)
# Turn counterclockwise
elif command == '-':
state = (x, y, angle - turn_amount)
# Remember current state
elif command == '[':
saved_states.append(state)
# Return to previous state
elif command == ']':
state = saved_states.pop()
yield (float('nan'), float('nan'))
x, y, _ = state
yield (x, y)
# Note: We silently ignore unknown commands
#7
def l_plot(axiom, transformations, iterations=0, angle=45, lw=0.5):
turtle_program = transform_multiple(axiom, transformations, iterations)
coords = branching_turtle_to_coords(turtle_program, angle)
plot_coords(coords, lw=lw, bare_plot=True)
# 예시
axiom = 'F-F-F-F'
production_rules = {'F':'F+FF-FF-F-F+F+FF-F-F+F+FF+FF-F'}
iterations = 2
angle = 90
# 함수 불러오기
# Plot the L-system fractal
l_plot(axiom, production_rules, iterations, angle)
* 참고
https://nbviewer.org/github/DanChitwood/PlantsAndPython/blob/master/PlantsAndPython6_STUDENT_Functions_and_Fractals.ipynb
https://nbviewer.org/github/DanChitwood/PlantsAndPython/tree/master/