My buddy Mark One asked me to make a golf-ball sized Thing that’s the intersection of three mutually orthogonal cylinders. He claims I (subtractively) machined one from solid plastic, many many years ago, but I cannot imagine I ever had that level of machine shop fu; right now, I’m not sure how I’d fixture the thing.

It’s much easier with a 3D printer…
Of course, spheroids aren’t printable without support, but you can chop one in half to reveal the nice, flat interior surfaces, then add holes for alignment pegs. Using 0.50 infill makes for a compact mesh inside the ball:

Smooth a few imperfections from the mating surfaces and add four pegs (the other two are busy propping the right-hand half off the countertop). Somewhat to my surprise, the alignment holes came out a perfect push fit for the 2.9 mm actual-OD filament with my more-or-less standard 0.2 mm HoleWindage Finagle Constant. This also uses the 1.005 XY scale factor to adjust for ABS shrinkage, not that that matters in this case:

Then solvent-bond everything together forever more:

The seam is almost imperceptible around the equator, perhaps because I didn’t slobber solvent right up to the edge. I did print one without the alignment pegs and demonstrated that you (well, I) can’t glue a spheroid without fixturing the halves; that one goes in my Show-n-Tell heap.
The 0.33 mm Z resolution produces sucky North and South poles; the East, West, Left, and Right poles are just fine, as are the eight Tropical Vertices. After mulling for a bit, I rotated a cylindrical profile upward:

The obvious contour lines fit the cylinder much better, although you can see where better Z resolution would pay off:

This was at 0.33 mm x 0.66 mm, 200 °C, 30 & 100 mm/s, 2 rpm. No delamination problems; I applied a wood chisel to persuade those big flat surfaces to part company with the Kapton tape.
The OpenSCAD source code:
// Three intersecting cylinders
// Ed Nisley KE4ZNU - Oct 2011
Layout = "Build"; // Show Build
//- Extrusion parameters must match reality!
// Print with +1 shells and 3 solid layers
// Use infill solidity = 0.5 or more...
ThreadThick = 0.33;
ThreadWidth = 2.0 * ThreadThick;
HoleWindage = 0.2;
Protrusion = 0.1; // make holes end cleanly
//------ Model dimensions
CylDia = 2*IntegerMultiple(40.0/2,ThreadThick);
CylRad = CylDia/2;
echo(str("Actual diameter: ",CylDia));
Angle = [45,0,0]; // rotate to choose build orientation
$fn=128;
AlignPegDia = 2.90;
//-------
function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
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);
}
//------- Model bits & pieces
module OneCyl() {
cylinder(r=CylRad,h=CylDia,center=true);
}
module ThreeCyl() {
intersection() {
OneCyl();
rotate([90,0,0]) OneCyl();
rotate([0,90,0]) OneCyl();
}
}
module HemiThing() {
difference() {
rotate(Angle)
ThreeCyl();
translate([0,0,-CylRad])
cube(CylDia,center=true);
for (Index = [0:3])
rotate(Index*90)
translate([CylRad/2,0,-Protrusion])
PolyCyl(AlignPegDia,5+Protrusion);
}
}
//---------
ShowPegGrid();
if (Layout == "Show")
ThreeCyl();
if (Layout == "Build") {
translate([CylRad,CylRad,0])
HemiThing();
translate([-CylRad,-CylRad,0])
HemiThing();
}