Although the current OpenSCAD could produce a solid model with the screw thread’s dedendum, I’d never actually printed one of them:

I need some fondlestuff illustrating how to handle overhangs, so I ran one standing vertically, which (pretty much as I expected) didn’t work well at all:

The trick is to split the model down the middle:

And put holes in each half for alignment pins:

Then you can print it lying down:

The internal overhang would probably call for some support material, particularly in the square recess at the end, but in this case it’s a lesson:

Glue some filament snippets into the holes, snap it together, and it looks just fine over there on the right:

Doesn’t matter how many I print, it still doesn’t make any economic sense as a broom repair…
The OpenSCAD source code now has a Layout
variable to control the orientation and, not as shown in the model, the alignment pins have glue gutters in the first layer:
// Broom Handle Screw End Plug // Ed Nisley KE4ZNU October 2013 Layout = "Horizontal"; // Vertical Horizontal Pin UseDedendum = true; // true to create full thread form //- Extrusion parameters must match reality! ThreadThick = 0.25; ThreadWidth = 0.40; HoleWindage = 0.2; Protrusion = 0.1; // make holes end cleanly //---------------------- // Dimensions PostOD = 22.3; // post inside metal handle PostLength = 25.0; FlangeOD = 24.0; // stop flange FlangeLength = 3.0; PitchDia = 15.5; // thread center diameter ScrewLength = 20.0; ThreadFormOD = 2.5; // diameter of thread form ThreadPitch = 5.0; NumSegments = 32; // .. number of cylinder approximations per turn BoltOD = 7.0; // clears 1/4-20 bolt BoltSquare = 6.5; // across flats BoltHeadThick = 3.0; RecessDia = 6.0; // recesss to secure post in handle OALength = PostLength + FlangeLength + ScrewLength; SplitOC = 1.25*FlangeOD; // separation in Horizontal layout PinOD = 1.75; // alignment pin diameter = filament stub PinLength = 7.0; // ... length $fn=8*4; // default cylinder sides echo("Pitch dia: ",PitchDia); echo("Root dia: ",PitchDia - ThreadFormOD); echo("Crest dia: ",PitchDia + ThreadFormOD); Pi = 3.14159265358979; //---------------------- // Useful routines // Wrap cylindrical thread segments around larger plug cylinder module CylinderThread(Pitch,Length,PitchDia,ThreadOD,PerTurn) { CylFudge = 1.02; // force overlap RotIncr = 1/PerTurn; PitchRad = PitchDia/2; Turns = Length/Pitch; NumCyls = Turns*PerTurn; ZStep = Pitch / PerTurn; HelixAngle = atan(Pitch/(Pi*PitchDia)); CylLength = CylFudge * (Pi*(PitchDia + ThreadOD) / PerTurn) / cos(HelixAngle); for (i = [0:NumCyls-1]) { assign(Angle = 360*i/PerTurn) translate([PitchRad*cos(Angle),PitchRad*sin(Angle),i*ZStep]) rotate([90+HelixAngle,0,Angle]) cylinder(r1=ThreadOD/2, r2=ThreadOD/(2*CylFudge), h=CylLength, center=true,$fn=12); } } // Build complete plug module ScrewPlug() { difference() { union() { cylinder(r=PostOD/2,h=PostLength); cylinder(r=PitchDia/2,h=OALength); translate([0,0,PostLength]) cylinder(r=FlangeOD/2,h=FlangeLength); color("Orange") translate([0,0,(PostLength + FlangeLength)]) CylinderThread(ThreadPitch,(ScrewLength - ThreadFormOD/2),PitchDia,ThreadFormOD,NumSegments); } translate([0,0,-Protrusion]) PolyCyl(BoltOD,(OALength + 2*Protrusion),6); translate([0,0,(OALength - BoltHeadThick)]) PolyCyl(BoltSquare,(BoltHeadThick + Protrusion),4); if (UseDedendum) translate([0,0,(PostLength + FlangeLength + ThreadFormOD/2 - ThreadPitch/(2*NumSegments))]) rotate(-90 - 360/(2*NumSegments)) CylinderThread(ThreadPitch,ScrewLength,PitchDia,ThreadFormOD,NumSegments); for (i = [0:90:270]) { rotate(45 + i) // 45 works better with Horizontal layout translate([PostOD/2,0,PostLength/2]) sphere(r=RecessDia/2,$fn=8); } } } // Locating pin hole with glue recess module LocatingPin() { translate([0,0,-ThreadThick]) PolyCyl((PinOD + 2*ThreadWidth),2*ThreadThick,4); translate([0,0,-(PinLength/2 + ThreadThick)]) PolyCyl(PinOD,(PinLength + 2*ThreadThick),4); } module PolyCyl(Dia,Height,ForceSides=0) { // based on nophead's polyholes Sides = (ForceSides != 0) ? ForceSides : (ceil(Dia) + 2); FixDia = Dia / cos(180/Sides); cylinder(r=(FixDia + HoleWindage)/2, h=Height, $fn=Sides); } module ShowPegGrid(Space = 10.0,Size = 1.0) { Range = floor(50 / Space); for (x=[-Range:Range]) for (y=[-Range:Range]) translate([x*Space,y*Space,Size/2]) %cube(Size,center=true); } //------------------- // Build it... ShowPegGrid(); if (Layout == "Vertical") ScrewPlug(); if (Layout == "Pin") LocatingPin(); if (Layout == "Horizontal") for (i=[-1,1]) difference() { translate([i*SplitOC/2,PostLength/2,0]) rotate([90,180*(i + 1)/2,0]) ScrewPlug(); translate([0,0,-FlangeOD/2]) cube([2*OALength,2*OALength,FlangeOD],center=true); for (j=[-1,1], pin=[-1,1]) assign(PinX = i*SplitOC/2 + pin*(PostOD + BoltOD)/4, PinY = j*PostLength/4) { translate([PinX,PinY,0]) rotate(45) LocatingPin(); echo("i j pin: ",i,j,pin); echo("X Y: ",PinX,PinY); } }