/Games/Wooden Block Puzzle/Box2.foocad

A two part box, with a lip. I didn't use this one in the end. Opting for three smaller boxes instead of one large box.
See Box3 for my final design.
include WoodenBlock.foocad
class Box2 : AbstractModel() {
@Custom
var part = "view" // top, bottom or debug or view or exploded
@Custom
var width = 123 // Internal size
@Custom
var depth = 123 // Internal size
@Custom
var height = 26 // Internal size
@Custom
var topHeight = 20 // Internal size
@Custom
var radius = 6 // Radius of the outside. Other radii are calculated.
@Custom
var radiusSides = 4
@Custom
var thickness = 4 // Thickness of the top (the bottom will be thicker)
@Custom
var patternThickness = 0.6
@Custom
var lipThickness = 2 // Should probably be half of thickness (or close to it)
@Custom
var lipHeight = 6 // The height of the lip on the bottom piece.
// I created small prototypes to find the best value for this.
// It is the additional space in the top part for the bottom's lip
// to fit into. I wanted an interferance fit.
@Custom
var lipSlack = 0.3
@Custom
var chamfer = 2 // Chamfer of the bottom and top edges.
override fun build() : Shape3d {
val contents = Cube( 120, 120, 40 )
.centerXY()
.translateZ(thickness + 1)
.color("Orange")
val inside = Square( width, depth ).center().roundAllCorners(radius- thickness, radiusSides)
val outside = Square(
width + thickness * 2,
depth + thickness * 2
).center().roundAllCorners(radius, radiusSides)
val outsideChamfer = Square(
width + thickness * 2 - chamfer * 2,
depth + thickness * 2 - chamfer * 2
).center().roundAllCorners(radius - chamfer, radiusSides)
val bottomLip = Square(
width + lipThickness*2,
depth + lipThickness*2
).center().roundAllCorners(radius - thickness + lipThickness, radiusSides)
val topLip = Square(
width + lipThickness*2 + lipSlack*2,
depth + lipThickness*2 + lipSlack*2
).center().roundAllCorners(radius - thickness + lipThickness + lipSlack, radiusSides)
val top = ExtrusionBuilder().apply {
crossSection( outsideChamfer )
forward( chamfer )
crossSection( outside )
forward( topHeight + thickness - chamfer )
crossSection( outside )
crossSection( topLip )
forward( -lipHeight - 1 )
crossSection( topLip )
crossSection( inside )
forward( -topHeight + lipHeight + 1 )
crossSection( inside )
}.build().color( "Blue" )
val bottom = ExtrusionBuilder().apply {
crossSection( outsideChamfer )
forward( chamfer )
crossSection( outside )
forward( height + thickness - chamfer )
crossSection( outside )
crossSection( bottomLip )
forward( lipHeight )
crossSection( bottomLip )
crossSection( inside )
forward( -height - lipHeight )
crossSection( inside )
}.build().color( "Blue" ).brighter()
val view = contents + bottom + top.rotateX(180).translateZ( height + topHeight + 9)
val pattern = topPattern()
.extrude( patternThickness )
.translateZ( -0.01)
.color( "WhiteSmoke" )
return if (part == "top" ) {
top - pattern
} else if (part == "bottom" ) {
bottom - pattern
} else if (part == "view" ) {
view
} else if (part == "exploded" ) {
contents + bottom + top.rotateX(180).translate( width + 10, 0, height + topHeight + 50)
} else {
val inspection = Cube( 400, 5, 400 ).center() + Cube( 5, 400, 400 ).center() + Cube(400, 1, 400).centerY().rotateZ(45)
view // inspection
}
}
fun topPattern() : Shape2d{
var foo = 10
val result = listOf<Shape2d>()
for ( x in 10..width.toInt() - foo step foo * 2 ) {
result.add (
Square( x, x ).center() -
Square( x - foo*1.2, x - foo*1.2 ).center()
)
}
val diagonal = Square( width * 4, foo ).center().rotate(45)
return Union2d( result ) - diagonal.mirrorX().also()
}
}

