summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--csg.cc3
-rw-r--r--example.scad4
-rw-r--r--expr.cc89
-rw-r--r--func.cc42
-rw-r--r--lexer.l16
-rw-r--r--module.cc10
-rw-r--r--openscad.h46
-rw-r--r--parser.y87
-rw-r--r--primitive.cc43
-rw-r--r--trans.cc2
-rw-r--r--value.cc223
11 files changed, 419 insertions, 146 deletions
diff --git a/csg.cc b/csg.cc
index 9ce2bdd..04f6798 100644
--- a/csg.cc
+++ b/csg.cc
@@ -47,6 +47,9 @@ public:
AbstractNode *CsgModule::evaluate(const Context*, const QVector<QString>&, const QVector<Value>&, const QVector<AbstractNode*> child_nodes) const
{
+ if (child_nodes.size() == 1)
+ return child_nodes[0];
+
CsgNode *node = new CsgNode(type);
foreach (AbstractNode *v, child_nodes)
node->children.append(v);
diff --git a/example.scad b/example.scad
index a2b86c1..9f21ea7 100644
--- a/example.scad
+++ b/example.scad
@@ -24,8 +24,8 @@ module test001()
module test002()
{
difference() {
- cube([2 2 0.5], 1);
- cube([0.5 0.5 2], 1);
+ cube([2 2 0.5], true);
+ cube([0.5 0.5 2], true);
}
}
diff --git a/expr.cc b/expr.cc
index 80d5666..759cc96 100644
--- a/expr.cc
+++ b/expr.cc
@@ -45,25 +45,79 @@ Value Expression::evaluate(const Context *context) const
return children[0]->evaluate(context) + children[1]->evaluate(context);
case '-':
return children[0]->evaluate(context) - children[1]->evaluate(context);
+ case '?':
+ {
+ Value v = children[0]->evaluate(context);
+ if (v.type == Value::BOOL)
+ return children[v.b ? 1 : 2]->evaluate(context);
+ return Value();
+ }
case 'I':
return children[0]->evaluate(context).inv();
case 'C':
return const_value;
+ case 'R':
+ {
+ Value v1 = children[0]->evaluate(context);
+ Value v2 = children[1]->evaluate(context);
+ Value v3 = children[2]->evaluate(context);
+ if (v1.type == Value::NUMBER && v2.type == Value::NUMBER && v3.type == Value::NUMBER) {
+ Value r = Value();
+ r.type = Value::RANGE;
+ r.r_begin = v1.num;
+ r.r_step = v2.num;
+ r.r_end = v3.num;
+ return r;
+ }
+ return Value();
+ }
case 'V':
- return Value(children[0]->evaluate(context), children[1]->evaluate(context), children[2]->evaluate(context));
+ {
+ Value v1 = children[0]->evaluate(context);
+ Value v2 = children[1]->evaluate(context);
+ Value v3 = children[2]->evaluate(context);
+ if (v1.type == Value::NUMBER && v2.type == Value::NUMBER && v3.type == Value::NUMBER)
+ return Value(v1.num, v2.num, v3.num);
+ return Value();
+ }
+ case 'M':
+ {
+ double m[16];
+ for (int i=0; i<16; i++) {
+ Value v = children[i]->evaluate(context);
+ if (v.type != Value::NUMBER)
+ return Value();
+ m[i] = v.num;
+ }
+ return Value(m);
+ }
case 'L':
return context->lookup_variable(var_name);
- case 'M':
+ case 'N':
{
Value v = children[0]->evaluate(context);
- if (v.is_nan || !v.is_vector)
- return Value();
- if (var_name == QString("x"))
+
+ if (v.type == Value::VECTOR && var_name == QString("x"))
return Value(v.x);
- if (var_name == QString("y"))
+ if (v.type == Value::VECTOR && var_name == QString("y"))
return Value(v.y);
- if (var_name == QString("z"))
+ if (v.type == Value::VECTOR && var_name == QString("z"))
return Value(v.z);
+
+ if (v.type == Value::RANGE && var_name == QString("begin"))
+ return Value(v.r_begin);
+ if (v.type == Value::RANGE && var_name == QString("step"))
+ return Value(v.r_step);
+ if (v.type == Value::RANGE && var_name == QString("end"))
+ return Value(v.r_end);
+
+ for (int i=0; i<16; i++) {
+ QString n;
+ n.sprintf("m%d", i+1);
+ if (v.type == Value::MATRIX && var_name == n)
+ return Value(v.m[i]);
+ }
+
return Value();
}
case 'F':
@@ -87,16 +141,33 @@ QString Expression::dump() const
case '%':
case '+':
case '-':
- return QString("(%1%2%3)").arg(children[0]->dump(), QString(type), children[1]->dump());
+ return QString("(%1 %2 %3)").arg(children[0]->dump(), QString(type), children[1]->dump());
+ case '?':
+ return QString("(%1 ? %2 : %3)").arg(children[0]->dump(), children[1]->dump(), children[2]->dump());
case 'I':
return QString("(-%1)").arg(children[0]->dump());
case 'C':
return const_value.dump();
+ case 'R':
+ return QString("[%1 : %2 : %3]").arg(children[0]->dump(), children[1]->dump(), children[2]->dump());
case 'V':
return QString("[%1, %2, %3]").arg(children[0]->dump(), children[1]->dump(), children[2]->dump());
+ case 'M':
+ {
+ QString text = "[";
+ for (int i = 0; i < 16; i++) {
+ if (i % 4 == 0 && i > 0)
+ text += ";";
+ if (i > 0)
+ text += " ";
+ text += children[i]->dump();
+ }
+ text += "]";
+ return text;
+ }
case 'L':
return var_name;
- case 'M':
+ case 'N':
return QString("(%1.%2)").arg(children[0]->dump(), var_name);
case 'F':
{
diff --git a/func.cc b/func.cc
index 9104653..fff9080 100644
--- a/func.cc
+++ b/func.cc
@@ -82,51 +82,51 @@ QString BuiltinFunction::dump(QString indent, QString name) const
Value builtin_sin(const QVector<Value> &args)
{
- if (args[0].is_nan || args[0].is_vector)
- return Value();
- return Value(sin(args[0].x));
+ if (args[0].type == Value::NUMBER)
+ Value(sin(args[0].num));
+ return Value();
}
Value builtin_cos(const QVector<Value> &args)
{
- if (args[0].is_nan || args[0].is_vector)
- return Value();
- return Value(cos(args[0].x));
+ if (args[0].type == Value::NUMBER)
+ Value(cos(args[0].num));
+ return Value();
}
Value builtin_asin(const QVector<Value> &args)
{
- if (args[0].is_nan || args[0].is_vector)
- return Value();
- return Value(asin(args[0].x));
+ if (args[0].type == Value::NUMBER)
+ Value(asin(args[0].num));
+ return Value();
}
Value builtin_acos(const QVector<Value> &args)
{
- if (args[0].is_nan || args[0].is_vector)
- return Value();
- return Value(acos(args[0].x));
+ if (args[0].type == Value::NUMBER)
+ Value(acos(args[0].num));
+ return Value();
}
Value builtin_tan(const QVector<Value> &args)
{
- if (args[0].is_nan || args[0].is_vector)
- return Value();
- return Value(tan(args[0].x));
+ if (args[0].type == Value::NUMBER)
+ Value(tan(args[0].num));
+ return Value();
}
Value builtin_atan(const QVector<Value> &args)
{
- if (args[0].is_nan || args[0].is_vector)
- return Value();
- return Value(atan(args[0].x));
+ if (args[0].type == Value::NUMBER)
+ Value(atan(args[0].num));
+ return Value();
}
Value builtin_atan2(const QVector<Value> &args)
{
- if (args[0].is_nan || args[0].is_vector || args[1].is_nan || args[1].is_vector)
- return Value();
- return Value(atan2(args[0].x, args[1].x));
+ if (args[0].type == Value::NUMBER && args[1].type == Value::NUMBER)
+ Value(atan2(args[0].num, args[1].num));
+ return Value();
}
void initialize_builtin_functions()
diff --git a/lexer.l b/lexer.l
index 20111e6..37dd9b5 100644
--- a/lexer.l
+++ b/lexer.l
@@ -32,10 +32,15 @@ int lexerget_lineno(void);
%x comment
-WS [\n\r\t ]
-
%%
+"module" return TOK_MODULE;
+"function" return TOK_FUNCTION;
+
+"true" return TOK_TRUE;
+"false" return TOK_FALSE;
+"undef" return TOK_UNDEF;
+
[0-9][0-9.]* { parserlval.number = atof(yytext); return TOK_NUMBER; }
[a-zA-Z0-9_]+ { parserlval.text = strdup(yytext); return TOK_ID; }
\"[^"]*\" { parserlval.text = strdup(yytext); return TOK_STRING; }
@@ -43,6 +48,7 @@ WS [\n\r\t ]
"." return '.';
"," return ',';
";" return ';';
+"?" return '?';
":" return ':';
"=" return '=';
"*" return '*';
@@ -57,15 +63,11 @@ WS [\n\r\t ]
"[" return '[';
"]" return ']';
-"module"/{WS} return TOK_MODULE;
-"function"/{WS} return TOK_FUNCTION;
-
+[\n\r\t ]
\/\/[^\n]*\n
"/*" BEGIN(comment);
<comment>"*/" BEGIN(INITIAL);
<comment>.|\n
-{WS}*
-
. { fprintf(stderr, "Unrecognized input character in line %d: %s\n", lexerget_lineno(), yytext); exit(1); }
diff --git a/module.cc b/module.cc
index acc37d6..6c443de 100644
--- a/module.cc
+++ b/module.cc
@@ -28,6 +28,9 @@ AbstractModule::~AbstractModule()
AbstractNode *AbstractModule::evaluate(const Context*, const QVector<QString>&, const QVector<Value>&, const QVector<AbstractNode*> child_nodes) const
{
+ if (child_nodes.size() == 1)
+ return child_nodes[0];
+
AbstractNode *node = new AbstractNode();
foreach (AbstractNode *v, child_nodes)
node->children.append(v);
@@ -120,6 +123,13 @@ AbstractNode *Module::evaluate(const Context *ctx, const QVector<QString> &call_
foreach (AbstractNode *v, child_nodes)
node->children.append(v);
+ if (node->children.size() == 1) {
+ AbstractNode *c = node->children[0];
+ node->children.clear();
+ delete node;
+ return c;
+ }
+
return node;
}
diff --git a/openscad.h b/openscad.h
index 3e65645..48d6c1e 100644
--- a/openscad.h
+++ b/openscad.h
@@ -47,21 +47,37 @@ class AbstractNode;
class Value
{
public:
+ enum type_e {
+ UNDEFINED,
+ BOOL,
+ NUMBER,
+ RANGE,
+ VECTOR,
+ MATRIX,
+ STRING
+ };
+
+ enum type_e type;
+
+ bool b;
+ double num;
double x, y, z;
+ double r_begin;
+ double r_step;
+ double r_end;
+ double m[16];
QString text;
- bool is_vector;
- bool is_range;
- bool is_string;
- bool is_nan;
-
- Value() : x(0), y(0), z(0), is_vector(false), is_range(false), is_string(false), is_nan(true) { }
- Value(const QString &t) : x(0), y(0), z(0), text(t), is_vector(false), is_range(false), is_string(true), is_nan(true) { }
- Value(double v1) : x(v1), y(0), z(0), is_vector(false), is_range(false), is_string(false), is_nan(false) { }
- Value(double v1, double v2, double v3) : x(v1), y(v2), z(v3), is_vector(true), is_range(false), is_string(false), is_nan(false) { }
- Value(const Value &v) : x(v.x), y(v.y), z(v.z), text(v.text), is_vector(v.is_vector), is_range(v.is_range), is_string(v.is_string), is_nan(v.is_nan) { }
- Value(const Value &v1, const Value &v2, const Value &v3);
+ Value();
+ Value(bool v);
+ Value(double v);
+ Value(double v1, double v2, double v3);
+ Value(double m[16]);
+ Value(const QString &t);
+
+ Value(const Value &v);
Value& operator = (const Value &v);
+
Value operator + (const Value &v) const;
Value operator - (const Value &v) const;
Value operator * (const Value &v) const;
@@ -70,6 +86,9 @@ public:
Value inv() const;
QString dump() const;
+
+private:
+ void reset_undef();
};
class Expression
@@ -84,11 +103,14 @@ public:
QVector<QString> call_argnames;
// Math operators: * / % + -
+ // Condition (?: operator): ?
// Invert (prefix '-'): I
// Constant value: C
+ // Create Range: R
// Create Vector: V
+ // Create Matrix: M
// Lookup Variable: L
- // Lookup Member: M
+ // Lookup member per name: N
// Function call: F
char type;
diff --git a/parser.y b/parser.y
index 123845c..cdeaf07 100644
--- a/parser.y
+++ b/parser.y
@@ -56,10 +56,15 @@ public:
%token TOK_MODULE
%token TOK_FUNCTION
+
%token <text> TOK_ID
%token <text> TOK_STRING
%token <number> TOK_NUMBER
+%token TOK_TRUE
+%token TOK_FALSE
+%token TOK_UNDEF
+
%left '+' '-'
%left '*' '/' '%'
%left '.'
@@ -163,6 +168,21 @@ single_module_instantciation:
} ;
expr:
+ TOK_TRUE {
+ $$ = new Expression();
+ $$->type = 'C';
+ $$->const_value = Value(true);
+ } |
+ TOK_FALSE {
+ $$ = new Expression();
+ $$->type = 'C';
+ $$->const_value = Value(false);
+ } |
+ TOK_UNDEF {
+ $$ = new Expression();
+ $$->type = 'C';
+ $$->const_value = Value();
+ } |
TOK_ID {
$$ = new Expression();
$$->type = 'L';
@@ -171,7 +191,7 @@ expr:
} |
expr '.' TOK_ID {
$$ = new Expression();
- $$->type = 'M';
+ $$->type = 'N';
$$->children.append($1);
$$->var_name = QString($3);
free($3);
@@ -187,23 +207,42 @@ expr:
$$->type = 'C';
$$->const_value = Value($1);
} |
- TOK_NUMBER ':' TOK_NUMBER {
+ '[' expr ':' expr ']' {
+ Expression *e_one = new Expression();
+ e_one->type = 'C';
+ e_one->const_value = Value(1.0);
$$ = new Expression();
- $$->type = 'C';
- $$->const_value = Value($1, 1, $3);
- $$->const_value.is_range = true;
+ $$->type = 'R';
+ $$->children.append($2);
+ $$->children.append(e_one);
+ $$->children.append($4);
} |
- TOK_NUMBER ':' TOK_NUMBER ':' TOK_NUMBER {
+ '[' expr ':' expr ':' expr ']' {
$$ = new Expression();
- $$->type = 'C';
- $$->const_value = Value($1, $3, $5);
- $$->const_value.is_range = true;
+ $$->type = 'R';
+ $$->children.append($2);
+ $$->children.append($4);
+ $$->children.append($6);
} |
'[' TOK_NUMBER TOK_NUMBER TOK_NUMBER ']' {
$$ = new Expression();
$$->type = 'C';
$$->const_value = Value($2, $3, $4);
} |
+ '[' TOK_NUMBER TOK_NUMBER TOK_NUMBER TOK_NUMBER ';'
+ TOK_NUMBER TOK_NUMBER TOK_NUMBER TOK_NUMBER ';'
+ TOK_NUMBER TOK_NUMBER TOK_NUMBER TOK_NUMBER ';'
+ TOK_NUMBER TOK_NUMBER TOK_NUMBER TOK_NUMBER ']' {
+ $$ = new Expression();
+ $$->type = 'C';
+ double m[16] = {
+ $2, $3, $4, $5,
+ $7, $8, $9, $10,
+ $12, $13, $14, $15,
+ $17, $18, $19, $20,
+ };
+ $$->const_value = Value(m);
+ } |
'[' expr ',' expr ',' expr ']' {
$$ = new Expression();
$$->type = 'V';
@@ -211,6 +250,29 @@ expr:
$$->children.append($4);
$$->children.append($6);
} |
+ '[' expr ',' expr ',' expr ',' expr ';'
+ expr ',' expr ',' expr ',' expr ';'
+ expr ',' expr ',' expr ',' expr ';'
+ expr ',' expr ',' expr ',' expr ']' {
+ $$ = new Expression();
+ $$->type = 'M';
+ $$->children.append($2);
+ $$->children.append($4);
+ $$->children.append($6);
+ $$->children.append($8);
+ $$->children.append($10);
+ $$->children.append($12);
+ $$->children.append($14);
+ $$->children.append($16);
+ $$->children.append($18);
+ $$->children.append($20);
+ $$->children.append($22);
+ $$->children.append($24);
+ $$->children.append($26);
+ $$->children.append($28);
+ $$->children.append($30);
+ $$->children.append($32);
+ } |
expr '*' expr {
$$ = new Expression();
$$->type = '*';
@@ -252,6 +314,13 @@ expr:
'(' expr ')' {
$$ = $2;
} |
+ expr '?' expr ':' expr {
+ $$ = new Expression();
+ $$->type = '?';
+ $$->children.append($1);
+ $$->children.append($3);
+ $$->children.append($5);
+ } |
TOK_ID '(' arguments_call ')' {
$$ = new Expression();
$$->type = 'F';
diff --git a/primitive.cc b/primitive.cc
index 9f5e7f3..91f84d5 100644
--- a/primitive.cc
+++ b/primitive.cc
@@ -73,24 +73,25 @@ AbstractNode *PrimitiveModule::evaluate(const Context *ctx, const QVector<QStrin
if (type == CUBE) {
Value size = c.lookup_variable("size");
Value center = c.lookup_variable("center");
- if (size.is_vector) {
+ if (size.type == Value::VECTOR) {
node->x = size.x;
node->y = size.y;
node->z = size.z;
- } else if (!size.is_nan) {
- node->x = size.x;
- node->y = size.x;
- node->z = size.x;
}
- if (!center.is_vector && !center.is_nan) {
- node->center = center.x != 0;
+ if (size.type == Value::NUMBER) {
+ node->x = size.num;
+ node->y = size.num;
+ node->z = size.num;
+ }
+ if (center.type == Value::BOOL) {
+ node->center = center.b;
}
}
if (type == SPHERE) {
Value r = c.lookup_variable("r");
- if (!r.is_vector && !r.is_nan) {
- node->r1 = r.x;
+ if (r.type == Value::NUMBER) {
+ node->r1 = r.num;
}
}
@@ -100,21 +101,21 @@ AbstractNode *PrimitiveModule::evaluate(const Context *ctx, const QVector<QStrin
Value r1 = c.lookup_variable("r1");
Value r2 = c.lookup_variable("r2");
Value center = c.lookup_variable("center");
- if (!h.is_vector && !h.is_nan) {
- node->h = h.x;
+ if (h.type == Value::NUMBER) {
+ node->h = h.num;
}
- if (!r.is_vector && !r.is_nan) {
- node->r1 = r.x;
- node->r2 = r.x;
+ if (r.type == Value::NUMBER) {
+ node->r1 = r.num;
+ node->r2 = r.num;
}
- if (!r1.is_vector && !r1.is_nan) {
- node->r1 = r1.x;
+ if (r1.type == Value::NUMBER) {
+ node->r1 = r1.num;
}
- if (!r2.is_vector && !r2.is_nan) {
+ if (r2.type == Value::NUMBER) {
node->r2 = r2.x;
}
- if (!center.is_vector && !center.is_nan) {
- node->center = center.x != 0;
+ if (center.type == Value::BOOL) {
+ node->center = center.b;
}
}
@@ -212,11 +213,11 @@ QString PrimitiveNode::dump(QString indent) const
{
QString text;
if (type == CUBE)
- text.sprintf("cube(size = [%f %f %f], center = %d);\n", x, y, z, center ? 1 : 0);
+ text.sprintf("cube(size = [%f %f %f], center = %s);\n", x, y, z, center ? "true" : "false");
if (type == SPHERE)
text.sprintf("sphere(r = %f);\n", r1);
if (type == CYLINDER)
- text.sprintf("cylinder(h = %f, r1 = %f, r2 = %f, center = %d);\n", h, r1, r2, center ? 1 : 0);
+ text.sprintf("cylinder(h = %f, r1 = %f, r2 = %f, center = %s);\n", h, r1, r2, center ? "true" : "false");
return indent + text;
}
diff --git a/trans.cc b/trans.cc
index b1a5c8d..5f0eca2 100644
--- a/trans.cc
+++ b/trans.cc
@@ -39,7 +39,7 @@ public:
AbstractNode *TransModule::evaluate(const Context*, const QVector<QString>&, const QVector<Value> &call_argvalues, const QVector<AbstractNode*> child_nodes) const
{
TransNode *node = new TransNode();
- if (call_argvalues.size() == 1 && call_argvalues[0].is_vector) {
+ if (call_argvalues.size() == 1 && call_argvalues[0].type == Value::VECTOR) {
node->x = call_argvalues[0].x;
node->y = call_argvalues[0].y;
node->z = call_argvalues[0].z;
diff --git a/value.cc b/value.cc
index 4e866d3..e669ef3 100644
--- a/value.cc
+++ b/value.cc
@@ -20,121 +20,216 @@
#include "openscad.h"
-Value::Value(const Value &v1, const Value &v2, const Value &v3)
-{
- if (v1.is_nan || v1.is_vector)
- goto create_nan;
- if (v2.is_nan || v2.is_vector)
- goto create_nan;
- if (v3.is_nan || v3.is_vector)
- goto create_nan;
-
- x = v1.x;
- y = v2.x;
- z = v3.x;
-
- is_vector = true;
- is_range = false;
- is_string = false;
- is_nan = false;
- return;
-
-create_nan:
- x = 0;
- y = 0;
- z = 0;
+Value::Value()
+{
+ reset_undef();
+}
+
+Value::Value(bool v)
+{
+ reset_undef();
+ type = BOOL;
+ b = v;
+}
+
+Value::Value(double v)
+{
+ reset_undef();
+ type = NUMBER;
+ num = v;
+}
+
+Value::Value(double v1, double v2, double v3)
+{
+ reset_undef();
+ type = VECTOR;
+ x = v1;
+ y = v2;
+ z = v3;
+}
- is_vector = false;
- is_range = false;
- is_string = false;
- is_nan = true;
+Value::Value(double m[16])
+{
+ reset_undef();
+ type = MATRIX;
+ for (int i=0; i<16; i++)
+ this->m[i] = m[i];
+}
+
+Value::Value(const QString &t)
+{
+ reset_undef();
+ type = STRING;
+ text = t;
+}
+
+Value::Value(const Value &v)
+{
+ reset_undef();
+ type = v.type;
+ b = v.b;
+ num = v.num;
+ x = v.x;
+ y = v.y;
+ z = v.z;
+ for (int i=0; i<16; i++)
+ m[i] = v.m[i];
+ text = v.text;
}
Value& Value::operator = (const Value &v)
{
+ reset_undef();
+ type = v.type;
+ b = v.b;
+ num = v.num;
x = v.x;
y = v.y;
z = v.z;
- is_vector = v.is_vector;
- is_nan = v.is_nan;
+ for (int i=0; i<16; i++)
+ m[i] = v.m[i];
+ text = v.text;
return *this;
}
Value Value::operator + (const Value &v) const
{
- if (is_nan || v.is_nan)
- return Value();
- if (is_vector && v.is_vector)
+ if (type == VECTOR && v.type == VECTOR) {
return Value(x + v.x, y + v.y, z + v.z);
- if (!is_vector && !v.is_vector)
- return Value(x + v.x);
+ }
+ if (type == MATRIX && v.type == MATRIX) {
+ double m_[16];
+ for (int i=0; i<16; i++)
+ m_[i] = m[i] + v.m[i];
+ return Value(m);
+ }
+ if (type == NUMBER && v.type == NUMBER) {
+ return Value(num + v.num);
+ }
return Value();
}
Value Value::operator - (const Value &v) const
{
- if (is_nan || v.is_nan)
- return Value();
- if (is_vector && v.is_vector)
- return Value(x - v.x, y - v.y, z - v.z);
- if (!is_vector && !v.is_vector)
- return Value(x - v.x);
+ if (type == VECTOR && v.type == VECTOR) {
+ return Value(x + v.x, y + v.y, z + v.z);
+ }
+ if (type == MATRIX && v.type == MATRIX) {
+ double m_[16];
+ for (int i=0; i<16; i++)
+ m_[i] = m[i] + v.m[i];
+ return Value(m);
+ }
+ if (type == NUMBER && v.type == NUMBER) {
+ return Value(num + v.num);
+ }
return Value();
}
Value Value::operator * (const Value &v) const
{
- if (is_nan || v.is_nan)
- return Value();
- if (is_vector && v.is_vector) {
+ if (type == VECTOR && v.type == VECTOR) {
double nx = (y-v.y)*(z-v.z) - (z-v.z)*(y-v.y);
double ny = (z-v.z)*(x-v.x) - (x-v.x)*(z-v.z);
double nz = (x-v.x)*(y-v.y) - (y-v.y)*(x-v.x);
return Value(nx, ny, nz);
}
- if (is_vector) {
- return Value(x * v.x, y * v.x, z * v.x);
+ if (type == VECTOR && v.type == NUMBER) {
+ return Value(x * v.num, y * v.num, z * v.num);
+ }
+ if (type == NUMBER && v.type == VECTOR) {
+ return Value(num * v.x, num * v.y, num * v.z);
}
- if (v.is_vector) {
- return Value(x * v.x, x * v.y, x * v.z);
+ if (type == NUMBER && v.type == NUMBER) {
+ return Value(num * v.num);
}
- return Value(x * v.x);
+ return Value();
}
Value Value::operator / (const Value &v) const
{
- if (is_nan || v.is_nan || is_vector || v.is_vector)
- return Value();
- return Value(x / v.x);
+ if (type == NUMBER && v.type == NUMBER) {
+ return Value(num / v.num);
+ }
+ return Value();
}
Value Value::operator % (const Value &v) const
{
- if (is_nan || v.is_nan || is_vector || v.is_vector)
- return Value();
- return Value(fmod(x, v.x));
+ if (type == NUMBER && v.type == NUMBER) {
+ return Value(fmod(num, v.num));
+ }
+ return Value();
}
Value Value::inv() const
{
- if (is_nan)
- return Value();
- if (is_vector)
+ if (type == MATRIX) {
+ double m_[16];
+ for (int i=0; i<16; i++)
+ m_[i] = -m[i];
+ return Value(m);
+ }
+ if (type == VECTOR)
return Value(-x, -y, -z);
- return Value(-x);
+ if (type == NUMBER)
+ return Value(-x);
+ return Value();
}
QString Value::dump() const
{
- if (is_nan)
- return QString("NaN");
- if (is_vector) {
+ if (type == STRING) {
+ return QString("\"") + text + QString("\"");
+ }
+ if (type == MATRIX) {
+ QString text = "[";
+ for (int i=0; i<16; i++) {
+ QString t;
+ t.sprintf("%f", m[i]);
+ if (i % 4 == 0 && i > 0)
+ text += ";";
+ if (i > 0)
+ text += " ";
+ text += t;
+ }
+ text += "]";
+ return text;
+ }
+ if (type == VECTOR) {
QString text;
text.sprintf("[%f %f %f]", x, y, z);
return text;
}
- QString text;
- text.sprintf("%f", x);
- return text;
+ if (type == RANGE) {
+ QString text;
+ text.sprintf("[ %f : %f : %f ]", r_begin, r_step, r_end);
+ return text;
+ }
+ if (type == NUMBER) {
+ QString text;
+ text.sprintf("%f", num);
+ return text;
+ }
+ if (type == BOOL) {
+ return QString(b ? "true" : "false");
+ }
+ return QString("undef");
+}
+
+void Value::reset_undef()
+{
+ type = UNDEFINED;
+ b = false;
+ num = 0;
+ r_begin = 0;
+ r_step = 0;
+ r_end = 0;
+ x = 0;
+ y = 0;
+ z = 0;
+ for (int i=0; i<16; i++)
+ m[i] = 0;
+ text = QString();
}
contact: Jan Huwald // Impressum