I just made some changes to rotate_extrude to make it more consistent
with itself and with other round things. There's a small incompatible
change, and a new warning.
The key question is in where the extrusion starts, when it goes all the
way around - that is, when the "angle" parameter is not set, or when
it's set to 360.
The original behavior of rotate_extrude(), before the "angle" parameter
was introduced, was to start on the -X axis, to the left of the origin.
This was an unfortunate choice, because other round objects (circles,
cylinders) start on the +X axis, to the right of the origin. If you are
trying to make a round thing, it probably doesn't matter to you, because
the difference is small. If you are trying to make a regular polygon
with an even number of sides, it doesn't matter to you because it's
left-right symmetric. If, however, you're trying to make a regular
polygon with an odd number of sides, it's important and inconvenient.
Consider this small program...
color("red") cylinder(h=1, r=10, $fn=3);
color("green") translate([0,0,1]) rotate_extrude($fn=3) square([10,1]);
You might think that that would stack two triangular prisms, one atop
the other. (Of course, in a real case you'd probably be extruding
something more complicated than a square.)
However, the cylinder starts on the +X axis; one point of the triangle
points to the right. The rotational extrusion, on the other hand,
starts on the -X axis, and so one point of the triangle points left.
The result:
Oops. You can easily work around this by rotating one or the other 180
degrees, but it's a nuisance.
When the "angle" parameter was added, this inconsistency was partially
addressed. With the "angle" parameter specified, the extrusion starts
on the +X axis:
rotate_extrude(angle=60) square(10);
Unfortunately, compatibility with the existing behavior led to another
somewhat-unfortunate decision. 360-degree extrusions, extrusions all
the way around the circle, behave the old way, starting on the -X axis,
left of the origin, whether invoked using the original style without
"angle" or with an explicit angle=360. Thus although you can almost
make an extrusion that's compatible with a circle or cylinder, by
extruding 359 degrees around, you can't quite close the gap without
reverting to the original behavior.
rotate_extrude(angle=359, $fn=3) square(10);
So close and yet so far... notice the thin gap on the right.
So that the background, the situation before the change I just made.
Now for the things I changed.
First, I changed it so that you can start an extrusion anywhere around
the circle you want to, using the "start" parameter.
rotate_extrude(angle=90, start=45) square(10);
By itself, this is a small thing; you can achieve the same result by
slapping a rotate() around your extrusion. However, it sets the stage
for the second change...
Second, I made it so that "start" defaults to zero if you specify
"angle", and defaults to 180 if you do not. This means that all
extrusions that specify "angle"[*], specifically including those that
specify angle=360, start on the +X axis, to the right of the origin.
[*] Technical note: it's actually when you specify "angle" and the
value can be converted into a number. Please don't go passing random
non-numbers into builtins; nothing good will come of it. However, it
can be useful to pass in "undef" to get the default behavior.
// No "angle", starts on -X.
rotate_extrude($fn=3) square(10);
// With "angle", starts on +X.
rotate_extrude(angle=360, $fn=3) square(10);
This is, in theory, an incompatible change. The behavior with angle=360
changed. My hope is that few if any people explicitly specify angle=360
when creating an all-the-way-around extrusion, and that fewer still will
do that and also depend on which way the polygon points. If that does
cause you trouble... sorry about that. There are roughly three workarounds:
So now rotate_extrude() with "angle" is fully consistent with itself and
with other round things... but the default rotate_extrude(), without
"angle", is still inconsistent with both. That leads to the third change.
Third, we'd really like to eventually change rotate_extrude() without
"angle" to start on +X, to be fully consistent with itself and with
other round things. But people are likely depending on the current
behavior.
I've added a deprecation warning that triggers if you do a default (no
"angle", no "start") rotational extrusion, with $fn set to an odd value.
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.
If you get this deprecation warning, you have a couple of options to
silence it and future-proof your model...
Unfortunately, I don't immediately see a way, other than checking
version(), to write a program that will be correct for a build before
today, a build today, and the future build where rotate_extrude() is
fully consistent.
I don't expect this future change until two release from now, at the
earliest. That's at least a couple of years.
Please let me know if anything surprising happens, or if the impact of
these changes is more than I expect.
Thanks Jordan, both for fixing the idiosyncracies and for giving a thorough and very clear explanation of what changed and why. I don't think this affects anything I've made personally, but I'm saving your explanation in case I start from someone else's work and get weird behaviors.
Lenore
On Jan 5, 2025, at 22:27, Jordan Brown via Discuss discuss@lists.openscad.org wrote:
I just made some changes to rotate_extrude to make it more consistent with itself and with other round things. There's a small incompatible change, and a new warning.
The key question is in where the extrusion starts, when it goes all the way around - that is, when the "angle" parameter is not set, or when it's set to 360.
The original behavior of rotate_extrude(), before the "angle" parameter was introduced, was to start on the -X axis, to the left of the origin. This was an unfortunate choice, because other round objects (circles, cylinders) start on the +X axis, to the right of the origin. If you are trying to make a round thing, it probably doesn't matter to you, because the difference is small. If you are trying to make a regular polygon with an even number of sides, it doesn't matter to you because it's left-right symmetric. If, however, you're trying to make a regular polygon with an odd number of sides, it's important and inconvenient.
Consider this small program...
color("red") cylinder(h=1, r=10, $fn=3);
color("green") translate([0,0,1]) rotate_extrude($fn=3) square([10,1]);
You might think that that would stack two triangular prisms, one atop the other. (Of course, in a real case you'd probably be extruding something more complicated than a square.)
However, the cylinder starts on the +X axis; one point of the triangle points to the right. The rotational extrusion, on the other hand, starts on the -X axis, and so one point of the triangle points left. The result:
<4orBVbO9XyuYCuW9.png>
Oops. You can easily work around this by rotating one or the other 180 degrees, but it's a nuisance.
When the "angle" parameter was added, this inconsistency was partially addressed. With the "angle" parameter specified, the extrusion starts on the +X axis:
rotate_extrude(angle=60) square(10);
<DPtxzRse0DvngcaO.png>
Unfortunately, compatibility with the existing behavior led to another somewhat-unfortunate decision. 360-degree extrusions, extrusions all the way around the circle, behave the old way, starting on the -X axis, left of the origin, whether invoked using the original style without "angle" or with an explicit angle=360. Thus although you can almost make an extrusion that's compatible with a circle or cylinder, by extruding 359 degrees around, you can't quite close the gap without reverting to the original behavior.
rotate_extrude(angle=359, $fn=3) square(10);
<GlCd10nSowNuFJG0.png>
So close and yet so far... notice the thin gap on the right.
So that the background, the situation before the change I just made. Now for the things I changed.
First, I changed it so that you can start an extrusion anywhere around the circle you want to, using the "start" parameter.
rotate_extrude(angle=90, start=45) square(10);
<iL8xvDQ7oL2WmuMN.png>
By itself, this is a small thing; you can achieve the same result by slapping a rotate() around your extrusion. However, it sets the stage for the second change...
Second, I made it so that "start" defaults to zero if you specify "angle", and defaults to 180 if you do not. This means that all extrusions that specify "angle"[*], specifically including those that specify angle=360, start on the +X axis, to the right of the origin.
[*] Technical note: it's actually when you specify "angle" and the value can be converted into a number. Please don't go passing random non-numbers into builtins; nothing good will come of it. However, it can be useful to pass in "undef" to get the default behavior.
// No "angle", starts on -X.
rotate_extrude($fn=3) square(10);
<OZl0BGlJQ3sLxO78.png>
// With "angle", starts on +X.
rotate_extrude(angle=360, $fn=3) square(10);
<bJ4ABRVXqAwfINIv.png>
This is, in theory, an incompatible change. The behavior with angle=360 changed. My hope is that few if any people explicitly specify angle=360 when creating an all-the-way-around extrusion, and that fewer still will do that and also depend on which way the polygon points. If that does cause you trouble... sorry about that. There are roughly three workarounds:
Don't specify "angle"; just accept the default. (Or specify angle=undef.) This has the advantage of working before or after this change.
Specify "start=180".
rotate(180) your extrusion.
So now rotate_extrude() with "angle" is fully consistent with itself and with other round things... but the default rotate_extrude(), without "angle", is still inconsistent with both. That leads to the third change.
Third, we'd really like to eventually change rotate_extrude() without "angle" to start on +X, to be fully consistent with itself and with other round things. But people are likely depending on the current behavior.
I've added a deprecation warning that triggers if you do a default (no "angle", no "start") rotational extrusion, with $fn set to an odd value.
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.
It doesn't trigger when "start" is set, because then you are taking control of your own fate.
It doesn't trigger when "angle" is set, because then you get the consistent "start on +X" behavior. (angle=360 excepted.)
It doesn't trigger when $fn isn't set, because then you are presumably trying to make a round thing and don't care exactly which way the vertexes point.
It doesn't trigger when $fn is even, because then the figure is symmetric and you'll get the same result when we change.
If you get this deprecation warning, you have a couple of options to silence it and future-proof your model...
Explicitly set start=180.
Rearrange your model so that it works with the vertex pointing the other way, and explicitly set start=0 or angle=360.
Explicitly set angle=360, and rotate(180) the extrusion.
Unfortunately, I don't immediately see a way, other than checking version(), to write a program that will be correct for a build before today, a build today, and the future build where rotate_extrude() is fully consistent.
I don't expect this future change until two release from now, at the earliest. That's at least a couple of years.
Please let me know if anything surprising happens, or if the impact of these changes is more than I expect.
OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org