Skip to content

Commit 92a13b4

Browse files
authored
Start rotate_extrude on -X only for no angle specified. (openscad#5553)
* Start rotate_extrude on -X only for no angle specified. Start on +X when an angle is specified, including 360. Add "start=" to let you explicitly specify. Give a deprecation warning with no args and $fn odd.
1 parent bf9188f commit 92a13b4

17 files changed

+80
-65
lines changed

src/core/RotateExtrudeNode.cc

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,16 +48,28 @@ std::shared_ptr<AbstractNode> builtin_rotate_extrude(const ModuleInstantiation *
4848
auto node = std::make_shared<RotateExtrudeNode>(inst);
4949

5050
const Parameters parameters = Parameters::parse(std::move(arguments), inst->location(),
51-
{"angle"}, {"convexity"});
51+
{"angle", "start"}, {"convexity"});
5252

5353
node->fn = parameters["$fn"].toDouble();
5454
node->fs = parameters["$fs"].toDouble();
5555
node->fa = parameters["$fa"].toDouble();
5656

5757
node->convexity = static_cast<int>(parameters["convexity"].toDouble());
58-
node->angle = 360;
59-
parameters["angle"].getFiniteDouble(node->angle);
60-
if ((node->angle <= -360) || (node->angle > 360)) node->angle = 360;
58+
// If an angle is specified, use it, defaulting to starting at zero.
59+
// If no angle is specified, use 360 and default to starting at 180.
60+
// Regardless, if a start angle is specified, use it.
61+
bool hasAngle = parameters["angle"].getFiniteDouble(node->angle);
62+
if (hasAngle) {
63+
node->start = 0;
64+
if ((node->angle <= -360) || (node->angle > 360)) node->angle = 360;
65+
} else {
66+
node->angle = 360;
67+
node->start = 180;
68+
}
69+
bool hasStart = parameters["start"].getFiniteDouble(node->start);
70+
if (!hasAngle && !hasStart && (int)node->fn % 2 != 0) {
71+
LOG(message_group::Deprecated, "In future releases, rotational extrusion without \"angle\" will start at zero, the +X axis. Set start=180 to explicitly start on the -X axis.");
72+
}
6173

6274
if (node->convexity <= 0) node->convexity = 2;
6375

@@ -72,11 +84,13 @@ std::string RotateExtrudeNode::toString() const
7284
{
7385
std::ostringstream stream;
7486

75-
stream << this->name() << "(";
76-
stream <<
87+
stream << this->name() << "("
7788
"angle = " << this->angle << ", "
89+
"start = " << this->start << ", "
7890
"convexity = " << this->convexity << ", "
79-
"$fn = " << this->fn << ", $fa = " << this->fa << ", $fs = " << this->fs << ")";
91+
"$fn = " << this->fn << ", "
92+
"$fa = " << this->fa << ", "
93+
"$fs = " << this->fs << ")";
8094

8195
return stream.str();
8296
}

src/core/RotateExtrudeNode.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,12 @@ class RotateExtrudeNode : public AbstractPolyNode
1313
convexity = 0;
1414
fn = fs = fa = 0;
1515
angle = 360;
16+
start = 0;
1617
}
1718
std::string toString() const override;
1819
std::string name() const override { return "rotate_extrude"; }
1920

2021
int convexity;
2122
double fn, fs, fa;
22-
double angle;
23+
double angle, start;
2324
};

src/geometry/GeometryEvaluator.cc

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -788,14 +788,14 @@ static void fill_ring(std::vector<Vector3d>& ring, const Outline2d& o, double a,
788788
if (flip) {
789789
unsigned int l = o.vertices.size() - 1;
790790
for (unsigned int i = 0; i < o.vertices.size(); ++i) {
791-
ring[i][0] = o.vertices[l - i][0] * sin_degrees(a);
792-
ring[i][1] = o.vertices[l - i][0] * cos_degrees(a);
791+
ring[i][0] = o.vertices[l - i][0] * cos_degrees(a);
792+
ring[i][1] = o.vertices[l - i][0] * sin_degrees(a);
793793
ring[i][2] = o.vertices[l - i][1];
794794
}
795795
} else {
796796
for (unsigned int i = 0; i < o.vertices.size(); ++i) {
797-
ring[i][0] = o.vertices[i][0] * sin_degrees(a);
798-
ring[i][1] = o.vertices[i][0] * cos_degrees(a);
797+
ring[i][0] = o.vertices[i][0] * cos_degrees(a);
798+
ring[i][1] = o.vertices[i][0] * sin_degrees(a);
799799
ring[i][2] = o.vertices[i][1];
800800
}
801801
}
@@ -843,12 +843,14 @@ static std::unique_ptr<Geometry> rotatePolygon(const RotateExtrudeNode& node, co
843843

844844
fragments = (unsigned int)std::ceil(fmax(Calc::get_fragments_from_r(max_x - min_x, node.fn, node.fs, node.fa) * std::abs(node.angle) / 360, 1));
845845

846-
bool flip_faces = (min_x >= 0 && node.angle > 0 && node.angle != 360) || (min_x < 0 && (node.angle < 0 || node.angle == 360));
846+
bool flip_faces = (min_x >= 0 && node.angle > 0) || (min_x < 0 && node.angle < 0);
847847

848+
// If not going all the way around, we have to create faces on each end.
848849
if (node.angle != 360) {
849850
auto ps_start = poly.tessellate(); // starting face
850-
Transform3d rot(angle_axis_degrees(90, Vector3d::UnitX()));
851-
ps_start->transform(rot);
851+
Transform3d rotx(angle_axis_degrees(90, Vector3d::UnitX()));
852+
Transform3d rotz1(angle_axis_degrees(node.start, Vector3d::UnitZ()));
853+
ps_start->transform(rotz1 * rotx);
852854
// Flip vertex ordering
853855
if (!flip_faces) {
854856
for (auto& p : ps_start->indices) {
@@ -858,8 +860,8 @@ static std::unique_ptr<Geometry> rotatePolygon(const RotateExtrudeNode& node, co
858860
builder.appendPolySet(*ps_start);
859861

860862
auto ps_end = poly.tessellate();
861-
Transform3d rot2(angle_axis_degrees(node.angle, Vector3d::UnitZ()) * angle_axis_degrees(90, Vector3d::UnitX()));
862-
ps_end->transform(rot2);
863+
Transform3d rotz2(angle_axis_degrees(node.start + node.angle, Vector3d::UnitZ()));
864+
ps_end->transform(rotz2 * rotx);
863865
if (flip_faces) {
864866
for (auto& p : ps_end->indices) {
865867
std::reverse(p.begin(), p.end());
@@ -873,11 +875,9 @@ static std::unique_ptr<Geometry> rotatePolygon(const RotateExtrudeNode& node, co
873875
rings[0].resize(o.vertices.size());
874876
rings[1].resize(o.vertices.size());
875877

876-
fill_ring(rings[0], o, (node.angle == 360) ? -90 : 90, flip_faces); // first ring
878+
fill_ring(rings[0], o, node.start, flip_faces); // first ring
877879
for (unsigned int j = 0; j < fragments; ++j) {
878-
double a;
879-
if (node.angle == 360) a = -90 + ((j + 1) % fragments) * 360.0 / fragments; // start on the -X axis, for legacy support
880-
else a = 90 - (j + 1) * node.angle / fragments; // start on the X axis
880+
double a = node.start + (j + 1) * node.angle / fragments; // start on the X axis
881881
fill_ring(rings[(j + 1) % 2], o, a, flip_faces);
882882

883883
for (size_t i = 0; i < o.vertices.size(); ++i) {

tests/data/scad/3D/issues/issue1105d.scad

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
difference() {
2-
rotate_extrude(convexity=2, $fn=8)
2+
rotate_extrude(convexity=4, $fn=8)
33
translate([5,0,0]) difference() {
44
circle(r=2);
55
circle(r=1);

tests/regression/dumptest-examples/example007-expected.csg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, -10], [0, 0, 0, 1]]) {
22
group() {
33
difference() {
4-
rotate_extrude(angle = 360, convexity = 3, $fn = 0, $fa = 12, $fs = 2) {
4+
rotate_extrude(angle = 360, start = 180, convexity = 3, $fn = 0, $fa = 12, $fs = 2) {
55
import(file = "example007.dxf", layer = "dorn", origin = [0, 0], scale = 1, convexity = 1, $fn = 0, $fa = 12, $fs = 2, timestamp = 1576020815);
66
}
77
group() {

tests/regression/dumptest-examples/example009-expected.csg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ intersection() {
1717
linear_extrude(height = 20, center = true, twist = -57.5288, $fn = 0, $fa = 3, $fs = 1, convexity = 10) {
1818
import(file = "example009.dxf", layer = "fan_top", origin = [0, 0], scale = 1, convexity = 1, $fn = 0, $fa = 3, $fs = 1, timestamp = 1576020815);
1919
}
20-
rotate_extrude(angle = 360, convexity = 10, $fn = 0, $fa = 3, $fs = 1) {
20+
rotate_extrude(angle = 360, start = 180, convexity = 10, $fn = 0, $fa = 3, $fs = 1) {
2121
import(file = "example009.dxf", layer = "fan_side", origin = [0, -40], scale = 1, convexity = 1, $fn = 0, $fa = 3, $fs = 1, timestamp = 1576020815);
2222
}
2323
}

tests/regression/dumptest-examples/example017-expected.csg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ group() {
187187
}
188188
% multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 12], [0, 0, 0, 1]]) {
189189
group() {
190-
rotate_extrude(angle = 360, convexity = 2, $fn = 0, $fa = 12, $fs = 2) {
190+
rotate_extrude(angle = 360, start = 180, convexity = 2, $fn = 0, $fa = 12, $fs = 2) {
191191
square(size = [25, 68], center = false);
192192
multmatrix([[1, 0, 0, 0], [0, 1, 0, 68], [0, 0, 1, 0], [0, 0, 0, 1]]) {
193193
intersection() {

tests/regression/dumptest-examples/rotate_extrude-expected.csg

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,40 @@
11
color([1, 0, 0, 1]) {
2-
rotate_extrude(angle = 360, convexity = 2, $fn = 0, $fa = 12, $fs = 2) {
2+
rotate_extrude(angle = 360, start = 180, convexity = 2, $fn = 0, $fa = 12, $fs = 2) {
33
multmatrix([[1, 0, 0, 10], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
44
square(size = [5, 5], center = false);
55
}
66
}
77
}
88
color([0, 1, 1, 1]) {
99
multmatrix([[1, 0, 0, 40], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
10-
rotate_extrude(angle = 360, convexity = 2, $fn = 80, $fa = 12, $fs = 2) {
10+
rotate_extrude(angle = 360, start = 180, convexity = 2, $fn = 80, $fa = 12, $fs = 2) {
1111
text(text = " J", size = 10, spacing = 1, font = "", direction = "ltr", language = "en", script = "Latn", halign = "default", valign = "default", $fn = 80, $fa = 12, $fs = 2);
1212
}
1313
}
1414
}
1515
color([0, 0.501961, 0, 1]) {
1616
multmatrix([[1, 0, 0, 0], [0, 1, 0, 30], [0, 0, 1, 0], [0, 0, 0, 1]]) {
17-
rotate_extrude(angle = 360, convexity = 2, $fn = 80, $fa = 12, $fs = 2) {
17+
rotate_extrude(angle = 360, start = 180, convexity = 2, $fn = 80, $fa = 12, $fs = 2) {
1818
polygon(points = [[0, 0], [8, 4], [4, 8], [4, 12], [12, 16], [0, 20]], paths = undef, convexity = 1);
1919
}
2020
}
2121
}
2222
color([1, 0, 1, 1]) {
2323
multmatrix([[1, 0, 0, 40], [0, 1, 0, 40], [0, 0, 1, 0], [0, 0, 0, 1]]) {
24-
rotate_extrude(angle = 180, convexity = 2, $fn = 0, $fa = 12, $fs = 2) {
24+
rotate_extrude(angle = 180, start = 0, convexity = 2, $fn = 0, $fa = 12, $fs = 2) {
2525
multmatrix([[1, 0, 0, 12.5], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
2626
square(size = [5, 5], center = false);
2727
}
2828
}
2929
multmatrix([[1, 0, 0, 7.5], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
30-
rotate_extrude(angle = 180, convexity = 2, $fn = 0, $fa = 12, $fs = 2) {
30+
rotate_extrude(angle = 180, start = 0, convexity = 2, $fn = 0, $fa = 12, $fs = 2) {
3131
multmatrix([[1, 0, 0, 5], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
3232
square(size = [5, 5], center = false);
3333
}
3434
}
3535
}
3636
multmatrix([[1, 0, 0, -7.5], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
37-
rotate_extrude(angle = -180, convexity = 2, $fn = 0, $fa = 12, $fs = 2) {
37+
rotate_extrude(angle = -180, start = 0, convexity = 2, $fn = 0, $fa = 12, $fs = 2) {
3838
multmatrix([[1, 0, 0, 5], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
3939
square(size = [5, 5], center = false);
4040
}

tests/regression/dumptest/allmodules-expected.csg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ union();
1111
difference();
1212
intersection();
1313
linear_extrude(height = 100, $fn = 0, $fa = 12, $fs = 2);
14-
rotate_extrude(angle = 360, convexity = 2, $fn = 0, $fa = 12, $fs = 2);
14+
rotate_extrude(angle = 360, start = 180, convexity = 2, $fn = 0, $fa = 12, $fs = 2);
1515
import(file = "", origin = [0, 0], scale = 1, convexity = 1, $fn = 0, $fa = 12, $fs = 2, timestamp = 0);
1616
group();
1717
cube(size = [1, 1, 1], center = false);
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
group() {
2-
rotate_extrude(convexity = 1, $fn = 0, $fa = 12, $fs = 2);
2+
rotate_extrude(angle = 360, start = 180, convexity = 1, $fn = 0, $fa = 12, $fs = 2);
33
}

0 commit comments

Comments
 (0)