Improved Lipstick and Lip Balm Holder With Text

For reasons that aren’t relevant here, Mary asked me to make four sets of improved lipstick / lip balm / sunscreen holders with five smaller tubes plus the central one and an inscription on the bottom. I ran off one with the last of the cyan PETG and the other three in natural PETG:

Improved Lipstick Holder - on platform
Improved Lipstick Holder – on platform

I embossed the text into the bottom three layers. The tiny spots of detached infill for lowercase letters like a didn’t adhere to the platform, mostly because the retraction settings that work well for larger areas don’t push enough plastic out to bond with the platform before retracting and moving away.

The bridging layer over the text shows Slic3r doing the best it can (clicky for more far more dots). Laying a uniform patch over all the letters in one shot would work better, but I don’t know how you’d define an algorithm that specifies when such a situation occurs:

Lip Balm Holder - text bridge layer - Slic3r preview
Lip Balm Holder – text bridge layer – Slic3r preview

The solid infill layer directly over the Hilbert Curve bottom layer came out grossly severely excessively overstuffed, to the extent that the accumulation reduced the flow of molten plastic and caused the filament drive to strip:

Overfilled layer 2
Overfilled layer 2

Previewing the G-Code show nothing out of the ordinary and, after considerable flailing around, I finally set Slic3r to begin the 3D Honeycomb infill directly atop the Hilbert Curve bottom layer. That provided enough open space to complete the mission, but more debugging was in order.

The OpenSCAD source code as a GitHub gist:

// Lipstick and Balm Tube Holder
// Ed Nisley KE4ZNU - February 2016
//- Extrusion parameters - must match reality!
ThreadThick = 0.25;
ThreadWidth = 0.40;
function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
Protrusion = 0.1;
HoleWindage = 0.2;
//------
// Dimensions
RawDia = [27,18,16,18,16,18]; // actual tube diameters in desired order, center = largest first
NumTubes = len(RawDia);
Clearance = 2.0;
TubeDia = [for (i=[0:NumTubes-1]) (RawDia[i] + Clearance)]; // actual tube diameters
TubeRad = TubeDia / 2;
echo(str("NumTubes: ",NumTubes));
Wall = 2.0;
BaseThick = 2.0;
BaseFactor = 2.0;
NumSides = 12*4;
// 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 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));
//----------------------
// Useful routines
// vector sum cribbed from doc
function sumv(v,i,s=0) = (i==s ? v[i] : v[i] + sumv(v,i-1,s));
//----------------------
//- Build it
difference() {
union() {
for (i=[0:NumTubes-1])
rotate(90 - TotalAngle/2 + sumv(Angle, (i>0) ? (i-1) : 0))
translate([Radius[i],0,0]) {
resize([0,0,2*BaseThick]) // bases
difference() {
sphere(r=BaseFactor*TubeRad[i],$fn=NumSides);
translate([0,0,-BaseFactor*TubeDia[i]])
cube(2*BaseFactor*TubeDia[i],center=true);
}
difference() { // tubes
cylinder(r=TubeRad[i] + Wall,h=1.5*TubeDia[i] + BaseThick,$fn=NumSides);
cylinder(d=TubeDia[i],h=1.5*TubeDia[i] + BaseThick + Protrusion,$fn=NumSides);
}
}
for (i=[1:NumTubes-2]) // gap plugs
rotate(90 - TotalAngle/2 + sumv(Angle,i-1) + (Angle[i])/2)
translate([(TubeRad[0] + Wall),0,0])
cylinder(r=2*Wall,h=1.5*min(TubeDia[i],TubeDia[i+1]) + BaseThick,$fn=3);
}
translate([0,0,-Protrusion]) // text
mirror([1,0,0])
linear_extrude(height=3*ThreadThick + Protrusion) {
translate([0,25,0])
text(text="Linda",size=7,spacing=1.05,font="Arial:style=Bold Italic",halign="center");
translate([0,15,0])
text(text="FDQ ExComm",size=5,spacing=1.05,font="Arial:style=Regular",halign="center");
translate([0,7,0])
text(text="2014 - 2016",size=5,spacing=1.05,font="Arial:style=Regular",halign="center");
translate([0,-3,0])
text(text="Thank you!",size=6,spacing=1.05,font="Arial:style=Regular",halign="center");
translate([0,-15,0])
text(text="Mary Nisley",size=7,spacing=1.10,font="ITC Zapf Chancery:style=Medium Italic",halign="center");
}
}

3 thoughts on “Improved Lipstick and Lip Balm Holder With Text

    1. It looks like S3D expects a single (or double?) thread width anchor to work perfectly every time, while Slic3r goes for a broad anchor that flat-out doesn’t work with a zillion close & tiny bridges. In this case, a few failures don’t matter, but I can see how either algorithm could get ugly.

      Running perimeter threads around the infill seems overly fussy. Why not ram the infill up against the bridges and be done with it?

      requires a development snapshot

      Unless there’s a killer problem, like Slic3r’s bridging mess earlier this year, I fetch whatever’s at the head of the master branch for both Slic3r and OpenSCAD whenever I start something new. In general, that works well enough and I get to follow the discussions about whatever the bulging brains come up with …

Comments are closed.