summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--context.cc5
-rw-r--r--dxfdata.cc63
-rw-r--r--dxflinextrude.cc49
-rw-r--r--dxfrotextrude.cc26
-rw-r--r--openscad.h5
-rw-r--r--openscad.pro3
-rw-r--r--value.cc20
7 files changed, 145 insertions, 26 deletions
diff --git a/context.cc b/context.cc
index 7e6174d..7f96f53 100644
--- a/context.cc
+++ b/context.cc
@@ -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();
}
diff --git a/dxfdata.cc b/dxfdata.cc
index a6d2cd8..8e4b6a4 100644
--- a/dxfdata.cc
+++ b/dxfdata.cc
@@ -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;
diff --git a/openscad.h b/openscad.h
index 191df31..9676947 100644
--- a/openscad.h
+++ b/openscad.h
@@ -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
+
diff --git a/value.cc b/value.cc
index 7168fc0..8cb370d 100644
--- a/value.cc
+++ b/value.cc
@@ -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)
contact: Jan Huwald // Impressum