/Games/BallHolder2.foocad

A wall mounted holder for 3 juggling balls. A companion to the ClubsHolder.
Print 1 "base" and three "ring" pieces. The rings can be TPU for a rubbery feel. Glue with cyanoacrylate (AKA superglue).
The design is flawed! Over time, it has sagged. In hindsight there should have been some kind of triangulation for strength. Surprisingly it has never broken, despite being knocked many times.
import uk.co.nickthecoder.foocad.screws.v3.*
import static uk.co.nickthecoder.foocad.layout.v1.Layout2d.*
import static uk.co.nickthecoder.foocad.layout.v1.Layout3d.*
class BallHolder2 : AbstractModel() {
// The diameter of the balls you wish to display.
@Custom
var ballD = 85
// The gap between adjascent balls
@Custom
var gap = 5
// The thickness of the rings (i.e. the "small" diameter of the torus).
@Custom
var ringT = 10
// The diameter of the rings compared to the ball's diameter.
@Custom
var ringScale = 0.6
fun ringD() = ballD * ringScale
@Piece
fun ring() : Shape3d {
val profile = Circle( ringT / 2 ).translateX( ringD()/2 ) /
Square( ringD() + 1 )
return profile.revolve().sides(50).color( "Green" )
}
@Piece
fun base() : Shape3d {
val rings = repeat(ring()).mirrorZ()
val line = ( Cylinder( ballD + gap, ringT/2 ) / Cube( ballD*3 ).centerY() )
.centerY()
.rotateY(90)
.centerX()
.translateY(ringD()/2)
val lines = line + line.toOriginX()
.mirrorY()
.rotateZ(60)
.translateY( -(ballD + gap) * Degrees.sin(60) )
.mirrorX().also()
val coneH = (ballD + 4 - ringD() + gap) / 2
val coneD = coneH*1.3
val keyHole = KeyholeHanger( 4, 8 ).mirrorZ()
.rotateX(90)
.translateY( coneH )
.translateZ(-6)
val cone = (
(
Cylinder( coneH *0.8, ringT*0.6, coneD ) +
Cylinder( coneH * 0.2, coneD ).translateZ( coneH * 0.8)
) /
Cube( ringT*3 ).centerX()
).rotateX(-90) - keyHole
val cones = cone.translateX( (ballD + gap)/2 )
.mirrorX().also().translateY( ringD()/2 )
val result = lines + rings + cones
return result.color("Yellow")
}
fun repeat( shape : Shape3d ) =
shape.repeatX( 2, ballD + gap ).centerX() +
shape.translateY(-(ballD+gap)*0.87)
@Piece
fun printBase() = base().centerXY().mirrorZ() + Cube( 200, 200, 1 ).center().previewOnly()
@Piece( printable = false )
override fun build() : Shape3d {
val balls = repeat( Sphere( ballD/2 ) )
.translateZ( ballD * 0.50 )
.previewOnly()
return base() + balls + repeat( ring() ) //+ Cube( 85,10,10 ).centerX().translateX(-44)
}
}

