mirror of https://github.com/vitalif/openscad
Clifford Wolf:
Improved DXF support git-svn-id: http://svn.clifford.at/openscad/trunk@61 b57f626f-c46c-0410-a088-ec61d464b74cstl_dim
parent
4c03dac385
commit
bd89f254ef
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
63
dxfdata.cc
63
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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -23,3 +23,6 @@ QMAKE_CXXFLAGS += -O0
|
|||
|
||||
QT += opengl
|
||||
|
||||
target.path = /usr/local/bin/
|
||||
INSTALLS += target
|
||||
|
||||
|
|
20
value.cc
20
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)
|
||||
|
|
Loading…
Reference in New Issue