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/