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 } }