Exit Full View
Up

/Boxes/SmoothInsideBox.foocad

SmoothInsideBox

A box, with thin walls, but thicker there the lip of the lid meets the main body.

The box can be built in 2, 3 or more parts. You will always need 1 "top" and 1 "bottom", and you can add 0 or more "middle" pieces.

"slack" is quite and important @Custom parameter, and will need fine tuning for your partiuclar printer. Too small, and the lid will jam on too tightly. Too large, and the lid will be horribly loose. Only the "top" piece uses "slack", so if you need to adjust it, only the "top" piece needs to be re-printed.

The shape of the box is arbitrary (override profile() method).

To get all the other profile sizes (for the lip, inside, chamfer etc), I currently use "scale". This ensures it works with any profile you want, but has the disadvantage that it doesn't produce perfectly consistant width lips.

The "better" solution would be to use Shape2d.offset(n), but this can produce non 1-to-1 correspondance between the points that make up sucessive profiles, and ExtrusionBuilder does a very bad job sometimes! A future version of FooCAD may fix this, and then Shape2d.offset will be better than Shape2d.scale.

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

class SmoothInsideBox : Model {
    
    @Custom
    var height = 40

    // Make the top higher than the "lipHeight" + "topChamfer"
    @Custom
    var extraTopHeight = 0

    @Custom
    var middleHeight = 30


    @Custom
    var topChamfer = 2.0

    @Custom
    var bottomChamfer = 2.0

    @Custom
    var lipHeight = 8.0

    @Custom
    var lipThickness = 2.0

    // Make this bigger than wallThickness, so that the rim of the bottom and middle
    // pieces are stronger. The "rims" are parts that are on the inside pointing upwards,
    // and the "lips" are outside pointing downwards.
    @Custom
    var rimThickness = 1.5

    @Custom
    var wallThickness = 1.0

    @Custom
    var baseThickness = 1.0

    @Custom
    var slack = 0.3

    fun profile() : Shape2d = Square( 70 ).center()
    
    fun inset( amount : double ) : Shape2d {
        val profile : Shape2d = profile()
        return profile.scale(
            (profile.size.x - amount * 2) / profile.size.x,
            (profile.size.y - amount * 2) / profile.size.y
        )
    }

    @Piece
    fun top() : Shape3d {
        val out = slack + lipThickness + rimThickness - wallThickness
        val topHeight = extraTopHeight + topChamfer + baseThickness

        val outside = inset( - out )
        val chamfered = inset( topChamfer - out )
        val lipA = inset( -slack - rimThickness + wallThickness )
        val inside = inset( wallThickness )
        val insideChamfered = inset( wallThickness + topChamfer )

        return ExtrusionBuilder().apply {
            joinStrategy = OneToOneJoinStrategy.instance

            crossSection( chamfered )
            forward( topChamfer )
            crossSection( outside )
            forward( topHeight + lipHeight - topChamfer )
            crossSection()
            crossSection( lipA )
            forward( -lipHeight )
            crossSection()
            crossSection( inside )
            forward( -topHeight + topChamfer + baseThickness )
            crossSection()
            forward( -topChamfer )
            crossSection( insideChamfered )
            
        }.build().mirrorX()
    }

    @Piece
    fun middle() : Shape3d {
        if ( middleHeight <= 0 ) return Cube(0)

        val out = slack + lipThickness + rimThickness - wallThickness
        val diff = rimThickness - wallThickness

        val profile : Shape2d = profile()
        val inside = inset( wallThickness )
        val outside = inset( -out )
        val lipA = inset( - diff - slack )
        val rim = inset( -rimThickness + wallThickness )


        return ExtrusionBuilder().apply {
            joinStrategy = OneToOneJoinStrategy.instance

            crossSection( rim )
            forward( lipHeight - diff )
            if ( diff != 0 ) {
                crossSection()
                forward( diff )
            }
            crossSection( profile )

            forward( middleHeight - lipHeight - out )
            crossSection()
            forward( out )
            crossSection( outside )
        
            forward( lipHeight - lipThickness )
            crossSection()
            forward( lipThickness )

            crossSection( lipA )
            forward( -lipHeight )
            crossSection()

            crossSection( inside )
            forward( -middleHeight  )
            crossSection()
            
        }.build().mirrorX() -
            Cube ( profile.size.x * 3, profile.size.y * 3, 2 )
                .centerXY().translateZ(-2)
    
    }

    @Piece
    fun bottom() : Shape3d {
        val diff = rimThickness - wallThickness

        val profile : Shape2d = profile()
        val chamfered = inset( bottomChamfer )
        val inside = inset( wallThickness )
        val insideChamfer = inset( wallThickness + bottomChamfer )
        val rim = inset( -diff )


        return ExtrusionBuilder().apply {
            joinStrategy = OneToOneJoinStrategy.instance

            crossSection( chamfered )
            forward( bottomChamfer )
            crossSection( profile )
            
            forward( height - bottomChamfer - lipHeight - diff )
            crossSection()

            forward( diff )
            crossSection( rim )
            forward( lipHeight )
            crossSection()

            crossSection( inside )
            forward( -height + bottomChamfer + baseThickness )

            crossSection()
            forward( -bottomChamfer )
            crossSection( insideChamfer )
        }.build()
    }

    @Piece
    override fun build() : Shape3d {

        var gap = 10

        return bottom()
                .color("Blue") +
            middle()
                .mirrorZ()
                .translateZ(height + middleHeight + slack + gap)
                .color("Silver") +
            top()
                .mirrorZ()
                .translateZ(height + middleHeight + extraTopHeight + topChamfer + baseThickness + slack*2 + gap*2 ) 
                .color("Green")
    }

}