Game AI & Unity/L-system algorithm

[L-system]Fractal Generation with L-Systems ②

bay07 2024. 4. 12. 10:07

1. 문자열 변환 규칙 

  • a → aba
  • c → bb

이러한 규칙을  딕셔너리  {'a': 'aba', 'c': 'bb'}를 사용해서 나타낼 수 있다. 

L-system에서도 비슷한 형태의 규칙이 사용되며, 

이 방법을 사용하면 간단한 입력으로 복잡한 이미지를 만들 수 있다. 

더보기
%matplotlib inline
import matplotlib.pyplot as plt
plt.style.use('bmh')  

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)

def plot_coords(coords, bare_plot=False):
    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);

def transform_sequence(sequence, transformations):
    return ''.join(transformations.get(c, c) for c in sequence)

transform_sequence('acab', {'a': 'aba', 'c': 'bb'})

 

2. 간단한 규칙을 사용하여 힐베르트 곡선 그리기 

 

* 힐베르트 곡선

2차원 펴면 상에서 시작점에서 출발하여 주어진 길이의 선분을 그린 후, 

90도 방향으로 각도를 전환하고, 같은 길이의 선분을 그리는 일을 반복하는 것 

프랙탈의 한가지 예시이고, 자연의 패턴과 유사한 면이 있다. 

 

def transform_multiple(sequence, transformations, iterations):
    for _ in range(iterations):
        sequence = transform_sequence(sequence, transformations)
    return sequence

print('0:', transform_multiple('abba', {'b': 'bab'}, 0))
print('1:', transform_multiple('abba', {'b': 'bab'}, 1))
print('2:', transform_multiple('abba', {'b': 'bab'}, 2))

plot_coords(turtle_to_coords(transform_multiple('F', {'F': '+F+F--F+F'}, 5)))

plot_coords(turtle_to_coords(transform_multiple('L', {
    'L': '-RF+LFL+FR-',
    'R': '+LF-RFR-FL+'
}, 5), 90))


* 참고 

https://mathworld.wolfram.com/HilbertCurve.html

https://nb.paulbutler.org/l-systems/