Skip to main content
Code Review

Return to Question

replaced http://codereview.stackexchange.com/ with https://codereview.stackexchange.com/
Source Link

Example: Draw a Koch snowflake (as in my previous question my previous question)

Example: Draw a Koch snowflake (as in my previous question)

Example: Draw a Koch snowflake (as in my previous question)

Tweeted twitter.com/StackCodeReview/status/736345856811663361
Source Link
Anna
  • 275
  • 1
  • 7

Small Python class for Lindenmayer Systems

L-systems are basically rules for recursively rewriting a string, which can be used to characterize e.g. some fractal and plant growth.

I wrote a small class to represent deterministic L-systems and used it for two examples. Any comments would be greatly appreciated, especially about the class design, the structure of the second example, and how to make things more pythonic. I'm new to Python and don't have any training in "grammars", this is just a hobby.

The class LSystem.py:

class LSystem:
 """ Lindenmayer System
 LSystem( alphabet, axiom )
 axiom: starting "string", a list of Symbols
 rules: dictionary with rules governing how each Symbol evolves,
 keys are Symbols and values are lists of Symbols
 """
 def __init__(self, axiom, rules):
 self.axiom = axiom
 self.rules = rules
 """ Evaluate system by recursively applying the rules on the axiom """
 def evaluate(self,depth):
 for symbol in self.axiom:
 self.evaluate_symbol( symbol, depth )
 """ Recursively apply the production rules to a symbol """
 def evaluate_symbol( self, symbol, depth ):
 if depth <= 0 or symbol not in self.rules:
 symbol.leaf_function()
 else:
 for produced_symbol in self.rules[symbol]:
 self.evaluate_symbol( produced_symbol, depth - 1 )
 
class Symbol:
 """ Symbol in an L-system alphabet
 Symbol( leaf_function )
 leaf_function: Function run when the symbol is evaluated at the final
 recursion depth. Could e.g. output a symbol or draw smth.
 """
 def __init__(self, leaf_function ):
 self.leaf_function = leaf_function

Example: Algae growth (example 1 from the wikipedia article)

import LSystem
# define symbols. their "leaf function" is to print themselves.
A = LSystem.Symbol( lambda:print('A',end='') )
B = LSystem.Symbol( lambda:print('B',end='') )
# define system
algae_system = LSystem.LSystem(
 axiom = [A],
 rules = { A: [A,B], B: [A] }
)
# run system
algae_system.evaluate(4) # prints "ABAABABA"

Example: Draw a Koch snowflake (as in my previous question)

import LSystem
import pygame
from math import pi, sin, cos
# some constants 
WINDOW_SIZE = [300,300]
LINE_WIDTH = 1
LINE_LENGTH = 1
# global variables for "turtle drawing"
# maybe I should pass around a turtle/cursor object instead?
turtle_angle = 0
turtle_x = 0
turtle_y = WINDOW_SIZE[1]*3/4
# define drawing functions used to draw the Koch snowflake
def draw_forward():
 global turtle_angle, turtle_x, turtle_y
 start = [turtle_x, turtle_y]
 turtle_x += LINE_LENGTH * cos(turtle_angle)
 turtle_y += LINE_LENGTH * sin(turtle_angle)
 end = [turtle_x, turtle_y ]
 pygame.draw.line(window, pygame.Color('black'), start, end, LINE_WIDTH )
def turn_left():
 global turtle_angle
 turtle_angle += pi/3
def turn_right():
 global turtle_angle
 turtle_angle -= pi/3
# symbols in the L-system
Line = LSystem.Symbol( draw_forward )
Left = LSystem.Symbol( turn_left )
Right = LSystem.Symbol( turn_right )
# L-system axiom and rules
koch_curve_system = LSystem.LSystem(
 axiom = [ Line, Right, Right, Line, Right, Right, Line ],
 rules = { Line: [ Line, Left, Line, Right, Right, Line, Left, Line ] }
)
# init pygame
pygame.init()
window = pygame.display.set_mode(WINDOW_SIZE)
window.fill(pygame.Color('white'))
# evaluate the L-system, which draws the Koch snowflake
# (recursion depth was chosen manually to fit window size and line length)
koch_curve_system.evaluate(5)
# display
pygame.display.flip()
# wait for the user to exit
while pygame.event.wait().type != pygame.QUIT:
 1
lang-py

AltStyle によって変換されたページ (->オリジナル) /