summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorclifford <clifford@b57f626f-c46c-0410-a088-ec61d464b74c>2009-06-21 11:41:11 (GMT)
committerclifford <clifford@b57f626f-c46c-0410-a088-ec61d464b74c>2009-06-21 11:41:11 (GMT)
commite24a87b8a37b8f71be30d99251908a5d80bb8bc7 (patch)
treedaea8c3a9841c723cd550d5d55617edd06f65247
parent0e4681913485cb450493e9a35ae297d88f12b19d (diff)
Clifford Wolf:
Compilation to CSG tree is working now git-svn-id: http://svn.clifford.at/openscad/trunk@6 b57f626f-c46c-0410-a088-ec61d464b74c
-rw-r--r--context.cc6
-rw-r--r--cube.cc81
-rw-r--r--difference.cc71
-rw-r--r--example.scad39
-rw-r--r--intersect.cc71
-rw-r--r--module.cc86
-rw-r--r--openscad.cc40
-rw-r--r--openscad.h45
-rw-r--r--openscad.pro13
-rw-r--r--parser.y3
-rw-r--r--trans.cc80
-rw-r--r--union.cc66
-rw-r--r--value.cc4
13 files changed, 553 insertions, 52 deletions
diff --git a/context.cc b/context.cc
index e75592a..60e19e6 100644
--- a/context.cc
+++ b/context.cc
@@ -55,12 +55,12 @@ Value Context::evaluate_function(QString name, const QVector<QString> &argnames,
return Value();
}
-AbstractNode *Context::evaluate_module(QString name, const QVector<QString> &argnames, const QVector<Value> &argvalues) const
+AbstractNode *Context::evaluate_module(QString name, const QVector<QString> &argnames, const QVector<Value> &argvalues, const QVector<AbstractNode*> child_nodes) const
{
if (modules_p->contains(name))
- return modules_p->value(name)->evaluate(this, argnames, argvalues);
+ return modules_p->value(name)->evaluate(this, argnames, argvalues, child_nodes);
if (parent)
- return parent->evaluate_module(name, argnames, argvalues);
+ return parent->evaluate_module(name, argnames, argvalues, child_nodes);
return NULL;
}
diff --git a/cube.cc b/cube.cc
new file mode 100644
index 0000000..83a07b9
--- /dev/null
+++ b/cube.cc
@@ -0,0 +1,81 @@
+/*
+ * OpenSCAD (www.openscad.at)
+ * Copyright (C) 2009 Clifford Wolf <clifford@clifford.at>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#define INCLUDE_ABSTRACT_NODE_DETAILS
+
+#include "openscad.h"
+
+class CubeModule : public AbstractModule
+{
+public:
+ virtual AbstractNode *evaluate(const Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues, const QVector<AbstractNode*> child_nodes) const;
+};
+
+class CubeNode : public AbstractNode
+{
+public:
+ double x, y, z;
+ virtual CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const;
+ virtual QString dump(QString indent) const;
+};
+
+AbstractNode *CubeModule::evaluate(const Context*, const QVector<QString>&, const QVector<Value> &call_argvalues, const QVector<AbstractNode*> child_nodes) const
+{
+ CubeNode *node = new CubeNode();
+ if (call_argvalues.size() == 1 && call_argvalues[0].is_vector) {
+ node->x = call_argvalues[0].x;
+ node->y = call_argvalues[0].y;
+ node->z = call_argvalues[0].z;
+ } else if (call_argvalues.size() == 1 && !call_argvalues[0].is_nan) {
+ node->x = call_argvalues[0].x;
+ node->y = call_argvalues[0].x;
+ node->z = call_argvalues[0].x;
+ }
+ foreach (AbstractNode *v, child_nodes)
+ delete v;
+ return node;
+}
+
+void register_builtin_cube()
+{
+ builtin_modules["cube"] = new CubeModule();
+}
+
+CGAL_Nef_polyhedron CubeNode::render_cgal_nef_polyhedron() const
+{
+ CGAL_Nef_polyhedron N1(CGAL_Plane(+1, 0, 0, -x/2));
+ CGAL_Nef_polyhedron N2(CGAL_Plane(-1, 0, 0, -x/2));
+ CGAL_Nef_polyhedron N3(CGAL_Plane( 0, +1, 0, -y/2));
+ CGAL_Nef_polyhedron N4(CGAL_Plane( 0, -1, 0, -y/2));
+ CGAL_Nef_polyhedron N5(CGAL_Plane( 0, 0, +1, -z/2));
+ CGAL_Nef_polyhedron N6(CGAL_Plane( 0, 0, -1, -z/2));
+ return N1 * N2 * N3 * N4 * N5 * N6;
+}
+
+QString CubeNode::dump(QString indent) const
+{
+ QString text;
+ if (x == y && y == z)
+ text.sprintf("cube(%f);\n", x);
+ else
+ text.sprintf("cube([%f %f %f]);\n", x, y, z);
+ return indent + text;
+}
+
diff --git a/difference.cc b/difference.cc
new file mode 100644
index 0000000..beeea20
--- /dev/null
+++ b/difference.cc
@@ -0,0 +1,71 @@
+/*
+ * OpenSCAD (www.openscad.at)
+ * Copyright (C) 2009 Clifford Wolf <clifford@clifford.at>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#define INCLUDE_ABSTRACT_NODE_DETAILS
+
+#include "openscad.h"
+
+class DifferenceModule : public AbstractModule
+{
+public:
+ virtual AbstractNode *evaluate(const Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues, const QVector<AbstractNode*> child_nodes) const;
+};
+
+class DifferenceNode : public AbstractNode
+{
+public:
+ virtual CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const;
+ virtual QString dump(QString indent) const;
+};
+
+AbstractNode *DifferenceModule::evaluate(const Context*, const QVector<QString>&, const QVector<Value>&, const QVector<AbstractNode*> child_nodes) const
+{
+ DifferenceNode *node = new DifferenceNode();
+ foreach (AbstractNode *v, child_nodes)
+ node->children.append(v);
+ return node;
+}
+
+CGAL_Nef_polyhedron DifferenceNode::render_cgal_nef_polyhedron() const
+{
+ bool first = true;
+ CGAL_Nef_polyhedron N;
+ foreach (AbstractNode *v, children) {
+ if (first)
+ N = v->render_cgal_nef_polyhedron();
+ else
+ N -= v->render_cgal_nef_polyhedron();
+ }
+ return N;
+}
+
+QString DifferenceNode::dump(QString indent) const
+{
+ QString text = indent + "difference() {\n";
+ foreach (AbstractNode *v, children)
+ text += v->dump(indent + QString("\t"));
+ return text + indent + "}\n";
+}
+
+void register_builtin_difference()
+{
+ builtin_modules["difference"] = new DifferenceModule();
+}
+
diff --git a/example.scad b/example.scad
index 35fa12e..7a80a5d 100644
--- a/example.scad
+++ b/example.scad
@@ -1,20 +1,33 @@
-function r_from_dia(d) = d / 2;
+module test001()
+{
+ function r_from_dia(d) = d / 2;
-module rotcy(rot, r, h) {
- rot(rot) cylinder(r = r, h = h);
-}
+ module rotcy(rot, r, h) {
+ rot(rot) cylinder(r = r, h = h);
+ }
+
+ difference() {
+ sphere(r = r_from_dia(size));
+ rotcy([ 0 0 0], cy_r, cy_h);
+ rotcy([90 0 0], cy_r, cy_h);
+ rotcy([ 0 90 0], cy_r, cy_h);
+ }
-difference() {
- sphere(r = r_from_dia(size));
- rotcy([ 0 0 0], cy_r, cy_h);
- rotcy([90 0 0], cy_r, cy_h);
- rotcy([ 0 90 0], cy_r, cy_h);
+ size = 10;
+ hole = 2;
+
+ cy_r = r_from_dia(hole);
+ cy_h = r_from_dia(size * 1.5);
}
-size = 10;
-hole = 2;
+module test002()
+{
+ difference() {
+ cube(1);
+ trans([0.5, 0.5, 0.5]) cube(1);
+ }
+}
-cy_r = r_from_dia(hole);
-cy_h = r_from_dia(size * 1.5);
+test002();
diff --git a/intersect.cc b/intersect.cc
new file mode 100644
index 0000000..c9743c7
--- /dev/null
+++ b/intersect.cc
@@ -0,0 +1,71 @@
+/*
+ * OpenSCAD (www.openscad.at)
+ * Copyright (C) 2009 Clifford Wolf <clifford@clifford.at>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#define INCLUDE_ABSTRACT_NODE_DETAILS
+
+#include "openscad.h"
+
+class IntersectModule : public AbstractModule
+{
+public:
+ virtual AbstractNode *evaluate(const Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues, const QVector<AbstractNode*> child_nodes) const;
+};
+
+class IntersectNode : public AbstractNode
+{
+public:
+ virtual CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const;
+ virtual QString dump(QString indent) const;
+};
+
+AbstractNode *IntersectModule::evaluate(const Context*, const QVector<QString>&, const QVector<Value>&, const QVector<AbstractNode*> child_nodes) const
+{
+ IntersectNode *node = new IntersectNode();
+ foreach (AbstractNode *v, child_nodes)
+ node->children.append(v);
+ return node;
+}
+
+CGAL_Nef_polyhedron IntersectNode::render_cgal_nef_polyhedron() const
+{
+ bool first = true;
+ CGAL_Nef_polyhedron N;
+ foreach (AbstractNode *v, children) {
+ if (first)
+ N = v->render_cgal_nef_polyhedron();
+ else
+ N *= v->render_cgal_nef_polyhedron();
+ }
+ return N;
+}
+
+QString IntersectNode::dump(QString indent) const
+{
+ QString text = indent + "intersect() {\n";
+ foreach (AbstractNode *v, children)
+ text += v->dump(indent + QString("\t"));
+ return text + indent + "}\n";
+}
+
+void register_builtin_intersect()
+{
+ builtin_modules["intersect"] = new IntersectModule();
+}
+
diff --git a/module.cc b/module.cc
index d8c5f31..ede55d1 100644
--- a/module.cc
+++ b/module.cc
@@ -18,15 +18,20 @@
*
*/
+#define INCLUDE_ABSTRACT_NODE_DETAILS
+
#include "openscad.h"
AbstractModule::~AbstractModule()
{
}
-AbstractNode *AbstractModule::evaluate(const Context*, const QVector<QString>&, const QVector<Value>&) const
+AbstractNode *AbstractModule::evaluate(const Context*, const QVector<QString>&, const QVector<Value>&, const QVector<AbstractNode*> child_nodes) const
{
- return NULL;
+ AbstractNode *node = new AbstractNode();
+ foreach (AbstractNode *v, child_nodes)
+ node->children.append(v);
+ return node;
}
QString AbstractModule::dump(QString indent, QString name) const
@@ -70,15 +75,22 @@ QString ModuleInstanciation::dump(QString indent) const
return text;
}
-AbstractNode *ModuleInstanciation::evaluate(const Context*) const
+AbstractNode *ModuleInstanciation::evaluate(const Context *ctx) const
{
- /* FIXME */
- return NULL;
+ QVector<Value> argvalues;
+ foreach (Expression *v, argexpr) {
+ argvalues.append(v->evaluate(ctx));
+ }
+ QVector<AbstractNode*> child_nodes;
+ foreach (ModuleInstanciation *v, children) {
+ child_nodes.append(v->evaluate(ctx));
+ }
+ return ctx->evaluate_module(modname, argnames, argvalues, child_nodes);
}
Module::~Module()
{
- foreach (Expression *v, assignments)
+ foreach (Expression *v, assignments_expr)
delete v;
foreach (AbstractFunction *v, functions)
delete v;
@@ -88,13 +100,27 @@ Module::~Module()
delete v;
}
-AbstractNode *Module::evaluate(const Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues) const
+AbstractNode *Module::evaluate(const Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues, const QVector<AbstractNode*> child_nodes) const
{
Context c(ctx);
c.args(argnames, argexpr, call_argnames, call_argvalues);
- /* FIXME */
- return NULL;
+ c.functions_p = &functions;
+ c.modules_p = &modules;
+
+ for (int i = 0; i < assignments_var.size(); i++) {
+ c.variables[assignments_var[i]] = assignments_expr[i]->evaluate(&c);
+ }
+
+ AbstractNode *node = new AbstractNode();
+ for (int i = 0; i < children.size(); i++) {
+ node->children.append(children[i]->evaluate(&c));
+ }
+
+ foreach (AbstractNode *v, child_nodes)
+ node->children.append(v);
+
+ return node;
}
QString Module::dump(QString indent, QString name) const
@@ -109,13 +135,6 @@ QString Module::dump(QString indent, QString name) const
}
text += QString(") {\n");
{
- QHashIterator<QString, Expression*> i(assignments);
- while (i.hasNext()) {
- i.next();
- text += QString("%1\t%2 = %3;\n").arg(indent, i.key(), i.value()->dump());
- }
- }
- {
QHashIterator<QString, AbstractFunction*> i(functions);
while (i.hasNext()) {
i.next();
@@ -129,6 +148,9 @@ QString Module::dump(QString indent, QString name) const
text += i.value()->dump(indent + QString("\t"), i.key());
}
}
+ for (int i = 0; i < assignments_var.size(); i++) {
+ text += QString("%1\t%2 = %3;\n").arg(indent, assignments_var[i], assignments_expr[i]->dump());
+ }
for (int i = 0; i < children.size(); i++) {
text += children[i]->dump(indent + QString("\t"));
}
@@ -140,7 +162,15 @@ QHash<QString, AbstractModule*> builtin_modules;
void initialize_builtin_modules()
{
- /* FIXME */
+ builtin_modules["group"] = new AbstractModule();
+
+ register_builtin_union();
+ register_builtin_difference();
+ register_builtin_intersect();
+
+ register_builtin_trans();
+
+ register_builtin_cube();
}
void destroy_builtin_modules()
@@ -150,3 +180,25 @@ void destroy_builtin_modules()
builtin_modules.clear();
}
+AbstractNode::~AbstractNode()
+{
+ foreach (AbstractNode *v, children)
+ delete v;
+}
+
+CGAL_Nef_polyhedron AbstractNode::render_cgal_nef_polyhedron() const
+{
+ CGAL_Nef_polyhedron N;
+ foreach (AbstractNode *v, children)
+ N += v->render_cgal_nef_polyhedron();
+ return N;
+}
+
+QString AbstractNode::dump(QString indent) const
+{
+ QString text = indent + "group() {\n";
+ foreach (AbstractNode *v, children)
+ text += v->dump(indent + QString("\t"));
+ return text + indent + "}\n";
+}
+
diff --git a/openscad.cc b/openscad.cc
index 85e6708..d4a411f 100644
--- a/openscad.cc
+++ b/openscad.cc
@@ -18,8 +18,15 @@
*
*/
+#define INCLUDE_ABSTRACT_NODE_DETAILS
+
#include "openscad.h"
+#include <CGAL/IO/Polyhedron_iostream.h>
+
+#include <fstream>
+#include <iostream>
+
int main()
{
int rc = 0;
@@ -27,18 +34,39 @@ int main()
initialize_builtin_functions();
initialize_builtin_modules();
- Context ctx(NULL);
- ctx.functions_p = &builtin_functions;
- ctx.modules_p = &builtin_modules;
+ Context root_ctx(NULL);
+ root_ctx.functions_p = &builtin_functions;
+ root_ctx.modules_p = &builtin_modules;
AbstractModule *root_module = parse(stdin, 0);
- QString text = root_module->dump("", "**root**");
- printf("%s", text.toAscii().data());
+
+ printf("--- Abstract Syntax Tree ---\n");
+ QString ast_text = root_module->dump("", "**root**");
+ printf("%s", ast_text.toAscii().data());
+
+ AbstractNode *root_node = root_module->evaluate(&root_ctx, QVector<QString>(), QVector<Value>(), QVector<AbstractNode*>());
+
+ printf("--- Compiled CSG Tree ---\n");
+ QString csg_text = root_node->dump("");
+ printf("%s", csg_text.toAscii().data());
+
+ CGAL_Nef_polyhedron N;
+ CGAL_Polyhedron P;
+ N = root_node->render_cgal_nef_polyhedron();
+ N.convert_to_Polyhedron(P);
+
+ std::ofstream outFile("output.off");
+ if (outFile.fail()) {
+ std::cerr << "unable to open output file merged.off for writing!" << std::endl;
+ exit(1);
+ }
+ outFile << P;
+
delete root_module;
destroy_builtin_functions();
destroy_builtin_modules();
- return rc;
+ return rc;
}
diff --git a/openscad.h b/openscad.h
index df89b57..9cafdf4 100644
--- a/openscad.h
+++ b/openscad.h
@@ -140,7 +140,7 @@ class AbstractModule
{
public:
virtual ~AbstractModule();
- virtual AbstractNode *evaluate(const Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues) const;
+ virtual AbstractNode *evaluate(const Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues, const QVector<AbstractNode*> child_nodes) const;
virtual QString dump(QString indent, QString name) const;
};
@@ -166,7 +166,9 @@ public:
QVector<QString> argnames;
QVector<Expression*> argexpr;
- QHash<QString, Expression*> assignments;
+ QVector<QString> assignments_var;
+ QVector<Expression*> assignments_expr;
+
QHash<QString, AbstractFunction*> functions;
QHash<QString, AbstractModule*> modules;
@@ -175,7 +177,7 @@ public:
Module() { }
virtual ~Module();
- virtual AbstractNode *evaluate(const Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues) const;
+ virtual AbstractNode *evaluate(const Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues, const QVector<AbstractNode*> child_nodes) const;
virtual QString dump(QString indent, QString name) const;
};
@@ -183,28 +185,59 @@ extern QHash<QString, AbstractModule*> builtin_modules;
extern void initialize_builtin_modules();
extern void destroy_builtin_modules();
+extern void register_builtin_union();
+extern void register_builtin_difference();
+extern void register_builtin_intersect();
+
+extern void register_builtin_trans();
+
+extern void register_builtin_cube();
+
class Context
{
public:
const Context *parent;
QHash<QString, Value> variables;
- QHash<QString, AbstractFunction*> *functions_p;
- QHash<QString, AbstractModule*> *modules_p;
+ const QHash<QString, AbstractFunction*> *functions_p;
+ const QHash<QString, AbstractModule*> *modules_p;
Context(const Context *parent) : parent(parent) { }
void args(const QVector<QString> &argnames, const QVector<Expression*> &argexpr, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues);
Value lookup_variable(QString name) const;
Value evaluate_function(QString name, const QVector<QString> &argnames, const QVector<Value> &argvalues) const;
- AbstractNode *evaluate_module(QString name, const QVector<QString> &argnames, const QVector<Value> &argvalues) const;
+ AbstractNode *evaluate_module(QString name, const QVector<QString> &argnames, const QVector<Value> &argvalues, const QVector<AbstractNode*> child_nodes) const;
};
+// The CGAL template magic slows down the compilation process by a factor of 5.
+// So we only include the declaration of AbstractNode where it is needed...
+#ifdef INCLUDE_ABSTRACT_NODE_DETAILS
+
+#include <CGAL/Gmpq.h>
+#include <CGAL/Cartesian.h>
+#include <CGAL/Polyhedron_3.h>
+#include <CGAL/Nef_polyhedron_3.h>
+
+typedef CGAL::Cartesian<CGAL::Gmpq> CGAL_Kernel;
+typedef CGAL::Polyhedron_3<CGAL_Kernel> CGAL_Polyhedron;
+typedef CGAL::Nef_polyhedron_3<CGAL_Kernel> CGAL_Nef_polyhedron;
+typedef CGAL_Nef_polyhedron::Aff_transformation_3 CGAL_Aff_transformation;
+typedef CGAL_Nef_polyhedron::Vector_3 CGAL_Vector;
+typedef CGAL_Nef_polyhedron::Plane_3 CGAL_Plane;
+typedef CGAL_Nef_polyhedron::Point_3 CGAL_Point;
+
class AbstractNode
{
public:
QVector<AbstractNode*> children;
+
+ virtual ~AbstractNode();
+ virtual CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const;
+ virtual QString dump(QString indent) const;
};
+#endif /* HIDE_ABSTRACT_NODE_DETAILS */
+
extern AbstractModule *parse(FILE *f, int debug);
#endif
diff --git a/openscad.pro b/openscad.pro
index e914eeb..274f886 100644
--- a/openscad.pro
+++ b/openscad.pro
@@ -2,9 +2,14 @@
CONFIG += qt
TEMPLATE = app
-LEXSOURCES = lexer.l
-YACCSOURCES = parser.y
+LIBS += -lCGAL
-HEADERS = openscad.h
-SOURCES = openscad.cc value.cc expr.cc func.cc module.cc context.cc
+LEXSOURCES += lexer.l
+YACCSOURCES += parser.y
+
+HEADERS += openscad.h
+SOURCES += openscad.cc value.cc expr.cc func.cc module.cc context.cc
+SOURCES += union.cc difference.cc intersect.cc
+SOURCES += trans.cc
+SOURCES += cube.cc
diff --git a/parser.y b/parser.y
index 6a70805..0b7ad8f 100644
--- a/parser.y
+++ b/parser.y
@@ -91,7 +91,8 @@ statement:
module->children.append($1);
} |
TOK_ID '=' expr ';' {
- module->assignments[$1] = $3;
+ module->assignments_var.append($1);
+ module->assignments_expr.append($3);
free($1);
} |
TOK_MODULE TOK_ID '(' arguments_decl ')' {
diff --git a/trans.cc b/trans.cc
new file mode 100644
index 0000000..8697a29
--- /dev/null
+++ b/trans.cc
@@ -0,0 +1,80 @@
+/*
+ * OpenSCAD (www.openscad.at)
+ * Copyright (C) 2009 Clifford Wolf <clifford@clifford.at>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#define INCLUDE_ABSTRACT_NODE_DETAILS
+
+#include "openscad.h"
+
+class TransModule : public AbstractModule
+{
+public:
+ virtual AbstractNode *evaluate(const Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues, const QVector<AbstractNode*> child_nodes) const;
+};
+
+class TransNode : public AbstractNode
+{
+public:
+ double x, y, z;
+ virtual CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const;
+ virtual QString dump(QString indent) const;
+};
+
+AbstractNode *TransModule::evaluate(const Context*, const QVector<QString>&, const QVector<Value> &call_argvalues, const QVector<AbstractNode*> child_nodes) const
+{
+ TransNode *node = new TransNode();
+ if (call_argvalues.size() == 1 && call_argvalues[0].is_vector) {
+ node->x = call_argvalues[0].x;
+ node->y = call_argvalues[0].y;
+ node->z = call_argvalues[0].z;
+ } else {
+ node->x = 0;
+ node->y = 0;
+ node->z = 0;
+ }
+ foreach (AbstractNode *v, child_nodes)
+ node->children.append(v);
+ return node;
+}
+
+CGAL_Nef_polyhedron TransNode::render_cgal_nef_polyhedron() const
+{
+ CGAL_Nef_polyhedron N;
+ foreach (AbstractNode *v, children)
+ N += v->render_cgal_nef_polyhedron();
+ CGAL_Aff_transformation t(CGAL::TRANSLATION, CGAL_Vector(x, y, z));
+ N.transform(t);
+ return N;
+}
+
+QString TransNode::dump(QString indent) const
+{
+ QString text;
+ text.sprintf("trans([%f %f %f])", x, y, z);
+ text = indent + text + " {\n";
+ foreach (AbstractNode *v, children)
+ text += v->dump(indent + QString("\t"));
+ return text + indent + "}\n";
+}
+
+void register_builtin_trans()
+{
+ builtin_modules["trans"] = new TransModule();
+}
+
diff --git a/union.cc b/union.cc
new file mode 100644
index 0000000..2df4d28
--- /dev/null
+++ b/union.cc
@@ -0,0 +1,66 @@
+/*
+ * OpenSCAD (www.openscad.at)
+ * Copyright (C) 2009 Clifford Wolf <clifford@clifford.at>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#define INCLUDE_ABSTRACT_NODE_DETAILS
+
+#include "openscad.h"
+
+class UnionModule : public AbstractModule
+{
+public:
+ virtual AbstractNode *evaluate(const Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues, const QVector<AbstractNode*> child_nodes) const;
+};
+
+class UnionNode : public AbstractNode
+{
+public:
+ virtual CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const;
+ virtual QString dump(QString indent) const;
+};
+
+AbstractNode *UnionModule::evaluate(const Context*, const QVector<QString>&, const QVector<Value>&, const QVector<AbstractNode*> child_nodes) const
+{
+ UnionNode *node = new UnionNode();
+ foreach (AbstractNode *v, child_nodes)
+ node->children.append(v);
+ return node;
+}
+
+CGAL_Nef_polyhedron UnionNode::render_cgal_nef_polyhedron() const
+{
+ CGAL_Nef_polyhedron N;
+ foreach (AbstractNode *v, children)
+ N += v->render_cgal_nef_polyhedron();
+ return N;
+}
+
+QString UnionNode::dump(QString indent) const
+{
+ QString text = indent + "union() {\n";
+ foreach (AbstractNode *v, children)
+ text += v->dump(indent + QString("\t"));
+ return text + indent + "}\n";
+}
+
+void register_builtin_union()
+{
+ builtin_modules["union"] = new UnionModule();
+}
+
diff --git a/value.cc b/value.cc
index 9b4ca2e..4e866d3 100644
--- a/value.cc
+++ b/value.cc
@@ -30,8 +30,8 @@ Value::Value(const Value &v1, const Value &v2, const Value &v3)
goto create_nan;
x = v1.x;
- y = v1.y;
- z = v1.z;
+ y = v2.x;
+ z = v3.x;
is_vector = true;
is_range = false;
contact: Jan Huwald // Impressum