Revised as of 17 January 2010 uses a custom grammar library (see Cesàro fractal in a later post)
##
# A Sierpinski Triangle implemented using a
# Lindenmayer System in ruby-processing by Martin Prout
###
require 'sierpinski'
class Sierpinski_Test < Processing::App
load_library :grammar
attr_reader :sierpinski
def setup
size 610, 600
@sierpinski = Sierpinski.new
sierpinski.create_grammar 8
no_loop
end
def draw
background 0
sierpinski.render
end
end
############################
# sierpinski.rb
###########################
class Sierpinski
include Processing::Proxy
attr_accessor :axiom, :grammar, :start_length, :production, :draw_length, :xpos, :ypos
XPOS = 0
YPOS = 1
ANGLE = 2
DELTA = (Math::PI/180) * 120 # convert degrees to radians
def initialize
@start_length = 300
setup_grammar
@xpos = width/60
@ypos = height*0.9
stroke 255
@draw_length = start_length
end
def setup_grammar
@axiom = "FX"
@grammar = Grammar.new axiom
grammar.add_rule "F", "FF" # replace F rule see grammar library
grammar.add_rule "X", "-FXF+FXF+FXF-" # replace X rule see grammar library
@production = axiom
end
def render # NB not using affine transforms here
turtle = [xpos, ypos, 0.0]
production.scan(/./).each do |element|
case element
when 'F'
turtle = draw_line(turtle, draw_length)
when '+'
turtle[ANGLE] += DELTA # rotate by + theta if going the affine transform route
when '-'
turtle[ANGLE] -= DELTA # rotate by - theta if going the affine transform route
when 'X' # do nothing except recognize 'X' as a word in the L-system grammar
else
puts "Character '#{element}' is not in grammar"
end
end
end
##############################
# create grammar from axiom and
# rules (adjust scale)
##############################
def create_grammar(gen)
@draw_length *= 0.5**gen
@production = grammar.generate gen
end
private
######################################################
# draws line using current turtle and length parameters
# returns a turtle corresponding to the new position
######################################################
def draw_line(turtle, length)
new_xpos = turtle[XPOS] + length * Math.cos(turtle[ANGLE])
new_ypos = turtle[YPOS] + length * Math.sin(turtle[ANGLE])
line(turtle[XPOS], turtle[YPOS], new_xpos, new_ypos)
turtle = [new_xpos, new_ypos, turtle[ANGLE]]
end
end
No comments:
Post a Comment