1 // Copyright (C) 2006 Erik Dahlberg
3 // This file is part of LSystem3d.
5 // LSystem3D is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
10 // LSystem3D 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 LSystem3D; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 #include "lindenmayersystem.h"
35 * @param model empty model
37 LindenmayerSystem::LindenmayerSystem(Model
*model
)
40 _turtle
= new Turtle(model
);
50 LindenmayerSystem::~LindenmayerSystem()
58 * Clear all parameters
60 void LindenmayerSystem::clear()
64 _turtle
->setAngle(0.0);
74 * Generate L-system data
76 void LindenmayerSystem::generate()
80 _model
->setColorIndex(0);
81 recursiveWalk(_axiom
, _numIterations
);
88 * Set the initial rule (the axiom)
89 * @param axiom the axiom
91 void LindenmayerSystem::setAxiom(string axiom
)
93 _axiom
= verifyAndPreprocessRule(axiom
);
100 * @param name rule name
101 * @param rule the rule
103 void LindenmayerSystem::setRule(string name
, string rule
)
105 _rules
[name
] = verifyAndPreprocessRule(rule
);
111 * Set the turn/pitch/roll angle
112 * @param degrees the angle, in degrees
114 void LindenmayerSystem::setAngle(double degrees
)
116 // convert from degrees to radians
117 double radians
= (degrees
/ 360.0) * (2.0 * M_PIl
);
119 _turtle
->setAngle(radians
);
125 * Set the number of iterations
126 * @param numIterations number of iterations
128 void LindenmayerSystem::setNumIterations(int numIterations
)
130 _numIterations
= numIterations
;
136 * Set diameter of segment
137 * @param diameter the diameter
139 void LindenmayerSystem::setDiameter(double diameter
)
141 _model
->setDiameter(diameter
);
147 * Set diameter factor
148 * @param diameterFactor the diameter factor
150 void LindenmayerSystem::setDiameterFactor(double diameterFactor
)
152 _model
->setDiameterFactor(diameterFactor
);
158 * Get the initial rule (the axiom)
161 string
LindenmayerSystem::getAxiom()
163 return unpreprocessRule(_axiom
);
172 map
<string
,string
> LindenmayerSystem::getRules()
174 map
<string
,string
> theUnpreprocessedRules
;
176 // unpreprocess all rules
177 map
<string
,string
>::iterator currentRule
;
178 for (currentRule
= _rules
.begin(); currentRule
!= _rules
.end(); currentRule
++)
180 theUnpreprocessedRules
[currentRule
->first
] = unpreprocessRule(currentRule
->second
);
183 return theUnpreprocessedRules
;
189 * Get the turn/pitch/roll angle
190 * @return the angle, in degrees
192 double LindenmayerSystem::getAngle()
194 double radians
= _turtle
->getAngle();
196 // convert from radians to degrees
197 double degrees
= 360.0 * (radians
/ (2.0 * M_PIl
));
205 * Get the number of iterations
206 * @return number of iterations
208 int LindenmayerSystem::getNumIterations()
210 return _numIterations
;
216 * Get the generated model
217 * @return generated model
219 Model
*LindenmayerSystem::getModel()
227 * Recursively apply the replacement rules
229 * @param level recursion level
231 void LindenmayerSystem::recursiveWalk(string rule
, int level
)
233 // process every element in the rule string
234 for (int i
= 0; i
< rule
.size(); i
++)
241 // ignore marker, i.e. the "@"
247 char ruleName
[] = {rule
[i
], '\0'};
248 recursiveWalk(_rules
[ruleName
], level
- 1);
257 // replacement rule for 'F'?
258 if (_rules
.count("F") != 0 && level
> 0)
260 recursiveWalk(_rules
["F"], level
- 1);
281 _turtle
->turnRight();
288 _turtle
->pitchDown();
309 _turtle
->rollRight();
313 // turn around 180 degrees
316 _turtle
->turnAround();
320 // save state to stack
327 // restore state from stack
334 // create a filled surface
341 // close a filled surface
348 // one vertex in a filled surface
355 // decrement diameter of segment
358 _model
->decrementDiameter();
362 // increment current index to color table
369 // decrement current index to color table
381 * Verify and preprocess one rule string
382 * @param rule the rule
383 * @return the preprocessed rule
385 string
LindenmayerSystem::verifyAndPreprocessRule(string rule
)
389 string preprocessedRule
;
391 // check every element in rule
392 for (int i
= 0; i
< rule
.size(); i
++)
394 // TODO: allow strings as names
395 if (rule
[i
] >= 'A' && rule
[i
] <= 'Z' && rule
[i
] != 'F')
398 preprocessedRule
+= '@';
400 preprocessedRule
+= rule
[i
];
403 return preprocessedRule
;
409 * Unpreprocess one rule string
410 * @param rule the rule
411 * @return the unpreprocessed rule
413 string
LindenmayerSystem::unpreprocessRule(string rule
)
415 string unpreprocessedRule
;
417 // check every element in rule
418 for (int i
= 0; i
< rule
.size(); i
++)
420 // ignore rule operator
423 unpreprocessedRule
+= rule
[i
];
427 return unpreprocessedRule
;