Experiments with ruby-processing (processing-2.2.1) and JRubyArt for processing-3.0

Monday 25 January 2010

Fern Fractal Using LSystems (includes a subtle color change)

Here is another LSystem example using the control panel to set the number of 'generations' of the fractal. This sketch requires my grammar library see the Cesàro fractal.

##############################################
# fern_test.rb inspired by processing fern by Gareth Spor
##############################################
require 'fern'

class FernTest < Processing::App
  load_libraries :control_panel, :grammar

  attr_accessor :init_color, :fern, :repeat

  def setup()
    size(800, 800)
    setup_panel
    @init_color = color(0, 240, 0)
    redraw
  end

  def draw()
    background(0)
    fern.render(250.0, 650.0, 0.0, 100.0, init_color)
  end

  def setup_panel
    control_panel do |c|
      c.title = "Control:"
      c.menu(:repeat, ['10', '12', '16', '20'], '12') {|m| load_menu_item(m) }
      c.button(:redraw)
    end
  end

  def redraw
    @fern = Fern.new()
    @production = fern.create_grammar(repeat.to_i)
  end

  def load_menu_item(item)
    repeat = item
  end

end

######################
# fern.rb
######################
class Fern
  include Processing::Proxy

  XPOS = 0   # place holders for pen array
  YPOS = 1
  THETA = 2
  LENGTH = 3
  HUE = 4
  DELTA = Math::PI/180 * 35.2 # NB: 36 is boring


  attr_accessor :pen, :production, :grammar, :axiom

  def initialize
    @axiom = "FD"
    @grammar = Grammar.new(axiom)
    grammar.add_rule("D", "C+@FD")
    grammar.add_rule("C", "B")
    grammar.add_rule("B", "[7+#FD][7-#FD]") # abbreviated lsystem grammar
    @production = axiom
    @pen = Array.new(5) # use a simple array for pen (for efficiency)
  end

  def render(x, y, theta, len, col)
    pen[XPOS] = x
    pen[YPOS] = y
    pen[THETA] = -Math::PI/2
    pen[LENGTH] = len
    pen[HUE] = col
    repeats = 1
    stack = Array.new  # use a locally defined array as the pen stack
    @production.each_char do |element|
      case(element)
      when "F"  # move forward
        @pen = draw_line(pen)      
      when "+"  #turn right
        pen[THETA] += (2 * Math::PI) % (repeats * DELTA)
        repeats = 1    
      when '-'  #turn left
        pen[THETA] -= (2 * Math::PI) % (repeats * DELTA)
        repeats = 1    
      when "#"  #resize line length & darken color
        pen[LENGTH] *= 0.33
        pen[HUE] = decrement_color(20)    
      when "@"  #resize line length & darken color
        pen[LENGTH] *= 0.9
        pen[HUE] = decrement_color(10)
      when "["  #push state
        stack.push(@pen.dup)    
      when "]"  #pop state
        @pen = stack.pop()    
      when "7"
        repeats = Integer(element)    
      when "B" # do nothing except confirm character in grammar        
      when "C" # do nothing except confirm character in grammar        
      when "D" # do nothing except confirm character in grammar        
      else
        puts("character '#{element}' not in grammar")    
      end
    end
  end

  def draw_line(pen)
    temp = pen.clone
    temp[XPOS] += temp[LENGTH] * Math.cos(temp[THETA])
    temp[YPOS] += temp[LENGTH] * Math.sin(temp[THETA])
    stroke_weight(2)
    stroke(temp[HUE])
    line(pen[XPOS], pen[YPOS], temp[XPOS], temp[YPOS])
    return temp
  end

  def decrement_color(hue_step)
    gree = green(pen[HUE]) - hue_step
    color(0, gree, 0)
  end

  def create_grammar(gen)
    @production = grammar.generate(gen)
  end

end




No comments:

Post a Comment

Followers

Blog Archive

About Me

My photo
I have developed JRubyArt and propane new versions of ruby-processing for JRuby-9.1.5.0 and processing-3.2.2