import static uk.co.nickthecoder.foocad.along.v2.Along.* import static uk.co.nickthecoder.foocad.extras.v1.Extras.* 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.* class WoodenComponentOrganiser : Model { // The size of the inserts. Note "insertGap" is subtracted from the // x and y sizes of the actual inserts. // Note Racco states that the smallest A insert is 39x55x47 // Swap width and depth for inserts oriented the other way. var unitWidth = 55 var unitDepth = 40 // NOTE this isn't 39! var unitHeight = 46.5 // Does NOT include the feet. var shoeHeight = 2.0 // The number of 1x1 inserts that can be fitted in a single drawer. var drawerX = 6 var drawerY = 6 var drawerCount = 4 var baseThickness = 6 var drawerThickness = 12 // The gap between the inserts. var insertGap = 0.5 var sliderWidth = 10 var storeyGap = 1 var extraDepth = 50 // The radius of the circles in the drawers that the feet fit into. var shoeRadius = 9 val ply = SheetLumber( "ply", drawerThickness ) val base = SheetLumber( "base", baseThickness ) fun freeWidth() = unitWidth * drawerX fun freeDepth() = unitDepth * drawerY fun drawerHeight() = unitHeight + shoeHeight + insertGap + baseThickness fun drawerWidth() = unitWidth * drawerX + drawerThickness*2 fun drawerDepth() = unitDepth * drawerY + drawerThickness*2 @Piece fun drawer() : Shape3d { val width = drawerWidth() val depth = drawerDepth() val height = drawerHeight() val bottom = base.cut( width, depth ) .color("Orange").label("bottom") .alongY2().center().topToOrigin() val side = ply.cut( height - base.thickness, depth ) .color("Green").label("side") .alongY() .centerY().leftTo(bottom.left).mirrorX().also() val frontBack = ply.cut( height - base.thickness, width - drawerThickness*2) .color("Green").brighter().label("frontBack") .alongX().centerX().frontTo(bottom.front) .mirrorY().also() val front = ply.cut( height, width + drawerThickness*2 + sliderWidth*2 - storeyGap * 2 ) .color("Silver").label("front") .alongX().centerX().backTo(frontBack.front) .translateZ(-baseThickness) val handle :Shape3d = handle().backTo( front.front ).centerX() .bottomTo( -baseThickness ).translateZ( height/2 ) val shoes = shoe() .tileX( drawerX ) .tileY( drawerY ) .center() .extrude( 1.8 ) val drawer = bottom + side + frontBack + front + handle + shoes println( "Drawer size ${drawer.size}" ) return drawer } @Piece fun corner() : Shape3d { val x = 20 val y = 10 val t = 2 val foo = drawerThickness + sliderWidth val profile = PolygonBuilder().apply { moveTo( 0,0 ) lineTo( 0, y ) lineTo( -t, y ) lineTo( -t, 0 ) lineTo( -foo, 0 ) lineTo( -foo, -t ) lineTo( -foo, -t ) radius( 0 ) lineTo( x-t*2, -t ) lineTo( x, 0 ) }.build() return profile.extrude( drawerHeight() ).color( "Purple" ) } @Piece fun handle() : Shape3d { val w = 80 val t = 10 val d = 30 val profile = PolygonBuilder().apply { moveTo( w/2, -d ) lineTo( w/2, 0 ) lineTo( w/2-t, 0 ) lineTo( w/2-t, -d+t ) lineTo(-w/2+t, -d+t ) lineTo(-w/2+t, 0 ) lineTo(-w/2, 0 ) lineTo(-w/2, -d ) }.build().roundAllCorners(1,1) val handle = profile.chamferedExtrude( t, 1 ).color("Purple") val holes = Cylinder( 20, 2 ).center().rotateX(90) .translate(w/2-t/2, 0, t/2).mirrorX().also() return handle - holes } @Piece fun cabinet() : Shape3d { val width = drawerWidth() + sliderWidth*2 + drawerThickness * 2 val depth = drawerDepth() + extraDepth + drawerThickness val height = ( drawerHeight() + storeyGap ) * drawerCount + storeyGap val bottom = ply.cut( width, depth + drawerThickness ) .color("Violet").label("bottom") .alongY2().center().topToOrigin() .translateY(-drawerThickness/2) val side = ply.cut( height, depth ) .color("Blue").label("side") .alongY() .centerY().leftTo(bottom.left).mirrorX().also() val top = ply.cut( width, depth + drawerThickness ) .color("Violet").label("bottom") .alongY2().center().bottomTo(side.top) .translateY(-drawerThickness/2) val back = ply.cut( height, width - drawerThickness*2) .color("Blue").darker().label("frontBack") .alongX().centerX().backTo(bottom.back) val cabinet = bottom + top + side + back return cabinet } @Piece fun shoe() : Shape2d { val rect = Square( unitWidth, unitDepth ).center() val corners = Circle( shoeRadius ) .translate( -unitWidth/2, -unitDepth/2 ) .mirrorX().also().mirrorY().also() val shape = rect - corners return shape - shape.offset( -1.8 ) } @Piece fun handles() = handle().tileX(2,2).tileY(2,2) @Piece fun corners() = corner().repeat( 8, 4, 4, 0 ) @Piece fun shoes() = shoe() .tileX( drawerX /2) .tileY( drawerY /2 ) .extrude( shoeHeight ) override fun build() : Shape3d { val cabinet : Shape3d = cabinet() val drawer : Shape3d = drawer().translateZ( baseThickness + storeyGap ) .translateY( -extraDepth / 2 - drawerThickness/2 ) cabinet + drawer.tileZ( drawerCount, storeyGap ) return cabinet + drawer } }