summaryrefslogtreecommitdiff
path: root/dxfdata.cc
diff options
context:
space:
mode:
Diffstat (limited to 'dxfdata.cc')
-rw-r--r--dxfdata.cc213
1 files changed, 213 insertions, 0 deletions
diff --git a/dxfdata.cc b/dxfdata.cc
new file mode 100644
index 0000000..06c2c3f
--- /dev/null
+++ b/dxfdata.cc
@@ -0,0 +1,213 @@
+/*
+ * OpenSCAD (www.openscad.at)
+ * Copyright (C) 2009 Clifford Wolf <clifford@clifford.at>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "openscad.h"
+
+#include <QFile>
+
+DxfData::DxfData(double /* fn */, double /* fs */, double /* fa */, QString filename, QString layername)
+{
+ QFile f(filename);
+
+ if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ PRINTF("WARNING: Can't open DXF file `%s'.", filename.toAscii().data());
+ return;
+ }
+
+ // WARNING: The algorithms used here are extreamly sub-optimal and perform
+ // as bad as O(n^3). So for reading large DXF paths one might consider optimizing
+ // the code in this function..
+ QVector<Line> lines;
+
+ QString mode, layer;
+ double x1 = 0, x2 = 0, y1 = 0, y2 = 0;
+
+ while (!f.atEnd())
+ {
+ QString id_str = QString(f.readLine()).remove("\n");
+ QString data = QString(f.readLine()).remove("\n");
+
+ bool status;
+ int id = id_str.toInt(&status);
+
+ if (!status)
+ break;
+
+ switch (id)
+ {
+ case 0:
+ if (mode == "LINE" && (layername.isNull() || layername == layer)) {
+ lines.append(Line(p(x1, y1), p(x2, y2)));
+ }
+ mode = data;
+ break;
+ case 8:
+ layer = data;
+ break;
+ case 10:
+ x1 = data.toDouble();
+ break;
+ case 11:
+ x2 = data.toDouble();
+ break;
+ case 20:
+ y1 = data.toDouble();
+ break;
+ case 21:
+ y2 = data.toDouble();
+ break;
+ }
+ }
+
+ // extract all open paths
+ while (lines.count() > 0)
+ {
+ int current_line, current_point;
+
+ for (int i = 0; i < lines.count(); i++) {
+ for (int j = 0; j < 2; j++) {
+ for (int k = 0; k < lines.count(); k++) {
+ if (lines[i].p[j] == lines[k].p[0])
+ goto next_open_path_j;
+ if (lines[i].p[j] == lines[k].p[1])
+ goto next_open_path_j;
+ }
+ current_line = i;
+ current_point = j;
+ goto create_open_path;
+ next_open_path_j:;
+ }
+ }
+
+ break;
+
+ create_open_path:
+ paths.append(Path());
+ Path *this_path = &paths.last();
+
+ this_path->points.append(lines[current_line].p[current_point]);
+ while (1) {
+ this_path->points.append(lines[current_line].p[!current_point]);
+ Point *ref_point = lines[current_line].p[!current_point];
+ lines.remove(current_line);
+ for (int k = 0; k < lines.count(); k++) {
+ if (ref_point == lines[k].p[0]) {
+ current_line = k;
+ current_point = 0;
+ goto found_next_line_in_open_path;
+ }
+ if (ref_point == lines[k].p[1]) {
+ current_line = k;
+ current_point = 1;
+ goto found_next_line_in_open_path;
+ }
+ }
+ break;
+ found_next_line_in_open_path:;
+ }
+ }
+
+ // extract all closed paths
+ while (lines.count() > 0)
+ {
+ int current_line = 0, current_point = 0;
+
+ paths.append(Path());
+ Path *this_path = &paths.last();
+ this_path->is_closed = true;
+
+ this_path->points.append(lines[current_line].p[current_point]);
+ while (1) {
+ this_path->points.append(lines[current_line].p[!current_point]);
+ Point *ref_point = lines[current_line].p[!current_point];
+ lines.remove(current_line);
+ for (int k = 0; k < lines.count(); k++) {
+ if (ref_point == lines[k].p[0]) {
+ current_line = k;
+ current_point = 0;
+ goto found_next_line_in_closed_path;
+ }
+ if (ref_point == lines[k].p[1]) {
+ current_line = k;
+ current_point = 1;
+ goto found_next_line_in_closed_path;
+ }
+ }
+ break;
+ found_next_line_in_closed_path:;
+ }
+ }
+
+ if (paths.count() > 0) {
+ double min_x1 = paths[0].points[0]->x;
+ int min_x_path = 0;
+ for (int i = 0; i < paths.count(); i++) {
+ if (!paths[i].is_closed)
+ break;
+ paths[i].is_inner = true;
+ double min_x2 = paths[i].points[0]->x;
+ int min_x_point = 0;
+ for (int j = 0; j < paths[i].points.count(); j++) {
+ if (paths[i].points[j]->x < min_x1) {
+ min_x1 = paths[i].points[j]->x;
+ min_x_path = i;
+ }
+ if (paths[i].points[j]->x < min_x2) {
+ min_x2 = paths[i].points[j]->x;
+ min_x_point = j;
+ }
+ }
+ // rotate points if the path is not in non-standard rotation
+ int b = min_x_point;
+ int a = b == 0 ? paths[i].points.count() - 1 : b - 1;
+ int c = b == paths[i].points.count() - 1 ? 0 : b + 1;
+ double ax = paths[i].points[a]->x - paths[i].points[b]->x;
+ double ay = paths[i].points[a]->y - paths[i].points[b]->y;
+ double cx = paths[i].points[c]->x - paths[i].points[c]->x;
+ double cy = paths[i].points[c]->y - paths[i].points[c]->y;
+ if (atan2(ax, ay) < atan2(cx, cy)) {
+ for (int j = 0; j < paths[i].points.count()/2; j++)
+ paths[i].points.swap(j, paths[i].points.count()-1-j);
+ }
+ }
+ paths[min_x_path].is_inner = false;
+ }
+
+#if 0
+ printf("----- DXF Data -----\n");
+ for (int i = 0; i < paths.count(); i++) {
+ printf("Path %d (%s, %s):\n", i, paths[i].is_closed ? "closed" : "open", paths[i].is_inner ? "inner" : "outer");
+ for (int j = 0; j < paths[i].points.count(); j++)
+ printf(" %f %f\n", paths[i].points[j]->x, paths[i].points[j]->y);
+ }
+ printf("--------------------\n");
+#endif
+}
+
+DxfData::Point *DxfData::p(double x, double y)
+{
+ for (int i = 0; i < points.count(); i++) {
+ if (abs(points[i].x - x) < 0.01 && abs(points[i].y - y) < 0.01)
+ return &points[i];
+ }
+ points.append(Point(x, y));
+ return &points[points.count()-1];
+}
+
contact: Jan Huwald // Impressum