Recently I've been looking at Povray, pyprocessing, and cfdg (version 3.0) as tools for creating digital images. I have branched two separate blogs where I mainly explore jruby + processing and processing.py

Wednesday, 12 January 2011

Python Doesn't Do Switch (A Lsystem Sierpinski in processing.py)

Get processing.py here.


import math

# some globals
XPOS = 0
YPOS = 1
ANGLE = 2
DELTA = PI*2/3

rules = {}                       # empty dictionary
rules['F'] = 'FF'
rules['X'] = '-FXF+FXF+FXF-'
axiom = 'FX'

def produce(axiom, rules):
  output = ""
  for i in axiom:
    output += rules.get(i, i)    # second i is returned when no dict key found
  return output
  
def repeat(n, axiom, rules):
  production = axiom
  for i in range(0, n):
    production = produce(production, rules)
  return production
  
############################################################################################
# python doesn't do switch, why? this is a work around (anticipating more complex grammar)
# the supposed preferred option is a dictionary of functions
############################################################################################

def switch(val):
  if val == "+": val="left"
  if val == "-": val="right"
  choose = val
  exec choose+"()"
  
def F():
  global turtle 
  turtle = draw_line(turtle, 3.5)
def left():
  global turtle
  turtle[ANGLE] += DELTA
def right():
  global turtle
  turtle[ANGLE] -= DELTA
def X():
  pass 

#############################################################################################

def render(production):
  global turtle
  turtle = [0, 0, -DELTA]
  for i in production:
    switch(i)
    
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)
  return [new_xpos, new_ypos, turtle[ANGLE]]   

def setup():
  size(500, 500)
  global rules
  rules = repeat(6, axiom, rules)
  translate(width*0.9, height*0.9) 
  render(rules)  

def draw():
  pass      
      

















Here is a more 'pythonic' version, including indentation convention of 4 spaces:-

"""
sierpinski.py is a python script for use in processing.py. 
It avoids switch, because python does not include it in the language, in my view this
is big mistake switch is very easy on the eye, I dislike chains of if/elif, however the 
alternatives in python are either dodgy or equally ugly
"""

import math

# some globals
XPOS = 0
YPOS = 1
ANGLE = 2
DELTA = math.pi*2/3

RULES = {
'F' : 'FF',
'X' : '-FXF+FXF+FXF-'
}

AXIOM = 'FX'


def produce(axiom, rules):
    """
    single rule substitution utility
    """
    output = ""
    for i in axiom:
        output += rules.get(i, i)    # second i is returned when no dict key found
    return output
    
 
def repeat(rpx, axiom, rules):
    """
    Repeat rule substitution in a recursive fashion rpx times
    """ 
    production = axiom
    for i in range(0, rpx):
        production = produce(production, rules)
    return production
    

def render(production):        # avoiding switch and globals
    """
    Render evaluates the production string and calls draw_line
    """
    turtle = [0, 0, -DELTA]
    for val in production:
        if val == "F": 
            turtle = draw_line(turtle, 3.5)
        elif val == "+": 
            turtle[ANGLE] += DELTA
        elif val == "-": 
            turtle[ANGLE] -= DELTA
        else: 
            pass


def draw_line(turtle, length):
    """
    Draw line utility uses processing 'line' function to draw lines
    """
    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)
    return [new_xpos, new_ypos, turtle[ANGLE]]     


def setup():
    """
    The processing setup statement
    """
    size(500, 500)
    production = repeat(6, AXIOM, RULES)
    width = 500
    height = 500
    translate(width*0.9, height*0.9) 
    render(production)    


def draw():
    """
    An empty processing draw statement seems to be required to prevent premature exit()?
    """
    pass 

No comments:

Post a Comment

Followers

Blog Archive

About Me

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