+++ /dev/null
-// Copyright (C) 2006 Erik Dahlberg
-//
-// This file is part of LSystem3d.
-//
-// LSystem3D is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// LSystem3D is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with LSystem3D; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
-
-
-
-#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
- */
-LindenmayerSystem::LindenmayerSystem(Model *model)
-{
- _model = model;
- _turtle = new Turtle(model);
-
- _axiom.clear();
- _rules.clear();
- _numIterations = 0;
-}
-
-
-
-/**
- * Destructor
- */
-LindenmayerSystem::~LindenmayerSystem()
-{
- delete _turtle;
-}
-
-
-
-/**
- * Set the initial rule (the axiom)
- * @param axiom the axiom
- */
-void LindenmayerSystem::setAxiom(string axiom)
-{
- _axiom = verifyAndPreprocessRule(axiom);
-}
-
-
-
-/**
- * Set one rule
- * @param name rule name
- * @param rule the rule
- */
-void LindenmayerSystem::setRule(string name, string rule)
-{
- _rules[name] = verifyAndPreprocessRule(rule);
-}
-
-
-
-/**
- * Set the turn/pitch/roll angle
- * @param degrees the angle, in degrees
- */
-void LindenmayerSystem::setAngle(double degrees)
-{
- // convert from degrees to radians
- double radians = (degrees / 360.0) * (2.0 * M_PIl);
-
- _turtle->setAngle(radians);
-}
-
-
-
-/**
- * Set the number of iterations
- * @param numIterations number of iterations
- */
-void LindenmayerSystem::setNumIterations(int numIterations)
-{
- _numIterations = numIterations;
-}
-
-
-
-/**
- * Get the initial rule (the axiom)
- * @return the axiom
- */
-string LindenmayerSystem::getAxiom()
-{
- return unpreprocessRule(_axiom);
-}
-
-
-
-/**
- * Get all rules
- * @return the rules
- */
-map<string,string> LindenmayerSystem::getRules()
-{
- map<string,string> theUnpreprocessedRules;
-
- // unpreprocess all rules
- map<string,string>::iterator currentRule;
- for (currentRule = _rules.begin(); currentRule != _rules.end(); currentRule++)
- {
- theUnpreprocessedRules[currentRule->first] = unpreprocessRule(currentRule->second);
- }
-
- return theUnpreprocessedRules;
-}
-
-
-
-/**
- * Get the turn/pitch/roll angle
- * @return the angle, in degrees
- */
-double LindenmayerSystem::getAngle()
-{
- double radians = _turtle->getAngle();
-
- // convert from radians to degrees
- double degrees = 360.0 * (radians / (2.0 * M_PIl));
-
- return degrees;
-}
-
-
-
-/**
- * Get the number of iterations
- * @return number of iterations
- */
-int LindenmayerSystem::getNumIterations()
-{
- return _numIterations;
-}
-
-
-
-/**
- * Generate l-system data
- */
-void LindenmayerSystem::generate()
-{
- _model->clear();
-
- recursiveWalk(_axiom, _numIterations);
-
- _turtle->reset();
-}
-
-
-
-/**
- * Walk through the rule string for specified number of levels
- * @param rule the rule
- * @param level current iteration level
- */
-void LindenmayerSystem::recursiveWalk(string rule, int level)
-{
- // Process every element in the rule string
- for (int i = 0; i < rule.size(); i++)
- {
- switch (rule[i])
- {
- // walk
- case '@':
-
- // ignore marker, i.e. the "@"
- i++;
-
- // recursion
- if (level == 0)
- {
- // at lowest level, start rendering
-
- _turtle->walk();
- }
- else
- {
- // more levels to go
-
- char ruleName[] = {rule[i], '\0'};
- recursiveWalk(_rules[ruleName], level - 1);
- }
-
- break;
-
-
- // turn left
- case '+':
-
- _turtle->turnLeft();
- break;
-
-
- // turn right
- case '-':
-
- _turtle->turnRight();
- break;
-
-
- // pitch down
- case '&':
-
- _turtle->pitchDown();
- break;
-
-
- // pitch up
- case '^':
-
- _turtle->pitchUp();
- break;
-
-
- // roll left
- case '\\':
-
- _turtle->rollLeft();
- break;
-
-
- // roll right
- case '/':
-
- _turtle->rollRight();
- break;
-
-
- // turn around 180 degrees
- case '|':
-
- _turtle->turnAround();
- break;
-
-
- // save state to stack
- case '[':
-
- _turtle->push();
- break;
-
-
- // restore state from stack
- case ']':
-
- _turtle->pop();
- break;
-
-
- // first vertex in a filled surface
- case '{':
-
- _turtle->fenceInBegin();
- break;
-
-
- // last vertex in a filled surface
- case '}':
-
- _turtle->fenceInEnd();
- break;
-
-
- // one vertex in a filled surface
- case 'f':
-
- _turtle->walk();
- break;
-
-
- // decrement diameter of segment
- case '!':
-
- _turtle->decrementDiameter();
- break;
-
-
- // unknown operation
- default :
-
- // TODO: filter these out when preprocessing
- cerr << "Unknown operator in rule string:" << rule[i] << endl;
- break;
- }
- }
-}
-
-
-
-/**
- * Verify and preprocess one rule string
- * @param ruleOrAxiom the rule
- * @return the preprocessed rule
- */
-string LindenmayerSystem::verifyAndPreprocessRule(string ruleOrAxiom)
-{
- // 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++)
- {
- // TODO: remove the A-Z limit: use strings, not single chars
- if (ruleOrAxiom[i] >= 'A' && ruleOrAxiom[i] <= 'Z')
- {
- // mark as rewriting operator
- preprocessedRule += '@';
- }
- preprocessedRule += ruleOrAxiom[i];
- }
-
- return preprocessedRule;
-}
-
-
-
-/**
- * Unpreprocess one rule string
- * @param ruleOrAxiom the rule
- * @return the unpreprocessed rule
- */
-string LindenmayerSystem::unpreprocessRule(string ruleOrAxiom)
-{
- string unpreprocessedRule;
-
- // check every element in rule
- for (int i = 0; i < ruleOrAxiom.size(); i++)
- {
- // ignore rewriting marker
- if (ruleOrAxiom[i] != '@')
- {
- unpreprocessedRule += ruleOrAxiom[i];
- }
- }
-
- return unpreprocessedRule;
-}