FooCAD Source Codeimport static uk.co.nickthecoder.foocad.ears.v1.Ear.*
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.*
/**
A shallow drawer for the underside of an over-bed table.
It is very shallow, so that no "leg room" is lost.
(The height is very nearly the same as the table's metalwork).
The table is 770x400, so the maximum length (y) is about (400-30)/2 = 185
The position of the runners is vital, so I've made the holes slots to allow for some adjustment.
Attach them to the table using round head screws and washers.
Pre-drill the holes with a depth stop on the drill bit.
There are no handles/knobs. Just slide the drawer by drawwing its base.
Print Notes
2 Perimeters
3 top and bottom layers
Low infill (10%)
I used 3DQF's beige for the runners, and will use a variety of colours for the drawers
Transluscent filament gives a nice effect if the wall thickness > 2 * perimeters (due to the infill)
(Monochrome is so dull ;-)
*/
class HangingDrawer : Model {
@Custom
var size = Vector3( 125, 170, 30 )
@Custom
var runnerSize = 6
@Custom
var radius = 8
@Custom
var chamfer = 3
@Custom
var glueWidth=5
@Custom
var text = Text("Lilian", BOLD, 40)
@Custom
var slack = 1
@Custom
var thickness = 3
@Custom
var clearance = 1
@Custom
var earSize = Vector2(45,4)
fun drawer() : Shape3d {
val lip = 1
val lip2 = lip * Math.sqrt(2)
val base = Square( size.x, size.y ).center().offset(-chamfer).roundAllCorners(radius)
val mid = base.offset(chamfer)
val inside = mid.offset(-thickness)
val top = Square( size.x + runnerSize*2 - lip*2, size.y ).center().roundAllCorners(radius)
val drawer = ExtrusionBuilder().apply {
crossSection( base )
forward(chamfer)
crossSection( mid )
forward( size.z -chamfer - runnerSize )
crossSection()
forward( runnerSize - lip )
crossSection(top)
forward(lip)
crossSection()
crossSection( -thickness )
forward( -runnerSize + lip/Math.sqrt(2) )
crossSection( inside )
forward( -size.z + chamfer*2 + runnerSize - lip/Math.sqrt(2) )
crossSection()
forward(-chamfer)
crossSection(-chamfer)
}.build()
val text = this.text
.mirrorX()
.rotate(90)
.extrude(0.6)
.centerXTo( drawer.middle.x ).centerYTo(drawer.middle.y)
return (drawer - text).margin(-runnerSize,0,0)
}
var lidThickness = 2.0
fun lid() : Shape3d {
val lip = 1
val top = Square( size.x + runnerSize*2 - lip*2 - thickness*2 - 2-0.4, size.y - thickness * 2 - 0.2 )
.center().roundAllCorners(radius - thickness - 0.1)
val bottom = Square( size.x + runnerSize*2 - lip*2 - thickness*2 - 0.4 - lidThickness*2, size.y - thickness * 2 - 0.2 )
.center().roundAllCorners(radius)
return ExtrusionBuilder().apply {
crossSection( top )
forward(1)
crossSection()
forward( lidThickness -1 )
crossSection( bottom )
}.build().color( "Purple" )
}
fun holes() : Shape3d {
val profile = Circle( 2 ).translateX(1) hull Circle( 2 ).translateX(-1)
val slot = profile.extrude(100)
return slot.spreadY( 2, size.y-20 )
.centerY()
.color("Red")
}
fun runner() : Shape3d {
val profile = PolygonBuilder().apply {
moveTo(0,0)
lineBy( glueWidth/2 + runnerSize, 0 )
lineBy( -runnerSize, runnerSize )
lineBy( 0, clearance )
lineBy( -glueWidth - runnerSize/2, 0 )
lineBy( 0, -runnerSize - clearance )
}.build().roundCorner(1,0.5,1)
val main = profile.chamferedExtrude(size.y,0,1).rotateX(90).centerY()
return main - holes()
}
fun doubleRunner() : Shape3d {
val profile = PolygonBuilder().apply {
moveTo(0,0)
lineBy( glueWidth/2 + runnerSize, 0 )
lineBy( -runnerSize, runnerSize )
lineBy( 0, clearance )
lineBy( -glueWidth, 0 )
lineBy( 0, -clearance )
lineBy( -runnerSize, -runnerSize )
}.build().roundCorners(listOf<int>(6,1),0.5,1)
val main = profile.chamferedExtrude(size.y,1).rotateX(90).centerY()
return main - holes()
}
fun withEars( shape : Shape3d ) = shape +
Ear( earSize.x/2 ).ribs(1.2,earSize.y).ribMargin(2).earsFor( shape )
@Piece
fun runnerWithEars() = withEars(runner())
@Piece
fun doubleRunnerWithEars() = withEars(doubleRunner())
@Piece
fun drawerWithEars() = withEars(drawer())
@Piece
fun lidWithEars() = withEars(lid())
@Piece
fun testLidCorner() = lid().toOrigin().intersection( Cube( 30 ) )
override fun build() : Shape3d {
val drawer = drawer()
val runner = runner()
.translateX( -size.x/2 - runnerSize - 1 - glueWidth/2)
.topTo( drawer.top )
val doubleRunner = doubleRunner()
.translateX( size.x/2 + runnerSize + 1 + glueWidth/2 )
.topTo( drawer.top)
val lid = lid()
.mirrorZ().topTo( drawer.top )
//.previewOnly()
return drawer + (runner + doubleRunner).color("Green") + lid
}
}