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() 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() } }