import static uk.co.nickthecoder.foocad.layout.v1.Layout2d.* import static uk.co.nickthecoder.foocad.layout.v1.Layout3d.* import uk.co.nickthecoder.foocad.threaded.v1.Threaded class LEDJugglingBall : Model { @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 @Piece fun outerSphere() = Sphere( diameter/2 ) @Piece fun thread() = Threaded.create( 2, innerD, 6 ).apply { 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().hole( 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().rod( 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 also use double sided foam tape. */ @Piece fun spacer() = bridge( innerD-thickness*4-1 ).color("Green") /** A ring on which to place a ball, to prevent the ball rolling around. */ @Piece fun ringStand() : Shape3d { return( Circle( diameter*0.05 ) / Square( diameter ).centerX() ) .translateX( diameter*0.2 ) .revolve() + Sphere( diameter/2 ).bottomToOrigin().previewOnly() } @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 fun spacers() = spacer().tileX(2,1).tileY(3,1) override fun build() : Shape3d { return hemiSphere() + ring().translateZ(-7.5) + spacer() } }