For reasons not relevant here, I was tapped to replace the plastic parts attaching the handle to a garden cart:

The owner tried to contact the “manufacturer” to no avail; repair parts are simply not available, even if the name painted on the cart had a meaningful relationship to anything else.
Well, I can fix that:

Fortunately, another cart in the fleet provided the missing bits so I could reverse-engineer their measurements.
The solid model looks about like you’d expect:

Printing the two halves with those nice (yellow) bosses in place wasn’t feasible. They were exactly 1 inch in diameter, so I just parted two cookies from the end of a stout acetal rod after drilling a hole for the 2-¼ inch 5/16-18 bolt.
The two pieces took nigh onto three hours with five perimeters and 50% infill:

While delivering and installing the parts, I got volunteered to haul plants to cars with one of the carts during the upcoming Spring Plant Sale. That’ll teach me to stay in the Basement Shop …
The OpenSCAD source code as a GitHub Gist:
// Garden Cart Handle Pivot | |
// Ed Nisley KE4ZNU 2022-05 | |
Layout = "Show"; // [Show,Build] | |
/* [Hidden] */ | |
ThreadThick = 0.25; | |
ThreadWidth = 0.40; | |
HoleWindage = 0.2; | |
Protrusion = 0.1; // make holes end cleanly | |
inch = 25.4; | |
function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit); | |
ID = 0; | |
OD = 1; | |
LENGTH = 2; | |
//---------- | |
// Dimensions | |
// Handle lies along X axis | |
HandleOD = (7/8) * inch; | |
BoltOD = (5/16) * inch; | |
Washer = [BoltOD,1.0 * inch,2.0]; // just for Show | |
Disk = [BoltOD,62.0,(3/16) * inch]; | |
ClampBase = [(1 + 7/8)*inch,(1 + 1/8)*inch,2.0]; | |
Kerf = 2.0; | |
CornerRadius = 1.0; | |
PivotOA = [Disk[OD],Disk[OD],HandleOD + 2*ClampBase.z + 2*Disk[LENGTH]]; | |
//---------------------- | |
// Useful routines | |
module PolyCyl(Dia,Height,ForceSides=0) { // based on nophead's polyholes | |
Sides = (ForceSides != 0) ? ForceSides : (ceil(Dia) + 2); | |
FixDia = Dia / cos(180/Sides); | |
cylinder(d=(FixDia + HoleWindage),h=Height,$fn=Sides); | |
} | |
//---------------------- | |
// Set up parts | |
module Handle() { | |
translate([-2*PivotOA.x,0,0]) | |
rotate([0,90,0]) | |
PolyCyl(HandleOD,4*PivotOA.x,24); | |
} | |
module Bolt() { | |
translate([0,0,-PivotOA.z]) | |
PolyCyl(BoltOD,2*PivotOA.z,12); | |
} | |
module Pivot() { | |
difference() { | |
union() { | |
hull() | |
for (i=[-1,1], j=[-1,1]) // rounded block | |
translate([i*(ClampBase.x/2 - CornerRadius),j*(ClampBase.y/2 - CornerRadius),-PivotOA.z/2]) | |
cylinder(r=CornerRadius,h=PivotOA.z,$fn=4*8); | |
for (k=[-1,1]) | |
translate([0,0,k*(PivotOA.z/2 - Disk[LENGTH]/2)]) | |
rotate(180/36) | |
cylinder(d=Disk[OD],h=Disk[LENGTH],$fn=36,center=true); | |
} | |
Handle(); | |
Bolt(); | |
cube([2*ClampBase.x,2*ClampBase.y,Kerf],center=true); // slice through center | |
} | |
} | |
//---------- | |
// Build them | |
if (Layout == "Show") { | |
rotate([90,-45,0]) { | |
Pivot(); | |
color("Green") | |
translate([2*PivotOA.x - PivotOA.x/2,0,0]) | |
Handle(); | |
color("Red") | |
Bolt(); | |
color("Yellow") | |
for (k=[-1,1]) | |
translate([0,0,k*(PivotOA.z/2 + Washer[LENGTH])]) | |
rotate(180/36) | |
cylinder(d=Washer[OD],h=Washer[LENGTH],$fn=36,center=true); | |
} | |
} | |
if (Layout == "Build") { | |
Offset = 5.0; | |
intersection() { | |
translate([-(PivotOA.x/2 + Offset),0,PivotOA.z/2]) | |
Pivot(); | |
translate([-2*PivotOA.x,-2*PivotOA.y,0]) | |
cube([4*PivotOA.x,4*PivotOA.y,PivotOA.z/2],center=false); | |
} | |
intersection() { | |
translate([(PivotOA.x/2 + Offset),0,PivotOA.z/2]) | |
rotate([180,0,0]) | |
Pivot(); | |
translate([-2*PivotOA.x,-2*PivotOA.y,0]) | |
cube([4*PivotOA.x,4*PivotOA.y,PivotOA.z/2],center=false); | |
} | |
} | |