Exit Full View
Up

/Games/BallHolder2.foocad

BallHolder2

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.

FooCAD Source Code
import static uk.co.nickthecoder.foocad.layout.v1.Layout2d.*
import static uk.co.nickthecoder.foocad.layout.v1.Layout3d.*
import static uk.co.nickthecoder.foocad.screws.v1.Screws.*

class BallHolder2 : Model {
    
    // 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()

    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)
    }
}