Exit Full View
Up

/Garden/BirdHouseFeeder2.foocad

BirdHouseFeeder2
FooCAD Source Code
import 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
    }

}