Skip Navigation

Any way to do a "pillowing" effect?

We all know about the linear_extrude(...) function that turns 2d things into 3d things.

I sometimes have found myself wishing for a similar function which could make a more rounded, result.

Just to illustrate what I'm hoping to achieve, my dream solution would, given this 2d outline:

Capsule-shaped 2d outline.

would give me something like the following:

The same outline "pillowed" up into the third dimension.

Another angle of demonstrating the "back"/"bottom" is flat.

Just to further illustrate, the code I used to generate outline above:

hull() {
	for (i=[-1:1])
		translate([i*15, 0])
			circle(d=10);
}

And the "pillowed" version that shows the desired result giving the above outline:

$fn=64;
rotate([0, 90, 0])
	linear_extrude(30, center=true)
		scale([4, 10])
			difference() {
				circle(d=1);
				translate([0.5, 0])
					square(1, center=true);
			}
for (i = [-1, 1])
	translate([i*15, 0, 0])
		scale([10, 10, 4])
			difference() {
				sphere(d=1);
				translate([0, 0, -0.5])
					cube(1, center=true);
			}

The outline I actually want to pillow for my particular current use case looks like this:

A pattern in the style of a Talavera tile.

(Credit to this person on Printables for the Talavera tile pattern.)

I'm hoping there's a way to do this I'm not thinking of, or a library I'm not familiar with. The example above makes an elliptical curve, but I'm not married to elliptical in particular. Anything somewhat similar would be fine.

Thanks in advance for any help!

4
4 comments
  • Disclaimer: I've never used OpenSCAD.

    But this seems like it might be useful?

    https://github.com/Irev-Dev/Round-Anything

    Documentation:

    https://learn.cadhub.xyz/docs/round-anything/api-reference/

    So, instead of linearExtrude, you'd do polyRoundExtrude, with topR(adius) equal to the extrusion height, and bottomR(adius) equal to zero, I think?

    • Thanks for the reply!

      So, it looks like Round Anything that you referred me to could do something like the kind of thing I'm looking for, but it does have a significant drawback. Namely that It looks like the polyRoundExtrude() requires a list of points and radii. All I have is an STL file that I can convert into an OpenSCAD 2d geometry with a projection(). To use polyRoundExtrude(), I'd basically have to rebuild the Talavera pattern from scratch using the Round Anything library. (Or maybe export to SVG and... write some custom code to convert that into an OpenSCAD syntax array? Still seems like a pain.)

      (One aside. I'd like to have an elliptical rounded corner rather than a circular one, but the above issue notwithstanding, that could be taken care of pretty easily with a bit of scaling magic.)

      With some searching and asking around elsewhere, I did find a bunch of other potential ways to accomplish something vaguely like I'm wanting:

      • BOSL2 - Might offer a solution to the second issue above. But it would similarly require rebuilding from scratch using BOSL2's facilities rather than modifying from what I've already got. (Also, it's pretty complex.)
      • roof() - It allows adding a chamfer. Only at a 45°, though. Definitely wouldn't give me what I want (at least not on its own, but more on that later.) Also, roof() is only available in versions of OpenSCAD more recent than the latest release of OpenSCAD. So I'd have to use a recent development version. Not a deal breaker, but it doesn't seem like it'll do quite what I want anyway.
      • minkowski() - This one involves doing a linear_extrude(<a very small value>) and a minkowski() with a sphere or ellipsoid. I'd also need to subtract off a bulge on the underside, not that that would be any big deal in itself. The major downsides of this option are 1) it's imprecise and 2) it's really slow. Like really slow.

      But! I think I've found a solution I'm happy with. It also has drawbacks, but they're drawbacks I'm more willing to live with than those from the above options.

      Ultimately, I'm planning to 3d-print the result on an FFF printer. (A Creality Ender 3 Pro and/or Ender 3 V2 Neo specifically.) I'm probably going to use the thinnest available layer height, which in Cura is 0.12mm.

      The reason I went into all of that is just to say that while I want it smooth, I don't actually need it any smoother than my printer can handle. If it's only smooth to a resolution of 0.12mm, that's fine.

      So, the solution I came to is to construct the elliptical curve like a stepped pyramid, which layers 0.12mm thick. To make it elliptical, I just used the equation for a unit circle: y=sqrt(1-x^2). Here's the code for this relatively simple solution:

      module pillow(height, delta) {
      	for (i = [0:floor(height/delta)])
      		linear_extrude(i*delta)
      			let(
      				x=i/floor(height/delta),
      				c=(1-sqrt(1-x^2))*height
      			)
      				offset(delta=-c)
      					children();
      }
      
      pillow(1.5, 0.12)
      	hull()
      		for (i=[-1:1])
      			translate([i*15, 0])
      				circle(d=10);
      

      And the result looks like:

      The first example in the original post with the stepped pyramid elliptical "pillowing" effect applied. It's "ribbed" or "stepped" with only right-angles, but it does a decent job of approximating an elliptical curve if you're good with ignoring any detail 0.12mm or smaller in size.

      The Talavera pattern with the same stepped effect applied. Looks kinda cool if I do say so myself.

      Drawbacks:

      • This solution is a little slow. Nowhere near as slow as the minkowski() solution, but kinda slow.
      • The stepping probably better be tailored to your specific planned layer height. Which means if you want to reprint with a different layer height, you're probably best off to start by making a change (a small change, but a change none the less) to the .scad file.

      Just as one final point, while I haven't yet had occasion to mess with roof() to really know the details of how it works and what it can do, I think the solution I came up with could be adapted to use roof() to make a much smoother and less stepped look. (Only in a version of OpenSCAD that supports roof() of course.)

      That's it. I figured I'd detail my solution in case it'd help anyone else.

      Thanks again for your input!