Exit Full View
Up

/Boxes/StackingBox.foocad

StackingBox

Stackable boxes, i.e., you can stack lots of boxes and the "lid" of the bottom box is the next box up.

NOTE. I also use these boxes to hold "component" inlay boxes size 38x54x45 So the custom size I chose is ( 542 , 384 , ?? ) = 108, 152, ??

FooCAD Source Code
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.*

class StackingBox : Model {
    
    @Custom
    var boxWidth = 150

    @Custom
    var boxDepth = 90

    @Custom
    var boxHeight = 46.2

    // The gap between the lid and the main piece. If you want an interferance fit,
    // then this must be tuned to your printer. A high uality printer will need a
    // smaller value than a low quality printer.
    @Custom
    var slack = 0.2

    @Custom
    var round = 6

    // You can make these @Custom too if you wish!

    var thickness = 1.2

    var lipThickness = 2.0

    var lidThickness = 3.0

    var baseThickness = 1.2

    var lidChamfer = 2
    
    var lidHeight = 4

    var baseChamfer = 1

    var lip = 5

    // Diameter of an additional circle at each corner to aid bed adhesion.
    // Set to zero if you don't want ears.
    // I used a brim as well as ears, but for my next print, I will try just a brim.
    var ears = 0

    // End of custom values.

    // The hole for the tissues.
    // This is just slightly smaller than the hole in Wilko's tissues.
    fun hole() : Shape2d = Circle( boxWidth/2 ).sides(120).scale( 0.65, 0.45 )

    // The shape of the box seen from above. This is the internal dimensions,
    // Using the boxWidth and boxDepth, with a 1mm gap.
    fun profile() : Shape2d {
        val width = boxWidth + (thickness + 1 ) * 2
        val depth = boxDepth + (thickness + 1 ) * 2

        return Square( width, depth ).center()
            .roundAllCorners( round )
    }

    // The main part of the box (the lid is separate).
    // Built using an extrusion of profile().
    // We start at the bottom, to the top, then back down again to hollow out the
    // box.
    // A pattern is added to the sides from an SVG file. The file contains other
    // flowers, so replace "flower1" with the id of another flower, or use a
    // competley different design.
    // In Inkscape, press Ctrl+Shift+O in inkscape to see/set the id of the currently
    // selected object. Note, the object must NOT be a group.
    // The pattern is ebossed on two sides, and sticks out on the other two.
    // Change the minus/plus depending on your preferences (I prefer it sticking out).
    @Piece
    fun main() = main( boxHeight )

    fun main( boxHeight : double ) : Shape3d {

        val height = boxHeight + baseThickness + 1
        val width = boxWidth + (thickness + 1 ) * 2
        val depth = boxDepth + (thickness + 1 ) * 2

        val lipChamfer = lipThickness + slack

        val body = ExtrusionBuilder().apply {
            
            // Chamfered base
            crossSection( profile().offset( -baseChamfer ) )
            forward( baseChamfer )
            crossSection( baseChamfer )

            // Main upright
            forward( height - baseChamfer -lipChamfer - baseThickness)
            crossSection()

            // lip
            forward(lipChamfer)
            crossSection(lipChamfer)
            forward(lip)
            crossSection()

            // Top
            crossSection( -lipThickness )
            
            // lip
            forward( -lip + thickness )
            crossSection()
            forward( -thickness )
            crossSection( -thickness )

            // Main
            forward( -height + baseChamfer + lipChamfer )
            crossSection()

            // Chamfered base
            forward( -baseChamfer )
            crossSection( - baseChamfer )

        }.build()

        val foo = Cube(boxWidth,boxDepth,boxHeight).centerXY()
            .bottomTo( baseThickness )
            //.topTo(0)
            .previewOnly()

        return body.color("Orange")
    }

    @Piece
    fun lid() : Shape3d {

        val solid = ExtrusionBuilder().apply {

            // We are building this upside down, so the top of the lid is pointing downwards

            // The chamfered top
            crossSection( profile().offset( lipThickness -lidChamfer ) )
            forward( lidChamfer )
            crossSection( lidChamfer )


            forward( lidHeight )
            crossSection()

            // Lid
            crossSection( -lipThickness-slack )
            forward( lip - thickness )
            crossSection()

            crossSection( -thickness )

            val insideChamfer = Math.max( 0, lidChamfer - lipThickness )

            // Heading back down
            forward( -lidHeight -lidChamfer -lip + insideChamfer + lidThickness )
            crossSection()
            forward( -insideChamfer )
            crossSection( -insideChamfer )
        }.build().color("Green" )

        return solid
    }

    @Piece
    fun stack() = main( 9 ).color( "Silver" )

    fun ears() : Shape3d {
        return Circle( ears ).translate( boxWidth/2, boxDepth/2 ).extrude( 0.2 )
            .mirrorX().also()
            .mirrorY().also()
            .color( "GhostWhite" )
    }

    override fun build() : Shape3d {

        val lid : Shape3d = lid().mirrorZ().toOriginZ()
        
        return main() +
            stack().translateZ(boxHeight-2).color("Yellow") +
            main().translateZ(boxHeight + 5) +
            lid.translateZ(boxHeight*2 + 4) +
            Cube( boxWidth, boxDepth, boxHeight )
                .centerXY().translateZ( baseThickness )
                .previewOnly()
    
    }
}