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();  } | 
