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
28 #include "lindenmayersystem.h"
38 * @param model the model for generation
40 LindenmayerSystem::LindenmayerSystem(Model
*model
)
43 _turtle
= new Turtle(model
);
55 LindenmayerSystem::~LindenmayerSystem()
63 * Set the initial rule (the axiom)
64 * @param axiom the axiom
66 void LindenmayerSystem::setAxiom(string axiom
)
68 _axiom
= verifyAndPreprocessRule(axiom
);
75 * @param name rule name
76 * @param rule the rule
78 void LindenmayerSystem::setRule(string name
, string rule
)
80 _rules
[name
] = verifyAndPreprocessRule(rule
);
86 * Set the turn/pitch/roll angle
87 * @param degrees the angle, in degrees
89 void LindenmayerSystem::setAngle(double degrees
)
91 // convert from degrees to radians
92 double radians
= (degrees
/ 360.0) * (2.0 * M_PIl
);
94 _turtle
->setAngle(radians
);
100 * Set the number of iterations
101 * @param numIterations number of iterations
103 void LindenmayerSystem::setNumIterations(int numIterations
)
105 _numIterations
= numIterations
;
111 * Get the initial rule (the axiom)
114 string
LindenmayerSystem::getAxiom()
116 return unpreprocessRule(_axiom
);
125 map
<string
,string
> LindenmayerSystem::getRules()
127 map
<string
,string
> theUnpreprocessedRules
;
129 // unpreprocess all rules
130 map
<string
,string
>::iterator currentRule
;
131 for (currentRule
= _rules
.begin(); currentRule
!= _rules
.end(); currentRule
++)
133 theUnpreprocessedRules
[currentRule
->first
] = unpreprocessRule(currentRule
->second
);
136 return theUnpreprocessedRules
;
142 * Get the turn/pitch/roll angle
143 * @return the angle, in degrees
145 double LindenmayerSystem::getAngle()
147 double radians
= _turtle
->getAngle();
149 // convert from radians to degrees
150 double degrees
= 360.0 * (radians
/ (2.0 * M_PIl
));
158 * Get the number of iterations
159 * @return number of iterations
161 int LindenmayerSystem::getNumIterations()
163 return _numIterations
;
169 * Generate l-system data
171 void LindenmayerSystem::generate()
175 recursiveWalk(_axiom
, _numIterations
);
183 * Walk through the rule string for specified number of levels
184 * @param rule the rule
185 * @param level current iteration level
187 void LindenmayerSystem::recursiveWalk(string rule
, int level
)
189 // Process every element in the rule string
190 for (int i
= 0; i
< rule
.size(); i
++)
197 // ignore marker, i.e. the "@"
203 // at lowest level, start rendering
211 char ruleName
[] = {rule
[i
], '\0'};
212 recursiveWalk(_rules
[ruleName
], level
- 1);
228 _turtle
->turnRight();
235 _turtle
->pitchDown();
256 _turtle
->rollRight();
260 // turn around 180 degrees
263 _turtle
->turnAround();
267 // save state to stack
274 // restore state from stack
281 // first vertex in a filled surface
284 _turtle
->fenceInBegin();
288 // last vertex in a filled surface
291 _turtle
->fenceInEnd();
295 // one vertex in a filled surface
302 // decrement diameter of segment
305 _turtle
->decrementDiameter();
312 // TODO: filter these out when preprocessing
313 cerr
<< "Unknown operator in rule string:" << rule
[i
] << endl
;
322 * Verify and preprocess one rule string
323 * @param ruleOrAxiom the rule
324 * @return the preprocessed rule
326 string
LindenmayerSystem::verifyAndPreprocessRule(string ruleOrAxiom
)
328 // for now, simply put "@" before every rewriting operator
331 string preprocessedRule
;
333 // check every element in rule
334 for (int i
= 0; i
< ruleOrAxiom
.size(); i
++)
336 // TODO: remove the A-Z limit: use strings, not single chars
337 if (ruleOrAxiom
[i
] >= 'A' && ruleOrAxiom
[i
] <= 'Z')
339 // mark as rewriting operator
340 preprocessedRule
+= '@';
342 preprocessedRule
+= ruleOrAxiom
[i
];
345 return preprocessedRule
;
351 * Unpreprocess one rule string
352 * @param ruleOrAxiom the rule
353 * @return the unpreprocessed rule
355 string
LindenmayerSystem::unpreprocessRule(string ruleOrAxiom
)
357 string unpreprocessedRule
;
359 // check every element in rule
360 for (int i
= 0; i
< ruleOrAxiom
.size(); i
++)
362 // ignore rewriting marker
363 if (ruleOrAxiom
[i
] != '@')
365 unpreprocessedRule
+= ruleOrAxiom
[i
];
369 return unpreprocessedRule
;