summaryrefslogtreecommitdiff
path: root/primitives.cc
diff options
context:
space:
mode:
authorkintel <kintel@b57f626f-c46c-0410-a088-ec61d464b74c>2010-01-30 04:17:05 (GMT)
committerkintel <kintel@b57f626f-c46c-0410-a088-ec61d464b74c>2010-01-30 04:17:05 (GMT)
commit6940d171812565209efe679a5d923417c3f47d4a (patch)
tree2a05d2f8865ff1127f854db41bf31143f64ccf2d /primitives.cc
parent2b19f33ee1ddce246c2bfe0a05fe379d0117a741 (diff)
reorganized file structure layout. more to follow...
git-svn-id: http://svn.clifford.at/openscad/trunk@364 b57f626f-c46c-0410-a088-ec61d464b74c
Diffstat (limited to 'primitives.cc')
-rw-r--r--primitives.cc529
1 files changed, 0 insertions, 529 deletions
diff --git a/primitives.cc b/primitives.cc
deleted file mode 100644
index 2f50578..0000000
--- a/primitives.cc
+++ /dev/null
@@ -1,529 +0,0 @@
-/*
- * 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"
-
-enum primitive_type_e {
- CUBE,
- SPHERE,
- CYLINDER,
- POLYHEDRON,
- SQUARE,
- CIRCLE,
- POLYGON
-};
-
-class PrimitiveModule : public AbstractModule
-{
-public:
- primitive_type_e type;
- PrimitiveModule(primitive_type_e type) : type(type) { }
- virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst) const;
-};
-
-class PrimitiveNode : public AbstractPolyNode
-{
-public:
- bool center;
- double x, y, z, h, r1, r2;
- double fn, fs, fa;
- primitive_type_e type;
- int convexity;
- Value points, paths, triangles;
- PrimitiveNode(const ModuleInstantiation *mi, primitive_type_e type) : AbstractPolyNode(mi), type(type) { }
- virtual PolySet *render_polyset(render_mode_e mode) const;
- virtual QString dump(QString indent) const;
-};
-
-AbstractNode *PrimitiveModule::evaluate(const Context *ctx, const ModuleInstantiation *inst) const
-{
- PrimitiveNode *node = new PrimitiveNode(inst, type);
-
- node->center = false;
- node->x = node->y = node->z = node->h = node->r1 = node->r2 = 1;
-
- QVector<QString> argnames;
- QVector<Expression*> argexpr;
-
- if (type == CUBE) {
- argnames = QVector<QString>() << "size" << "center";
- }
- if (type == SPHERE) {
- argnames = QVector<QString>() << "r";
- }
- if (type == CYLINDER) {
- argnames = QVector<QString>() << "h" << "r1" << "r2" << "center";
- }
- if (type == POLYHEDRON) {
- argnames = QVector<QString>() << "points" << "triangles" << "convexity";
- }
- if (type == SQUARE) {
- argnames = QVector<QString>() << "size" << "center";
- }
- if (type == CIRCLE) {
- argnames = QVector<QString>() << "r";
- }
- if (type == POLYGON) {
- argnames = QVector<QString>() << "points" << "paths" << "convexity";
- }
-
- Context c(ctx);
- c.args(argnames, argexpr, inst->argnames, inst->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");
- 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;
- }
- }
-
- 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, 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;
- }
- 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;
- }
- }
-
- if (type == POLYHEDRON) {
- node->points = c.lookup_variable("points");
- node->triangles = c.lookup_variable("triangles");
- }
-
- if (type == SQUARE) {
- Value size = c.lookup_variable("size");
- Value center = c.lookup_variable("center");
- size.getnum(node->x);
- size.getnum(node->y);
- size.getv2(node->x, node->y);
- if (center.type == Value::BOOL) {
- node->center = center.b;
- }
- }
-
- if (type == CIRCLE) {
- Value r = c.lookup_variable("r");
- if (r.type == Value::NUMBER) {
- node->r1 = r.num;
- }
- }
-
- if (type == POLYGON) {
- node->points = c.lookup_variable("points");
- node->paths = c.lookup_variable("paths");
- }
-
- node->convexity = c.lookup_variable("convexity", true).num;
- if (node->convexity < 1)
- node->convexity = 1;
-
- return node;
-}
-
-void register_builtin_primitives()
-{
- builtin_modules["cube"] = new PrimitiveModule(CUBE);
- builtin_modules["sphere"] = new PrimitiveModule(SPHERE);
- builtin_modules["cylinder"] = new PrimitiveModule(CYLINDER);
- builtin_modules["polyhedron"] = new PrimitiveModule(POLYHEDRON);
- builtin_modules["square"] = new PrimitiveModule(SQUARE);
- builtin_modules["circle"] = new PrimitiveModule(CIRCLE);
- builtin_modules["polygon"] = new PrimitiveModule(POLYGON);
-}
-
-/*!
- Returns the number of subdivision of a whole circle, given radius and
- the three special variables $fn, $fs and $fa
-*/
-int get_fragments_from_r(double r, double fn, double fs, double fa)
-{
- if (fn > 0.0)
- return (int)fn;
- return (int)ceil(fmax(fmin(360.0 / fa, r*M_PI / fs), 5));
-}
-
-PolySet *PrimitiveNode::render_polyset(render_mode_e) 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, 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, 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;
- 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), fn, 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; i<fragments; i++) {
- double phi = (M_PI*2*i) / fragments;
- if (r1 > 0) {
- circle1[i].x = r1*cos(phi);
- circle1[i].y = r1*sin(phi);
- } else {
- circle1[i].x = 0;
- circle1[i].y = 0;
- }
- if (r2 > 0) {
- circle2[i].x = r2*cos(phi);
- circle2[i].y = r2*sin(phi);
- } else {
- circle2[i].x = 0;
- circle2[i].y = 0;
- }
- }
-
- for (int i=0; i<fragments; i++) {
- int j = (i+1) % fragments;
- if (r1 > 0) {
- p->append_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);
- }
- if (r2 > 0) {
- 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; i<fragments; i++)
- p->insert_vertex(circle1[i].x, circle1[i].y, z1);
- }
-
- if (r2 > 0) {
- p->append_poly();
- for (int i=0; i<fragments; i++)
- p->append_vertex(circle2[i].x, circle2[i].y, z2);
- }
- }
-
- if (type == POLYHEDRON)
- {
- p->convexity = convexity;
- for (int i=0; i<triangles.vec.size(); i++)
- {
- p->append_poly();
- for (int j=0; j<triangles.vec[i]->vec.size(); j++) {
- int pt = triangles.vec[i]->vec[j]->num;
- if (pt < points.vec.size()) {
- double px, py, pz;
- if (points.vec[pt]->getv3(px, py, pz))
- p->insert_vertex(px, py, pz);
- }
- }
- }
- }
-
- if (type == SQUARE)
- {
- double x1, x2, y1, y2;
- if (center) {
- x1 = -x/2;
- x2 = +x/2;
- y1 = -y/2;
- y2 = +y/2;
- } else {
- x1 = y1 = 0;
- x2 = x;
- y2 = y;
- }
-
- p->is2d = true;
- p->append_poly();
- p->append_vertex(x1, y1);
- p->append_vertex(x2, y1);
- p->append_vertex(x2, y2);
- p->append_vertex(x1, y2);
- }
-
- if (type == CIRCLE)
- {
- int fragments = get_fragments_from_r(r1, fn, fs, fa);
-
- struct point2d {
- double x, y;
- };
-
- point2d circle[fragments];
-
- for (int i=0; i<fragments; i++) {
- double phi = (M_PI*2*i) / fragments;
- circle[i].x = r1*cos(phi);
- circle[i].y = r1*sin(phi);
- }
-
- p->is2d = true;
- p->append_poly();
- for (int i=0; i<fragments; i++)
- p->append_vertex(circle[i].x, circle[i].y);
- }
-
- if (type == POLYGON)
- {
- DxfData dd;
-
- for (int i=0; i<points.vec.size(); i++) {
- double x = points.vec[i]->vec[0]->num;
- double y = points.vec[i]->vec[1]->num;
- dd.points.append(DxfData::Point(x, y));
- }
-
- if (paths.vec.size() == 0)
- {
- dd.paths.append(DxfData::Path());
- for (int i=0; i<points.vec.size(); i++) {
- if (i < dd.points.size()) {
- DxfData::Point *p = &dd.points[i];
- dd.paths.last().points.append(p);
- }
- }
- if (dd.paths.last().points.size() > 0) {
- dd.paths.last().points.append(dd.paths.last().points.first());
- dd.paths.last().is_closed = true;
- }
- }
- else
- {
- for (int i=0; i<paths.vec.size(); i++)
- {
- dd.paths.append(DxfData::Path());
- for (int j=0; j<paths.vec[i]->vec.size(); j++) {
- int idx = paths.vec[i]->vec[j]->num;
- if (idx < dd.points.size()) {
- DxfData::Point *p = &dd.points[idx];
- dd.paths.last().points.append(p);
- }
- }
- if (dd.paths.last().points.isEmpty()) {
- dd.paths.removeLast();
- } else {
- dd.paths.last().points.append(dd.paths.last().points.first());
- dd.paths.last().is_closed = true;
- }
- }
- }
-
- p->is2d = true;
- p->convexity = convexity;
- dxf_tesselate(p, &dd, 0, true, false, 0);
- dxf_border_to_ps(p, &dd);
- }
-
- return p;
-}
-
-QString PrimitiveNode::dump(QString indent) const
-{
- if (dump_cache.isEmpty()) {
- QString text;
- if (type == CUBE)
- text.sprintf("cube(size = [%g, %g, %g], center = %s);\n", x, y, z, center ? "true" : "false");
- if (type == SPHERE)
- text.sprintf("sphere($fn = %g, $fa = %g, $fs = %g, r = %g);\n", fn, fa, fs, r1);
- if (type == CYLINDER)
- text.sprintf("cylinder($fn = %g, $fa = %g, $fs = %g, h = %g, r1 = %g, r2 = %g, center = %s);\n", fn, fa, fs, h, r1, r2, center ? "true" : "false");
- if (type == POLYHEDRON)
- text.sprintf("polyhedron(points = %s, triangles = %s, convexity = %d);\n", points.dump().toAscii().data(), triangles.dump().toAscii().data(), convexity);
- if (type == SQUARE)
- text.sprintf("square(size = [%g, %g], center = %s);\n", x, y, center ? "true" : "false");
- if (type == CIRCLE)
- text.sprintf("circle($fn = %g, $fa = %g, $fs = %g, r = %g);\n", fn, fa, fs, r1);
- if (type == POLYGON)
- text.sprintf("polygon(points = %s, paths = %s, convexity = %d);\n", points.dump().toAscii().data(), paths.dump().toAscii().data(), convexity);
- ((AbstractNode*)this)->dump_cache = indent + QString("n%1: ").arg(idx) + text;
- }
- return dump_cache;
-}
-
contact: Jan Huwald // Impressum