/Games/HexBall.foocad

I have some ball bearings going spare, and I thoght I would make them into a sphere for heavy juggling !
The tricky part of the design was finding a way to print it without steep overhangs.
Print 8 pieces. You may also print a "center" piece in TPU. The glue the eight pieces to the center only, and you get enough flexibility to insert the balls (hopefully!)
import static uk.co.nickthecoder.foocad.layout.v1.Layout2d.*
import static uk.co.nickthecoder.foocad.layout.v1.Layout3d.*
import static uk.co.nickthecoder.foocad.chamferedextrude.v1.ChamferedExtrude.*
class HexBall : AbstractModel() {
@Custom
val ballD = 20.5
// The size of the "inner" sphere.
// A larger number will capture the balls more completely,
// If you get this number "just right", you may be able to pop the balls
// in and out of a TPU printed object. ???
@Custom
var innerScale = 1.25
// I like to print a 2 to test the fit.
// Adjust ballD and innerScale if the fit isn't quite perfect.
// Only then will I print the remaining 6 pieces.
@Custom
var quantity = 8
fun whole() : Shape3d {
val hole = Sphere(ballD/2)
val end = hole.tileX(2).tileY(2).center()
val dist = ballD * Math.sqrt(2)
val middle = hole.repeatX( 2, dist ).repeatY( 2, dist ).center().rotateZ(45)
val holes = middle + end.translateZ( dist/2 ).mirrorZ().also()
val sphere = Sphere( ballD * innerScale )
val result = (sphere - holes)
return result
}
@Piece
fun eighth() = eighth(1)
fun eighth( quantity : double ) : Shape3d {
val sphere = Sphere( ballD * innerScale )
val quarter = Cube( ballD *2 ).rotateZ(45)
val hole = Sphere(ballD/2)
val dist = ballD * Degrees.cos(60) //Math.sqrt(2)
val piece = (sphere / quarter) -
hole.translateY( ballD ) -
hole.translateY( ballD ).rotateX(45).rotateZ(45).mirrorX().also()
// 8 pieces will make a complete sphere.
// But now lets make them easy to print, with less overhang, putting the
// corner stright down, and then slicing it off for good bed contact.
// NOTE. 54.735 isn't the "right" rotation, but my maths is poor :-(
// I obtained this by trial and error (with a binary chop to get ever closer).
val eighth = piece.rotateX(54.735).translateZ(-ballD*0.3) / Cube( ballD*2 ).centerXY()
// See how the eighth piece compares to the whole sphere
//return eighth + whole().rotateX(54.735).translateZ(-ballD*0.3).previewOnly()
return if ( quantity %2 == 0) {
eighth.tileX(quantity/2).tileY(2)
} else {
eighth.tileX(quantity)
}
}
@Piece
fun center() : Shape3d {
val delta = ballD*0.3
val debug = eighth(1).previewOnly()
.rotateX(180)
val size = ballD*0.52 + 0.3
val solid = PolygonBuilder().apply {
moveTo(0,-size)
lineTo(size,0)
lineTo(0,size)
}.build().revolve().sides(4)
.rotateZ(45)
.rotateX(54.735)
.toPolyhedron()
.toOriginZ()
return solid + debug
}
override fun build() : Shape3d {
return center().translateY(-30) + eighth(quantity)
}
}

