Exit Full View
Up

/Games/BallHolder.foocad

BallHolder
FooCAD Source Code
/**
    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).
*/

import static uk.co.nickthecoder.foocad.layout.Layout2d.*
import static uk.co.nickthecoder.foocad.layout.Layout3d.*
import static uk.co.nickthecoder.foocad.screws.Screws.*

class BallHolder : Model {
    
    // The diameter of the balls you wish to display.
    @Custom
    var ballD = 85

    // The gap between adjascent balls
    @Custom
    var gap = 2

    // 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 * 2 + gap * 2, ringT/2 ) / Cube( ballD*3 ).centerY() )
            .centerY()
            .rotateY(90)
            .centerX()
            .translateY(ringD()/2)

        val coneH = (ballD + 4  - ringD()) / 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 = repeat( cone.translateY( ringD()/2 ) )
            

        val result = line + rings + cones

        return result.color("Yellow")

    }

    fun repeat( shape : Shape3d ) = shape.repeatX( 3, ballD + gap ).centerX()

    @Piece
    fun printBase() = base().mirrorZ().rotateZ(45) + Cube( 230, 230, 1 ).center().previewOnly()
    override fun build() : Shape3d {
        val balls = repeat( Sphere( ballD/2 ) )
            .translateZ( ballD * 0.50 )
            .previewOnly()

        return base() + balls + repeat( ring() )
    }
}