import dash
from dash import dcc, html
from dash.dependencies import Input, Output
import plotly.express as px
import numpy as np
from PIL import Image, ImageDraw
import random
app = dash.Dash(__name__)
# Define L-system rules
rules = {
'F': lambda: random.choice(['F-F++F-F', 'F+F-F-F+F']),
'X': lambda: random.choice(['F-[[X]+X]+F[+FX]-X', 'F-[[X]+X]+F[+FX]+X'])
}
# Generate L-system string
def generate_l_system(axiom, rules, iterations):
for _ in range(iterations):
axiom = ''.join(rules.get(c, lambda: c)() for c in axiom)
return axiom
# Draw L-system
def draw_l_system(axiom, length, angle):
stack = []
position = (400, 800)
direction = -np.pi / 2
lines = []
for command in axiom:
if command == 'F':
new_position = (position[0] + length * np.cos(direction),
position[1] + length * np.sin(direction))
lines.append((position, new_position))
position = new_position
elif command == '+':
direction += angle
elif command == '-':
direction -= angle
elif command == '[':
stack.append((position, direction))
elif command == ']':
position, direction = stack.pop()
return lines
# Convert lines to image
def lines_to_image(lines, img_size=(800, 800)):
image = Image.new('RGB', img_size, (255, 255, 255))
draw = ImageDraw.Draw(image)
for line in lines:
draw.line([line[0], line[1]], fill=(0, 0, 0), width=2)
return image
# Layout of the app
app.layout = html.Div(style={'backgroundColor': '#ffffff', 'color': '#333333', 'fontFamily': 'Georgia, serif'}, children=[
html.H1('Random L-System Fractals', style={'textAlign': 'center', 'fontWeight': 'bold', 'marginTop': '20px'}),
dcc.Graph(id='l-system-graph', style={'height': '80vh'}),
html.Div([
html.Button('Generate L-System Fractal', id='generate-button', n_clicks=0)
], style={'textAlign': 'center', 'margin': '20px'}),
])
@app.callback(
Output('l-system-graph', 'figure'),
[Input('generate-button', 'n_clicks')]
)
def update_l_system(n_clicks):
if n_clicks == 0:
return dash.no_update
axiom = random.choice(['F', 'X'])
iterations = random.randint(3, 5)
angle = random.choice([np.pi / 6, np.pi / 4, np.pi / 3])
l_system_string = generate_l_system(axiom, rules, iterations)
lines = draw_l_system(l_system_string, length=5, angle=angle)
image = lines_to_image(lines)
# Convert PIL image to numpy array
img_array = np.array(image)
# Convert numpy array to plotly figure
fig = px.imshow(img_array)
fig.update_layout(coloraxis_showscale=False)
return fig
if __name__ == '__main__':
app.run_server(debug=True)