Exit Full View
Up

/Boxes/WoodenComponentOrganiser.foocad

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

}