From 221ae1832702367047232bd0f12970f0422a0478 Mon Sep 17 00:00:00 2001 From: clifford Date: Fri, 26 Jun 2009 22:09:50 +0000 Subject: Clifford Wolf: Some housekeeping.. git-svn-id: http://svn.clifford.at/openscad/trunk@28 b57f626f-c46c-0410-a088-ec61d464b74c diff --git a/csg.cc b/csg.cc deleted file mode 100644 index 57899e9..0000000 --- a/csg.cc +++ /dev/null @@ -1,126 +0,0 @@ -/* - * OpenSCAD (www.openscad.at) - * Copyright (C) 2009 Clifford Wolf - * - * 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" - -enum csg_type_e { - UNION, - DIFFERENCE, - INTERSECTION -}; - -class CsgModule : public AbstractModule -{ -public: - csg_type_e type; - CsgModule(csg_type_e type) : type(type) { } - virtual AbstractNode *evaluate(const Context *ctx, const QVector &call_argnames, const QVector &call_argvalues, const QVector child_nodes) const; -}; - -class CsgNode : public AbstractNode -{ -public: - csg_type_e type; - CsgNode(csg_type_e type) : type(type) { } -#ifdef ENABLE_CGAL - virtual CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const; -#endif - CSGTerm *render_csg_term(double m[16]) const; - virtual QString dump(QString indent) const; -}; - -AbstractNode *CsgModule::evaluate(const Context*, const QVector&, const QVector&, const QVector child_nodes) const -{ - if (child_nodes.size() == 1) - return child_nodes[0]; - - CsgNode *node = new CsgNode(type); - foreach (AbstractNode *v, child_nodes) - node->children.append(v); - return node; -} - -#ifdef ENABLE_CGAL - -CGAL_Nef_polyhedron CsgNode::render_cgal_nef_polyhedron() const -{ - bool first; - CGAL_Nef_polyhedron N; - foreach (AbstractNode *v, children) { - if (first) { - N = v->render_cgal_nef_polyhedron(); - first = false; - } else if (type == UNION) { - N += v->render_cgal_nef_polyhedron(); - } else if (type == DIFFERENCE) { - N -= v->render_cgal_nef_polyhedron(); - } else if (type == INTERSECTION) { - N *= v->render_cgal_nef_polyhedron(); - } - } - progress_report(); - return N; -} - -#endif /* ENABLE_CGAL */ - -CSGTerm *CsgNode::render_csg_term(double m[16]) const -{ - CSGTerm *t1 = NULL; - foreach (AbstractNode *v, children) { - CSGTerm *t2 = v->render_csg_term(m); - if (t2 && !t1) { - t1 = t2; - } else if (t2 && t1) { - if (type == UNION) { - t1 = new CSGTerm(CSGTerm::UNION, t1, t2); - } else if (type == DIFFERENCE) { - t1 = new CSGTerm(CSGTerm::DIFFERENCE, t1, t2); - } else if (type == INTERSECTION) { - t1 = new CSGTerm(CSGTerm::INTERSECTION, t1, t2); - } - } - } - return t1; -} - -QString CsgNode::dump(QString indent) const -{ - QString text = indent + QString("n%1: ").arg(idx); - if (type == UNION) - text += "union() {\n"; - if (type == DIFFERENCE) - text += "difference() {\n"; - if (type == INTERSECTION) - text += "intersection() {\n"; - foreach (AbstractNode *v, children) - text += v->dump(indent + QString("\t")); - return text + indent + "}\n"; -} - -void register_builtin_csg() -{ - builtin_modules["union"] = new CsgModule(UNION); - builtin_modules["difference"] = new CsgModule(DIFFERENCE); - builtin_modules["intersection"] = new CsgModule(INTERSECTION); -} - diff --git a/csgops.cc b/csgops.cc new file mode 100644 index 0000000..57899e9 --- /dev/null +++ b/csgops.cc @@ -0,0 +1,126 @@ +/* + * OpenSCAD (www.openscad.at) + * Copyright (C) 2009 Clifford Wolf + * + * 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" + +enum csg_type_e { + UNION, + DIFFERENCE, + INTERSECTION +}; + +class CsgModule : public AbstractModule +{ +public: + csg_type_e type; + CsgModule(csg_type_e type) : type(type) { } + virtual AbstractNode *evaluate(const Context *ctx, const QVector &call_argnames, const QVector &call_argvalues, const QVector child_nodes) const; +}; + +class CsgNode : public AbstractNode +{ +public: + csg_type_e type; + CsgNode(csg_type_e type) : type(type) { } +#ifdef ENABLE_CGAL + virtual CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const; +#endif + CSGTerm *render_csg_term(double m[16]) const; + virtual QString dump(QString indent) const; +}; + +AbstractNode *CsgModule::evaluate(const Context*, const QVector&, const QVector&, const QVector child_nodes) const +{ + if (child_nodes.size() == 1) + return child_nodes[0]; + + CsgNode *node = new CsgNode(type); + foreach (AbstractNode *v, child_nodes) + node->children.append(v); + return node; +} + +#ifdef ENABLE_CGAL + +CGAL_Nef_polyhedron CsgNode::render_cgal_nef_polyhedron() const +{ + bool first; + CGAL_Nef_polyhedron N; + foreach (AbstractNode *v, children) { + if (first) { + N = v->render_cgal_nef_polyhedron(); + first = false; + } else if (type == UNION) { + N += v->render_cgal_nef_polyhedron(); + } else if (type == DIFFERENCE) { + N -= v->render_cgal_nef_polyhedron(); + } else if (type == INTERSECTION) { + N *= v->render_cgal_nef_polyhedron(); + } + } + progress_report(); + return N; +} + +#endif /* ENABLE_CGAL */ + +CSGTerm *CsgNode::render_csg_term(double m[16]) const +{ + CSGTerm *t1 = NULL; + foreach (AbstractNode *v, children) { + CSGTerm *t2 = v->render_csg_term(m); + if (t2 && !t1) { + t1 = t2; + } else if (t2 && t1) { + if (type == UNION) { + t1 = new CSGTerm(CSGTerm::UNION, t1, t2); + } else if (type == DIFFERENCE) { + t1 = new CSGTerm(CSGTerm::DIFFERENCE, t1, t2); + } else if (type == INTERSECTION) { + t1 = new CSGTerm(CSGTerm::INTERSECTION, t1, t2); + } + } + } + return t1; +} + +QString CsgNode::dump(QString indent) const +{ + QString text = indent + QString("n%1: ").arg(idx); + if (type == UNION) + text += "union() {\n"; + if (type == DIFFERENCE) + text += "difference() {\n"; + if (type == INTERSECTION) + text += "intersection() {\n"; + foreach (AbstractNode *v, children) + text += v->dump(indent + QString("\t")); + return text + indent + "}\n"; +} + +void register_builtin_csg() +{ + builtin_modules["union"] = new CsgModule(UNION); + builtin_modules["difference"] = new CsgModule(DIFFERENCE); + builtin_modules["intersection"] = new CsgModule(INTERSECTION); +} + diff --git a/mainwin.cc b/mainwin.cc index 30e90ad..2d482a0 100644 --- a/mainwin.cc +++ b/mainwin.cc @@ -32,10 +32,8 @@ MainWindow::MainWindow(const char *filename) { root_ctx.functions_p = &builtin_functions; root_ctx.modules_p = &builtin_modules; - root_ctx.set_variable("$fs_render", Value(1.0)); - root_ctx.set_variable("$fa_render", Value(12.0)); - root_ctx.set_variable("$fs_preview", Value(1.0)); - root_ctx.set_variable("$fa_preview", Value(12.0)); + root_ctx.set_variable("$fs", Value(1.0)); + root_ctx.set_variable("$fa", Value(12.0)); root_module = NULL; root_node = NULL; diff --git a/openscad.pro b/openscad.pro index d8aa98a..0b0f6f1 100644 --- a/openscad.pro +++ b/openscad.pro @@ -14,8 +14,8 @@ YACCSOURCES += parser.y HEADERS += openscad.h SOURCES += openscad.cc mainwin.cc glview.cc SOURCES += value.cc expr.cc func.cc module.cc context.cc -SOURCES += csgterm.cc polyset.cc csg.cc trans.cc -SOURCES += primitive.cc +SOURCES += csgterm.cc polyset.cc csgops.cc transform.cc +SOURCES += primitives.cc QT += opengl diff --git a/primitive.cc b/primitive.cc deleted file mode 100644 index b2a7a01..0000000 --- a/primitive.cc +++ /dev/null @@ -1,343 +0,0 @@ -/* - * OpenSCAD (www.openscad.at) - * Copyright (C) 2009 Clifford Wolf - * - * 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" - -enum primitive_type_e { - CUBE, - SPHERE, - CYLINDER -}; - -class PrimitiveModule : public AbstractModule -{ -public: - primitive_type_e type; - PrimitiveModule(primitive_type_e type) : type(type) { } - virtual AbstractNode *evaluate(const Context *ctx, const QVector &call_argnames, const QVector &call_argvalues, const QVector child_nodes) const; -}; - -class PrimitiveNode : public AbstractPolyNode -{ -public: - bool center; - double x, y, z, h, r1, r2; - double fs_render, fa_render; - double fs_preview, fa_preview; - primitive_type_e type; - PrimitiveNode(primitive_type_e type) : type(type) { } - virtual PolySet *render_polyset(render_mode_e mode) const; - virtual QString dump(QString indent) const; -}; - -AbstractNode *PrimitiveModule::evaluate(const Context *ctx, const QVector &call_argnames, const QVector &call_argvalues, const QVector child_nodes) const -{ - PrimitiveNode *node = new PrimitiveNode(type); - - node->center = false; - node->x = node->y = node->z = node->h = node->r1 = node->r2 = 1; - - QVector argnames; - QVector argexpr; - - if (type == CUBE) { - argnames = QVector() << "size" << "center"; - } - if (type == SPHERE) { - argnames = QVector() << "r"; - } - if (type == CYLINDER) { - argnames = QVector() << "h" << "r1" << "r2" << "center"; - } - - Context c(ctx); - c.args(argnames, argexpr, call_argnames, call_argvalues); - - node->fs_render = c.lookup_variable("$fs_render").num; - node->fa_render = c.lookup_variable("$fa_render").num; - node->fs_preview = c.lookup_variable("$fs_preview").num; - node->fa_preview = c.lookup_variable("$fa_preview").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; - } - if (center.type == Value::BOOL) { - node->center = center.b; - } - } - - if (type == SPHERE) { - Value r = c.lookup_variable("r"); - if (r.type == Value::NUMBER) { - node->r1 = r.num; - } - } - - 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 center = c.lookup_variable("center"); - if (h.type == Value::NUMBER) { - node->h = h.num; - } - if (r.type == Value::NUMBER) { - node->r1 = r.num; - node->r2 = r.num; - } - if (r1.type == Value::NUMBER) { - node->r1 = r1.num; - } - if (r2.type == Value::NUMBER) { - node->r2 = r2.num; - } - if (center.type == Value::BOOL) { - node->center = center.b; - } - } - - foreach (AbstractNode *v, child_nodes) - delete v; - - return node; -} - -void register_builtin_primitive() -{ - builtin_modules["cube"] = new PrimitiveModule(CUBE); - builtin_modules["sphere"] = new PrimitiveModule(SPHERE); - builtin_modules["cylinder"] = new PrimitiveModule(CYLINDER); -} - -int get_fragments_from_r(double r, double fs, double fa) -{ - return (int)ceil(fmax(fmin(360.0 / fa, r*M_PI / fs), 5)); -} - -PolySet *PrimitiveNode::render_polyset(render_mode_e mode) const -{ - PolySet *p = new PolySet(); - double fs = mode == RENDER_CGAL ? fs_render : fs_preview; - double fa = mode == RENDER_CGAL ? fa_render : fa_preview; - - if (type == CUBE && x > 0 && y > 0 && z > 0) - { - double x1, x2, y1, y2, z1, z2; - if (center) { - x1 = -x/2; - x2 = +x/2; - y1 = -y/2; - y2 = +y/2; - z1 = -z/2; - z2 = +z/2; - } else { - x1 = y1 = z1 = 0; - x2 = x; - y2 = y; - z2 = z; - } - - p->append_poly(); // top - p->append_vertex(x1, y1, z2); - p->append_vertex(x2, y1, z2); - p->append_vertex(x2, y2, z2); - p->append_vertex(x1, y2, z2); - - p->append_poly(); // bottom - p->append_vertex(x1, y2, z1); - p->append_vertex(x2, y2, z1); - p->append_vertex(x2, y1, z1); - p->append_vertex(x1, y1, z1); - - p->append_poly(); // side1 - p->append_vertex(x1, y1, z1); - p->append_vertex(x2, y1, z1); - p->append_vertex(x2, y1, z2); - p->append_vertex(x1, y1, z2); - - p->append_poly(); // side2 - p->append_vertex(x2, y1, z1); - p->append_vertex(x2, y2, z1); - p->append_vertex(x2, y2, z2); - p->append_vertex(x2, y1, z2); - - p->append_poly(); // side3 - p->append_vertex(x2, y2, z1); - p->append_vertex(x1, y2, z1); - p->append_vertex(x1, y2, z2); - p->append_vertex(x2, y2, z2); - - p->append_poly(); // side4 - p->append_vertex(x1, y2, z1); - p->append_vertex(x1, y1, z1); - p->append_vertex(x1, y1, z2); - p->append_vertex(x1, y2, z2); - } - - if (type == SPHERE && r1 > 0) - { - struct point2d { - double x, y; - }; - - struct ring_s { - int fragments; - point2d *points; - double r, z; - }; - - int rings = get_fragments_from_r(r1, 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].points = new point2d[ring[i].fragments]; - for (int j = 0; j < ring[i].fragments; j++) { - phi = (M_PI*2*j) / ring[i].fragments; - ring[i].points[j].x = ring[i].r * cos(phi); - ring[i].points[j].y = ring[i].r * sin(phi); - } - } - - p->append_poly(); - for (int i = 0; i < ring[0].fragments; i++) - p->append_vertex(ring[0].points[i].x, ring[0].points[i].y, ring[0].z); - - for (int i = 0; i < rings-1; i++) { - ring_s *r1 = &ring[i]; - ring_s *r2 = &ring[i+1]; - int r1i = 0, r2i = 0; - while (r1i < r1->fragments || r2i < r2->fragments) - { - if (r1i >= r1->fragments) - goto sphere_next_r2; - if (r2i >= r2->fragments) - goto sphere_next_r1; - if ((double)r1i / r1->fragments < - (double)r2i / r2->fragments) - { -sphere_next_r1: - p->append_poly(); - int r1j = (r1i+1) % r1->fragments; - p->insert_vertex(r1->points[r1i].x, r1->points[r1i].y, r1->z); - p->insert_vertex(r1->points[r1j].x, r1->points[r1j].y, r1->z); - p->insert_vertex(r2->points[r2i % r2->fragments].x, r2->points[r2i % r2->fragments].y, r2->z); - r1i++; - } else { -sphere_next_r2: - p->append_poly(); - int r2j = (r2i+1) % r2->fragments; - p->append_vertex(r2->points[r2i].x, r2->points[r2i].y, r2->z); - p->append_vertex(r2->points[r2j].x, r2->points[r2j].y, r2->z); - p->append_vertex(r1->points[r1i % r1->fragments].x, r1->points[r1i % r1->fragments].y, r1->z); - r2i++; - } - } - } - - p->append_poly(); - for (int i = 0; i < ring[rings-1].fragments; i++) - p->insert_vertex(ring[rings-1].points[i].x, ring[rings-1].points[i].y, ring[rings-1].z); - } - - if (type == CYLINDER && h > 0 && r1 >=0 && r2 >= 0 && (r1 > 0 || r2 > 0)) - { - int fragments = get_fragments_from_r(fmax(r1, r2), fs, fa); - - double z1, z2; - if (center) { - z1 = -h/2; - z2 = +h/2; - } else { - z1 = 0; - z2 = h; - } - - struct point2d { - double x, y; - }; - - point2d circle1[fragments]; - point2d circle2[fragments]; - - for (int i=0; iappend_poly(); - p->insert_vertex(circle1[i].x, circle1[i].y, z1); - p->insert_vertex(circle2[i].x, circle2[i].y, z2); - p->insert_vertex(circle1[j].x, circle1[j].y, z1); - p->append_poly(); - p->insert_vertex(circle2[i].x, circle2[i].y, z2); - p->insert_vertex(circle2[j].x, circle2[j].y, z2); - p->insert_vertex(circle1[j].x, circle1[j].y, z1); - } - - if (r1 > 0) { - p->append_poly(); - for (int i=0; iinsert_vertex(circle1[i].x, circle1[i].y, z1); - } - - if (r2 > 0) { - p->append_poly(); - for (int i=0; iappend_vertex(circle2[i].x, circle2[i].y, z2); - } - } - - return p; -} - -QString PrimitiveNode::dump(QString indent) const -{ - QString text; - if (type == CUBE) - text.sprintf("cube(size = [%f %f %f], center = %s);\n", x, y, z, center ? "true" : "false"); - if (type == SPHERE) - text.sprintf("sphere(r = %f);\n", r1); - if (type == CYLINDER) - text.sprintf("cylinder(h = %f, r1 = %f, r2 = %f, center = %s);\n", h, r1, r2, center ? "true" : "false"); - return indent + QString("n%1: ").arg(idx) + text; -} - diff --git a/primitives.cc b/primitives.cc new file mode 100644 index 0000000..1430d10 --- /dev/null +++ b/primitives.cc @@ -0,0 +1,338 @@ +/* + * OpenSCAD (www.openscad.at) + * Copyright (C) 2009 Clifford Wolf + * + * 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" + +enum primitive_type_e { + CUBE, + SPHERE, + CYLINDER +}; + +class PrimitiveModule : public AbstractModule +{ +public: + primitive_type_e type; + PrimitiveModule(primitive_type_e type) : type(type) { } + virtual AbstractNode *evaluate(const Context *ctx, const QVector &call_argnames, const QVector &call_argvalues, const QVector child_nodes) const; +}; + +class PrimitiveNode : public AbstractPolyNode +{ +public: + bool center; + double x, y, z, h, r1, r2; + double fs, fa; + primitive_type_e type; + PrimitiveNode(primitive_type_e type) : type(type) { } + virtual PolySet *render_polyset(render_mode_e mode) const; + virtual QString dump(QString indent) const; +}; + +AbstractNode *PrimitiveModule::evaluate(const Context *ctx, const QVector &call_argnames, const QVector &call_argvalues, const QVector child_nodes) const +{ + PrimitiveNode *node = new PrimitiveNode(type); + + node->center = false; + node->x = node->y = node->z = node->h = node->r1 = node->r2 = 1; + + QVector argnames; + QVector argexpr; + + if (type == CUBE) { + argnames = QVector() << "size" << "center"; + } + if (type == SPHERE) { + argnames = QVector() << "r"; + } + if (type == CYLINDER) { + argnames = QVector() << "h" << "r1" << "r2" << "center"; + } + + Context c(ctx); + c.args(argnames, argexpr, call_argnames, call_argvalues); + + 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; + } + if (center.type == Value::BOOL) { + node->center = center.b; + } + } + + if (type == SPHERE) { + Value r = c.lookup_variable("r"); + if (r.type == Value::NUMBER) { + node->r1 = r.num; + } + } + + 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 center = c.lookup_variable("center"); + if (h.type == Value::NUMBER) { + node->h = h.num; + } + if (r.type == Value::NUMBER) { + node->r1 = r.num; + node->r2 = r.num; + } + if (r1.type == Value::NUMBER) { + node->r1 = r1.num; + } + if (r2.type == Value::NUMBER) { + node->r2 = r2.num; + } + if (center.type == Value::BOOL) { + node->center = center.b; + } + } + + foreach (AbstractNode *v, child_nodes) + delete v; + + return node; +} + +void register_builtin_primitive() +{ + builtin_modules["cube"] = new PrimitiveModule(CUBE); + builtin_modules["sphere"] = new PrimitiveModule(SPHERE); + builtin_modules["cylinder"] = new PrimitiveModule(CYLINDER); +} + +int get_fragments_from_r(double r, double fs, double fa) +{ + return (int)ceil(fmax(fmin(360.0 / fa, r*M_PI / fs), 5)); +} + +PolySet *PrimitiveNode::render_polyset(render_mode_e mode) const +{ + PolySet *p = new PolySet(); + + if (type == CUBE && x > 0 && y > 0 && z > 0) + { + double x1, x2, y1, y2, z1, z2; + if (center) { + x1 = -x/2; + x2 = +x/2; + y1 = -y/2; + y2 = +y/2; + z1 = -z/2; + z2 = +z/2; + } else { + x1 = y1 = z1 = 0; + x2 = x; + y2 = y; + z2 = z; + } + + p->append_poly(); // top + p->append_vertex(x1, y1, z2); + p->append_vertex(x2, y1, z2); + p->append_vertex(x2, y2, z2); + p->append_vertex(x1, y2, z2); + + p->append_poly(); // bottom + p->append_vertex(x1, y2, z1); + p->append_vertex(x2, y2, z1); + p->append_vertex(x2, y1, z1); + p->append_vertex(x1, y1, z1); + + p->append_poly(); // side1 + p->append_vertex(x1, y1, z1); + p->append_vertex(x2, y1, z1); + p->append_vertex(x2, y1, z2); + p->append_vertex(x1, y1, z2); + + p->append_poly(); // side2 + p->append_vertex(x2, y1, z1); + p->append_vertex(x2, y2, z1); + p->append_vertex(x2, y2, z2); + p->append_vertex(x2, y1, z2); + + p->append_poly(); // side3 + p->append_vertex(x2, y2, z1); + p->append_vertex(x1, y2, z1); + p->append_vertex(x1, y2, z2); + p->append_vertex(x2, y2, z2); + + p->append_poly(); // side4 + p->append_vertex(x1, y2, z1); + p->append_vertex(x1, y1, z1); + p->append_vertex(x1, y1, z2); + p->append_vertex(x1, y2, z2); + } + + if (type == SPHERE && r1 > 0) + { + struct point2d { + double x, y; + }; + + struct ring_s { + int fragments; + point2d *points; + double r, z; + }; + + int rings = get_fragments_from_r(r1, 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].points = new point2d[ring[i].fragments]; + for (int j = 0; j < ring[i].fragments; j++) { + phi = (M_PI*2*j) / ring[i].fragments; + ring[i].points[j].x = ring[i].r * cos(phi); + ring[i].points[j].y = ring[i].r * sin(phi); + } + } + + p->append_poly(); + for (int i = 0; i < ring[0].fragments; i++) + p->append_vertex(ring[0].points[i].x, ring[0].points[i].y, ring[0].z); + + for (int i = 0; i < rings-1; i++) { + ring_s *r1 = &ring[i]; + ring_s *r2 = &ring[i+1]; + int r1i = 0, r2i = 0; + while (r1i < r1->fragments || r2i < r2->fragments) + { + if (r1i >= r1->fragments) + goto sphere_next_r2; + if (r2i >= r2->fragments) + goto sphere_next_r1; + if ((double)r1i / r1->fragments < + (double)r2i / r2->fragments) + { +sphere_next_r1: + p->append_poly(); + int r1j = (r1i+1) % r1->fragments; + p->insert_vertex(r1->points[r1i].x, r1->points[r1i].y, r1->z); + p->insert_vertex(r1->points[r1j].x, r1->points[r1j].y, r1->z); + p->insert_vertex(r2->points[r2i % r2->fragments].x, r2->points[r2i % r2->fragments].y, r2->z); + r1i++; + } else { +sphere_next_r2: + p->append_poly(); + int r2j = (r2i+1) % r2->fragments; + p->append_vertex(r2->points[r2i].x, r2->points[r2i].y, r2->z); + p->append_vertex(r2->points[r2j].x, r2->points[r2j].y, r2->z); + p->append_vertex(r1->points[r1i % r1->fragments].x, r1->points[r1i % r1->fragments].y, r1->z); + r2i++; + } + } + } + + p->append_poly(); + for (int i = 0; i < ring[rings-1].fragments; i++) + p->insert_vertex(ring[rings-1].points[i].x, ring[rings-1].points[i].y, ring[rings-1].z); + } + + if (type == CYLINDER && h > 0 && r1 >=0 && r2 >= 0 && (r1 > 0 || r2 > 0)) + { + int fragments = get_fragments_from_r(fmax(r1, r2), fs, fa); + + double z1, z2; + if (center) { + z1 = -h/2; + z2 = +h/2; + } else { + z1 = 0; + z2 = h; + } + + struct point2d { + double x, y; + }; + + point2d circle1[fragments]; + point2d circle2[fragments]; + + for (int i=0; iappend_poly(); + p->insert_vertex(circle1[i].x, circle1[i].y, z1); + p->insert_vertex(circle2[i].x, circle2[i].y, z2); + p->insert_vertex(circle1[j].x, circle1[j].y, z1); + p->append_poly(); + p->insert_vertex(circle2[i].x, circle2[i].y, z2); + p->insert_vertex(circle2[j].x, circle2[j].y, z2); + p->insert_vertex(circle1[j].x, circle1[j].y, z1); + } + + if (r1 > 0) { + p->append_poly(); + for (int i=0; iinsert_vertex(circle1[i].x, circle1[i].y, z1); + } + + if (r2 > 0) { + p->append_poly(); + for (int i=0; iappend_vertex(circle2[i].x, circle2[i].y, z2); + } + } + + return p; +} + +QString PrimitiveNode::dump(QString indent) const +{ + QString text; + if (type == CUBE) + text.sprintf("cube(size = [%f %f %f], center = %s);\n", x, y, z, center ? "true" : "false"); + if (type == SPHERE) + text.sprintf("sphere(r = %f);\n", r1); + if (type == CYLINDER) + text.sprintf("cylinder(h = %f, r1 = %f, r2 = %f, center = %s);\n", h, r1, r2, center ? "true" : "false"); + return indent + QString("n%1: ").arg(idx) + text; +} + diff --git a/trans.cc b/trans.cc deleted file mode 100644 index 978de53..0000000 --- a/trans.cc +++ /dev/null @@ -1,87 +0,0 @@ -/* - * OpenSCAD (www.openscad.at) - * Copyright (C) 2009 Clifford Wolf - * - * 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 &call_argnames, const QVector &call_argvalues, const QVector child_nodes) const; -}; - -class TransNode : public AbstractNode -{ -public: - double x, y, z; -#ifdef ENABLE_CGAL - virtual CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const; -#endif - virtual QString dump(QString indent) const; -}; - -AbstractNode *TransModule::evaluate(const Context*, const QVector&, const QVector &call_argvalues, const QVector child_nodes) const -{ - TransNode *node = new TransNode(); - if (call_argvalues.size() == 1 && call_argvalues[0].type == Value::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; -} - -#ifdef ENABLE_CGAL - -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); - progress_report(); - return N; -} - -#endif /* ENABLE_CGAL */ - -QString TransNode::dump(QString indent) const -{ - QString text; - text.sprintf("n%d: trans([%f %f %f])", idx, 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/transform.cc b/transform.cc new file mode 100644 index 0000000..978de53 --- /dev/null +++ b/transform.cc @@ -0,0 +1,87 @@ +/* + * OpenSCAD (www.openscad.at) + * Copyright (C) 2009 Clifford Wolf + * + * 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 &call_argnames, const QVector &call_argvalues, const QVector child_nodes) const; +}; + +class TransNode : public AbstractNode +{ +public: + double x, y, z; +#ifdef ENABLE_CGAL + virtual CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const; +#endif + virtual QString dump(QString indent) const; +}; + +AbstractNode *TransModule::evaluate(const Context*, const QVector&, const QVector &call_argvalues, const QVector child_nodes) const +{ + TransNode *node = new TransNode(); + if (call_argvalues.size() == 1 && call_argvalues[0].type == Value::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; +} + +#ifdef ENABLE_CGAL + +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); + progress_report(); + return N; +} + +#endif /* ENABLE_CGAL */ + +QString TransNode::dump(QString indent) const +{ + QString text; + text.sprintf("n%d: trans([%f %f %f])", idx, 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(); +} + -- cgit v0.10.1