/Garden/CaneTop.foocad

Place on the top of a cane to prevent eye damage if someone trips and fall onto it. This is often done with corks, cans and other upcycled items.
I wanted something that looks nicer, and also supplies a perch for birds (instead of on my chairs!!)
For fun, I've included a mini tray,
which can be placed on top of roundPerch to add a few seeds/peanuts.
import static uk.co.nickthecoder.foocad.layout.v1.Layout2d.*
import static uk.co.nickthecoder.foocad.layout.v1.Layout3d.*
import uk.co.nickthecoder.foocad.extras.v1.*
import static uk.co.nickthecoder.foocad.extras.v1.Extras.*
import uk.co.nickthecoder.foocad.smartextrusion.v1.*
import static uk.co.nickthecoder.foocad.smartextrusion.v1.SmartExtrusion.*
import uk.co.nickthecoder.foocad.cup.v1.*
import static uk.co.nickthecoder.foocad.cup.v1.Cup.*
class CaneTop : Model {
@Custom
var holeDiameter = 7
@Custom
var length = 40
@Custom
var thickness = 3.5
@Custom
var perchSize = Vector2( 100, 8 )
@Custom
var ribSize = Vector2( 2, 1.2 )
@Custom
var flatDiameter = 40
@Piece
meth plain() : Shape3d {
val chamfer = thickness / 4
val inside = Circle( holeDiameter/2 )
val main = inside.offset( thickness )
.cup( length, thickness )
.cavity(true)
.bottom( Chamfer( thickness / 2 ) )
.top( Chamfer( chamfer ) )
.mirrorZ()
.bottomTo(0)
val ribs = Square( ribSize.x + chamfer, ribSize.y ).centerY()
.rightTo( holeDiameter/2 + chamfer )
.extrude( length - thickness )
.repeatAroundZ(5)
.color("Purple")
val ribCone = Cylinder( length - thickness, holeDiameter/2 + chamfer, holeDiameter/2 - ribSize.x )
.bottomTo( -0.01 )
return main insert (ribs remove ribCone)
}
@Piece
meth simplePerch() : Shape3d {
val plain = plain()
val perch = Circle( perchSize.y / 2 )
.safeOverhang().rotate(90)
.smartExtrude( perchSize.x )
.edges( Fillet(perchSize.y/3) )
.rotateY(90).centerX()
.topTo(plain.top)
return (perch and plain).mirrorZ().bottomTo(0)
}
@Piece
meth roundPerch() : Shape3d {
val plain = plain()
val perch = Circle( perchSize.y / 2 )
.safeOverhang()
.translateX( perchSize.x/2 )
.revolve()
.topTo(plain.top)
val chamfer = Chamfer( perchSize.y/8 )
val spokes = Square( perchSize.x / 2, perchSize.y * 0.7 ).centerY()
.smartExtrude( perchSize.y * 0.9 )
.edges( chamfer )
.topTo(plain.top)
.repeatAroundZ(3)
val flat = Circle( flatDiameter/2 )
.cup( spokes.size.z - chamfer.height, 2 )
.bottom( chamfer )
.mirrorZ().topTo( spokes.top )
return (perch and spokes and flat and plain).mirrorZ().bottomTo(0)
}
@Piece
meth tray() : Shape3d {
val radius = flatDiameter/2 + 0.2
val cup = Circle( radius + 3 ).cup( 20, 3 )
.baseThickness(10)
.top( Fillet( 1.5 ) )
.insideBottom( Fillet(4) )
val bottomShape = Circle( radius )
val spokesShape = Square( perchSize.x / 2, perchSize.y * 0.7 + 0.4 ).centerY()
.repeatAround(3)
val remove = (bottomShape + spokesShape).extrude( 10 - 2 ).bottomTo(-0.01)
return cup - remove
}
@Piece( print="roundPerch" )
override fun build() : Shape3d {
val perch = roundPerch().mirrorZ()
val tray = tray()
return perch + tray.previewOnly()
}
}

