-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathLSystem.py
More file actions
116 lines (105 loc) · 3.71 KB
/
LSystem.py
File metadata and controls
116 lines (105 loc) · 3.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import os
os.environ['PYGAME_HIDE_SUPPORT_PROMPT'] = 'hide'
import pygame
import json
import sys
import math
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
BACKGROUND = (40, 55, 71)
YELLOW = (248, 196, 113)
class LSystem():
def __init__(self, axiom, rules):
self.sequence = axiom
self.rules = rules
def updateSystem(self):
newSequence = ""
for i in range(len(self.sequence)):
if self.sequence[i] in self.rules:
newSequence += self.rules[self.sequence[i]]
else: newSequence += self.sequence[i]
self.sequence = newSequence
def __str__(self):
return self.sequence
class Visualizer():
def __init__(self, width, height, x, y, angle, lineSize, maxDepth, axiom, rules):
self.w = width
self.h = height
self.x = x
self.y = y
self.angle = math.pi / 2
self.deltaAngle = angle
self.lineSize = lineSize
self.RUN = True
self.stack = []
self.maxDepth = maxDepth
self.initSystem(axiom, rules)
self.initPygame()
self.winLoop()
def initSystem(self, axiom, rules):
self.Lsys = LSystem(axiom, rules)
def initPygame(self):
pygame.init()
self.win = pygame.display.set_mode((self.w, self.h))
pygame.display.set_caption('L-System Visualizer')
self.win.fill(BACKGROUND)
pygame.display.update()
def drawSystem(self, depth):
x = self.x
y = self.y
angle = self.angle
sentence = self.Lsys.__str__()
color = YELLOW
for char in sentence:
if (char != '+' and char != '-' and char != '[' and char != ']'):
x2 = x - (self.lineSize / math.exp(depth / 5)) * math.cos(angle)
y2 = y - (self.lineSize / math.exp(depth / 5)) * math.sin(angle)
pygame.draw.line(self.win,
(color[0], color[1], color[2], 100),
(x, y), (x2, y2), width=1)
x = x2
y = y2
elif (char == '+'):
angle += self.deltaAngle
elif (char == '-'):
angle -= self.deltaAngle
elif (char == '['):
self.stack.append(
{'x': x, 'y': y, 'angle': angle})
elif (char == ']'):
save = self.stack.pop()
x = save['x']
y = save['y']
angle = save['angle']
color = ((color[0] + depth * 2) % 255, color[1], color[2])
def winLoop(self):
depth = 1
while self.RUN:
try:
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.RUN = False
if event.type == pygame.MOUSEBUTTONDOWN:
if (depth < self.maxDepth):
self.win.fill(BACKGROUND)
self.drawSystem(depth)
self.Lsys.updateSystem()
depth += 1
pygame.display.update()
except KeyboardInterrupt:
self.RUN = False
pygame.quit()
exit()
if __name__ == '__main__':
if len(sys.argv) != 2:
print('Not enough arguments. try : python3 LSystem.py path/parameters.json')
exit()
try:
with open(sys.argv[1], 'r') as f:
data = json.load(f)
except Exception as e:
print(f'\n{e}\n')
exit(1)
vis = Visualizer(data['width'], data['height'], data['x'], data['y'],
math.radians(data['angle']), data['size'], data['maxDepth'],
data['axiom'], data['rules'])