3
#include "CustomRule.h"
4
#include "AmbiguousRule.h"
5
#include "PrimitiveRule.h"
11
#include "../../SyntopiaCore/Exceptions/Exception.h"
12
#include "../../SyntopiaCore/Logging/Logging.h"
13
#include "../../SyntopiaCore/Math/Vector3.h"
15
using namespace SyntopiaCore::Exceptions;
16
using namespace SyntopiaCore::Logging;
17
using namespace SyntopiaCore::Math;
19
namespace StructureSynth {
22
/// Constructor. Automatically adds built-in rules.
24
topLevelRule = new CustomRule("TopLevelRule");
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);
40
for (int i = 0; i < rules.size(); i++) delete(rules[i]);
43
void RuleSet::addRule(Rule* rule) {
44
// Check if the rule name is already used...
45
QString name = rule->getName();
47
for (int i = 0; i < rules.size(); i++) {
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.
56
CustomRule* cr1 = dynamic_cast<CustomRule*>(r);
58
AmbiguousRule* ar = new AmbiguousRule(name);
61
CustomRule* cr2 = dynamic_cast<CustomRule*>(rule);
62
if (!cr2) throw Exception("Trying to add non-custom rule to ambiguous rule: '%1'. "+name);
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);
79
WARNING("Unknown typeid");
89
/// Resolve symbolic names into pointers
90
void RuleSet::resolveNames() {
93
QMap<QString, Rule*> map;
94
for (int i = 0; i < rules.size(); i++) map[rules[i]->getName()] = rules[i];
99
for (int i = 0; i < rules.size(); i++) {
101
QList<RuleRef*> refs = rules[i]->getRuleRefs();
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];
113
if (!map.contains(baseName)) {
114
throw Exception(QString("Unable to resolve base rule name: %1 for rule %2").arg(baseName).arg(name));
117
// Now we have to create a new instance of this rule.
118
Rule* r = map[baseName];
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));
124
PrimitiveRule* pr = (PrimitiveRule*)r;
125
PrimitiveRule* newRule = new PrimitiveRule(*pr);
126
newRule->setClass(classID);
129
INFO("Created new class for rule: " + name);
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));
137
QStringList l = r.cap(1).split(";");
139
throw Exception(QString("Unable to parse Triangle definition - must be triangle(p1;p2;p3) - found : %1").arg(name));
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]));
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));
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]);
164
throw Exception(QString("Unable to resolve rule: %1").arg(name));
168
refs[j]->setRef(map[name]);
176
QStringList RuleSet::getUnreferencedNames() {
178
WARNING("RuleSet::getUnreferencedNames(): Not implemented yet!");
179
return QStringList();
183
Rule* RuleSet::getStartRule() const {
188
void RuleSet::dumpInfo() const {
194
for (int i = 0; i < rules.size(); i++) {
197
CustomRule* cr = dynamic_cast<CustomRule*>(rules[i]);
200
AmbiguousRule* ar = dynamic_cast<AmbiguousRule*>(rules[i]);
203
PrimitiveRule* pr = dynamic_cast<PrimitiveRule*>(rules[i]);
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));