/Garden/FatBallShelter.foocad

Put a roof over a fat ball (bird food).
Print Notes
Use a brim, to prevent lifting - there is very little contact with the bed!
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 : AbstractModel() {
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
}
@Piece( printable = false )
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
}
}

