diff options
author | Marius Kintel <marius@kintel.net> | 2013-05-10 16:01:50 (GMT) |
---|---|---|
committer | Marius Kintel <marius@kintel.net> | 2013-05-10 16:01:50 (GMT) |
commit | adffb9121fbf5d12542ae0d8c5a010e78cc8a4f9 (patch) | |
tree | b13fa35d6b9d807b3c2d7a4c195b49624c2c3297 | |
parent | 130e10778e9d74ceb07dfc813b85d75a52a71e10 (diff) |
Added support for 2D scaling in linear_extrude
-rw-r--r-- | src/CGALRenderer.cc | 2 | ||||
-rw-r--r-- | src/CGAL_Nef_polyhedron.cc | 2 | ||||
-rw-r--r-- | src/CGAL_Nef_polyhedron_DxfData.cc | 2 | ||||
-rw-r--r-- | src/PolySetCGALEvaluator.cc | 55 | ||||
-rw-r--r-- | src/dxftess-cgal.cc | 10 | ||||
-rw-r--r-- | src/dxftess-glu.cc | 6 | ||||
-rw-r--r-- | src/dxftess.h | 4 | ||||
-rw-r--r-- | src/import.cc | 2 | ||||
-rw-r--r-- | src/linearextrude.cc | 12 | ||||
-rw-r--r-- | src/linearextrudenode.h | 5 | ||||
-rw-r--r-- | src/primitives.cc | 2 | ||||
-rw-r--r-- | testdata/scad/features/linear_extrude-scale-tests.scad | 17 |
12 files changed, 72 insertions, 47 deletions
diff --git a/src/CGALRenderer.cc b/src/CGALRenderer.cc index aadc2b4..0a75266 100644 --- a/src/CGALRenderer.cc +++ b/src/CGALRenderer.cc @@ -52,7 +52,7 @@ CGALRenderer::CGALRenderer(const CGAL_Nef_polyhedron &root) : root(root) this->polyhedron = NULL; this->polyset = new PolySet(); this->polyset->is2d = true; - dxf_tesselate(this->polyset, *dd, 0, 1, true, false, 0); + dxf_tesselate(this->polyset, *dd, 0, Vector2d(1,1), true, false, 0); delete dd; } else if (root.dim == 3) { diff --git a/src/CGAL_Nef_polyhedron.cc b/src/CGAL_Nef_polyhedron.cc index d9cd174..440f4ed 100644 --- a/src/CGAL_Nef_polyhedron.cc +++ b/src/CGAL_Nef_polyhedron.cc @@ -90,7 +90,7 @@ PolySet *CGAL_Nef_polyhedron::convertToPolyset() ps = new PolySet(); DxfData *dd = this->convertToDxfData(); ps->is2d = true; - dxf_tesselate(ps, *dd, 0, 1, true, false, 0); + dxf_tesselate(ps, *dd, 0, Vector2d(1,1), true, false, 0); dxf_border_to_ps(ps, *dd); delete dd; } diff --git a/src/CGAL_Nef_polyhedron_DxfData.cc b/src/CGAL_Nef_polyhedron_DxfData.cc index 0388fe5..c4347e8 100644 --- a/src/CGAL_Nef_polyhedron_DxfData.cc +++ b/src/CGAL_Nef_polyhedron_DxfData.cc @@ -123,7 +123,7 @@ void CGAL_Nef_polyhedron::transform( const Transform3d &matrix ) PolySet ps; ps.is2d = true; - dxf_tesselate(&ps, *dd, 0, true, false, 0); + dxf_tesselate(&ps, *dd, 0, Vector2d(1,1), true, false, 0); Tree nulltree; CGALEvaluator tmpeval(nulltree); diff --git a/src/PolySetCGALEvaluator.cc b/src/PolySetCGALEvaluator.cc index 6d0704e..f0c274f 100644 --- a/src/PolySetCGALEvaluator.cc +++ b/src/PolySetCGALEvaluator.cc @@ -205,31 +205,32 @@ PolySet *PolySetCGALEvaluator::evaluatePolySet(const ProjectionNode &node) static void add_slice(PolySet *ps, const DxfData &dxf, DxfData::Path &path, double rot1, double rot2, double h1, double h2, - double scale1, double scale2) + double scale1_x, double scale1_y, + double scale2_x, double scale2_y) { // FIXME: If scale2 == 0 we need to handle tessellation separately bool splitfirst = sin(rot2 - rot1) >= 0.0; for (size_t j = 1; j < path.indices.size(); j++) { int k = j - 1; - double jx1 = scale1 * (dxf.points[path.indices[j]][0] * cos(rot1*M_PI/180) + + double jx1 = scale1_x * (dxf.points[path.indices[j]][0] * cos(rot1*M_PI/180) + dxf.points[path.indices[j]][1] * sin(rot1*M_PI/180)); - double jy1 = scale1 * (dxf.points[path.indices[j]][0] * -sin(rot1*M_PI/180) + + double jy1 = scale1_y * (dxf.points[path.indices[j]][0] * -sin(rot1*M_PI/180) + dxf.points[path.indices[j]][1] * cos(rot1*M_PI/180)); - double jx2 = scale2 * (dxf.points[path.indices[j]][0] * cos(rot2*M_PI/180) + + double jx2 = scale2_x * (dxf.points[path.indices[j]][0] * cos(rot2*M_PI/180) + dxf.points[path.indices[j]][1] * sin(rot2*M_PI/180)); - double jy2 = scale2 * (dxf.points[path.indices[j]][0] * -sin(rot2*M_PI/180) + + double jy2 = scale2_y * (dxf.points[path.indices[j]][0] * -sin(rot2*M_PI/180) + dxf.points[path.indices[j]][1] * cos(rot2*M_PI/180)); - double kx1 = scale1 * (dxf.points[path.indices[k]][0] * cos(rot1*M_PI/180) + + double kx1 = scale1_x * (dxf.points[path.indices[k]][0] * cos(rot1*M_PI/180) + dxf.points[path.indices[k]][1] * sin(rot1*M_PI/180)); - double ky1 = scale1 * (dxf.points[path.indices[k]][0] * -sin(rot1*M_PI/180) + + double ky1 = scale1_y * (dxf.points[path.indices[k]][0] * -sin(rot1*M_PI/180) + dxf.points[path.indices[k]][1] * cos(rot1*M_PI/180)); - double kx2 = scale2 * (dxf.points[path.indices[k]][0] * cos(rot2*M_PI/180) + + double kx2 = scale2_x * (dxf.points[path.indices[k]][0] * cos(rot2*M_PI/180) + dxf.points[path.indices[k]][1] * sin(rot2*M_PI/180)); - double ky2 = scale2 * (dxf.points[path.indices[k]][0] * -sin(rot2*M_PI/180) + + double ky2 = scale2_y * (dxf.points[path.indices[k]][0] * -sin(rot2*M_PI/180) + dxf.points[path.indices[k]][1] * cos(rot2*M_PI/180)); if (splitfirst) { @@ -244,7 +245,7 @@ static void add_slice(PolySet *ps, const DxfData &dxf, DxfData::Path &path, ps->insert_vertex(jx2, jy2, h2); } - if (scale2 > 0) { + if (scale2_x > 0 || scale2_y > 0) { ps->append_poly(); if (path.is_inner) { ps->append_vertex(kx2, ky2, h2); @@ -269,7 +270,7 @@ static void add_slice(PolySet *ps, const DxfData &dxf, DxfData::Path &path, ps->insert_vertex(kx2, ky2, h2); } - if (scale2 > 0) { + if (scale2_x > 0 || scale2_y > 0) { ps->append_poly(); if (path.is_inner) { ps->append_vertex(jx2, jy2, h2); @@ -311,7 +312,7 @@ PolySet *PolySetCGALEvaluator::evaluatePolySet(const LinearExtrudeNode &node) if (sum.isNull()) return NULL; dxf = sum.convertToDxfData();; } else { - dxf = new DxfData(node.fn, node.fs, node.fa, node.filename, node.layername, node.origin_x, node.origin_y, node.scale); + dxf = new DxfData(node.fn, node.fs, node.fa, node.filename, node.layername, node.origin_x, node.origin_y, node.scale_x); } PolySet *ps = extrudeDxfData(node, *dxf); @@ -343,39 +344,41 @@ PolySet *PolySetCGALEvaluator::extrudeDxfData(const LinearExtrudeNode &node, Dxf first_open_path = false; } PRINTB(" %9.5f %10.5f ... %10.5f %10.5f", - (dxf.points[dxf.paths[i].indices.front()][0] / node.scale + node.origin_x) % - (dxf.points[dxf.paths[i].indices.front()][1] / node.scale + node.origin_y) % - (dxf.points[dxf.paths[i].indices.back()][0] / node.scale + node.origin_x) % - (dxf.points[dxf.paths[i].indices.back()][1] / node.scale + node.origin_y)); + (dxf.points[dxf.paths[i].indices.front()][0] / node.scale_x + node.origin_x) % + (dxf.points[dxf.paths[i].indices.front()][1] / node.scale_y + node.origin_y) % + (dxf.points[dxf.paths[i].indices.back()][0] / node.scale_x + node.origin_x) % + (dxf.points[dxf.paths[i].indices.back()][1] / node.scale_y + node.origin_y)); } if (node.has_twist) { - dxf_tesselate(ps, dxf, 0, 1, false, true, h1); - if (node.scale > 0) { - dxf_tesselate(ps, dxf, node.twist, node.scale, true, true, h2); + dxf_tesselate(ps, dxf, 0, Vector2d(1,1), false, true, h1); // bottom + if (node.scale_x > 0 || node.scale_y > 0) { + dxf_tesselate(ps, dxf, node.twist, Vector2d(node.scale_x, node.scale_y), true, true, h2); // top } for (int j = 0; j < node.slices; j++) { double t1 = node.twist*j / node.slices; double t2 = node.twist*(j+1) / node.slices; double g1 = h1 + (h2-h1)*j / node.slices; double g2 = h1 + (h2-h1)*(j+1) / node.slices; - double s1 = 1 - (1-node.scale)*j / node.slices; - double s2 = 1 - (1-node.scale)*(j+1) / node.slices; + double s1x = 1 - (1-node.scale_x)*j / node.slices; + double s1y = 1 - (1-node.scale_y)*j / node.slices; + double s2x = 1 - (1-node.scale_x)*(j+1) / node.slices; + double s2y = 1 - (1-node.scale_y)*(j+1) / node.slices; for (size_t i = 0; i < dxf.paths.size(); i++) { if (!dxf.paths[i].is_closed) continue; - add_slice(ps, dxf, dxf.paths[i], t1, t2, g1, g2, s1, s2); + add_slice(ps, dxf, dxf.paths[i], t1, t2, g1, g2, s1x, s1y, s2x, s2y); } } } else { - dxf_tesselate(ps, dxf, 0, 1, false, true, h1); - if (node.scale > 0) { - dxf_tesselate(ps, dxf, 0, node.scale, true, true, h2); + dxf_tesselate(ps, dxf, 0, Vector2d(1,1), false, true, h1); //bottom + if (node.scale_x > 0 || node.scale_y > 0) { + dxf_tesselate(ps, dxf, 0, Vector2d(node.scale_x, node.scale_y), true, true, h2); // top } for (size_t i = 0; i < dxf.paths.size(); i++) { if (!dxf.paths[i].is_closed) continue; - add_slice(ps, dxf, dxf.paths[i], 0, 0, h1, h2, 1, node.scale); + add_slice(ps, dxf, dxf.paths[i], 0, 0, h1, h2, 1, 1, node.scale_x, node.scale_y); } } diff --git a/src/dxftess-cgal.cc b/src/dxftess-cgal.cc index fffa4f1..16eaf9f 100644 --- a/src/dxftess-cgal.cc +++ b/src/dxftess-cgal.cc @@ -101,7 +101,7 @@ void mark_inner_outer(std::vector<struct triangle> &tri, Grid2d<point_info_t> &p } } -void dxf_tesselate(PolySet *ps, DxfData &dxf, double rot, double scale, bool up, bool /* do_triangle_splitting */, double h) +void dxf_tesselate(PolySet *ps, DxfData &dxf, double rot, Vector2d scale, bool up, bool /* do_triangle_splitting */, double h) { CDT cdt; @@ -124,8 +124,8 @@ void dxf_tesselate(PolySet *ps, DxfData &dxf, double rot, double scale, bool up, struct point_info_t *first_pi = NULL, *prev_pi = NULL; for (size_t j = 1; j < dxf.paths[i].indices.size(); j++) { - double x = scale * dxf.points[dxf.paths[i].indices[j]][0]; - double y = scale * dxf.points[dxf.paths[i].indices[j]][1]; + double x = dxf.points[dxf.paths[i].indices[j]][0]; + double y = dxf.points[dxf.paths[i].indices[j]][1]; if (point_info.has(x, y)) { // FIXME: How can the same path set contain the same point twice? @@ -314,8 +314,8 @@ void dxf_tesselate(PolySet *ps, DxfData &dxf, double rot, double scale, bool up, int idx = up ? j : (2-j); double px = tri[i].p[idx].x; double py = tri[i].p[idx].y; - ps->append_vertex(px * cos(rot*M_PI/180) + py * sin(rot*M_PI/180), - px * -sin(rot*M_PI/180) + py * cos(rot*M_PI/180), h); + ps->append_vertex(scale[0] * (px * cos(rot*M_PI/180) + py * sin(rot*M_PI/180)), + scale[1] * (px * -sin(rot*M_PI/180) + py * cos(rot*M_PI/180)), h); path[j] = point_info.data(px, py).pathidx; point[j] = point_info.data(px, py).pointidx; } diff --git a/src/dxftess-glu.cc b/src/dxftess-glu.cc index 38b09e9..89999c3 100644 --- a/src/dxftess-glu.cc +++ b/src/dxftess-glu.cc @@ -201,7 +201,7 @@ inline void do_emplace( boost::unordered_multimap<int, pair_ii> &tri_by_atan2, i rot: CLOCKWISE rotation around positive Z axis */ -void dxf_tesselate(PolySet *ps, DxfData &dxf, double rot, double scale, bool up, bool do_triangle_splitting, double h) +void dxf_tesselate(PolySet *ps, DxfData &dxf, double rot, Vector2d scale, bool up, bool do_triangle_splitting, double h) { GLUtesselator *tobj = gluNewTess(); @@ -244,8 +244,8 @@ void dxf_tesselate(PolySet *ps, DxfData &dxf, double rot, double scale, bool up, dxf.points[dxf.paths[i].indices[j]][1], h) = std::pair<int,int>(i, j); vl.push_back(tess_vdata()); - vl.back().v[0] = scale * dxf.points[dxf.paths[i].indices[j]][0]; - vl.back().v[1] = scale * dxf.points[dxf.paths[i].indices[j]][1]; + vl.back().v[0] = scale[0] * dxf.points[dxf.paths[i].indices[j]][0]; + vl.back().v[1] = scale[1] * dxf.points[dxf.paths[i].indices[j]][1]; vl.back().v[2] = h; gluTessVertex(tobj, vl.back().v, vl.back().v); } diff --git a/src/dxftess.h b/src/dxftess.h index 92c85ea..f0f27b5 100644 --- a/src/dxftess.h +++ b/src/dxftess.h @@ -1,9 +1,11 @@ #ifndef DXFTESS_H_ #define DXFTESS_H_ +#include "linalg.h" + class DxfData; class PolySet; -void dxf_tesselate(PolySet *ps, DxfData &dxf, double rot, double scale, bool up, bool do_triangle_splitting, double h); +void dxf_tesselate(PolySet *ps, DxfData &dxf, double rot, Vector2d scale, bool up, bool do_triangle_splitting, double h); void dxf_border_to_ps(PolySet *ps, const DxfData &dxf); #endif diff --git a/src/import.cc b/src/import.cc index bf21780..2180684 100644 --- a/src/import.cc +++ b/src/import.cc @@ -294,7 +294,7 @@ PolySet *ImportNode::evaluate_polyset(class PolySetEvaluator *) const p = new PolySet(); DxfData dd(this->fn, this->fs, this->fa, this->filename, this->layername, this->origin_x, this->origin_y, this->scale); p->is2d = true; - dxf_tesselate(p, dd, 0, 1, true, false, 0); + dxf_tesselate(p, dd, 0, Vector2d(1,1), true, false, 0); dxf_border_to_ps(p, dd); } else diff --git a/src/linearextrude.cc b/src/linearextrude.cc index 89e92ba..9a7365b 100644 --- a/src/linearextrude.cc +++ b/src/linearextrude.cc @@ -91,7 +91,10 @@ AbstractNode *LinearExtrudeModule::instantiate(const Context *ctx, const ModuleI node->height = height.toDouble(); node->convexity = (int)convexity.toDouble(); origin.getVec2(node->origin_x, node->origin_y); - node->scale = scale.isUndefined() ? 1 : scale.toDouble(); + node->scale_x = node->scale_y = 1; + scale.getDouble(node->scale_x); + scale.getDouble(node->scale_y); + scale.getVec2(node->scale_x, node->scale_y); if (center.type() == Value::BOOL) node->center = center.toBool(); @@ -102,8 +105,8 @@ AbstractNode *LinearExtrudeModule::instantiate(const Context *ctx, const ModuleI if (node->convexity <= 0) node->convexity = 1; - if (node->scale < 0) - node->scale = 0; + if (node->scale_x < 0) node->scale_x = 0; + if (node->scale_y < 0) node->scale_y = 0; if (twist.type() == Value::NUMBER) { node->twist = twist.toDouble(); @@ -151,7 +154,6 @@ std::string LinearExtrudeNode::toString() const "file = " << this->filename << ", " "layer = " << QuotedString(this->layername) << ", " "origin = [" << this->origin_x << ", " << this->origin_y << "], " - "scale = " << this->scale << ", " #ifndef OPENSCAD_TESTING // timestamp is needed for caching, but disturbs the test framework << "timestamp = " << (fs::exists(path) ? fs::last_write_time(path) : 0) << ", " @@ -166,7 +168,7 @@ std::string LinearExtrudeNode::toString() const if (this->has_twist) { stream << ", twist = " << this->twist << ", slices = " << this->slices; } - stream << ", scale = " << this->scale; + stream << ", scale = [" << this->scale_x << ", " << this->scale_y << "]"; stream << ", $fn = " << this->fn << ", $fa = " << this->fa << ", $fs = " << this->fs << ")"; return stream.str(); diff --git a/src/linearextrudenode.h b/src/linearextrudenode.h index 112eccc..6ff8c56 100644 --- a/src/linearextrudenode.h +++ b/src/linearextrudenode.h @@ -11,7 +11,8 @@ public: LinearExtrudeNode(const ModuleInstantiation *mi) : AbstractPolyNode(mi) { convexity = slices = 0; fn = fs = fa = height = twist = 0; - origin_x = origin_y = scale = 0; + origin_x = origin_y = 0; + scale_x = scale_y = 1; center = has_twist = false; } virtual Response accept(class State &state, Visitor &visitor) const { @@ -22,7 +23,7 @@ public: int convexity, slices; double fn, fs, fa, height, twist; - double origin_x, origin_y, scale; + double origin_x, origin_y, scale_x, scale_y; bool center, has_twist; Filename filename; std::string layername; diff --git a/src/primitives.cc b/src/primitives.cc index 3298073..9b755ef 100644 --- a/src/primitives.cc +++ b/src/primitives.cc @@ -546,7 +546,7 @@ sphere_next_r2: p->is2d = true; p->convexity = convexity; - dxf_tesselate(p, dd, 0, 1, true, false, 0); + dxf_tesselate(p, dd, 0, Vector2d(1,1), true, false, 0); dxf_border_to_ps(p, dd); } diff --git a/testdata/scad/features/linear_extrude-scale-tests.scad b/testdata/scad/features/linear_extrude-scale-tests.scad new file mode 100644 index 0000000..9a82c9d --- /dev/null +++ b/testdata/scad/features/linear_extrude-scale-tests.scad @@ -0,0 +1,17 @@ +difference() { + linear_extrude(height=40, scale=[0, 0]) { + square(10, center=true); + translate([10,0]) circle(10); + } + translate([0,0,35]) sphere(10); +} + +/* +Test case ideas: +o off-center starting point +o Concave polygon +o Disjoint polygons +o multi-rotation twist +o zero scales, zero scales in only one axis (for the above cases) +o boolean operations on scaled extrusion (including zero scale) +*/ |