diff options
| -rw-r--r-- | context.cc | 2 | ||||
| -rw-r--r-- | dxfdata.cc | 2 | ||||
| -rw-r--r-- | dxflinextrude.cc | 97 | ||||
| -rw-r--r-- | dxftess.cc | 40 | ||||
| -rw-r--r-- | openscad.h | 2 | 
5 files changed, 104 insertions, 39 deletions
| @@ -72,7 +72,7 @@ Value Context::lookup_variable(QString name, bool silent) const  	if (variables.contains(name))  		return variables[name];  	if (parent) -		return parent->lookup_variable(name); +		return parent->lookup_variable(name, silent);  	if (!silent)  		PRINTA("WARNING: Ignoring unkown variable '%1'.", name);  	return Value(); @@ -83,7 +83,7 @@ DxfData::DxfData(double fn, double fs, double fa, QString filename, QString laye  				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)); +				n = ceil(n * (stop_angle-start_angle) / 360);  				for (int i = 0; i < n; i++) {  					double a1 = ((stop_angle-start_angle)*i)/n;  					double a2 = ((stop_angle-start_angle)*(i+1))/n; diff --git a/dxflinextrude.cc b/dxflinextrude.cc index 09d98d1..0bb771f 100644 --- a/dxflinextrude.cc +++ b/dxflinextrude.cc @@ -36,16 +36,16 @@ public:  class DxfLinearExtrudeNode : public AbstractPolyNode  {  public: -	int convexity; -	double fn, fs, fa, height; +	int convexity, slices; +	double fn, fs, fa, height, twist;  	double origin_x, origin_y, scale; -	bool center; +	bool center, has_twist;  	QString filename, layername;  	DxfLinearExtrudeNode(const ModuleInstanciation *mi) : AbstractPolyNode(mi) { -		convexity = 0; -		fn = fs = fa = height = 0; +		convexity = slices = 0; +		fn = fs = fa = height = twist = 0;  		origin_x = origin_y = scale = 0; -		center = false; +		center = has_twist = false;  	}  	virtual PolySet *render_polyset(render_mode_e mode) const;  	virtual QString dump(QString indent) const; @@ -72,6 +72,8 @@ AbstractNode *DxfLinearExtrudeModule::evaluate(const Context *ctx, const ModuleI  	Value origin = c.lookup_variable("origin", true);  	Value scale = c.lookup_variable("scale", true);  	Value center = c.lookup_variable("center", true); +	Value twist = c.lookup_variable("twist", true); +	Value slices = c.lookup_variable("slices", true);  	node->filename = file.text;  	node->layername = layer.text; @@ -92,6 +94,17 @@ AbstractNode *DxfLinearExtrudeModule::evaluate(const Context *ctx, const ModuleI  	if (node->scale <= 0)  		node->scale = 1; +	if (twist.type == Value::NUMBER) { +		node->twist = twist.num; +		if (slices.type == Value::NUMBER) { +			node->slices = slices.num; +		} else { +			node->slices = fmax(2, fabs(get_fragments_from_r(node->height, +					node->fn, node->fs, node->fa) * node->twist / 360)); +		} +		node->has_twist = true; +	} +  	return node;  } @@ -100,31 +113,44 @@ 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) +static void add_slice(PolySet *ps, DxfData::Path *pt, double rot1, double rot2, double h1, double h2)  {  	for (int j = 1; j < pt->points.count(); j++)  	{  		int k = j - 1; + +		double jx1 = pt->points[j]->x *  cos(rot1*M_PI/180) + pt->points[j]->y * sin(rot1*M_PI/180); +		double jy1 = pt->points[j]->x * -sin(rot1*M_PI/180) + pt->points[j]->y * cos(rot1*M_PI/180); + +		double jx2 = pt->points[j]->x *  cos(rot2*M_PI/180) + pt->points[j]->y * sin(rot2*M_PI/180); +		double jy2 = pt->points[j]->x * -sin(rot2*M_PI/180) + pt->points[j]->y * cos(rot2*M_PI/180); + +		double kx1 = pt->points[k]->x *  cos(rot1*M_PI/180) + pt->points[k]->y * sin(rot1*M_PI/180); +		double ky1 = pt->points[k]->x * -sin(rot1*M_PI/180) + pt->points[k]->y * cos(rot1*M_PI/180); + +		double kx2 = pt->points[k]->x *  cos(rot2*M_PI/180) + pt->points[k]->y * sin(rot2*M_PI/180); +		double ky2 = pt->points[k]->x * -sin(rot2*M_PI/180) + pt->points[k]->y * cos(rot2*M_PI/180); +  		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); +			ps->append_vertex(kx1, ky1, h1); +			ps->append_vertex(jx1, jy1, h1); +			ps->append_vertex(jx2, jy2, 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->insert_vertex(kx1, ky1, h1); +			ps->insert_vertex(jx1, jy1, h1); +			ps->insert_vertex(jx2, jy2, 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); +			ps->append_vertex(kx2, ky2, h2); +			ps->append_vertex(kx1, ky1, h1); +			ps->append_vertex(jx2, jy2, 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); +			ps->insert_vertex(kx2, ky2, h2); +			ps->insert_vertex(kx1, ky1, h1); +			ps->insert_vertex(jx2, jy2, h2);  		}  	}  } @@ -163,14 +189,35 @@ PolySet *DxfLinearExtrudeNode::render_polyset(render_mode_e) const  				dxf.paths[i].points.last()->y / scale + origin_y);  	} -	dxf_tesselate(ps, &dxf, false, h1); -	dxf_tesselate(ps, &dxf, true, h2); -	for (int i = 0; i < dxf.paths.count(); i++) +	if (has_twist)  	{ -		if (!dxf.paths[i].is_closed) -			continue; -		add_slice(ps, &dxf.paths[i], h1, h2); +		dxf_tesselate(ps, &dxf, 0, false, h1); +		dxf_tesselate(ps, &dxf, twist, true, h2); +		for (int j = 0; j < slices; j++) +		{ +			double t1 = twist*j / slices; +			double t2 = twist*(j+1) / slices; +			double g1 = h1 + (h2-h1)*j / slices; +			double g2 = h1 + (h2-h1)*(j+1) / slices; +			for (int i = 0; i < dxf.paths.count(); i++) +			{ +				if (!dxf.paths[i].is_closed) +					continue; +				add_slice(ps, &dxf.paths[i], t1, t2, g1, g2); +			} +		} +	} +	else +	{ +		dxf_tesselate(ps, &dxf, 0, false, h1); +		dxf_tesselate(ps, &dxf, 0, true, h2); +		for (int i = 0; i < dxf.paths.count(); i++) +		{ +			if (!dxf.paths[i].is_closed) +				continue; +			add_slice(ps, &dxf.paths[i], 0, 0, h1, h2); +		}  	}  	return ps; @@ -22,6 +22,8 @@  #include "openscad.h" +#undef DEBUG_TRIANGLE_SPLITTING +  struct tess_vdata {  	GLdouble v[3];  }; @@ -152,7 +154,7 @@ static bool point_on_line(double *p1, double *p2, double *p3)  	return true;  } -void dxf_tesselate(PolySet *ps, DxfData *dxf, bool up, double h) +void dxf_tesselate(PolySet *ps, DxfData *dxf, double rot, bool up, double h)  {  	GLUtesselator *tobj = gluNewTess(); @@ -233,7 +235,9 @@ void dxf_tesselate(PolySet *ps, DxfData *dxf, bool up, double h)  	while (added_triangles)  	{  		added_triangles = false; -		// printf("*** Triangle splitting (%d) ***\n", tess_tri.count()+1); +#ifdef DEBUG_TRIANGLE_SPLITTING +		printf("*** Triangle splitting (%d) ***\n", tess_tri.count()+1); +#endif  		for (int i = 0; i < tess_tri.count(); i++)  		for (int k = 0; k < 3; k++)  		{ @@ -245,16 +249,20 @@ void dxf_tesselate(PolySet *ps, DxfData *dxf, bool up, double h)  					if (i != jl.first)  						possible_neigh[jl] = jl;  			} -			// printf("%d/%d: %d\n", i, k, possible_neigh.count()); +#ifdef DEBUG_TRIANGLE_SPLITTING +			printf("%d/%d: %d\n", i, k, possible_neigh.count()); +#endif  			foreach (QPair_ii jl, possible_neigh) {  				int j = jl.first;  				for (int l = jl.second; l != (jl.second + 2) % 3; l = (l + 1) % 3)  				if (point_on_line(tess_tri[i].p[k], tess_tri[j].p[l], tess_tri[i].p[(k+1)%3])) { -					// printf("%% %f %f %f %f %f %f [%d %d]\n", -					// 		tess_tri[i].p[k][0], tess_tri[i].p[k][1], -					// 		tess_tri[j].p[l][0], tess_tri[j].p[l][1], -					// 		tess_tri[i].p[(k+1)%3][0], tess_tri[i].p[(k+1)%3][1], -					// 		i, j); +#ifdef DEBUG_TRIANGLE_SPLITTING +					printf("%% %f %f %f %f %f %f [%d %d]\n", +							tess_tri[i].p[k][0], tess_tri[i].p[k][1], +							tess_tri[j].p[l][0], tess_tri[j].p[l][1], +							tess_tri[i].p[(k+1)%3][0], tess_tri[i].p[(k+1)%3][1], +							i, j); +#endif  					tess_tri.append(tess_triangle(tess_tri[j].p[l],  							tess_tri[i].p[(k+1)%3], tess_tri[i].p[(k+2)%3]));  					for (int m = 0; m < 2; m++) { @@ -283,10 +291,20 @@ void dxf_tesselate(PolySet *ps, DxfData *dxf, bool up, double h)  		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 +		double x, y;  		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]); + +		x = tess_tri[i].p[0][0] *  cos(rot*M_PI/180) + tess_tri[i].p[0][1] * sin(rot*M_PI/180); +		y = tess_tri[i].p[0][0] * -sin(rot*M_PI/180) + tess_tri[i].p[0][1] * cos(rot*M_PI/180); +		ps->insert_vertex(x, y, tess_tri[i].p[0][2]); + +		x = tess_tri[i].p[1][0] *  cos(rot*M_PI/180) + tess_tri[i].p[1][1] * sin(rot*M_PI/180); +		y = tess_tri[i].p[1][0] * -sin(rot*M_PI/180) + tess_tri[i].p[1][1] * cos(rot*M_PI/180); +		ps->insert_vertex(x, y, tess_tri[i].p[1][2]); + +		x = tess_tri[i].p[2][0] *  cos(rot*M_PI/180) + tess_tri[i].p[2][1] * sin(rot*M_PI/180); +		y = tess_tri[i].p[2][0] * -sin(rot*M_PI/180) + tess_tri[i].p[2][1] * cos(rot*M_PI/180); +		ps->insert_vertex(x, y, tess_tri[i].p[2][2]);  		int i0 = point_to_path.data(tess_tri[i].p[0][0], tess_tri[i].p[0][1], tess_tri[i].p[0][2]).first;  		int j0 = point_to_path.data(tess_tri[i].p[0][0], tess_tri[i].p[0][1], tess_tri[i].p[0][2]).second; @@ -583,7 +583,7 @@ extern void *progress_report_vp;  void progress_report_prep(AbstractNode *root, void (*f)(const class AbstractNode *node, void *vp, int mark), void *vp);  void progress_report_fin(); -void dxf_tesselate(PolySet *ps, DxfData *dxf, bool up, double h); +void dxf_tesselate(PolySet *ps, DxfData *dxf, double rot, bool up, double h);  #else | 
