Improved Lip Balm / Lipstick Holder

Mary asked for a less angular version of the Lip Balm Holder, which gave me a chance to practice my list comprehension:

Improved Lipstick and Balm Holder

Improved Lipstick and Balm Holder

You hand the OpenSCAD program a list of desired tube diameters in the order you want them, the program plunks the first one (ideally, the largest diameter) in the middle, arranges the others around it counterclockwise from left to right, then slips a lilypad under each tube.

As long as you don’t ask for anything egregiously stupid, the results look reasonably good:

Improved Lipstick and Balm Holder - 8 tubes

Improved Lipstick and Balm Holder – 8 tubes

As before, each tube length is 1.5 times its diameter; the lipsticks / balms fit loosely and don’t flop around.

Given the tube diameters and the wall thickness, list comprehensions simplify creating lists of the radii from the center tube to each surrounding tube, the center-to-center distances between each of the outer tubes, and the angles between successive tubes:

// per-tube info, first element forced to 0 to make entries match RawDia vector indexes

Radius = [0, for (i=[1:NumTubes-1]) (TubeRad[0] + TubeRad[i] + Wall)];			// Tube[i] distance to center pointRadius = [0, for (i=[1:NumTubes-1]) (TubeRad[0] + TubeRad[i] + Wall)];			// Tube[i] distance to center point
echo(str("Radius: ",Radius));

CtrToCtr = [0, for (i=[1:NumTubes-2]) (TubeRad[i] + TubeRad[i+1] + Wall)];		// Tube[i] distance to Tube[i+1]
echo(str("CtrToCtr: ",CtrToCtr));

Angle = [0, for (i=[1:NumTubes-2]) acos((pow(Radius[i],2) + pow(Radius[i+1],2) - pow(CtrToCtr[i],2)) / (2 * Radius[i] * Radius[i+1]))];
echo(str("Angle: ",Angle));

TotalAngle = sumv(Angle,len(Angle)-1);
echo(str("TotalAngle: ",TotalAngle));

The angles come from the oblique triangle solution when you know all three sides (abc) and want the angle (C) between a and b:

C = arccos( (a2 + b2 - c2) / (2ab) )

Peering down inside, the Slic3r preview shows the lily pads are the tops of squashed spheres:

Improved Lipstick and Balm Holder - Slic3r preview

Improved Lipstick and Balm Holder – Slic3r preview

The pads are 2.0 times the tube diameter, which seemed most pleasing to the eye. They top out at 2.0 mm thick, which might make the edges too thin for comfort.

Update: Here’s what it looks like with a convex hull wrapped around all the lilypads:

Improved Lipstick and Balm Holder - hulled base

Improved Lipstick and Balm Holder – hulled base

I’m awaiting reports from My Spies concerning the typical diameter(s) of lipstick tubes, then I’ll run off a prototype and see about the lily pad edges.

The OpenSCAD source code as a GitHub gist:



  1. #1 by rkward on 2016-02-23 - 07:55


    • #2 by Ed on 2016-02-23 - 09:12

      Well played, sir…

  2. #3 by Keith Neufeld on 2016-02-23 - 09:27

    Hm, I’m curious what it would look like with the hull of the lilypads instead of the individual lilypads. I’m afraid the answer may be that it would look like you set chapsticks on top of the wood-burning stove and the wax is puddling underneath. But still curious.

    • #4 by Ed on 2016-02-23 - 09:44

      That took a quick-and-dirty rework of the loop, because I originally slipped a lilypad under each tube. There’s a picture of the result in the post.

      I can’t make a strong case either way, but the individual lilypads seem prettier …

      • #5 by Keith Neufeld on 2016-02-23 - 10:30

        You’re right — the molten wax is not prettier. :-)

        OpenSCAD question — in the lilypad version, would you know how to fillet the lilypad intersections?

        • #6 by Ed on 2016-02-23 - 10:40


          Filleting seems to be one of those things that’s hard to describe programmatically, particularly for arbitrary shapes and angles. The topic comes up on the mailing list every now & again, with various folks proposing solutions I can’t even pronounce…

          • #7 by Keith Neufeld on 2016-02-23 - 10:47

            It seems to me that one could Minkowski the object, then subtract that from an enclosing block of the same height, then Minkowski that, then subtract that from the same block. In other words, shrink the negative space around the object and Minkwoski the negative space back to the same size, just with rounder edges.

            I do not volunteer to do that to your lilypads.

            • #8 by Ed on 2016-02-23 - 10:56

              OpenSCAD can offset a 2D boundary in a reasonable manner without unleashing a Minkowski sum, but that doesn’t help with shapes that aren’t 2.5 D.

              I rest my case: fillets are easy when you’re driving the mouse / watching the display and very difficult algorithmically…

          • #9 by Vedran on 2016-02-23 - 12:15

            I wanted to ask for some time now: Is there some particular reason why you model everything in OpenSCAD? OK, there are situations in which it really shines and I’ll admit I didn’t really try too hard to use it, but compared to SketchUp it sees much less productive. Especially when trying to make something on the perimeter of a cylinder or some other example that requires to dig into trigonometry functions.

            • #10 by Ed on 2016-02-23 - 14:53

              why you model everything in OpenSCAD?

              Primarily, because it works perfectly for the stuff I build around here: if I avoid obvious design blunders, it produces a manifold model that Just Works Every Time. OpenSCAD lets me design a thing, then change that thing in very small, very precise ways, without having to redraw the whole thing: the equations do all the heavy lifting for me.

              A good CAD program with relational modeling lets you do that, too, but by the time you feed in all the relations, you’ve done exactly the same work you’d do with OpenSCAD, plus you’ve spent a lot of money for the privilege of using your model for a year. When you stop paying, you lose access to your models.

              Some models show up in my Digital Machinist column, where having a freely available modeling program counts for a lot.

              Not to mention that I’ve outlived a fair number of CAD programs, have no incentive to pay for anything fancy, and regard figuring out the modeling math as much better than Sudoku to keep my few remaining wits sharpened up.

              OpenSCAD is an acquired taste that I’ve gotten accustomed to…

              compared to SketchUp

              Reliable sources that I trust implicitly tell me that Sketchup remains an unparalleled way to produce terrible solid models, which agrees with the evidence I’ve seen. Fighting a CAD program to the death in order to get a workable mesh isn’t my idea of a Good Time, even for free.

            • #11 by Vedran on 2016-02-25 - 11:35

              Well, when you put it like that it makes a lot of sense :)

              I wouldn’t count myself as a SketchUp fanboy by any stretch of imagination, and I’ll readily admit that out-of-the-box it’s … well… pretty useless. But if you add a couple of free plugins it becomes pretty usable.

              My pet peeves are: lack of support for true circles, strange bug that rounds small distances when drawing in millimeters, but doesn’t seem to affect models drawn in meters, propensity to union or subtract two solids in a way that produces an unnoticeable hole somewhere in the resulting mesh… oh and the fact that union, subtract and similar solid operations are not available in the free version.

              Where it shines is designing parts where you know features A, B and C must fit into allotted space, but have no idea how or if it’s even possible. Simply draw everything as a crude model then move it around until you’re happy and add details. Along the way you can easily measure distances, use snap points, and see what you did right away without endlessly recompiling the model.

              BTW, I used OpenSCAD to generate metric threads and resulting STL’s regularly sported holes in the generated mesh when imported into SketchUp. I can’t tell whether it was OpenSCAD’s or SketchUp’s fault.

            • #12 by Ed on 2016-02-25 - 13:26

              regularly sported holes in the generated mesh when imported into SketchUp

              Well, I know which end of that bet I’d take… [grin]

              The myriad polygons involved in threadmaking can produce non-manifold results, particularly fitting the successive cuts together without the proper overlap. I managed to get that broom handle screw working, but with more effort than seemed reasonable.

              see what you did right away without endlessly recompiling

              “Automatic reload and compile” plus an external editor: hit Ctrl-S and what you just did pops into view. Made for two big monitors!