FooCAD Source Codeimport static uk.co.nickthecoder.foocad.layout.v1.Layout2d.*
import static uk.co.nickthecoder.foocad.layout.v1.Layout3d.*
import static uk.co.nickthecoder.foocad.chamferedextrude.v1.ChamferedExtrude.*
import static uk.co.nickthecoder.foocad.screws.v3.Screws.*
import uk.co.nickthecoder.foocad.threaded.v1.Threaded
import static uk.co.nickthecoder.foocad.threaded.v1.Threaded.*
import static uk.co.nickthecoder.foocad.extras.v1.Extras.*
import uk.co.nickthecoderfoocad.smartextrusion.v1.SmartExtrusion
import static uk.co.nickthecoder.foocad.smartextrusion.v1.SmartExtrusion.*
class BirdHouseFeeder : Model {
@Custom( about="Size of the glass. Add extra to y for clearance" )
var glassSize = Vector3( 150, 4, 100 )
@Custom
var sideSize = Vector3( 6, 40, 130 )
@Custom
var baseSize = Vector3( glassSize.x + 20, 90, 8 )
@Custom( about= "" )
var openingHeight = 3
@Custom
var grooveDepth = 3
@Custom( about="How far back is the front of the glass relative to the side piece")
var glassOverlap = 2.0
@Custom( about="Governs (indirectly) the thickness of where the eve screws to the roof" )
var eveAttachmentDelta = 6
@Custom
var slack = 0.3
@Custom
var thread = Threaded( 2, 10, 4 )
@Custom
var screw = Countersink( 4, 8 )
@Custom
var topBoltOffset = 20
@Custom
var bottomBoltOffset = 10
@Piece
fun topBolt() = thread.bolt( sideSize.x + 10, 3 )
.color("Orange")
@Piece
fun bottomBolt() : Shape3d {
val regular = thread.bolt( sideSize.x + 3, 3 )
val extra = Circle( thread.innerR() )
.smartExtrude( 9 )
.chamferTop( 1 )
.bottomTo( regular.top - 2 )
return (regular + extra).color("Orange")
}
@Piece
fun side() : Shape3d {
val plainSide = Square( sideSize.x, sideSize.y )
.roundCorner(2,3,1)
.roundCorner(1,3,1)
.centerY()
.extrude( sideSize.z )
val angleTop = Cube( 100 )
.rotateX(-45)
.centerZTo(plainSide.top)
.centerXTo(0)
val grooves = Cube( grooveDepth, glassSize.y, sideSize.z )
.frontTo(plainSide.front + glassOverlap )
.leftTo(-0.01)
.bottomTo( openingHeight )
.mirrorY().also()
.color("Red")
val screwHoles = thread.hole( 30 )
.rotateY(90)
.centerX()
.centerZTo( sideSize.z - topBoltOffset )
.centerZTo( bottomBoltOffset ).also()
val side = plainSide - angleTop - angleTop.mirrorY() - grooves - screwHoles
return side.rotateY(90).bottomTo(0)
}
@Piece
fun eve() : Shape3d {
val side = side()
val thickness = 3
val attachWidth = 10
val triangle = Square( sideSize.y * 1.4 )
.center()
.rotate(45)
.intersection( Square( 300 ).centerY() )
val plate = triangle.smartExtrude( thickness + attachWidth ).chamferBottom(1) -
triangle.extrude( thickness + attachWidth )
.translateX( - eveAttachmentDelta )
.translateZ( thickness )
val sideHole = Cylinder( 30, thread.diameter/2 + 1 )
.center()
.centerXTo( triangle.right - eveAttachmentDelta - topBoltOffset )
val screwHoles = screw.depth( 10 )
.rotateX(-90)
.translateX( -12 )
.translateX( -25 ).also()
.rotateZ(45)
.translateX( plate.right - eveAttachmentDelta )
.translateZ( 3 + attachWidth/2 )
.mirrorY().also()
return (plate - sideHole -screwHoles ).color("GhostWhite")
}
@Piece
fun base() : Shape3d {
val insetSize = Vector3( glassSize.x - 20, baseSize.y-16, baseSize.z-3 )
val shape = Square( baseSize.x, baseSize.y )
.center()
.roundAllCorners( 30 )
val base = shape.smartExtrude( baseSize.z ).filletTop( 4 )
.color("green")
val inset = Square( insetSize.x, insetSize.y )
.roundAllCorners(12)
.center()
.roundedExtrude( insetSize.z, insetSize.z - 3, -3 )
.topTo( base.top + 0.01 )
.color("LightGreen")
val supportBlocks = Square( 20, sideSize.y - glassSize.y*2 - glassOverlap*2 )
.centerY()
.smartExtrude( baseSize.z + 30 )
.scaleTop( Vector2( 0.1, 1 ) )
.leftTo( -glassSize.x /2 + grooveDepth )
.mirrorX().also()
.color("green")
val screwHoles = Cylinder(20, thread.innerR() + slack )
.rotateY(90)
.leftTo( supportBlocks.right - 8 )
.centerZTo( baseSize.z + bottomBoltOffset )
.mirrorX().also()
val drainHoles = Cube( 2, 2, 30 )
.center()
.rotateZ(45)
.repeatX( 4, 30 )
.repeatY( 3, 30 )
.center()
return (base - inset + supportBlocks) - screwHoles - drainHoles
}
@Piece
fun hanger() : Shape3d {
val length = 30
val v = Square( 6, 24 )
.rotate(45)
.mirrorX().also()
val upright = Square( 6, 12 )
.centerX().backTo(5)
val profile = v + upright
val screws = screw.depth( 10 )
.rotateX(90)
.translateX(13)
.rotateZ(45)
.translateZ( length/2 )
.mirrorX().also()
val hole = Cylinder(20, 2).sides(6)
.rotateY(90)
.center()
.translateY(-2)
.translateZ( length/2 )
return profile.extrude(length) - screws - hole
}
override fun build() : Shape3d {
val glass = Cube( glassSize )
.backTo( sideSize.y/2 - glassOverlap )
.bottomTo( openingHeight )
.centerX()
.mirrorY().also()
.previewOnly()
val side = side().rotateY(-90)
.leftTo(glass.right - grooveDepth)
val eve = eve().rotateY(-90)
.rightTo( side.right + 3 )
.topTo( side.top + eveAttachmentDelta )
val topBolt = topBolt().rotateY(-90)
.translateZ( side.top - topBoltOffset )
.rightTo(eve.right+2)
val bottomBolt = bottomBolt()
.rotateZ(79)
.rotateY(-90)
.translateZ( bottomBoltOffset )
.rightTo(side.right+3)
val base = base().bottomTo(-baseSize.z)
val roof = Cube( 200, 12, 90 )
.translateZ(-12)
.rotateX(45+90)
.translateZ( sideSize.z + eveAttachmentDelta)
.mirrorY().also()
.centerX()
.color("Green")
val hangers = hanger().rotateX(-90).rotateZ(90)
.center()
.bottomTo(roof.top - 12)
.translateX(50)
.mirrorX().also()
return (side + eve + topBolt + bottomBolt ).mirrorX().also() +
base + roof + hangers + glass
}
}