~ubuntu-branches/ubuntu/lucid/structure-synth/lucid

« back to all changes in this revision

Viewing changes to StructureSynth/Model/RuleSet.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Miriam Ruiz
  • Date: 2009-04-13 13:28:45 UTC
  • Revision ID: james.westby@ubuntu.com-20090413132845-d7d42t4llxjxq0ez
Tags: upstream-0.9
ImportĀ upstreamĀ versionĀ 0.9

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "RuleSet.h"
 
2
#include "RuleRef.h"
 
3
#include "CustomRule.h"
 
4
#include "AmbiguousRule.h"
 
5
#include "PrimitiveRule.h"
 
6
 
 
7
#include <QStringList>
 
8
#include <QMap>
 
9
#include <typeinfo>
 
10
 
 
11
#include "../../SyntopiaCore/Exceptions/Exception.h"
 
12
#include "../../SyntopiaCore/Logging/Logging.h"
 
13
#include "../../SyntopiaCore/Math/Vector3.h"
 
14
 
 
15
using namespace SyntopiaCore::Exceptions;
 
16
using namespace SyntopiaCore::Logging;
 
17
using namespace SyntopiaCore::Math;
 
18
 
 
19
namespace StructureSynth {
 
20
        namespace Model {       
 
21
 
 
22
                /// Constructor. Automatically adds built-in rules.
 
23
                RuleSet::RuleSet() {
 
24
                        topLevelRule = new CustomRule("TopLevelRule");
 
25
 
 
26
                        /// Add instances of predefined built-in types.
 
27
                        rules.append(new PrimitiveRule(PrimitiveRule::Box));
 
28
                        rules.append(new PrimitiveRule(PrimitiveRule::Sphere));
 
29
                        rules.append(new PrimitiveRule(PrimitiveRule::Cylinder));
 
30
                        rules.append(new PrimitiveRule(PrimitiveRule::Mesh));
 
31
                        rules.append(new PrimitiveRule(PrimitiveRule::Line));
 
32
                        rules.append(new PrimitiveRule(PrimitiveRule::Dot));
 
33
                        rules.append(new PrimitiveRule(PrimitiveRule::Grid));
 
34
                        rules.append(topLevelRule);
 
35
                };
 
36
 
 
37
 
 
38
                /// Deletes rules
 
39
                RuleSet::~RuleSet() {
 
40
                        for (int i = 0; i < rules.size(); i++) delete(rules[i]);
 
41
                }
 
42
 
 
43
                void RuleSet::addRule(Rule* rule) { 
 
44
                        // Check if the rule name is already used...
 
45
                        QString name = rule->getName();
 
46
                        
 
47
                        for (int i = 0; i < rules.size(); i++) {
 
48
 
 
49
                                if (rules[i]->getName() == name) {
 
50
                                        if (typeid(*rules[i]) == typeid(CustomRule)) {
 
51
                                                // A Custom rule already exists with the same name.
 
52
                                                // Now we must remove the existing rule, and create a new ambiguous rule hosting them both.
 
53
                        
 
54
                                                Rule* r = rules[i];
 
55
                                                rules.removeAll(r);
 
56
                                                CustomRule* cr1 = dynamic_cast<CustomRule*>(r);
 
57
                                        
 
58
                                                AmbiguousRule* ar = new AmbiguousRule(name);
 
59
                                                ar->appendRule(cr1);
 
60
 
 
61
                                                CustomRule* cr2 = dynamic_cast<CustomRule*>(rule);
 
62
                                                if (!cr2) throw Exception("Trying to add non-custom rule to ambiguous rule: '%1'. "+name);
 
63
                                                ar->appendRule(cr2);
 
64
 
 
65
                                                rules.append(ar);
 
66
 
 
67
                                                return;
 
68
                                        } else if (typeid(*rules[i]) == typeid(PrimitiveRule)) {
 
69
                                                // A primitive rule already exists with the same name. This is not acceptable.
 
70
                                                throw Exception(QString("A primitive rule already exists with the name: '%1'. New definitions can not merged.").arg(name));
 
71
                                        } else if (typeid(*rules[i]) == typeid(AmbiguousRule)) {
 
72
                                                // A ambiguous rule already exists with the same name. We will add to it.
 
73
                                                AmbiguousRule* ar = dynamic_cast<AmbiguousRule*>(rules[i]);
 
74
                                                CustomRule* cr = dynamic_cast<CustomRule*>(rule);
 
75
                                                if (!cr) throw Exception("Trying to add non-custom rule to ambiguous rule: '%1'. "+name);
 
76
                                                ar->appendRule(cr);
 
77
                                                return;
 
78
                                        } else {
 
79
                                                WARNING("Unknown typeid");
 
80
                                        }
 
81
                                }
 
82
 
 
83
                        }
 
84
 
 
85
                        rules.append(rule);
 
86
                }
 
87
 
 
88
 
 
89
                /// Resolve symbolic names into pointers
 
90
                void RuleSet::resolveNames() {
 
91
 
 
92
                        // build map
 
93
                        QMap<QString, Rule*> map;
 
94
                        for (int i = 0; i < rules.size(); i++) map[rules[i]->getName()] = rules[i];
 
95
 
 
96
 
 
97
 
 
98
                        // resolve rules.
 
99
                        for (int i = 0; i < rules.size(); i++) {
 
100
 
 
101
                                QList<RuleRef*> refs = rules[i]->getRuleRefs();
 
102
 
 
103
                                for (int j = 0; j < refs.size(); j++) {
 
104
                                        QString name = refs[j]->getReference();
 
105
                                        if (!map.contains(name)) {
 
106
                                                // We could not resolve the name.
 
107
                                                // Check if it has a class specifier.
 
108
                                                QStringList sl = name.split("::");
 
109
                                                if (sl.size() == 2) {
 
110
                                                        QString baseName = sl[0];
 
111
                                                        QString classID = sl[1];
 
112
 
 
113
                                                        if (!map.contains(baseName)) {
 
114
                                                                throw Exception(QString("Unable to resolve base rule name: %1 for rule %2").arg(baseName).arg(name));
 
115
                                                        }
 
116
                                        
 
117
                                                        // Now we have to create a new instance of this rule.
 
118
                                                        Rule* r = map[baseName];
 
119
 
 
120
                                                        if (typeid(*r) != typeid(PrimitiveRule)) {
 
121
                                                                throw Exception(QString("Only primitive rules (box, sphere, ...) may have a class specifier: %1 is invalid").arg(name));
 
122
                                                        }
 
123
 
 
124
                                                        PrimitiveRule* pr = (PrimitiveRule*)r;
 
125
                                                        PrimitiveRule* newRule = new PrimitiveRule(*pr);
 
126
                                                        newRule->setClass(classID);
 
127
                                                        map[name] = newRule;
 
128
                                                        
 
129
                                                        INFO("Created new class for rule: " + name);
 
130
                                                } else {
 
131
                                                        // The Polygons rules (i.e. Triangle[x,y,z]) are special rules, each created on the fly.
 
132
                                                        QRegExp r("triangle\\[(.*)\\]");
 
133
                                                        if (r.exactMatch(name)) {
 
134
                                                                // Check the arguments.
 
135
                                                                INFO("Found:" + r.cap(1));
 
136
                                                                QVector<Vector3f> v;
 
137
                                                                QStringList l = r.cap(1).split(";");
 
138
                                                                if (l.size() != 3) {
 
139
                                                                        throw Exception(QString("Unable to parse Triangle definition - must be triangle(p1;p2;p3) - found : %1").arg(name));
 
140
                                                                }
 
141
 
 
142
                                                                for (unsigned int i = 0; i < 3; i++) {
 
143
                                                                        QStringList l2 = l[i].split(",");
 
144
                                                                        if (l2.size() != 3) {
 
145
                                                                                        throw Exception(QString("Unable to parse Triangle definition - coordinates must be like '0.1,0.2,0.3' - found : %1").arg(l[i]));
 
146
                                                                        }
 
147
                                                                        bool ok = false;
 
148
                                                                        float f1 = l2[0].toFloat(&ok);
 
149
                                                                        if (!ok) throw Exception(QString("Unable to parse Triangle definition - error in first coordinate - found in : %1").arg(name));
 
150
                                                                        float f2 = l2[1].toFloat(&ok);
 
151
                                                                        if (!ok) throw Exception(QString("Unable to parse Triangle definition - error in second coordinate - found in : %1").arg(name));
 
152
                                                                        float f3 = l2[2].toFloat(&ok);
 
153
                                                                        if (!ok) throw Exception(QString("Unable to parse Triangle definition - error in third coordinate - found in : %1").arg(name));
 
154
                                                                        v.append(Vector3f(f1,f2,f3));
 
155
                                                                }       
 
156
 
 
157
                                                                INFO(QString("Created new Triangle-rule: %1 ; %2 ; %3")
 
158
                                                                        .arg(v[0].toString())
 
159
                                                                        .arg(v[1].toString())
 
160
                                                                        .arg(v[2].toString()));
 
161
                                                                map[name] = new TriangleRule(v[0], v[1], v[2]);
 
162
                                                        
 
163
                                                        } else {
 
164
                                                                throw Exception(QString("Unable to resolve rule: %1").arg(name));
 
165
                                                        }
 
166
                                                }
 
167
                                        }
 
168
                                        refs[j]->setRef(map[name]);
 
169
                                }
 
170
 
 
171
                        }
 
172
 
 
173
                }
 
174
 
 
175
                ///
 
176
                QStringList RuleSet::getUnreferencedNames() {
 
177
 
 
178
                        WARNING("RuleSet::getUnreferencedNames(): Not implemented yet!");
 
179
                        return QStringList();
 
180
 
 
181
                };
 
182
 
 
183
                Rule* RuleSet::getStartRule() const {
 
184
                        return topLevelRule;
 
185
                };
 
186
 
 
187
                /// For debug
 
188
                void  RuleSet::dumpInfo() const {
 
189
                        int custom = 0;
 
190
                        int ambi = 0;
 
191
                        int primitive = 0;
 
192
                        int rulesCount = 0;
 
193
 
 
194
                        for (int i = 0; i < rules.size(); i++) {
 
195
                                rulesCount++; 
 
196
 
 
197
                                CustomRule* cr = dynamic_cast<CustomRule*>(rules[i]);
 
198
                                if (cr) custom++;
 
199
 
 
200
                                AmbiguousRule* ar = dynamic_cast<AmbiguousRule*>(rules[i]);
 
201
                                if (ar) ambi++;
 
202
 
 
203
                                PrimitiveRule* pr = dynamic_cast<PrimitiveRule*>(rules[i]);
 
204
                                if (pr) primitive++;
 
205
                        }
 
206
 
 
207
                        Debug(QString("Loaded %1 user rules: %2 Custom Rules, %3 Ambiguous Rules")
 
208
                                .arg(rulesCount-primitive).arg(custom).arg(ambi));
 
209
                        Debug(QString("Loaded %1 built-in rules.").arg(primitive));
 
210
                }
 
211
 
 
212
        }
 
213
}
 
214