diff options
-rw-r--r-- | context.cc | 5 | ||||
-rw-r--r-- | dxfdata.cc | 63 | ||||
-rw-r--r-- | dxflinextrude.cc | 49 | ||||
-rw-r--r-- | dxfrotextrude.cc | 26 | ||||
-rw-r--r-- | openscad.h | 5 | ||||
-rw-r--r-- | openscad.pro | 3 | ||||
-rw-r--r-- | value.cc | 20 |
7 files changed, 145 insertions, 26 deletions
@@ -60,7 +60,7 @@ void Context::set_variable(QString name, Value value) variables[name] = value; } -Value Context::lookup_variable(QString name) const +Value Context::lookup_variable(QString name, bool silent) const { if (name.startsWith("$")) { for (int i = ctx_stack.size()-1; i >= 0; i--) { @@ -73,7 +73,8 @@ Value Context::lookup_variable(QString name) const return variables[name]; if (parent) return parent->lookup_variable(name); - PRINTA("WARNING: Ignoring unkown variable '%1'.", name); + if (!silent) + PRINTA("WARNING: Ignoring unkown variable '%1'.", name); return Value(); } @@ -22,7 +22,7 @@ #include <QFile> -DxfData::DxfData(double /* fn */, double /* fs */, double /* fa */, QString filename, QString layername) +DxfData::DxfData(double fn, double fs, double fa, QString filename, QString layername, double xorigin, double yorigin, double scale) { QFile f(filename); @@ -38,6 +38,9 @@ DxfData::DxfData(double /* fn */, double /* fs */, double /* fa */, QString file QString mode, layer; double x1 = 0, x2 = 0, y1 = 0, y2 = 0; + double radius = 0, start_angle = 0, stop_angle = 0; + bool in_entities_section = false; + QHash<QString, int> unsupported_entities_list; while (!f.atEnd()) { @@ -56,26 +59,72 @@ DxfData::DxfData(double /* fn */, double /* fs */, double /* fa */, QString file if (mode == "LINE" && (layername.isNull() || layername == layer)) { lines.append(Line(p(x1, y1), p(x2, y2))); } + if (mode == "CIRCLE" && (layername.isNull() || layername == layer)) { + int n = get_fragments_from_r(radius, fn, fs, fa); + for (int i = 0; i < n; i++) { + double a1 = (2*M_PI*i)/n; + double a2 = (2*M_PI*(i+1))/n; + lines.append(Line(p(cos(a1)*radius + x1, sin(a1)*radius + y1), + p(cos(a2)*radius + x1, sin(a2)*radius + y1))); + } + } + if (mode == "ARC" && (layername.isNull() || layername == layer)) { + int n = get_fragments_from_r(radius, fn, fs, fa); + while (start_angle > stop_angle) + stop_angle += 360.0; + n = ceil(n * 360 / (stop_angle-start_angle)); + for (int i = 0; i < n; i++) { + double a1 = ((stop_angle-start_angle)*i)/n; + double a2 = ((stop_angle-start_angle)*(i+1))/n; + a1 = (start_angle + a1) * M_PI / 180.0; + a2 = (start_angle + a2) * M_PI / 180.0; + lines.append(Line(p(cos(a1)*radius + x1, sin(a1)*radius + y1), + p(cos(a2)*radius + x1, sin(a2)*radius + y1))); + } + } + if (in_entities_section) { + if (data != "SECTION" && data != "ENDSEC" && + data != "LINE" && data != "ARC" && data != "CIRCLE") + unsupported_entities_list[data]++; + } mode = data; break; + case 2: + in_entities_section = data == "ENTITIES"; case 8: layer = data; break; case 10: - x1 = data.toDouble(); + x1 = (data.toDouble() - xorigin) * scale; break; case 11: - x2 = data.toDouble(); + x2 = (data.toDouble() - xorigin) * scale; break; case 20: - y1 = data.toDouble(); + y1 = (data.toDouble() - yorigin) * scale; break; case 21: - y2 = data.toDouble(); + y2 = (data.toDouble() - yorigin) * scale; + break; + case 40: + radius = data.toDouble() * scale; + break; + case 50: + start_angle = data.toDouble(); + break; + case 51: + stop_angle = data.toDouble(); break; } } + QHashIterator<QString, int> i(unsupported_entities_list); + while (i.hasNext()) { + i.next(); + PRINTA("WARNING: Unsupported DXF Entity `%1' (%2x) in `%3'.", + i.key(), QString::number(i.value()), filename); + } + // extract all open paths while (lines.count() > 0) { @@ -84,6 +133,8 @@ DxfData::DxfData(double /* fn */, double /* fs */, double /* fa */, QString file for (int i = 0; i < lines.count(); i++) { for (int j = 0; j < 2; j++) { for (int k = 0; k < lines.count(); k++) { + if (i == k) + continue; if (lines[i].p[j] == lines[k].p[0]) goto next_open_path_j; if (lines[i].p[j] == lines[k].p[1]) @@ -174,7 +225,7 @@ DxfData::DxfData(double /* fn */, double /* fs */, double /* fa */, QString file min_x_point = j; } } - // rotate points if the path is not in non-standard rotation + // rotate points if the path is in non-standard rotation int b = min_x_point; int a = b == 0 ? paths[i].points.count() - 2 : b - 1; int c = b == paths[i].points.count() - 1 ? 1 : b + 1; diff --git a/dxflinextrude.cc b/dxflinextrude.cc index c03da0a..0fa285c 100644 --- a/dxflinextrude.cc +++ b/dxflinextrude.cc @@ -34,8 +34,15 @@ class DxfLinearExtrudeNode : public AbstractPolyNode public: int convexity; double fn, fs, fa, height; + double origin_x, origin_y, scale; + bool center; QString filename, layername; - DxfLinearExtrudeNode(const ModuleInstanciation *mi) : AbstractPolyNode(mi) { } + DxfLinearExtrudeNode(const ModuleInstanciation *mi) : AbstractPolyNode(mi) { + convexity = 0; + fn = fs = fa = height = 0; + origin_x = origin_y = scale = 0; + center = false; + } virtual PolySet *render_polyset(render_mode_e mode) const; virtual QString dump(QString indent) const; }; @@ -44,7 +51,7 @@ AbstractNode *DxfLinearExtrudeModule::evaluate(const Context *ctx, const ModuleI { DxfLinearExtrudeNode *node = new DxfLinearExtrudeNode(inst); - QVector<QString> argnames = QVector<QString>() << "file" << "layer" << "height"; + QVector<QString> argnames = QVector<QString>() << "file" << "layer" << "height" << "origin" << "scale" << "center"; QVector<Expression*> argexpr; Context c(ctx); @@ -55,14 +62,22 @@ AbstractNode *DxfLinearExtrudeModule::evaluate(const Context *ctx, const ModuleI node->fa = c.lookup_variable("$fa").num; Value file = c.lookup_variable("file"); - Value layer = c.lookup_variable("layer"); - Value height = c.lookup_variable("height"); - Value convexity = c.lookup_variable("convexity"); + Value layer = c.lookup_variable("layer", true); + Value height = c.lookup_variable("height", true); + Value convexity = c.lookup_variable("convexity", true); + Value origin = c.lookup_variable("origin", true); + Value scale = c.lookup_variable("scale", true); + Value center = c.lookup_variable("center", true); node->filename = file.text; node->layername = layer.text; node->height = height.num; node->convexity = convexity.num; + origin.getv2(node->origin_x, node->origin_y); + node->scale = scale.num; + + if (center.type == Value::BOOL) + node->center = center.b; if (node->height <= 0) node->height = 100; @@ -70,6 +85,9 @@ AbstractNode *DxfLinearExtrudeModule::evaluate(const Context *ctx, const ModuleI if (node->convexity <= 0) node->convexity = 1; + if (node->scale <= 0) + node->scale = 1; + return node; } @@ -319,20 +337,30 @@ static void tess(PolySet *ps, DxfData *dxf, bool up, double h) PolySet *DxfLinearExtrudeNode::render_polyset(render_mode_e) const { - DxfData dxf(fn, fs, fa, filename, layername); + DxfData dxf(fn, fs, fa, filename, layername, origin_x, origin_y, scale); PolySet *ps = new PolySet(); ps->convexity = convexity; + double h1, h2; + + if (center) { + h1 = -height/2.0; + h2 = -height/2.0; + } else { + h1 = 0; + h2 = height; + } + for (int i = 0; i < dxf.paths.count(); i++) { if (!dxf.paths[i].is_closed) continue; - add_slice(ps, &dxf.paths[i], 0, height); + add_slice(ps, &dxf.paths[i], h1, h2); } - tess(ps, &dxf, false, 0); - tess(ps, &dxf, true, height); + tess(ps, &dxf, false, h1); + tess(ps, &dxf, true, h2); return ps; } @@ -342,9 +370,10 @@ QString DxfLinearExtrudeNode::dump(QString indent) const if (dump_cache.isEmpty()) { QString text; text.sprintf("dxf_linear_extrude(file = \"%s\", layer = \"%s\", height = %f, " + "origin = [ %f %f ], scale = %f, " "$fn = %f, $fa = %f, $fs = %f);\n", filename.toAscii().data(), layername.toAscii().data(), - height, fn, fs, fa); + height, origin_x, origin_y, scale, fn, fs, fa); ((AbstractNode*)this)->dump_cache = indent + QString("n%1: ").arg(idx) + text; } return dump_cache; diff --git a/dxfrotextrude.cc b/dxfrotextrude.cc index 489f222..3bb1ccd 100644 --- a/dxfrotextrude.cc +++ b/dxfrotextrude.cc @@ -34,8 +34,13 @@ class DxfRotateExtrudeNode : public AbstractPolyNode public: int convexity; double fn, fs, fa; + double origin_x, origin_y, scale; QString filename, layername; - DxfRotateExtrudeNode(const ModuleInstanciation *mi) : AbstractPolyNode(mi) { } + DxfRotateExtrudeNode(const ModuleInstanciation *mi) : AbstractPolyNode(mi) { + convexity = 0; + fn = fs = fa = 0; + origin_x = origin_y = scale = 0; + } virtual PolySet *render_polyset(render_mode_e mode) const; virtual QString dump(QString indent) const; }; @@ -44,7 +49,7 @@ AbstractNode *DxfRotateExtrudeModule::evaluate(const Context *ctx, const ModuleI { DxfRotateExtrudeNode *node = new DxfRotateExtrudeNode(inst); - QVector<QString> argnames = QVector<QString>() << "file" << "layer"; + QVector<QString> argnames = QVector<QString>() << "file" << "layer" << "origin" << "scale"; QVector<Expression*> argexpr; Context c(ctx); @@ -55,16 +60,23 @@ AbstractNode *DxfRotateExtrudeModule::evaluate(const Context *ctx, const ModuleI node->fa = c.lookup_variable("$fa").num; Value file = c.lookup_variable("file"); - Value layer = c.lookup_variable("layer"); - Value convexity = c.lookup_variable("convexity"); + Value layer = c.lookup_variable("layer", true); + Value convexity = c.lookup_variable("convexity", true); + Value origin = c.lookup_variable("origin", true); + Value scale = c.lookup_variable("scale", true); node->filename = file.text; node->layername = layer.text; node->convexity = convexity.num; + origin.getv2(node->origin_x, node->origin_y); + node->scale = scale.num; if (node->convexity <= 0) node->convexity = 1; + if (node->scale <= 0) + node->scale = 1; + return node; } @@ -75,7 +87,7 @@ void register_builtin_dxf_rotate_extrude() PolySet *DxfRotateExtrudeNode::render_polyset(render_mode_e) const { - DxfData dxf(fn, fs, fa, filename, layername); + DxfData dxf(fn, fs, fa, filename, layername, origin_x, origin_y, scale); PolySet *ps = new PolySet(); ps->convexity = convexity; @@ -143,8 +155,10 @@ QString DxfRotateExtrudeNode::dump(QString indent) const if (dump_cache.isEmpty()) { QString text; text.sprintf("dxf_rotate_extrude(file = \"%s\", layer = \"%s\", " + "origin = [ %f %f ], scale = %f, " "$fn = %f, $fa = %f, $fs = %f);\n", - filename.toAscii().data(), layername.toAscii().data(),fn, fs, fa); + filename.toAscii().data(), layername.toAscii().data(), + origin_x, origin_y, scale, fn, fs, fa); ((AbstractNode*)this)->dump_cache = indent + QString("n%1: ").arg(idx) + text; } return dump_cache; @@ -124,6 +124,7 @@ public: Value inv() const; bool getnum(double &v) const; + bool getv2(double &x, double &y) const; bool getv3(double &x, double &y, double &z) const; QString dump() const; @@ -284,7 +285,7 @@ public: void args(const QVector<QString> &argnames, const QVector<Expression*> &argexpr, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues); void set_variable(QString name, Value value); - Value lookup_variable(QString name) const; + Value lookup_variable(QString name, bool silent = false) const; Value evaluate_function(QString name, const QVector<QString> &argnames, const QVector<Value> &argvalues) const; AbstractNode *evaluate_module(const ModuleInstanciation *inst) const; @@ -312,7 +313,7 @@ public: QList<Point> points; QList<Path> paths; - DxfData(double fn, double fs, double fa, QString filename, QString layername = QString()); + DxfData(double fn, double fs, double fa, QString filename, QString layername = QString(), double xorigin = 0.0, double yorigin = 0.0, double scale = 1.0); Point *p(double x, double y); }; diff --git a/openscad.pro b/openscad.pro index 1d9df65..2e7d8f1 100644 --- a/openscad.pro +++ b/openscad.pro @@ -23,3 +23,6 @@ QMAKE_CXXFLAGS += -O0 QT += opengl +target.path = /usr/local/bin/ +INSTALLS += target + @@ -255,8 +255,28 @@ bool Value::getnum(double &v) const return true; } +bool Value::getv2(double &x, double &y) const +{ + if (type != VECTOR || vec.size() != 2) + return false; + if (vec[0]->type != NUMBER) + return false; + if (vec[1]->type != NUMBER) + return false; + x = vec[0]->num; + y = vec[1]->num; + return true; +} + bool Value::getv3(double &x, double &y, double &z) const { + if (type == VECTOR && vec.size() == 2) { + if (getv2(x, y)) { + z = 0; + return true; + } + return false; + } if (type != VECTOR || vec.size() != 3) return false; if (vec[0]->type != NUMBER) |