import static uk.co.nickthecoder.foocad.chamferedextrude.v1.ChamferedExtrude.* import static uk.co.nickthecoder.foocad.layout.v1.Layout2d.* import static uk.co.nickthecoder.foocad.layout.v1.Layout3d.* import static uk.co.nickthecoder.foocad.pathextrude.v1.PathExtrude.* class FatBallShelter : Model { var diameter = 100 var thickness = 3.0 @Custom( about="Length the handle sticks out the bottom os the brolly. Can be negative." ) var handleL = 2 fun path( diameter : double, height : double ) = PolygonBuilder().apply { moveTo( diameter/2, 0 ) bezierBy( Vector2( -diameter*0.1, height*0.5 ), Vector2( -diameter*0.25, 0 ), Vector2( -diameter/2, height ) ) }.buildPath() fun umbrella() : Shape3d { val profile = Circle( diameter/2 ).sides( 6 ).roundAllCorners(3) val outsidePath = path( diameter, diameter* 0.3 ) val insidePath = path( diameter-thickness, diameter*0.3-thickness ) val umbrella = profile.extrudePathScaled( outsidePath ) - profile.offset(-thickness).extrudePathScaled( insidePath ) val handleProfile = Circle( 2.5 ) val handleD = 12 val handlePath = PolygonBuilder().apply { moveTo( 0, 0 ) // length of the umbrella's rod lineBy( 0, -umbrella.size.z - handleL ) // Make a hook shape at the end or the rod bezierBy( Vector2( 0, -handleD*0.4 ), Vector2( 0, -handleD*0.5 ), Vector2( handleD*0.5, -handleD) ) bezierBy( Vector2( 0, -handleD*0.7 ), Vector2( handleD*0.2, handleD*0.9 ), Vector2( -handleD, handleD*0.2 ) ) }.buildPath().toPath3d() val handle = ExtrusionBuilder.followPath( handlePath, handleProfile ) .rotateX(90) .rotateZ(90) .topTo(umbrella.top-thickness/2) val hoop = (Circle(7)-Circle(4)).chamferedExtrude(4,0.8) .rotateY(90) .center() .bottomTo(umbrella.top-2) return umbrella + handle + hoop } @Piece fun half() : Shape3d { val umbrella : Shape3d = umbrella() val half = umbrella / Cube( umbrella.size*2 ).centerY().centerZ() return half.rotateY(-90) } @Piece fun otherHalf() = half().mirrorX() @Piece fun ring80() = basketRing( 70 ) @Piece fun ring60() = basketRing( 60 ) @Piece fun ring50() = basketRing( 50 ) fun basketRing(d : double) : Shape3d { val width = 4 val profile = Circle( d/2 + width/2 ) - Circle( d/2 - width/2 ) val extra = Circle(5).translateX(d/2).repeatAround( 10 ) val holes = Circle(2).translateX(d/2).repeatAround( 10 ) val main = (profile + extra - holes).extrude(2) return main } override fun build() : Shape3d { val umbrella : Shape3d = umbrella() val largeRing = ring80().topTo( umbrella.bottom - 10 ) val fatBall = Sphere( 55/2 ).previewOnly().topTo(largeRing.bottom) val midRing = ring60().topTo( fatBall.bottom+5 ) val smallRing = ring50().topTo( fatBall.bottom-5 ) return umbrella + fatBall + largeRing + midRing +smallRing } }