mirror of https://github.com/vitalif/openscad
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-ec61d464b74cstl_dim
parent
a70715ab8c
commit
78244d3289
38
control.cc
38
control.cc
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
19
example.scad
19
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();
|
||||
|
||||
|
|
67
expr.cc
67
expr.cc
|
@ -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
34
func.cc
|
@ -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));
|
||||
|
||||
|
|
18
openscad.h
18
openscad.h
|
@ -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;
|
||||
|
|
86
parser.y
86
parser.y
|
@ -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();
|
||||
|
|
|
@ -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) {
|
||||
|
|
44
transform.cc
44
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],
|
||||
|
|
180
value.cc
180
value.cc
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue