Code

Super duper mega (fun!) commit: replaced encoding=utf-8 with fileencoding=utf-8 in...
[inkscape.git] / share / extensions / lindenmayer.py
1 #!/usr/bin/env python 
2 '''
3 Copyright (C) 2005 Aaron Spike, aaron@ekips.org
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 '''
19 import inkex, simplestyle, pturtle, random
21 def stripme(s):
22     return s.strip()
24 class LSystem(inkex.Effect):
25     def __init__(self):
26         inkex.Effect.__init__(self)
27         self.OptionParser.add_option("-o", "--order",
28                         action="store", type="int", 
29                         dest="order", default=3,
30                         help="number of iteration")
31         self.OptionParser.add_option("-l", "--langle",
32                         action="store", type="float", 
33                         dest="langle", default=16.0,
34                         help="angle for turning left")
35         self.OptionParser.add_option("-r", "--rangle",
36                         action="store", type="float", 
37                         dest="rangle", default=16.0,
38                         help="angle for turning right")
39         self.OptionParser.add_option("-s", "--step",
40                         action="store", type="float", 
41                         dest="step", default=25.0,
42                         help="step size")
43         self.OptionParser.add_option("-p", "--randomizestep",
44                         action="store", type="float", 
45                         dest="randomizestep", default=0.0,
46                         help="randomize step")
47         self.OptionParser.add_option("-z", "--randomizeangle",
48                         action="store", type="float", 
49                         dest="randomizeangle", default=0.0,
50                         help="randomize angle")
51         self.OptionParser.add_option("-x", "--axiom",
52                         action="store", type="string", 
53                         dest="axiom", default="++F",
54                         help="initial state of system")
55         self.OptionParser.add_option("-u", "--rules",
56                         action="store", type="string", 
57                         dest="rules", default="F=FF-[-F+F+F]+[+F-F-F]",
58                         help="replacement rules")
59         self.OptionParser.add_option("-t", "--tab",
60                         action="store", type="string",
61                         dest="tab")
62         self.stack = []
63         self.turtle = pturtle.pTurtle()
64     def iterate(self):
65         self.rules = dict([map(stripme, i.split("=")) for i in self.options.rules.upper().split(";") if i.count("=")==1])
66         string = self.__recurse(self.options.axiom.upper(),0)
67         self.__compose_path(string)
68         return self.turtle.getPath()
69     def __compose_path(self, string):
70         self.turtle.pu()
71         self.turtle.setpos(self.view_center)
72         self.turtle.pd()
73         for c in string:
74             if c in 'ABCDEF':
75                 self.turtle.pd()
76                 self.turtle.fd(self.options.step * (random.normalvariate(1.0, 0.01 * self.options.randomizestep)))
77             elif c in 'GHIJKL':
78                 self.turtle.pu()
79                 self.turtle.fd(self.options.step * (random.normalvariate(1.0,  0.01 * self.options.randomizestep)))
80             elif c == '+':
81                 self.turtle.lt(self.options.langle * (random.normalvariate(1.0,  0.01 * self.options.randomizeangle)))
82             elif c == '-':
83                 self.turtle.rt(self.options.rangle * (random.normalvariate(1.0,  0.01 * self.options.randomizeangle)))
84             elif c == '|':
85                 self.turtle.lt(180)
86             elif c == '[':
87                 self.stack.append([self.turtle.getpos(), self.turtle.getheading()])
88             elif c == ']':
89                 self.turtle.pu()
90                 pos,heading = self.stack.pop()
91                 self.turtle.setpos(pos)
92                 self.turtle.setheading(heading)
94     def __recurse(self,rule,level):
95         level_string = ''
96         for c in rule:
97             if level < self.options.order:
98                 try:
99                     level_string = level_string + self.__recurse(self.rules[c],level+1)
100                 except KeyError:
101                     level_string = level_string + c
102             else:
103                 level_string = level_string + c 
104         return level_string
105             
106     def effect(self):
107         s = {'stroke-linejoin': 'miter', 'stroke-width': '1.0px', 
108             'stroke-opacity': '1.0', 'fill-opacity': '1.0', 
109             'stroke': '#000000', 'stroke-linecap': 'butt', 
110             'fill': 'none'}
111         attribs = {'style':simplestyle.formatStyle(s),'d':self.iterate()}
112         inkex.etree.SubElement(self.current_layer,inkex.addNS('path','svg'),attribs)
114 if __name__ == '__main__':
115     e = LSystem()
116     e.affect()
119 # vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 fileencoding=utf-8 textwidth=99