**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 """importmath # some globals XPOS=0 YPOS=1 ANGLE=2 DELTA=math.pi*2/3 RULES={ 'F':'FF', 'X':'-FXF+FXF+FXF-' } AXIOM='FX'defproduce(axiom, rules):""" single rule substitution utility """ output=""foriinaxiom:output+=rules.get(i, i)# second i is returned when no dict key foundreturnoutputdefrepeat(rpx, axiom, rules):""" Repeat rule substitution in a recursive fashion rpx times """ production=axiomforiinrange(0, rpx):production=produce(production, rules)returnproductiondefrender(production):# avoiding switch and globals """ Render evaluates the production string and calls draw_line """ turtle=[0, 0,-DELTA]forvalinproduction:ifval=="F":turtle=draw_line(turtle, 3.5)elifval=="+":turtle[ANGLE]+=DELTAelifval=="-":turtle[ANGLE]-=DELTAelse:passdefdraw_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]]defsetup():""" 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)defdraw():""" An empty processing draw statement seems to be required to prevent premature exit()? """pass

## No comments:

## Post a Comment