Exit Full View
Up

/Boxes/ThickWalledBox2.foocad

ThickWalledBox2

A rounded rectangular thick walled box which snaps together with an interferance fit of lips. The ouside and inside of the box are smooth.

Comprised of a bottom and a top, and optionaly middle sections, which are hollow tubes (with the same lip connectors). You can include as many middle sections as you like, and either keep them free, or glue them to the bottom.

An upgraded version of ThickWalledBox, but changed the name so that other scripts can use the old version still.

Print Notes

I highly recommend trying colour transparent PLA. It give an amazing striped effect from the infill pattern.

Use 2 perimeters, and 10% infill

The corners of the lip are over-extruded when I create a perfectly square box, so I have to cut a little with a knife. YMMV.

FooCAD Source Code
import static uk.co.nickthecoder.foocad.layout.Layout2d.*
import static uk.co.nickthecoder.foocad.layout.Layout3d.*

class ThickWalledBox2 : RoundedThickWalledBox2 {

    @Custom( about="Size (not including the height) of the insides of the box" )
    var size = Vector2(70,30)

    override fun profile() = Square( size ).center()
}

abstract class RoundedThickWalledBox2 : AbstractThickWalledBox2 {

    // NOTE Unlike the old ThickneWalledBox, the exterior is always rounded
    @Custom( about="Internal radius of the box" ) 
    var radius = 0

    abstract fun profile() : Shape2d

    override fun profile(offset : double ) : Shape2d {
        val p = profile().offset(offset)
        return if (radius + offset <= 0 ) {
            p
        } else {
            p.roundAllCorners( radius + offset)
        }
    }

}

/**
    A thick walled box which snaps together with an interferance fit of lips.
    The ouside and inside of the box are smooth.
    The shape of the box can be anything you like (not only rectangular).
    override the  method profile(), or use ThickWalledBox2 which is a rectanngular box.
    
    Comprised of a bottom and a top, and optionaly middle sections, which are hollow
    tubes (with the same lip connectors).
    You can include as many middle sections as you like, and either keep them
    free, or glue them to the bottom.
    
    An upgraded version of ThickWalledBox, but changed the name so that other scripts
    can use the old version still.
*/
abstract class AbstractThickWalledBox2 : AbstractModel {
    
    @Custom
    var middleHeight = 20.0 // Internal size

    @Custom
    var topHeight = 10.0 // Internal size

    @Custom
    var bottomHeight = 30.0 // Internal size

    @Custom
    var thickness = 4.0 // Thickness of the top (sides and top/bottom)

    @Custom
    var baseThickness = 2.0

    @Custom
    var lipThickness = 2.0 // Should probably be half of thickness (or close to it)

    @Custom
    var lipHeight = 6.0 // 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. 
    @Custom
    var lipSlack = 0.3

    @Custom
    var chamfer = 2.0 // Chamfer of the bottom and top edges.

   abstract fun profile( offset: double ) : Shape2d
   

    @Piece
    fun top() : Shape3d {
        
        val inside = profile(0)
        val outside = profile( thickness )
        val outsideChamfer = profile( thickness - chamfer )
        val outsideLip = profile( lipThickness )

        val top : Shape3d = ExtrusionBuilder().apply {
            crossSection( outsideChamfer )
            forward( chamfer )
            crossSection( outside )
            forward( topHeight + baseThickness - chamfer )
            crossSection( outside )
            crossSection( outsideLip )
            forward( -lipHeight )
            crossSection( outsideLip )
            crossSection( inside )
            forward( -topHeight + lipHeight)
            crossSection( inside )
        }.build().color( "Green" )

        return top.mirrorX()
    }

    @Piece
    fun middle() : Shape3d {
        val inside = profile(0)
        val outside = profile( thickness )
        val slackLip = profile( lipThickness - lipSlack )
        val outsideLip = profile( lipThickness )

        val middleSolid = ExtrusionBuilder().apply {
            crossSection( outside )
            forward( middleHeight )
            crossSection( outside )
            crossSection( slackLip )
            forward( lipHeight )
            crossSection( slackLip )
        
        }.build()
            .color( "Blue" ).brighter()

        val middleHole = ExtrusionBuilder().apply {
            forward(-0.1)
            crossSection( outsideLip )
            forward(0.1 + lipHeight + 1 )
            crossSection( outsideLip )
            forward( thickness ) // Chamfer so that we don't need support material
            crossSection( inside )
            forward( middleHeight - thickness -1 + 0.1)
            crossSection( inside )
            
        }.build()

        return ( middleSolid - middleHole ).mirrorX()
    }

    @Piece
    fun bottom() : Shape3d {
 
        val inside = profile(0)
        val outside = profile( thickness )
        val outsideChamfer = profile( thickness - chamfer)
        val slackLip = profile( lipThickness - lipSlack )

        val bottom : Shape3d = ExtrusionBuilder().apply {
            crossSection( outsideChamfer )
            forward( chamfer )
            crossSection( outside )
            forward( bottomHeight + baseThickness - chamfer )
            crossSection( outside )
            crossSection( slackLip )
            forward( lipHeight - 1 )
            crossSection( slackLip )
            crossSection( inside )
            forward( -bottomHeight - lipHeight + 1 )
            crossSection( inside )
        }.build().color( "Blue" )

        return bottom
    }


    override fun build() : Shape3d {

        val gap = 10

        val bottom : Shape3d = bottom()
        val middle : Shape3d = if ( middleHeight <= 0 ) {
            Cube(0).bottomTo( bottom.top )
        } else {
            middle().bottomTo(bottom.top + gap ).color("Yellow")
        }
        val top : Shape3d = top().rotateX(180).rotateZ(180).bottomTo( middle.top + gap )

        return bottom + middle + top
    }

}