diff options
author | clifford <clifford@b57f626f-c46c-0410-a088-ec61d464b74c> | 2009-06-30 18:05:10 (GMT) |
---|---|---|
committer | clifford <clifford@b57f626f-c46c-0410-a088-ec61d464b74c> | 2009-06-30 18:05:10 (GMT) |
commit | 78244d328918b149b86d9b925010e934244d0137 (patch) | |
tree | 54228d6e3480fc309143a4ed3d9deb0d51994f56 | |
parent | a70715ab8c31160f1be2a74d208681c2ad422bbb (diff) |
Clifford Wolf:
Improved value handling
Fixed math functions
Improved control statements
git-svn-id: http://svn.clifford.at/openscad/trunk@39 b57f626f-c46c-0410-a088-ec61d464b74c
-rw-r--r-- | control.cc | 38 | ||||
-rw-r--r-- | example.scad | 19 | ||||
-rw-r--r-- | expr.cc | 67 | ||||
-rw-r--r-- | func.cc | 34 | ||||
-rw-r--r-- | mainwin.cc | 1 | ||||
-rw-r--r-- | openscad.h | 18 | ||||
-rw-r--r-- | parser.y | 86 | ||||
-rw-r--r-- | primitives.cc | 35 | ||||
-rw-r--r-- | transform.cc | 44 | ||||
-rw-r--r-- | value.cc | 176 |
10 files changed, 273 insertions, 245 deletions
@@ -23,6 +23,7 @@ #include "openscad.h" enum control_type_e { + ECHO, ASSIGN, FOR, IF @@ -43,9 +44,24 @@ void for_eval(AbstractNode *node, int l, const QVector<QString> &call_argnames, Value it_values = call_argvalues[l]; Context c(arg_context); if (it_values.type == Value::RANGE) { - for (double i = it_values.r_begin; i <= it_values.r_end; i += it_values.r_step) { - fprintf(stderr, "%f\n", i); - c.set_variable(it_name, Value(i)); + double range_begin = it_values.range_begin; + double range_end = it_values.range_end; + double range_step = it_values.range_step; + if (range_end < range_begin) { + double t = range_begin; + range_begin = range_end; + range_end = t; + } + if (range_step > 0 && (range_begin-range_end)/range_step < 10000) { + for (double i = range_begin; i <= range_end; i += range_step) { + c.set_variable(it_name, Value(i)); + for_eval(node, l+1, call_argnames, call_argvalues, arg_children, &c); + } + } + } + else if (it_values.type == Value::VECTOR) { + for (int i = 0; i < it_values.vec.size(); i++) { + c.set_variable(it_name, *it_values.vec[i]); for_eval(node, l+1, call_argnames, call_argvalues, arg_children, &c); } } @@ -65,6 +81,19 @@ AbstractNode *ControlModule::evaluate(const Context*, const QVector<QString> &ca { AbstractNode *node = new AbstractNode(); + if (type == ECHO) + { + QString msg = QString("ECHO: "); + for (int i = 0; i < call_argnames.size(); i++) { + if (i > 0) + msg += QString(", "); + if (!call_argnames[i].isEmpty()) + msg += call_argnames[i] + QString(" = "); + msg += call_argvalues[i].dump(); + } + PRINT(msg); + } + if (type == ASSIGN) { Context c(arg_context); @@ -99,8 +128,9 @@ AbstractNode *ControlModule::evaluate(const Context*, const QVector<QString> &ca void register_builtin_control() { + builtin_modules["echo"] = new ControlModule(ECHO); builtin_modules["assign"] = new ControlModule(ASSIGN); - // builtin_modules["for"] = new ControlModule(FOR); + builtin_modules["for"] = new ControlModule(FOR); builtin_modules["if"] = new ControlModule(IF); } diff --git a/example.scad b/example.scad index 7df8277..c55798a 100644 --- a/example.scad +++ b/example.scad @@ -66,4 +66,23 @@ module test004() } } +module test005() +{ + translate([0 0 -120]) { + difference() { + cylinder(h = 50, r = 100); + translate([0 0 10]) cylinder(h = 50, r = 80); + translate([100 0 35]) cube(50, center = true); + } + for (i = [0:5]) { + echo(360*i/6, sin(360*i/6)*80, cos(360*i/6)*80); + translate([sin(360*i/6)*80, cos(360*i/6)*80, 0 ]) + cylinder(h = 200, r=10); + } + translate([0 0 200]) + cylinder(h = 80, r1 = 120, r2 = 0); + } +} + test001(); + @@ -23,12 +23,15 @@ Expression::Expression() { type = 0; + const_value = NULL; } Expression::~Expression() { for (int i=0; i < children.size(); i++) delete children[i]; + if (const_value) + delete const_value; } Value Expression::evaluate(const Context *context) const @@ -55,7 +58,7 @@ Value Expression::evaluate(const Context *context) const case 'I': return children[0]->evaluate(context).inv(); case 'C': - return const_value; + return *const_value; case 'R': { Value v1 = children[0]->evaluate(context); @@ -64,32 +67,20 @@ Value Expression::evaluate(const Context *context) const 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; + r.range_begin = v1.num; + r.range_step = v2.num; + r.range_end = v3.num; return r; } return Value(); } case 'V': { - 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 == 15 ? 15 : (i*4) % 15] = v.num; - } - return Value(m); + Value v; + v.type = Value::VECTOR; + for (int i = 0; i < children.size(); i++) + v.vec.append(new Value(children[i]->evaluate(context))); + return v; } case 'L': return context->lookup_variable(var_name); @@ -98,25 +89,18 @@ Value Expression::evaluate(const Context *context) const Value v = children[0]->evaluate(context); if (v.type == Value::VECTOR && var_name == QString("x")) - return Value(v.x); + return *v.vec[0]; if (v.type == Value::VECTOR && var_name == QString("y")) - return Value(v.y); + return *v.vec[1]; if (v.type == Value::VECTOR && var_name == QString("z")) - return Value(v.z); + return *v.vec[2]; if (v.type == Value::RANGE && var_name == QString("begin")) - return Value(v.r_begin); + return Value(v.range_begin); if (v.type == Value::RANGE && var_name == QString("step")) - return Value(v.r_step); + return Value(v.range_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(v.range_end); return Value(); } @@ -147,24 +131,11 @@ QString Expression::dump() const case 'I': return QString("(-%1)").arg(children[0]->dump()); case 'C': - return const_value.dump(); + 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 'N': @@ -80,52 +80,72 @@ QString BuiltinFunction::dump(QString indent, QString name) const return QString("%1builtin function %2();\n").arg(indent, name); } +static double deg2rad(double x) +{ + while (x < 0.0) + x += 360.0; + while (x >= 360.0) + x -= 360.0; + x = x * M_PI * 2.0 / 360.0; + return x; +} + +static double rad2deg(double x) +{ + x = x * 360.0 / (M_PI * 2.0); + while (x < 0.0) + x += 360.0; + while (x >= 360.0) + x -= 360.0; + return x; +} + Value builtin_sin(const QVector<Value> &args) { if (args[0].type == Value::NUMBER) - Value(sin(args[0].num)); + return Value(sin(deg2rad(args[0].num))); return Value(); } Value builtin_cos(const QVector<Value> &args) { if (args[0].type == Value::NUMBER) - Value(cos(args[0].num)); + return Value(cos(deg2rad(args[0].num))); return Value(); } Value builtin_asin(const QVector<Value> &args) { if (args[0].type == Value::NUMBER) - Value(asin(args[0].num)); + return Value(rad2deg(asin(args[0].num))); return Value(); } Value builtin_acos(const QVector<Value> &args) { if (args[0].type == Value::NUMBER) - Value(acos(args[0].num)); + return Value(rad2deg(acos(args[0].num))); return Value(); } Value builtin_tan(const QVector<Value> &args) { if (args[0].type == Value::NUMBER) - Value(tan(args[0].num)); + return Value(tan(deg2rad(args[0].num))); return Value(); } Value builtin_atan(const QVector<Value> &args) { if (args[0].type == Value::NUMBER) - Value(atan(args[0].num)); + return Value(rad2deg(atan(args[0].num))); return Value(); } Value builtin_atan2(const QVector<Value> &args) { if (args[0].type == Value::NUMBER && args[1].type == Value::NUMBER) - Value(atan2(args[0].num, args[1].num)); + return Value(rad2deg(atan2(args[0].num, args[1].num))); return Value(); } @@ -35,6 +35,7 @@ MainWindow::MainWindow(const char *filename) { root_ctx.functions_p = &builtin_functions; root_ctx.modules_p = &builtin_modules; + root_ctx.set_variable("$fn", Value(0.0)); root_ctx.set_variable("$fs", Value(1.0)); root_ctx.set_variable("$fa", Value(12.0)); @@ -88,18 +88,17 @@ public: bool b; double num; - double x, y, z; - double r_begin; - double r_step; - double r_end; - double m[16]; + QVector<Value*> vec; + double range_begin; + double range_step; + double range_end; QString text; Value(); + ~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); @@ -112,6 +111,9 @@ public: Value operator % (const Value &v) const; Value inv() const; + bool getnum(double &v) const; + bool getv3(double &x, double &y, double &z) const; + QString dump() const; private: @@ -123,7 +125,7 @@ class Expression public: QVector<Expression*> children; - Value const_value; + Value *const_value; QString var_name; QString call_funcname; @@ -48,6 +48,7 @@ public: %union { char *text; double number; + class Value *value; class Expression *expr; class ModuleInstanciation *inst; class ArgContainer *arg; @@ -70,6 +71,8 @@ public: %left '.' %type <expr> expr +%type <value> vector_const +%type <expr> vector_expr %type <inst> module_instantciation %type <inst> module_instantciation_list @@ -171,17 +174,17 @@ expr: TOK_TRUE { $$ = new Expression(); $$->type = 'C'; - $$->const_value = Value(true); + $$->const_value = new Value(true); } | TOK_FALSE { $$ = new Expression(); $$->type = 'C'; - $$->const_value = Value(false); + $$->const_value = new Value(false); } | TOK_UNDEF { $$ = new Expression(); $$->type = 'C'; - $$->const_value = Value(); + $$->const_value = new Value(); } | TOK_ID { $$ = new Expression(); @@ -199,18 +202,18 @@ expr: TOK_STRING { $$ = new Expression(); $$->type = 'C'; - $$->const_value = Value(QString($1)); + $$->const_value = new Value(QString($1)); free($1); } | TOK_NUMBER { $$ = new Expression(); $$->type = 'C'; - $$->const_value = Value($1); + $$->const_value = new Value($1); } | '[' expr ':' expr ']' { Expression *e_one = new Expression(); e_one->type = 'C'; - e_one->const_value = Value(1.0); + e_one->const_value = new Value(1.0); $$ = new Expression(); $$->type = 'R'; $$->children.append($2); @@ -224,54 +227,19 @@ expr: $$->children.append($4); $$->children.append($6); } | - '[' TOK_NUMBER TOK_NUMBER TOK_NUMBER ']' { + '[' ']' { $$ = new Expression(); $$->type = 'C'; - $$->const_value = Value($2, $3, $4); + $$->const_value = new Value(); + $$->const_value->type = Value::VECTOR; } | - '[' 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 ']' { + '[' vector_const ']' { $$ = 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'; - $$->children.append($2); - $$->children.append($4); - $$->children.append($6); + $$->const_value = $2; } | - '[' 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); + '[' vector_expr ']' { + $$ = $2; } | expr '*' expr { $$ = new Expression(); @@ -331,6 +299,28 @@ expr: delete $3; } ; +vector_const: + TOK_NUMBER { + $$ = new Value(); + $$->type = Value::VECTOR; + $$->vec.append(new Value($1)); + } | + vector_const TOK_NUMBER { + $$ = $1; + $$->vec.append(new Value($2)); + } ; + +vector_expr: + expr { + $$ = new Expression(); + $$->type = 'V'; + $$->children.append($1); + } | + vector_expr ',' expr { + $$ = $1; + $$->children.append($3); + } ; + arguments_decl: /* empty */ { $$ = new ArgsContainer(); diff --git a/primitives.cc b/primitives.cc index 59c5938..ae43a58 100644 --- a/primitives.cc +++ b/primitives.cc @@ -41,7 +41,7 @@ class PrimitiveNode : public AbstractPolyNode public: bool center; double x, y, z, h, r1, r2; - double fs, fa; + double fn, fs, fa; primitive_type_e type; PrimitiveNode(primitive_type_e type) : type(type) { } virtual PolySet *render_polyset(render_mode_e mode) const; @@ -71,22 +71,17 @@ AbstractNode *PrimitiveModule::evaluate(const Context *ctx, const QVector<QStrin Context c(ctx); c.args(argnames, argexpr, call_argnames, call_argvalues); + node->fn = c.lookup_variable("$fn").num; node->fs = c.lookup_variable("$fs").num; node->fa = c.lookup_variable("$fa").num; if (type == CUBE) { Value size = c.lookup_variable("size"); Value center = c.lookup_variable("center"); - if (size.type == Value::VECTOR) { - node->x = size.x; - node->y = size.y; - node->z = size.z; - } - if (size.type == Value::NUMBER) { - node->x = size.num; - node->y = size.num; - node->z = size.num; - } + size.getnum(node->x); + size.getnum(node->y); + size.getnum(node->z); + size.getv3(node->x, node->y, node->z); if (center.type == Value::BOOL) { node->center = center.b; } @@ -101,9 +96,11 @@ AbstractNode *PrimitiveModule::evaluate(const Context *ctx, const QVector<QStrin if (type == CYLINDER) { Value h = c.lookup_variable("h"); - Value r = c.lookup_variable("r"); - Value r1 = c.lookup_variable("r1"); - Value r2 = c.lookup_variable("r2"); + Value r, r1, r2; + r1 = c.lookup_variable("r1"); + r2 = c.lookup_variable("r2"); + if (r1.type != Value::NUMBER && r1.type != Value::NUMBER) + r = c.lookup_variable("r"); Value center = c.lookup_variable("center"); if (h.type == Value::NUMBER) { node->h = h.num; @@ -133,8 +130,10 @@ void register_builtin_primitives() builtin_modules["cylinder"] = new PrimitiveModule(CYLINDER); } -int get_fragments_from_r(double r, double fs, double fa) +int get_fragments_from_r(double r, double fn, double fs, double fa) { + if (fn > 0.0) + return fn; return (int)ceil(fmax(fmin(360.0 / fa, r*M_PI / fs), 5)); } @@ -208,14 +207,14 @@ PolySet *PrimitiveNode::render_polyset(render_mode_e) const double r, z; }; - int rings = get_fragments_from_r(r1, fs, fa); + int rings = get_fragments_from_r(r1, fn, fs, fa); ring_s ring[rings]; for (int i = 0; i < rings; i++) { double phi = (M_PI * (i + 0.5)) / rings; ring[i].r = r1 * sin(phi); ring[i].z = r1 * cos(phi); - ring[i].fragments = get_fragments_from_r(ring[i].r, fs, fa); + ring[i].fragments = get_fragments_from_r(ring[i].r, fn, fs, fa); ring[i].points = new point2d[ring[i].fragments]; for (int j = 0; j < ring[i].fragments; j++) { phi = (M_PI*2*j) / ring[i].fragments; @@ -267,7 +266,7 @@ sphere_next_r2: if (type == CYLINDER && h > 0 && r1 >=0 && r2 >= 0 && (r1 > 0 || r2 > 0)) { - int fragments = get_fragments_from_r(fmax(r1, r2), fs, fa); + int fragments = get_fragments_from_r(fmax(r1, r2), fn, fs, fa); double z1, z2; if (center) { diff --git a/transform.cc b/transform.cc index de29aaf..6c73993 100644 --- a/transform.cc +++ b/transform.cc @@ -78,16 +78,10 @@ AbstractNode *TransformModule::evaluate(const Context *ctx, const QVector<QStrin if (type == SCALE) { Value v = c.lookup_variable("v"); - if (v.type == Value::NUMBER) { - node->m[0] = v.num; - node->m[5] = v.num; - node->m[10] = v.num; - } - if (v.type == Value::VECTOR) { - node->m[0] = v.x; - node->m[5] = v.y; - node->m[10] = v.z; - } + v.getnum(node->m[0]); + v.getnum(node->m[5]); + v.getnum(node->m[10]); + v.getv3(node->m[0], node->m[5], node->m[10]); } if (type == ROTATE) { @@ -95,15 +89,14 @@ AbstractNode *TransformModule::evaluate(const Context *ctx, const QVector<QStrin Value val_v = c.lookup_variable("v"); double a = 0, x = 0, y = 0, z = 1; - if (val_a.type == Value::NUMBER) { - a = val_a.num; - } + val_a.getnum(a); - if (val_v.type == Value::VECTOR) { - if (val_v.x != 0.0 || val_v.y != 0.0 || val_v.z != 0.0) { - x = val_v.x; y = val_v.y; z = val_v.z; + if (val_v.getv3(x, y, z)) { + if (x != 0.0 || y != 0.0 || z != 0.0) { double sn = 1.0 / sqrt(x*x + y*y + z*z); - x *= sn; y *= sn; z *= sn; + x *= sn, y *= sn, z *= sn; + } else { + x = 0, y = 0, z = 1; } } @@ -125,18 +118,17 @@ AbstractNode *TransformModule::evaluate(const Context *ctx, const QVector<QStrin if (type == TRANSLATE) { Value v = c.lookup_variable("v"); - if (v.type == Value::VECTOR) { - node->m[12] = v.x; - node->m[13] = v.y; - node->m[14] = v.z; - } + v.getv3(node->m[12], node->m[13], node->m[14]); } if (type == MULTMATRIX) { Value v = c.lookup_variable("m"); - if (v.type == Value::MATRIX) { - for (int i = 0; i < 16; i++) - node->m[i] = v.m[i]; + if (v.type == Value::VECTOR) { + for (int i = 0; i < 16; i++) { + int x = i / 4, y = i % 4; + if (y < v.vec.size() && v.vec[y]->type == Value::VECTOR && x < v.vec[y]->vec.size()) + v.vec[y]->vec[x]->getnum(node->m[i]); + } } } @@ -196,7 +188,7 @@ CSGTerm *TransformNode::render_csg_term(double c[16]) const QString TransformNode::dump(QString indent) const { QString text; - text.sprintf("n%d: multmatrix([%f %f %f %f; %f %f %f %f; %f %f %f %f; %f %f %f %f])", idx, + text.sprintf("n%d: multmatrix([[%f %f %f %f], [%f %f %f %f], [%f %f %f %f], [%f %f %f %f]])", idx, m[0], m[4], m[ 8], m[12], m[1], m[5], m[ 9], m[13], m[2], m[6], m[10], m[14], @@ -25,6 +25,13 @@ Value::Value() reset_undef(); } +Value::~Value() +{ + for (int i = 0; i < vec.size(); i++) + delete vec[i]; + vec.clear(); +} + Value::Value(bool v) { reset_undef(); @@ -39,23 +46,6 @@ Value::Value(double v) num = v; } -Value::Value(double v1, double v2, double v3) -{ - reset_undef(); - type = VECTOR; - x = v1; - y = v2; - z = v3; -} - -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(); @@ -65,16 +55,7 @@ Value::Value(const QString &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; + *this = v; } Value& Value::operator = (const Value &v) @@ -83,11 +64,11 @@ Value& Value::operator = (const Value &v) 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]; + for (int i = 0; i < v.vec.size(); i++) + vec.append(new Value(*v.vec[i])); + range_begin = v.range_begin; + range_step = v.range_step; + range_end = v.range_end; text = v.text; return *this; } @@ -95,13 +76,11 @@ Value& Value::operator = (const Value &v) Value Value::operator + (const Value &v) const { 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); + Value r; + r.type = VECTOR; + for (int i = 0; i < vec.size() && i < v.vec.size(); i++) + r.vec.append(new Value(*vec[i] + *v.vec[i])); + return r; } if (type == NUMBER && v.type == NUMBER) { return Value(num + v.num); @@ -112,13 +91,11 @@ Value Value::operator + (const Value &v) const Value Value::operator - (const Value &v) const { 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); + Value r; + r.type = VECTOR; + for (int i = 0; i < vec.size() && i < v.vec.size(); i++) + r.vec.append(new Value(*vec[i] - *v.vec[i])); + return r; } if (type == NUMBER && v.type == NUMBER) { return Value(num + v.num); @@ -128,17 +105,19 @@ Value Value::operator - (const Value &v) const Value Value::operator * (const Value &v) const { - 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 (type == VECTOR && v.type == NUMBER) { - return Value(x * v.num, y * v.num, z * v.num); + Value r; + r.type = VECTOR; + for (int i = 0; i < vec.size(); i++) + r.vec.append(new Value(*vec[i] * v)); + return r; } if (type == NUMBER && v.type == VECTOR) { - return Value(num * v.x, num * v.y, num * v.z); + Value r; + r.type = VECTOR; + for (int i = 0; i < v.vec.size(); i++) + r.vec.append(new Value(v * *v.vec[i])); + return r; } if (type == NUMBER && v.type == NUMBER) { return Value(num * v.num); @@ -148,6 +127,20 @@ Value Value::operator * (const Value &v) const Value Value::operator / (const Value &v) const { + if (type == VECTOR && v.type == NUMBER) { + Value r; + r.type = VECTOR; + for (int i = 0; i < vec.size(); i++) + r.vec.append(new Value(*vec[i] / v)); + return r; + } + if (type == NUMBER && v.type == VECTOR) { + Value r; + r.type = VECTOR; + for (int i = 0; i < v.vec.size(); i++) + r.vec.append(new Value(v / *v.vec[i])); + return r; + } if (type == NUMBER && v.type == NUMBER) { return Value(num / v.num); } @@ -164,46 +157,59 @@ Value Value::operator % (const Value &v) const Value Value::inv() const { - if (type == MATRIX) { - double m_[16]; - for (int i=0; i<16; i++) - m_[i] = -m[i]; - return Value(m); + if (type == VECTOR) { + Value r; + r.type = VECTOR; + for (int i = 0; i < vec.size(); i++) + r.vec.append(new Value(vec[i]->inv())); + return r; } - if (type == VECTOR) - return Value(-x, -y, -z); if (type == NUMBER) - return Value(-x); + return Value(-num); return Value(); } +bool Value::getnum(double &v) const +{ + if (type != NUMBER) + return false; + v = num; + return true; +} + +bool Value::getv3(double &x, double &y, double &z) const +{ + if (type != VECTOR || vec.size() != 3) + return false; + if (vec[0]->type != NUMBER) + return false; + if (vec[1]->type != NUMBER) + return false; + if (vec[2]->type != NUMBER) + return false; + x = vec[0]->num; + y = vec[1]->num; + z = vec[2]->num; + return true; +} + QString Value::dump() const { if (type == STRING) { return QString("\"") + text + QString("\""); } - if (type == MATRIX) { + if (type == VECTOR) { QString text = "["; - for (int i=0; i<16; i++) { - QString t; - t.sprintf("%f", m[i == 15 ? 15 : (i*4) % 15]); - if (i % 4 == 0 && i > 0) - text += ";"; + for (int i = 0; i < vec.size(); i++) { if (i > 0) - text += " "; - text += t; + text += ", "; + text += vec[i]->dump(); } - text += "]"; - return text; - } - if (type == VECTOR) { - QString text; - text.sprintf("[%f %f %f]", x, y, z); - return text; + return text + "]"; } if (type == RANGE) { QString text; - text.sprintf("[ %f : %f : %f ]", r_begin, r_step, r_end); + text.sprintf("[ %f : %f : %f ]", range_begin, range_step, range_end); return text; } if (type == NUMBER) { @@ -222,14 +228,12 @@ 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; + for (int i = 0; i < vec.size(); i++) + delete vec[i]; + vec.clear(); + range_begin = 0; + range_step = 0; + range_end = 0; text = QString(); } |