import uk.co.nickthecoder.foocad.threaded.v2.* import static uk.co.nickthecoder.foocad.layout.v1.Layout2d.* import static uk.co.nickthecoder.foocad.layout.v1.Layout3d.* class LEDJugglingBall : AbstractModel() { @Custom var diameter = 80 // The inner diameter @Custom var innerD = 75 @Custom var thickness = 2 // Height of the threaded section which joins a hemisphere to the ring part. // Note the ring is twice this height. var joinH= 10 // The overhang angle where an internal flat spot is placed. @Custom var overhang = 65 fun outerSphere() = Sphere( diameter/2 ) fun thread() = Thread( innerD, 6 ).rodChamfer(0.5) @Piece fun hemiSphere() : Shape3d { val flat = Cube( diameter ).centerXY() .translateZ(Degrees.sin(overhang)* diameter/2) val sphere = outerSphere() - (Sphere( diameter/2 - thickness ) - flat) val result = sphere / Cube( diameter+2 ).centerXY() val thread : Shape3d = Cylinder( joinH, innerD/2 + thickness ) / Sphere( diameter/2 ) - thread().threadedHole( joinH + 4 ).translateZ(-2) val floor = ( Circle( diameter/2 ) - Circle( innerD/2 ) ) .extrude( thickness ) return result + thread + floor } @Piece fun ring() : Shape3d { val thread : Shape3d = thread().threadedRod( joinH * 2) val hole = Cylinder( joinH*3, innerD/2 - thickness*2 ).translateZ(-0.01) val battery = Cube( 50, 34, 5 ).centerXY().translateZ(thickness).previewOnly() return (thread - hole + bridge(innerD-thickness*3)).color("Orange") + battery } fun bridge(diameter : double) : Shape3d { return (Circle( diameter/2 ) / Square( innerD, 35 ).center() ) .extrude( thickness ) } /** Each "layer" of electronics has a spacer between it. Then the lasagne is taped together with the "join" piece. I haven't used these pieces. In hindsight, I should make them clip together with the flat part of the [ring] piece. */ @Piece fun spacer() = bridge( innerD-thickness*4-1 ).color("Green") @Piece fun domeStand() : Shape3d { val hemi = Sphere( diameter/2 ) - Sphere( diameter/2 - thickness ) remove Cube( diameter ).centerXY().topTo(0) val minus = Sphere( diameter/2 ).bottomTo( 5 ) val ball = outerSphere().bottomTo( 5 ).previewOnly() return hemi remove minus + ball } @Piece fun trippleDomeStand() : Shape3d { val one = domeStand() val edge = one.translateX( diameter * 0.59 ) val main = edge and edge.rotateZ(120) and edge.rotateZ(-120) and one val foo = 0.12 val inner = (Circle( diameter * foo ) - Circle( diameter * foo - thickness )) .extrude( 5 ) return main + inner } @Piece( printable = false ) override fun build() : Shape3d { return hemiSphere() + ring().translateZ(-7.5) + spacer() } }