diff options
| author | clifford <clifford@b57f626f-c46c-0410-a088-ec61d464b74c> | 2009-07-16 23:11:08 (GMT) | 
|---|---|---|
| committer | clifford <clifford@b57f626f-c46c-0410-a088-ec61d464b74c> | 2009-07-16 23:11:08 (GMT) | 
| commit | d05ea4453b875870375884d6671ca4f0cea624d8 (patch) | |
| tree | 53ca5894e2f8d11afa33cbeaffb67bd9f15da1d2 | |
| parent | cc3291a4f1def85273e0e1cc6e43bb0079965946 (diff) | |
Clifford Wolf:
	Added first steps towards dxf extrusion support
git-svn-id: http://svn.clifford.at/openscad/trunk@57 b57f626f-c46c-0410-a088-ec61d464b74c
| -rw-r--r-- | dxfdata.cc | 213 | ||||
| -rw-r--r-- | dxflinextrude.cc | 352 | ||||
| -rw-r--r-- | lexer.l | 7 | ||||
| -rw-r--r-- | mainwin.cc | 2 | ||||
| -rw-r--r-- | module.cc | 1 | ||||
| -rw-r--r-- | openscad.h | 28 | ||||
| -rw-r--r-- | openscad.pro | 4 | ||||
| -rw-r--r-- | polyset.cc | 20 | 
8 files changed, 625 insertions, 2 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]; +} + diff --git a/dxflinextrude.cc b/dxflinextrude.cc new file mode 100644 index 0000000..c03da0a --- /dev/null +++ b/dxflinextrude.cc @@ -0,0 +1,352 @@ +/* + *  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 + * + */ + +#define INCLUDE_ABSTRACT_NODE_DETAILS + +#include "openscad.h" + +class DxfLinearExtrudeModule : public AbstractModule +{ +public: +	DxfLinearExtrudeModule() { } +	virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstanciation *inst) const; +}; + +class DxfLinearExtrudeNode : public AbstractPolyNode +{ +public: +	int convexity; +	double fn, fs, fa, height; +	QString filename, layername; +	DxfLinearExtrudeNode(const ModuleInstanciation *mi) : AbstractPolyNode(mi) { } +	virtual PolySet *render_polyset(render_mode_e mode) const; +	virtual QString dump(QString indent) const; +}; + +AbstractNode *DxfLinearExtrudeModule::evaluate(const Context *ctx, const ModuleInstanciation *inst) const +{ +	DxfLinearExtrudeNode *node = new DxfLinearExtrudeNode(inst); + +	QVector<QString> argnames = QVector<QString>() << "file" << "layer" << "height"; +	QVector<Expression*> argexpr; + +	Context c(ctx); +	c.args(argnames, argexpr, inst->argnames, inst->argvalues); + +	node->fn = c.lookup_variable("$fn").num; +	node->fs = c.lookup_variable("$fs").num; +	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"); + +	node->filename = file.text; +	node->layername = layer.text; +	node->height = height.num; +	node->convexity = convexity.num; + +	if (node->height <= 0) +		node->height = 100; + +	if (node->convexity <= 0) +		node->convexity = 1; + +	return node; +} + +void register_builtin_dxf_linear_extrude() +{ +	builtin_modules["dxf_linear_extrude"] = new DxfLinearExtrudeModule(); +} + +static void add_slice(PolySet *ps, DxfData::Path *pt, double h1, double h2) +{ +	for (int j = 1; j < pt->points.count(); j++) +	{ +		int k = j - 1; +		ps->append_poly(); +		if (pt->is_inner) { +			ps->append_vertex(pt->points[k]->x, pt->points[k]->y, h1); +			ps->append_vertex(pt->points[j]->x, pt->points[j]->y, h1); +			ps->append_vertex(pt->points[j]->x, pt->points[j]->y, h2); +		} else { +			ps->insert_vertex(pt->points[k]->x, pt->points[k]->y, h1); +			ps->insert_vertex(pt->points[j]->x, pt->points[j]->y, h1); +			ps->insert_vertex(pt->points[j]->x, pt->points[j]->y, h2); +		} + +		ps->append_poly(); +		if (pt->is_inner) { +			ps->append_vertex(pt->points[k]->x, pt->points[k]->y, h2); +			ps->append_vertex(pt->points[k]->x, pt->points[k]->y, h1); +			ps->append_vertex(pt->points[j]->x, pt->points[j]->y, h2); +		} else { +			ps->insert_vertex(pt->points[k]->x, pt->points[k]->y, h2); +			ps->insert_vertex(pt->points[k]->x, pt->points[k]->y, h1); +			ps->insert_vertex(pt->points[j]->x, pt->points[j]->y, h2); +		} +	} +} + +struct tess_vdata { +	GLdouble v[3]; +}; + +struct tess_triangle { +	GLdouble *p[3]; +	tess_triangle() { p[0] = NULL; p[1] = NULL; p[2] = NULL; } +	tess_triangle(double *p1, double *p2, double *p3) { p[0] = p1; p[1] = p2; p[2] = p3; } +}; + +static GLenum tess_type; +static int tess_count; +static QVector<tess_triangle> tess_tri; +static GLdouble *tess_p1, *tess_p2; + +static void tess_vertex(void *vertex_data) +{ +	GLdouble *p = (double*)vertex_data; +#if 0 +	printf("  %d: %f %f %f\n", tess_count, p[0], p[1], p[2]); +#endif +	if (tess_type == GL_TRIANGLE_FAN) { +		if (tess_count == 0) { +			tess_p1 = p; +		} +		if (tess_count == 1) { +			tess_p2 = p; +		} +		if (tess_count > 1) { +			tess_tri.append(tess_triangle(tess_p1, tess_p2, p)); +			tess_p2 = p; +		} +	} +	if (tess_type == GL_TRIANGLE_STRIP) { +		if (tess_count == 0) { +			tess_p1 = p; +		} +		if (tess_count == 1) { +			tess_p2 = p; +		} +		if (tess_count > 1) { +			if (tess_count % 2 == 1) { +				tess_tri.append(tess_triangle(tess_p2, tess_p1, p)); +			} else { +				tess_tri.append(tess_triangle(tess_p1, tess_p2, p)); +			} +			tess_p1 = tess_p2; +			tess_p2 = p; +		} +	} +	if (tess_type == GL_TRIANGLES) { +		if (tess_count == 0) { +			tess_p1 = p; +		} +		if (tess_count == 1) { +			tess_p2 = p; +		} +		if (tess_count == 2) { +			tess_tri.append(tess_triangle(tess_p1, tess_p2, p)); +			tess_count = -1; +		} +	} +	tess_count++; +} + +static void tess_begin(GLenum type) +{ +#if 0 +	if (type == GL_TRIANGLE_FAN) { +		printf("GL_TRIANGLE_FAN:\n"); +	} +	if (type == GL_TRIANGLE_STRIP) { +		printf("GL_TRIANGLE_STRIP:\n"); +	} +	if (type == GL_TRIANGLES) { +		printf("GL_TRIANGLES:\n"); +	} +#endif +	tess_count = 0; +	tess_type = type; +} + +static void tess_end(void) +{ +	/* nothing to be done here */ +} + +static void tess_error(GLenum errno) +{ +	PRINTF("GLU tesselation error %d!", errno); +} + +static bool point_on_line(double *p1, double *p2, double *p3) +{ +	if (fabs(p1[0] - p2[0]) < 0.0001 && fabs(p1[1] - p2[1]) < 0.0001) +		return false; + +	if (fabs(p3[0] - p2[0]) < 0.0001 && fabs(p3[1] - p2[1]) < 0.0001) +		return false; + +	double v1[2] = { p2[0] - p1[0], p2[1] - p1[1] }; +	double v2[2] = { p3[0] - p1[0], p3[1] - p1[1] }; + +	if (fabs(atan2(v1[0], v1[1]) - atan2(v2[0], v2[1])) < 0.0001 && +			sqrt(v1[0]*v1[0] + v1[1]*v1[1]) < sqrt(v2[0]*v2[0] + v2[1]*v2[1])) { +#if 0 +		printf("Point on line: %f/%f %f/%f %f/%f\n", p1[0], p1[1], p2[0], p2[1], p3[0], p3[1]); +#endif +		return true; +	} + +	return false; +} + +static void tess(PolySet *ps, DxfData *dxf, bool up, double h) +{ +	GLUtesselator *tobj = gluNewTess(); + +	gluTessCallback(tobj, GLU_TESS_VERTEX, (GLvoid(*)())&tess_vertex); +	gluTessCallback(tobj, GLU_TESS_BEGIN, (GLvoid(*)())&tess_begin); +	gluTessCallback(tobj, GLU_TESS_END, (GLvoid(*)())&tess_end); +	gluTessCallback(tobj, GLU_TESS_ERROR, (GLvoid(*)())&tess_error); + +	tess_tri.clear(); +	QList<tess_vdata> vl; + +	gluTessBeginPolygon(tobj, NULL); + +	for (int i = 0; i < dxf->paths.count(); i++) { +		if (!dxf->paths[i].is_closed) +			continue; +		gluTessBeginContour(tobj); +		if (up != dxf->paths[i].is_inner) { +			for (int j = 1; j < dxf->paths[i].points.count(); j++) { +				vl.append(tess_vdata()); +				vl.last().v[0] = dxf->paths[i].points[j]->x; +				vl.last().v[1] = dxf->paths[i].points[j]->y; +				vl.last().v[2] = h; +				gluTessVertex(tobj, vl.last().v, vl.last().v); +			} +		} else { +			for (int j = dxf->paths[i].points.count() - 1; j > 0; j--) { +				vl.append(tess_vdata()); +				vl.last().v[0] = dxf->paths[i].points[j]->x; +				vl.last().v[1] = dxf->paths[i].points[j]->y; +				vl.last().v[2] = h; +				gluTessVertex(tobj, vl.last().v, vl.last().v); +			} +		} +		gluTessEndContour(tobj); +	} + +	gluTessEndPolygon(tobj); +	gluDeleteTess(tobj); + +#if 0 +	for (int i = 0; i < tess_tri.count(); i++) { +		printf("~~~\n"); +		printf("  %f %f %f\n", tess_tri[i].p[0][0], tess_tri[i].p[0][1], tess_tri[i].p[0][2]); +		printf("  %f %f %f\n", tess_tri[i].p[1][0], tess_tri[i].p[1][1], tess_tri[i].p[1][2]); +		printf("  %f %f %f\n", tess_tri[i].p[2][0], tess_tri[i].p[2][1], tess_tri[i].p[2][2]); +	} +#endif + +	// GLU tessing sometimes generates degenerated triangles. We must find and remove +	// them so we can use the triangle array with CGAL.. +	for (int i = 0; i < tess_tri.count(); i++) { +		if (point_on_line(tess_tri[i].p[0], tess_tri[i].p[1], tess_tri[i].p[2]) || +				point_on_line(tess_tri[i].p[1], tess_tri[i].p[2], tess_tri[i].p[0]) || +				point_on_line(tess_tri[i].p[2], tess_tri[i].p[0], tess_tri[i].p[1])) { +			tess_tri.remove(i--); +		} +	} + +	// GLU tessing might merge points into edges. This is ok for GL displaying but +	// creates invalid polyeders for CGAL. So we split this tirangles up again in order +	// to create polyeders that are also accepted by CGAL.. +	bool added_triangles = true; +	while (added_triangles) +	{ +		added_triangles = false; +		for (int i = 0; i < tess_tri.count(); i++) +		for (int j = 0; j < tess_tri.count(); j++) +		for (int k = 0; k < 3; k++) +		for (int l = 0; l < 3; l++) { +			if (point_on_line(tess_tri[i].p[k], tess_tri[j].p[l], tess_tri[i].p[(k+1)%3])) { +				tess_tri.append(tess_triangle(tess_tri[j].p[l], +						tess_tri[i].p[(k+1)%3], tess_tri[i].p[(k+2)%3])); +				tess_tri[i].p[(k+1)%3] = tess_tri[j].p[l]; +				added_triangles = true; +			} +		} +	} + +	for (int i = 0; i < tess_tri.count(); i++) { +#if 0 +		printf("---\n"); +		printf("  %f %f %f\n", tess_tri[i].p[0][0], tess_tri[i].p[0][1], tess_tri[i].p[0][2]); +		printf("  %f %f %f\n", tess_tri[i].p[1][0], tess_tri[i].p[1][1], tess_tri[i].p[1][2]); +		printf("  %f %f %f\n", tess_tri[i].p[2][0], tess_tri[i].p[2][1], tess_tri[i].p[2][2]); +#endif +		ps->append_poly(); +		ps->insert_vertex(tess_tri[i].p[0][0], tess_tri[i].p[0][1], tess_tri[i].p[0][2]); +		ps->insert_vertex(tess_tri[i].p[1][0], tess_tri[i].p[1][1], tess_tri[i].p[1][2]); +		ps->insert_vertex(tess_tri[i].p[2][0], tess_tri[i].p[2][1], tess_tri[i].p[2][2]); +	} + +	tess_tri.clear(); +} + +PolySet *DxfLinearExtrudeNode::render_polyset(render_mode_e) const +{ +	DxfData dxf(fn, fs, fa, filename, layername); + +	PolySet *ps = new PolySet(); +	ps->convexity = convexity; + +	for (int i = 0; i < dxf.paths.count(); i++) +	{ +		if (!dxf.paths[i].is_closed) +			continue; +		add_slice(ps, &dxf.paths[i], 0, height); +	} + +	tess(ps, &dxf, false, 0); +	tess(ps, &dxf, true, height); + +	return ps; +} + +QString DxfLinearExtrudeNode::dump(QString indent) const +{ +	if (dump_cache.isEmpty()) { +		QString text; +		text.sprintf("dxf_linear_extrude(file = \"%s\", layer = \"%s\", height = %f, " +				"$fn = %f, $fa = %f, $fs = %f);\n", +				filename.toAscii().data(), layername.toAscii().data(), +				height, fn, fs, fa); +		((AbstractNode*)this)->dump_cache = indent + QString("n%1: ").arg(idx) + text; +	} +	return dump_cache; +} + @@ -54,7 +54,12 @@ extern const char *parser_input_buffer;  [+-]?[0-9][0-9.]* { parserlval.number = atof(yytext); return TOK_NUMBER; }  "$"?[a-zA-Z0-9_]+ { parserlval.text = strdup(yytext); return TOK_ID; } -\"[^"]*\" { parserlval.text = strdup(yytext); return TOK_STRING; } + +\"[^"]*\" { +	parserlval.text = strdup(yytext+1); +	parserlval.text[strlen(parserlval.text)-1] = 0; +	return TOK_STRING; +}  [\n\r\t ]  \/\/[^\n]*\n @@ -645,6 +645,7 @@ void MainWindow::actionExportSTL()  {  	current_win = this; +#ifdef ENABLE_CGAL  	if (!root_N) {  		PRINT("Nothing to export! Try building first (press F6).");  		current_win = NULL; @@ -736,6 +737,7 @@ void MainWindow::actionExportSTL()  	PRINT("STL export finished.");  	delete pd; +#endif /* ENABLE_CGAL */  	current_win = NULL;  } @@ -191,6 +191,7 @@ void initialize_builtin_modules()  	register_builtin_primitives();  	register_builtin_control();  	register_builtin_render(); +	register_builtin_dxf_linear_extrude();  }  void destroy_builtin_modules() @@ -264,6 +264,7 @@ extern void register_builtin_transform();  extern void register_builtin_primitives();  extern void register_builtin_control();  extern void register_builtin_render(); +extern void register_builtin_dxf_linear_extrude();  class Context  { @@ -288,6 +289,33 @@ public:  	AbstractNode *evaluate_module(const ModuleInstanciation *inst) const;  }; +class DxfData +{ +public: +	struct Point { +		double x, y; +		Point() : x(0), y(0) { } +		Point(double x, double y) : x(x), y(y) { } +	}; +	struct Line { +		Point *p[2]; +		Line(Point *p1, Point *p2) { p[0] = p1; p[1] = p2; } +		Line() { p[0] = NULL; p[1] = NULL; } +	}; +	struct Path { +		QList<Point*> points; +		bool is_closed, is_inner; +		Path() : is_closed(false), is_inner(false) { } +	}; + +	QList<Point> points; +	QList<Path> paths; + +	DxfData(double fn, double fs, double fa, QString filename, QString layername = QString()); + +	Point *p(double x, double y); +}; +  // The CGAL template magic slows down the compilation process by a factor of 5.  // So we only include the declaration of AbstractNode where it is needed...  #ifdef INCLUDE_ABSTRACT_NODE_DETAILS diff --git a/openscad.pro b/openscad.pro index cd990e1..3d24bd8 100644 --- a/openscad.pro +++ b/openscad.pro @@ -16,8 +16,10 @@ SOURCES += openscad.cc mainwin.cc glview.cc  SOURCES += value.cc expr.cc func.cc module.cc context.cc  SOURCES += csgterm.cc polyset.cc csgops.cc transform.cc  SOURCES += primitives.cc control.cc render.cc +SOURCES += dxfdata.cc dxflinextrude.cc -QMAKE_CXXFLAGS += -O3 -march=pentium +QMAKE_CXXFLAGS += -O0 +// QMAKE_CXXFLAGS += -O3 -march=pentium  // QMAKE_CXXFLAGS += -O3 -march=athlon64  QT += opengl @@ -180,6 +180,8 @@ void PolySet::render_edges(colormode_e colormode) const  #ifdef ENABLE_CGAL +#undef GEN_SURFACE_DEBUG +  class CGAL_Build_PolySet : public CGAL::Modifier_base<CGAL_HDS>  {  public: @@ -211,23 +213,41 @@ public:  		}  		B.begin_surface(vertices.size(), ps->polygons.size()); +#ifdef GEN_SURFACE_DEBUG +		printf("=== CGAL Surface ===\n"); +#endif  		for (int i = 0; i < vertices.size(); i++) {  			const PolySet::Point *p = &vertices[i];  			B.add_vertex(Point(p->x, p->y, p->z)); +#ifdef GEN_SURFACE_DEBUG +			printf("%d: %f %f %f\n", i, p->x, p->y, p->z); +#endif  		}  		for (int i = 0; i < ps->polygons.size(); i++) {  			const PolySet::Polygon *poly = &ps->polygons[i];  			B.begin_facet(); +#ifdef GEN_SURFACE_DEBUG +			printf("F:"); +#endif  			for (int j = 0; j < poly->size(); j++) {  				const PolySet::Point *p = &poly->at(j);  				PointKey_t pk = PointKey(p->x, p->y, p->z); +#ifdef GEN_SURFACE_DEBUG +				printf(" %d", vertices_idx[pk]); +#endif  				B.add_vertex_to_facet(vertices_idx[pk]);  			} +#ifdef GEN_SURFACE_DEBUG +			printf("\n"); +#endif  			B.end_facet();  		} +#ifdef GEN_SURFACE_DEBUG +		printf("====================\n"); +#endif  		B.end_surface();  		#undef PointKey | 
