X-Git-Url: https://git.piment-noir.org/?p=lsystem3d.git;a=blobdiff_plain;f=src%2Flindenmayersystem.cpp;h=a4016346ae49b4664c44f3fd9aaf91375fcb23df;hp=9a660233f29d9043f846c80a00b5ae83e78165a3;hb=526db67540bf69a4c09ed0d0f4d62bad0a37ee70;hpb=3025996ba17bf59f5bc64def5d55b95c4d732a8a diff --git a/src/lindenmayersystem.cpp b/src/lindenmayersystem.cpp index 9a66023..a401634 100644 --- a/src/lindenmayersystem.cpp +++ b/src/lindenmayersystem.cpp @@ -22,29 +22,24 @@ #include #include -#include #include #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(); } @@ -59,6 +54,36 @@ LindenmayerSystem::~LindenmayerSystem() +/** + * 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 @@ -107,6 +132,28 @@ void LindenmayerSystem::setNumIterations(int numIterations) +/** + * 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 @@ -166,52 +213,58 @@ int LindenmayerSystem::getNumIterations() /** - * 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; @@ -278,39 +331,45 @@ void LindenmayerSystem::recursiveWalk(string rule, int level) 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; } } @@ -320,26 +379,25 @@ void LindenmayerSystem::recursiveWalk(string rule, int level) /** * 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; @@ -349,20 +407,20 @@ string LindenmayerSystem::verifyAndPreprocessRule(string ruleOrAxiom) /** * 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]; } }