diff options
Diffstat (limited to 'src/primitives.cc')
-rw-r--r-- | src/primitives.cc | 231 |
1 files changed, 145 insertions, 86 deletions
diff --git a/src/primitives.cc b/src/primitives.cc index 5180c16..204bb11 100644 --- a/src/primitives.cc +++ b/src/primitives.cc @@ -33,6 +33,9 @@ #include "builtin.h" #include "printutils.h" #include <assert.h> +#include "visitor.h" +#include <sstream> +#include <assert.h> #define F_MINIMUM 0.01 @@ -57,20 +60,52 @@ public: class PrimitiveNode : public AbstractPolyNode { public: + PrimitiveNode(const ModuleInstantiation *mi, primitive_type_e type) : AbstractPolyNode(mi), type(type) { } + virtual Response accept(class State &state, Visitor &visitor) const { + return visitor.visit(state, *this); + } + virtual std::string toString() const; + virtual std::string name() const { + switch (this->type) { + case CUBE: + return "cube"; + break; + case SPHERE: + return "sphere"; + break; + case CYLINDER: + return "cylinder"; + break; + case POLYHEDRON: + return "polyhedron"; + break; + case SQUARE: + return "square"; + break; + case CIRCLE: + return "circle"; + break; + case POLYGON: + return "polygon"; + break; + default: + assert(false && "PrimitiveNode::name(): Unknown primitive type"); + return AbstractPolyNode::name(); + } + } + 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; + virtual PolySet *evaluate_polyset(render_mode_e mode, class PolySetEvaluator *) const; }; AbstractNode *PrimitiveModule::evaluate(const Context *ctx, const ModuleInstantiation *inst) const { - PrimitiveNode *node = new PrimitiveNode(inst, type); + PrimitiveNode *node = new PrimitiveNode(inst, this->type); node->center = false; node->x = node->y = node->z = node->h = node->r1 = node->r2 = 1; @@ -78,26 +113,30 @@ AbstractNode *PrimitiveModule::evaluate(const Context *ctx, const ModuleInstanti QVector<QString> argnames; QVector<Expression*> argexpr; - if (type == CUBE) { + switch (this->type) { + case CUBE: argnames = QVector<QString>() << "size" << "center"; - } - if (type == SPHERE) { + break; + case SPHERE: argnames = QVector<QString>() << "r"; - } - if (type == CYLINDER) { + break; + case CYLINDER: argnames = QVector<QString>() << "h" << "r1" << "r2" << "center"; - } - if (type == POLYHEDRON) { + break; + case POLYHEDRON: argnames = QVector<QString>() << "points" << "triangles" << "convexity"; - } - if (type == SQUARE) { + break; + case SQUARE: argnames = QVector<QString>() << "size" << "center"; - } - if (type == CIRCLE) { + break; + case CIRCLE: argnames = QVector<QString>() << "r"; - } - if (type == POLYGON) { + break; + case POLYGON: argnames = QVector<QString>() << "points" << "paths" << "convexity"; + break; + default: + assert(false && "PrimitiveModule::evaluate(): Unknown node type"); } Context c(ctx); @@ -233,25 +272,25 @@ static void generate_circle(point2d *circle, double r, int fragments) } } -PolySet *PrimitiveNode::render_polyset(render_mode_e) const +PolySet *PrimitiveNode::evaluate_polyset(render_mode_e, class PolySetEvaluator *) const { PolySet *p = new PolySet(); - if (type == CUBE && x > 0 && y > 0 && z > 0) + if (this->type == CUBE && this->x > 0 && this->y > 0 && this->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; + if (this->center) { + x1 = -this->x/2; + x2 = +this->x/2; + y1 = -this->y/2; + y2 = +this->y/2; + z1 = -this->z/2; + z2 = +this->z/2; } else { x1 = y1 = z1 = 0; - x2 = x; - y2 = y; - z2 = z; + x2 = this->x; + y2 = this->y; + z2 = this->z; } p->append_poly(); // top @@ -291,7 +330,7 @@ PolySet *PrimitiveNode::render_polyset(render_mode_e) const p->append_vertex(x1, y2, z2); } - if (type == SPHERE && r1 > 0) + if (this->type == SPHERE && this->r1 > 0) { struct ring_s { point2d *points; @@ -358,17 +397,18 @@ sphere_next_r2: delete[] ring; } - if (type == CYLINDER && h > 0 && r1 >=0 && r2 >= 0 && (r1 > 0 || r2 > 0)) + if (this->type == CYLINDER && + this->h > 0 && this->r1 >=0 && this->r2 >= 0 && (this->r1 > 0 || this->r2 > 0)) { - int fragments = get_fragments_from_r(fmax(r1, r2), fn, fs, fa); + int fragments = get_fragments_from_r(fmax(this->r1, this->r2), this->fn, this->fs, this->fa); double z1, z2; - if (center) { - z1 = -h/2; - z2 = +h/2; + if (this->center) { + z1 = -this->h/2; + z2 = +this->h/2; } else { z1 = 0; - z2 = h; + z2 = this->h; } point2d *circle1 = new point2d[fragments]; @@ -401,13 +441,13 @@ sphere_next_r2: } } - if (r1 > 0) { + if (this->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) { + if (this->r2 > 0) { p->append_poly(); for (int i=0; i<fragments; i++) p->append_vertex(circle2[i].x, circle2[i].y, z2); @@ -417,35 +457,35 @@ sphere_next_r2: delete[] circle2; } - if (type == POLYHEDRON) + if (this->type == POLYHEDRON) { - p->convexity = convexity; - for (int i=0; i<triangles.vec.size(); i++) + p->convexity = this->convexity; + for (size_t i=0; i<this->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()) { + for (size_t j=0; j<this->triangles.vec[i]->vec.size(); j++) { + int pt = this->triangles.vec[i]->vec[j]->num; + if (pt < this->points.vec.size()) { double px, py, pz; - if (points.vec[pt]->getv3(px, py, pz)) + if (this->points.vec[pt]->getv3(px, py, pz)) p->insert_vertex(px, py, pz); } } } } - if (type == SQUARE) + if (this->type == SQUARE) { double x1, x2, y1, y2; - if (center) { - x1 = -x/2; - x2 = +x/2; - y1 = -y/2; - y2 = +y/2; + if (this->center) { + x1 = -this->x/2; + x2 = +this->x/2; + y1 = -this->y/2; + y2 = +this->y/2; } else { x1 = y1 = 0; - x2 = x; - y2 = y; + x2 = this->x; + y2 = this->y; } p->is2d = true; @@ -456,37 +496,37 @@ sphere_next_r2: p->append_vertex(x1, y2); } - if (type == CIRCLE) + if (this->type == CIRCLE) { - int fragments = get_fragments_from_r(r1, fn, fs, fa); + int fragments = get_fragments_from_r(this->r1, this->fn, this->fs, this->fa); p->is2d = true; p->append_poly(); for (int i=0; i < fragments; i++) { double phi = (M_PI*2*i) / fragments; - p->append_vertex(r1*cos(phi), r1*sin(phi)); + p->append_vertex(this->r1*cos(phi), this->r1*sin(phi)); } } - if (type == POLYGON) + if (this->type == POLYGON) { DxfData dd; - for (int i=0; i<points.vec.size(); i++) { + for (size_t i=0; i<this->points.vec.size(); i++) { double x,y; - if (!points.vec[i]->getv2(x, y)) { + if (!this->points.vec[i]->getv2(x, y)) { PRINTF("ERROR: Unable to convert point at index %d to a vec2 of numbers", i); - // FIXME: Return NULL and make sure this is checked by all callers? - return p; + p->unlink(); + return NULL; } dd.points.append(DxfData::Point(x, y)); } - if (paths.vec.size() == 0) + if (this->paths.vec.size() == 0) { dd.paths.append(DxfData::Path()); - for (int i=0; i<points.vec.size(); i++) { + for (size_t i=0; i<this->points.vec.size(); i++) { assert(i < dd.points.size()); // FIXME: Not needed, but this used to be an 'if' DxfData::Point *p = &dd.points[i]; dd.paths.last().points.append(p); @@ -498,11 +538,11 @@ sphere_next_r2: } else { - for (int i=0; i<paths.vec.size(); i++) + for (size_t i=0; i<this->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; + for (size_t j=0; j<this->paths.vec[i]->vec.size(); j++) { + int idx = this->paths.vec[i]->vec[j]->num; if (idx < dd.points.size()) { DxfData::Point *p = &dd.points[idx]; dd.paths.last().points.append(p); @@ -526,26 +566,45 @@ sphere_next_r2: return p; } -QString PrimitiveNode::dump(QString indent) const +std::string PrimitiveNode::toString() 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; + std::stringstream stream; + + stream << this->name(); + + switch (this->type) { + case CUBE: + stream << "(size = [" << this->x << ", " << this->y << ", " << this->z << "], " + << "center = " << (center ? "true" : "false") << ")"; + break; + case SPHERE: + stream << "($fn = " << this->fn << ", $fa = " << this->fa + << ", $fs = " << this->fs << ", r = " << this->r1 << ")"; + break; + case CYLINDER: + stream << "($fn = " << this->fn << ", $fa = " << this->fa + << ", $fs = " << this->fs << ", h = " << this->h << ", r1 = " << this->r1 + << ", r2 = " << this->r2 << ", center = " << (center ? "true" : "false") << ")"; + break; + case POLYHEDRON: + stream << "(points = " << this->points + << ", triangles = " << this->triangles + << ", convexity = " << this->convexity << ")"; + break; + case SQUARE: + stream << "(size = [" << this->x << ", " << this->y << "], " + << "center = " << (center ? "true" : "false") << ")"; + break; + case CIRCLE: + stream << "($fn = " << this->fn << ", $fa = " << this->fa + << ", $fs = " << this->fs << ", r = " << this->r1 << ")"; + break; + case POLYGON: + stream << "(points = " << this->points << ", paths = " << this->paths << ", convexity = " << this->convexity << ")"; + break; + default: + assert(false); } - return dump_cache; -} + return stream.str(); +} |