diff options
Diffstat (limited to 'src/transform.cc')
-rw-r--r-- | src/transform.cc | 291 |
1 files changed, 107 insertions, 184 deletions
diff --git a/src/transform.cc b/src/transform.cc index 7b15a7e..b22b766 100644 --- a/src/transform.cc +++ b/src/transform.cc @@ -24,8 +24,8 @@ * */ +#include "transformnode.h" #include "module.h" -#include "node.h" #include "context.h" #include "dxfdata.h" #include "csgterm.h" @@ -33,6 +33,10 @@ #include "dxftess.h" #include "builtin.h" #include "printutils.h" +#include "visitor.h" +#include <sstream> +#include <vector> +#include <assert.h> enum transform_type_e { SCALE, @@ -51,63 +55,80 @@ public: virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst) const; }; -class TransformNode : public AbstractNode +using std::string; +using std::vector; + +static vector<string> split(const string &str, const string &delim) { -public: - double m[20]; - TransformNode(const ModuleInstantiation *mi) : AbstractNode(mi) { } -#ifdef ENABLE_CGAL - virtual CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const; -#endif - virtual CSGTerm *render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const; - virtual QString dump(QString indent) const; -}; + assert(delim.size() > 0); + + vector<string> strvec; + size_t start = 0, end = 0; + while (end != string::npos) { + end = str.find(delim, start); + // If at end, use length=maxLength. Else use length=end-start. + strvec.push_back(str.substr(start, (end == string::npos) ? string::npos : end - start)); + // If at end, use start=maxSize. Else use start=end+delimiter. + start = ((end > (string::npos - delim.size())) ? string::npos : end + delim.size()); + } + return strvec; +} + +template <class T> static bool from_string(T &t, const string &s) +{ + std::istringstream iss(s); + return !(iss >> t).fail(); +} AbstractNode *TransformModule::evaluate(const Context *ctx, const ModuleInstantiation *inst) const { TransformNode *node = new TransformNode(inst); for (int i = 0; i < 16; i++) - node->m[i] = i % 5 == 0 ? 1.0 : 0.0; + node->matrix[i] = i % 5 == 0 ? 1.0 : 0.0; for (int i = 16; i < 20; i++) - node->m[i] = -1; + node->matrix[i] = -1; QVector<QString> argnames; QVector<Expression*> argexpr; - if (type == SCALE) { + switch (this->type) { + case SCALE: argnames = QVector<QString>() << "v"; - } - if (type == ROTATE) { + break; + case ROTATE: argnames = QVector<QString>() << "a" << "v"; - } - if (type == MIRROR) { + break; + case MIRROR: argnames = QVector<QString>() << "v"; - } - if (type == TRANSLATE) { + break; + case TRANSLATE: argnames = QVector<QString>() << "v"; - } - if (type == MULTMATRIX) { + break; + case MULTMATRIX: argnames = QVector<QString>() << "m"; - } - if (type == COLOR) { + break; + case COLOR: argnames = QVector<QString>() << "c" << "alpha"; + break; + default: + assert(false); } Context c(ctx); c.args(argnames, argexpr, inst->argnames, inst->argvalues); - if (type == SCALE) + if (this->type == SCALE) { Value v = c.lookup_variable("v"); - v.getnum(node->m[0]); - v.getnum(node->m[5]); - v.getnum(node->m[10]); - v.getv3(node->m[0], node->m[5], node->m[10]); - if (node->m[10] <= 0) - node->m[10] = 1; + v.getnum(node->matrix[0]); + v.getnum(node->matrix[5]); + v.getnum(node->matrix[10]); + v.getv3(node->matrix[0], node->matrix[5], node->matrix[10]); + if (node->matrix[10] <= 0) + node->matrix[10] = 1; } - if (type == ROTATE) + else if (this->type == ROTATE) { Value val_a = c.lookup_variable("a"); if (val_a.type == Value::VECTOR) @@ -139,10 +160,10 @@ AbstractNode *TransformModule::evaluate(const Context *ctx, const ModuleInstanti { m[x+y*4] = 0; for (int i = 0; i < 4; i++) - m[x+y*4] += node->m[i+y*4] * mr[x+i*4]; + m[x+y*4] += node->matrix[i+y*4] * mr[x+i*4]; } for (int i = 0; i < 16; i++) - node->m[i] = m[i]; + node->matrix[i] = m[i]; } } else @@ -164,21 +185,21 @@ AbstractNode *TransformModule::evaluate(const Context *ctx, const ModuleInstanti double c = cos(a*M_PI/180.0); double s = sin(a*M_PI/180.0); - node->m[ 0] = x*x*(1-c)+c; - node->m[ 1] = y*x*(1-c)+z*s; - node->m[ 2] = z*x*(1-c)-y*s; + node->matrix[ 0] = x*x*(1-c)+c; + node->matrix[ 1] = y*x*(1-c)+z*s; + node->matrix[ 2] = z*x*(1-c)-y*s; - node->m[ 4] = x*y*(1-c)-z*s; - node->m[ 5] = y*y*(1-c)+c; - node->m[ 6] = z*y*(1-c)+x*s; + node->matrix[ 4] = x*y*(1-c)-z*s; + node->matrix[ 5] = y*y*(1-c)+c; + node->matrix[ 6] = z*y*(1-c)+x*s; - node->m[ 8] = x*z*(1-c)+y*s; - node->m[ 9] = y*z*(1-c)-x*s; - node->m[10] = z*z*(1-c)+c; + node->matrix[ 8] = x*z*(1-c)+y*s; + node->matrix[ 9] = y*z*(1-c)-x*s; + node->matrix[10] = z*z*(1-c)+c; } } } - if (type == MIRROR) + else if (this->type == MIRROR) { Value val_v = c.lookup_variable("v"); double x = 1, y = 0, z = 0; @@ -192,59 +213,62 @@ AbstractNode *TransformModule::evaluate(const Context *ctx, const ModuleInstanti if (x != 0.0 || y != 0.0 || z != 0.0) { - node->m[ 0] = 1-2*x*x; - node->m[ 1] = -2*y*x; - node->m[ 2] = -2*z*x; + node->matrix[ 0] = 1-2*x*x; + node->matrix[ 1] = -2*y*x; + node->matrix[ 2] = -2*z*x; - node->m[ 4] = -2*x*y; - node->m[ 5] = 1-2*y*y; - node->m[ 6] = -2*z*y; + node->matrix[ 4] = -2*x*y; + node->matrix[ 5] = 1-2*y*y; + node->matrix[ 6] = -2*z*y; - node->m[ 8] = -2*x*z; - node->m[ 9] = -2*y*z; - node->m[10] = 1-2*z*z; + node->matrix[ 8] = -2*x*z; + node->matrix[ 9] = -2*y*z; + node->matrix[10] = 1-2*z*z; } } - if (type == TRANSLATE) + else if (this->type == TRANSLATE) { Value v = c.lookup_variable("v"); - v.getv3(node->m[12], node->m[13], node->m[14]); + v.getv3(node->matrix[12], node->matrix[13], node->matrix[14]); } - if (type == MULTMATRIX) + else if (this->type == MULTMATRIX) { Value v = c.lookup_variable("m"); if (v.type == Value::VECTOR) { for (int i = 0; i < 16; i++) { int x = i / 4, y = i % 4; if (y < v.vec.size() && v.vec[y]->type == Value::VECTOR && x < v.vec[y]->vec.size()) - v.vec[y]->vec[x]->getnum(node->m[i]); + v.vec[y]->vec[x]->getnum(node->matrix[i]); } } } - if (type == COLOR) + else if (this->type == COLOR) { Value v = c.lookup_variable("c"); if (v.type == Value::VECTOR) { for (int i = 0; i < 4; i++) - node->m[16+i] = i < v.vec.size() ? v.vec[i]->num : 1.0; + node->matrix[16+i] = i < v.vec.size() ? v.vec[i]->num : 1.0; +// FIXME: Port to non-Qt +#if 0 } else if (v.type == Value::STRING) { QString colorname = v.text; QColor color; color.setNamedColor(colorname); if (color.isValid()) { - node->m[16+0] = color.redF(); - node->m[16+1] = color.greenF(); - node->m[16+2] = color.blueF(); + node->matrix[16+0] = color.redF(); + node->matrix[16+1] = color.greenF(); + node->matrix[16+2] = color.blueF(); } else { PRINTF_NOCACHE("WARNING: Color name \"%s\" unknown. Please see",v.text.toUtf8().data()); PRINTF_NOCACHE("WARNING: http://en.wikipedia.org/wiki/Web_colors"); } +#endif } Value alpha = c.lookup_variable("alpha"); if (alpha.type == Value::NUMBER) { - node->m[16+3] = alpha.num; + node->matrix[16+3] = alpha.num; } else { - node->m[16+3] = 1.0; + node->matrix[16+3] = 1.0; } } @@ -257,134 +281,34 @@ AbstractNode *TransformModule::evaluate(const Context *ctx, const ModuleInstanti return node; } -#ifdef ENABLE_CGAL - -CGAL_Nef_polyhedron TransformNode::render_cgal_nef_polyhedron() const +string TransformNode::toString() const { - QString cache_id = mk_cache_id(); - if (cgal_nef_cache.contains(cache_id)) { - progress_report(); - PRINT(cgal_nef_cache[cache_id]->msg); - return cgal_nef_cache[cache_id]->N; - } - - print_messages_push(); - - bool first = true; - CGAL_Nef_polyhedron N; + std::stringstream stream; - foreach (AbstractNode *v, children) { - if (v->modinst->tag_background) - continue; - if (first) { - N = v->render_cgal_nef_polyhedron(); - if (N.dim != 0) - first = false; - } else if (N.dim == 2) { - N.p2 += v->render_cgal_nef_polyhedron().p2; - } else if (N.dim == 3) { - N.p3 += v->render_cgal_nef_polyhedron().p3; - } - v->progress_report(); + if (this->matrix[16] >= 0 || this->matrix[17] >= 0 || this->matrix[18] >= 0 || this->matrix[19] >= 0) { + stream << "color([" << this->matrix[16] << ", " << this->matrix[17] << ", " << this->matrix[18] << ", " << this->matrix[19] << "])"; } - - if (N.dim == 2) - { - // Unfortunately CGAL provides no transform method for CGAL_Nef_polyhedron2 - // objects. So we convert in to our internal 2d data format, transform it, - // tesselate it and create a new CGAL_Nef_polyhedron2 from it.. What a hack! - - CGAL_Aff_transformation2 t( - m[0], m[4], m[12], - m[1], m[5], m[13], m[15]); - - DxfData dd(N); - for (int i=0; i < dd.points.size(); i++) { - CGAL_Kernel2::Point_2 p = CGAL_Kernel2::Point_2(dd.points[i].x, dd.points[i].y); - p = t.transform(p); - dd.points[i].x = to_double(p.x()); - dd.points[i].y = to_double(p.y()); + else { + stream << "multmatrix(["; + for (int j=0;j<4;j++) { + stream << "["; + for (int i=0;i<4;i++) { + // FIXME: The 0 test is to avoid a leading minus before a single 0 (cosmetics) + stream << ((this->matrix[i*4+j]==0)?0:this->matrix[i*4+j]); + if (i != 3) stream << ", "; + } + stream << "]"; + if (j != 3) stream << ", "; } - - PolySet ps; - ps.is2d = true; - dxf_tesselate(&ps, &dd, 0, true, false, 0); - - N = ps.render_cgal_nef_polyhedron(); - ps.refcount = 0; - } - if (N.dim == 3) { - CGAL_Aff_transformation t( - m[0], m[4], m[ 8], m[12], - m[1], m[5], m[ 9], m[13], - m[2], m[6], m[10], m[14], m[15]); - N.p3.transform(t); - } - - cgal_nef_cache.insert(cache_id, new cgal_nef_cache_entry(N), N.weight()); - print_messages_pop(); - progress_report(); - - return N; -} - -#endif /* ENABLE_CGAL */ - -CSGTerm *TransformNode::render_csg_term(double c[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const -{ - double x[20]; - - for (int i = 0; i < 16; i++) - { - int c_row = i%4; - int m_col = i/4; - x[i] = 0; - for (int j = 0; j < 4; j++) - x[i] += c[c_row + j*4] * m[m_col*4 + j]; + stream << "])"; } - for (int i = 16; i < 20; i++) - x[i] = m[i] < 0 ? c[i] : m[i]; - - CSGTerm *t1 = NULL; - foreach(AbstractNode *v, children) - { - CSGTerm *t2 = v->render_csg_term(x, highlights, background); - if (t2 && !t1) { - t1 = t2; - } else if (t2 && t1) { - t1 = new CSGTerm(CSGTerm::TYPE_UNION, t1, t2); - } - } - if (t1 && modinst->tag_highlight && highlights) - highlights->append(t1->link()); - if (t1 && modinst->tag_background && background) { - background->append(t1); - return NULL; - } - return t1; + return stream.str(); } -QString TransformNode::dump(QString indent) const +string TransformNode::name() const { - if (dump_cache.isEmpty()) { - QString text; - if (m[16] >= 0 || m[17] >= 0 || m[18] >= 0 || m[19] >= 0) - text.sprintf("n%d: color([%g, %g, %g, %g])", idx, - m[16], m[17], m[18], m[19]); - else - text.sprintf("n%d: multmatrix([[%g, %g, %g, %g], [%g, %g, %g, %g], " - "[%g, %g, %g, %g], [%g, %g, %g, %g]])", idx, - m[0], m[4], m[ 8], m[12], - m[1], m[5], m[ 9], m[13], - m[2], m[6], m[10], m[14], - m[3], m[7], m[11], m[15]); - text = indent + text + " {\n"; - foreach (AbstractNode *v, children) - text += v->dump(indent + QString("\t")); - ((AbstractNode*)this)->dump_cache = text + indent + "}\n"; - } - return dump_cache; + return "transform"; } void register_builtin_transform() @@ -396,4 +320,3 @@ void register_builtin_transform() builtin_modules["multmatrix"] = new TransformModule(MULTMATRIX); builtin_modules["color"] = new TransformModule(COLOR); } - |