import static uk.co.nickthecoder.foocad.ears.v1.Ears.* 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(6,1),0.5,1) val main = profile.chamferedExtrude(size.y,1).rotateX(90).centerY() return main - holes() } fun withEars( shape : Shape3d ) = shape + shape.ears( earSize.x/2 ).ribs(1.2,earSize.y).ribsMargin(2) @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 } }