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
stl_dim
clifford 2009-06-30 18:05:10 +00:00
parent a70715ab8c
commit 78244d3289
10 changed files with 275 additions and 247 deletions

View File

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

View File

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

67
expr.cc
View File

@ -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':

34
func.cc
View File

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

View File

@ -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));

View File

@ -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;

View File

@ -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);
$$->const_value = $2;
} |
'[' expr ',' expr ',' expr ']' {
$$ = new Expression();
$$->type = 'V';
$$->children.append($2);
$$->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);
'[' 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();

View File

@ -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) {

View File

@ -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],

180
value.cc
View File

@ -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) {
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 += ";";
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 = "[";
for (int i = 0; i < vec.size(); i++) {
if (i > 0)
text += ", ";
text += vec[i]->dump();
}
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();
}