#include <cmath>
#include <map>
-#include <iostream>
#include <string>
#include "lindenmayersystem.h"
#include "model.h"
#include "turtle.h"
-using namespace std;
-
/**
* Constructor
- * @param model the model for generation
+ * @param model empty model
*/
LindenmayerSystem::LindenmayerSystem(Model *model)
{
_model = model;
_turtle = new Turtle(model);
- _axiom.clear();
- _rules.clear();
- _numIterations = 0;
+ clear();
}
+/**
+ * Clear all parameters
+ */
+void LindenmayerSystem::clear()
+{
+ _axiom.clear();
+ _rules.clear();
+ _turtle->setAngle(0.0);
+ _numIterations = 0;
+
+ _turtle->reset();
+ _model->clear();
+}
+
+
+
+/**
+ * Generate L-system data
+ */
+void LindenmayerSystem::generate()
+{
+ // model session
+ _model->begin();
+ _model->setColorIndex(0);
+ recursiveWalk(_axiom, _numIterations);
+ _model->end();
+}
+
+
+
/**
* Set the initial rule (the axiom)
* @param axiom the axiom
+/**
+ * Set diameter of segment
+ * @param diameter the diameter
+ */
+void LindenmayerSystem::setDiameter(double diameter)
+{
+ _model->setDiameter(diameter);
+}
+
+
+
+/**
+ * Set diameter factor
+ * @param diameterFactor the diameter factor
+ */
+void LindenmayerSystem::setDiameterFactor(double diameterFactor)
+{
+ _model->setDiameterFactor(diameterFactor);
+}
+
+
+
/**
* Get the initial rule (the axiom)
* @return the axiom
/**
- * Generate l-system data
+ * Get the generated model
+ * @return generated model
*/
-void LindenmayerSystem::generate()
+Model *LindenmayerSystem::getModel()
{
- _model->clear();
-
- recursiveWalk(_axiom, _numIterations);
-
- _turtle->reset();
+ return _model;
}
/**
- * Walk through the rule string for specified number of levels
- * @param rule the rule
- * @param level current iteration level
+ * Recursively apply the replacement rules
+ * @param rule rule
+ * @param level recursion level
*/
void LindenmayerSystem::recursiveWalk(string rule, int level)
{
- // Process every element in the rule string
+ // process every element in the rule string
for (int i = 0; i < rule.size(); i++)
{
switch (rule[i])
{
- // walk
+ // rule
case '@':
-
+
// ignore marker, i.e. the "@"
i++;
// recursion
- if (level == 0)
+ if (level > 0)
{
- // at lowest level, start rendering
+ char ruleName[] = {rule[i], '\0'};
+ recursiveWalk(_rules[ruleName], level - 1);
+ }
- _turtle->walk();
+ break;
+
+
+ // walk / rule
+ case 'F':
+
+ // replacement rule for 'F'?
+ if (_rules.count("F") != 0 && level > 0)
+ {
+ recursiveWalk(_rules["F"], level - 1);
}
else
{
- // more levels to go
-
- char ruleName[] = {rule[i], '\0'};
- recursiveWalk(_rules[ruleName], level - 1);
+ // no rule for "F"
+ _turtle->walk();
}
-
+
break;
break;
- // first vertex in a filled surface
+ // create a filled surface
case '{':
- _turtle->fenceInBegin();
+ _model->fillBegin();
break;
- // last vertex in a filled surface
+ // close a filled surface
case '}':
- _turtle->fenceInEnd();
+ _model->fillEnd();
break;
// one vertex in a filled surface
case 'f':
- _turtle->walk();
+ _turtle->fillWalk();
break;
// decrement diameter of segment
case '!':
- _turtle->decrementDiameter();
+ _model->decrementDiameter();
break;
- // unknown operation
- default :
+ // increment current index to color table
+ case '\'':
- // TODO: filter these out when preprocessing
- cerr << "Unknown operator in rule string:" << rule[i] << endl;
+ _model->nextColor();
+ break;
+
+
+ // decrement current index to color table
+ case ',':
+
+ _model->prevColor();
break;
}
}
/**
* Verify and preprocess one rule string
- * @param ruleOrAxiom the rule
+ * @param rule the rule
* @return the preprocessed rule
*/
-string LindenmayerSystem::verifyAndPreprocessRule(string ruleOrAxiom)
+string LindenmayerSystem::verifyAndPreprocessRule(string rule)
{
- // for now, simply put "@" before every rewriting operator
// TODO: verifying
string preprocessedRule;
// check every element in rule
- for (int i = 0; i < ruleOrAxiom.size(); i++)
+ for (int i = 0; i < rule.size(); i++)
{
- // TODO: remove the A-Z limit: use strings, not single chars
- if (ruleOrAxiom[i] >= 'A' && ruleOrAxiom[i] <= 'Z')
+ // TODO: allow strings as names
+ if (rule[i] >= 'A' && rule[i] <= 'Z' && rule[i] != 'F')
{
- // mark as rewriting operator
+ // add rule operator
preprocessedRule += '@';
}
- preprocessedRule += ruleOrAxiom[i];
+ preprocessedRule += rule[i];
}
return preprocessedRule;
/**
* Unpreprocess one rule string
- * @param ruleOrAxiom the rule
+ * @param rule the rule
* @return the unpreprocessed rule
*/
-string LindenmayerSystem::unpreprocessRule(string ruleOrAxiom)
+string LindenmayerSystem::unpreprocessRule(string rule)
{
string unpreprocessedRule;
// check every element in rule
- for (int i = 0; i < ruleOrAxiom.size(); i++)
+ for (int i = 0; i < rule.size(); i++)
{
- // ignore rewriting marker
- if (ruleOrAxiom[i] != '@')
+ // ignore rule operator
+ if (rule[i] != '@')
{
- unpreprocessedRule += ruleOrAxiom[i];
+ unpreprocessedRule += rule[i];
}
}