*** empty log message ***
[lsystem3d.git] / src / lindenmayersystem.cpp
index 9a660233f29d9043f846c80a00b5ae83e78165a3..a4016346ae49b4664c44f3fd9aaf91375fcb23df 100644 (file)
 #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();
 }
 
 
@@ -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];
         }
     }