summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarius Kintel <marius@kintel.net>2013-05-10 16:01:50 (GMT)
committerMarius Kintel <marius@kintel.net>2013-05-10 16:01:50 (GMT)
commitadffb9121fbf5d12542ae0d8c5a010e78cc8a4f9 (patch)
treeb13fa35d6b9d807b3c2d7a4c195b49624c2c3297
parent130e10778e9d74ceb07dfc813b85d75a52a71e10 (diff)
Added support for 2D scaling in linear_extrude
-rw-r--r--src/CGALRenderer.cc2
-rw-r--r--src/CGAL_Nef_polyhedron.cc2
-rw-r--r--src/CGAL_Nef_polyhedron_DxfData.cc2
-rw-r--r--src/PolySetCGALEvaluator.cc55
-rw-r--r--src/dxftess-cgal.cc10
-rw-r--r--src/dxftess-glu.cc6
-rw-r--r--src/dxftess.h4
-rw-r--r--src/import.cc2
-rw-r--r--src/linearextrude.cc12
-rw-r--r--src/linearextrudenode.h5
-rw-r--r--src/primitives.cc2
-rw-r--r--testdata/scad/features/linear_extrude-scale-tests.scad17
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)
+*/
contact: Jan Huwald // Impressum