initial revision
[lsystem3d.git] / src / ruleset.cpp
diff --git a/src/ruleset.cpp b/src/ruleset.cpp
new file mode 100644 (file)
index 0000000..024f77e
--- /dev/null
@@ -0,0 +1,161 @@
+// 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 <ctime>
+
+#include <string>
+#include <utility>
+
+#include "rule.h"
+#include "ruleset.h"
+
+
+
+/**
+ * Constructor
+ */
+RuleSet::RuleSet()
+{
+    srand(time(NULL));
+}
+
+
+
+/**
+ * Destructor
+ */
+RuleSet::~RuleSet()
+{
+}
+
+
+
+/**
+ * Clear rule set
+ */
+void RuleSet::clear()
+{
+    _rules.clear();
+}
+
+
+
+/**
+ * Add one rule
+ * @param rule the rule
+ */
+void RuleSet::addRule(Rule rule)
+{
+    _rules.insert(make_pair(rule.getName(), rule));
+}
+
+
+
+/**
+ * Get one rule with repect of probability factor
+ * @param name the rule name
+ * @return the rule
+ */
+Rule RuleSet::findRule(string ruleName)
+{
+    // TODO: clean up...
+    
+    
+    int numRules = _rules.count(ruleName);
+    Rule selectedRule;
+    
+    if (numRules == 0)
+    {
+        // no rule with this name
+        selectedRule.setProbability(0.0);
+    }
+    else if (numRules == 1)
+    {
+        // only one rule with this name
+        selectedRule = _rules.find(ruleName)->second;
+    }
+    else
+    {
+        // many rules with this name
+        
+        
+        // find ranges
+        
+        // TODO: int ok?
+        int ranges[numRules + 1];
+        
+        double lastRange = ranges[0] = 0;
+        int index = 1;
+        
+        // TODO: move to addRule()
+        pair<rulemap::iterator, rulemap::iterator> interval = _rules.equal_range(ruleName);
+        for (rulemap::iterator it = interval.first; it != interval.second; it++)
+        {
+            // calculate and store ranges
+            lastRange += it->second.getProbability() * RAND_MAX;
+            ranges[index++] = (int)lastRange;
+        }
+        
+        ranges[numRules] = RAND_MAX;
+        
+        
+        // choose random range
+        
+        int selection = 0;
+        int random = rand();
+        
+        for (int i = 0; i < numRules; i++)
+        {
+            if (random >= ranges[i] && random <= ranges[i + 1])
+            {
+                // in range
+                selection = i;
+                
+                break;
+            }
+        }
+        
+        
+        // make selection
+        
+        rulemap::iterator it = interval.first;
+        for (int i = 0; i < selection; i++)
+        {
+            it++;
+        }
+        selectedRule = it->second;
+    }
+    
+    
+    return selectedRule;
+}
+
+
+
+/**
+ * Get all rules
+ * @return the rules
+ */
+rulemap RuleSet::getRules()
+{
+    return _rules;
+}