/Boxes/PinBox.foocad

A box, which slides open, with catches at the sides to prevent it opening by accident.
Includes a slope to help get pins out by dragging them up the slope.
import static uk.co.nickthecoder.foocad.chamferedextrude.v1.ChamferedExtrude.*
class PinBox : AbstractModel() {
// The -0.8 and -1.6 are bodges to let me change the thickness of the
// outside without re-printing the inside.
@Custom
var width = 50 - 0.8 + 1/2
@Custom
var depth = 70 - 1.6 + 1
@Custom
var height = 20 - 1.6 + 1
@Custom
var innerThickness = 1.6
@Custom
var outerThickness = 0.8
@Custom
var text = ""
@Custom
var patternDepth = 0.3
@Custom
var frontText = "↑ PINS ↑"
@Custom
var slope = true
var slack = 1.5
var gap = 0.5
var chamfer = 1
var thumbR = 10
fun thumb() : Shape2d {
return Circle( thumbR ) / Square( thumbR*3 ).centerY()
}
fun clip() = clip( 10, 2, 10, width*0.5, 1, innerThickness )
fun clip( clipWidth : double, clipThickness : double, clipHeight : double, span : double, gap : double, thickness : double ) : Shape3d {
val clipP = PolygonBuilder().apply {
moveTo(0,0)
lineTo(clipWidth,0)
lineTo(clipWidth,clipThickness)
lineTo(clipWidth-clipThickness, clipThickness)
}.build()
val clip = clipP.extrude(clipHeight) - Cube( clipP.size.x ).rotateX(-45)
val clipGapP = Square( span, gap ).rightTo(gap)
.translateY(clipHeight+gap).also() +
Square( gap, clipHeight+gap-0.6 ).translateY(gap+0.6)
val clipGaps = clipGapP.extrude( thickness+0.01 )
.rotateX(90).centerZ()//.translateX( -clipWidth-gap )
return clip.centerZ().rightToOrigin().color("Blue")
.remove( clipGaps.color("Red") )
}
@Piece
fun inside() : Shape3d {
val h = height- outerThickness*2-slack
val w = width - outerThickness -slack/2
val d = depth - outerThickness*2-slack
val profile = Square( w, d )
.roundAllCorners(2)
.center()
val inside = ExtrusionBuilder().apply {
crossSection( profile.offset(-chamfer) )
forward( chamfer )
crossSection( profile )
forward( h-chamfer )
crossSection()
crossSection( -innerThickness )
forward( -h + innerThickness )
crossSection()
}.build().center().color("Yellow")
val thumb : Shape3d = thumb().chamferedExtrude( h + slack, 0, chamfer ).center()
.translateZ(innerThickness)
.mirrorX().rightTo( w/2 )
val insideHeight = h - innerThickness
val curve1 :Shape3d =
(
Square( insideHeight ) -
Circle( insideHeight )
).extrude( d-innerThickness*6 ).center().rotateX(90).rotateY(180)
.leftTo(-width/2+innerThickness)
val curve : Shape3d = if (slope == true) curve1 else Cube(0)
val side = (
Cube( w-innerThickness*2, innerThickness, h-innerThickness ).centerZ().centerX() +
Cube( w-innerThickness*2, innerThickness*3, innerThickness ).centerX().topTo(h/2)
).backTo(d/2-innerThickness)
val clip : Shape3d = clip()
.translateY(d/2)
.translateX(w/2-6)
val text = Text(frontText).center()
.extrude(patternDepth)
.rotateX(90)
.rotateZ(90)
.leftTo( inside.right )
.color("Green")
return text + inside.and(clip).and(clip.mirrorY()) + thumb + side.mirrorY().also() + curve
}
@Piece
fun outside() : Shape3d {
val outsideP = Square( height, depth ).center()
.roundAllCorners( chamfer, 1 )
val insideP = outsideP.offset(-outerThickness) //Square( height-outerThickness*2, depth-outerThickness*2 ).center()
val cham = chamfer / Math.sqrt(2)
val solid = ExtrusionBuilder().apply {
crossSection( outsideP.offset(-chamfer) )
forward( chamfer )
crossSection( outsideP )
forward( width - chamfer + cham )
crossSection()
crossSection( insideP )
forward( - width + outerThickness )
crossSection()
forward( -cham )
crossSection( -cham )
}.build()
val thumb : Shape3d = thumb().offset(gap)
.chamferedExtrude( height+0.2, -0.5 )
.rotateY(90)
.centerX()
.topTo(width+gap+cham+0.1)
val text3d = Text(text).center().extrude(0.4)
.rotateZ(-90).rotateY(90)
.translateZ(width/2)
.translateX(height/2)
val slots = Cube( 11 ,depth+2, 11 ).center()
.translateZ(width-10)
return (solid - thumb).color("Green") - slots + text3d
}
@Piece
fun both() = inside().toOriginZ() +
outside().toOriginZ().translateX(-width/2-height/2-2)
@Piece( printable = false )
override fun build() : Shape3d {
val result =
inside() +
outside()
.center().rotateY(90).translateX(-outerThickness/2)
.translateX( -40 )
return result
}
}

