summaryrefslogtreecommitdiff
path: root/src/primitives.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/primitives.cc')
-rw-r--r--src/primitives.cc231
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();
+}
contact: Jan Huwald // Impressum