/Boxes/StackingBox.foocad

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, ??
import static uk.co.nickthecoder.foocad.layout.v1.Layout2d.*
import static uk.co.nickthecoder.foocad.layout.v1.Layout3d.*
class StackingBox : AbstractModel() {
@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" )
}
@Piece( printable = false )
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()
}
}

