Exit Full View
Up

/Boxes/TissueBoxCover.foocad

TissueBoxCover

A tissue box cover, for those who don't like to look at cardboard boxes! Print the main body using "vase" mode, and make the walls thicker than normal by increasing the "Default Extrusion Width" to say 200%

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

class TissueBoxCover : Model {
    
    var boxWidth = 120

    var boxDepth = 120

    var boxHeight = 130

    var margin = 10

    var cornerRadius = 3

    var extra = 8

    fun profile( amplitude : double ) : Shape2d {

        val width = boxWidth + extra
        val depth = boxWidth + extra

        val profile = PolygonBuilder().apply {

            val bumps = 4
            val dx = (width - margin) / bumps
            val dy = (depth - margin) / bumps

            val xRadius = Vector2( dx/4, amplitude )
            val yRadius = Vector2( amplitude, dy/4 )

            // First side
            moveTo( margin, 0 )
            radius( 0 )

            for ( i in 0 until bumps ) {
                arcTo( Vector2(margin + dx * i, 0), xRadius, 0, true, true )
                arcTo( Vector2(margin + dx * i + dx/2, 0), xRadius, 0, true, false )
            }
            radius( cornerRadius )
            lineTo( width, 0 )
            radius( 0 )

            // Second side
            lineTo( width, margin )
            for ( i in 0 until bumps ) {
                arcTo( Vector2( width, margin + dy * i), yRadius, 0, true, true )
                arcTo( Vector2( width, margin + dy * i + dy/2), yRadius, 0, true, false )
            }
            radius( cornerRadius )
            lineTo( width, depth )
            radius( 0 )

            // Third side
            lineTo( width-margin, depth )
            for ( i in 0 until bumps ) {
                arcTo( Vector2( width - (margin + dx * i), depth), xRadius, 0, true, true )
                arcTo( Vector2( width - (margin + dx * i + dx/2), depth), xRadius, 0, true, false )
            }
            radius( cornerRadius )
            lineTo( 0, depth )
            radius( 0 )

            // Forth side
            lineTo( 0, depth - margin )
            for ( i in 0 until bumps ) {
                arcTo( Vector2( 0, depth - (margin + dy * i) ), yRadius, 0, true, true )
                arcTo( Vector2( 0, depth - (margin + dy * i + dy/2) ), yRadius, 0, true, false )
            }

            radius( cornerRadius )
            lineTo( 0,0 )
        }.build()

        return profile
    }

    @Piece
    fun body() : Shape3d {

        val middle = ExtrusionBuilder().apply {
            crossSection( profile( 1 ) )
            forward( 2 )
            crossSection( profile( 3 ) )
            forward( boxHeight - margin * 2 - 4 )
            crossSection()
            forward( 2 )
            crossSection( profile( 1 ) )
        }.build()

        val ends = baseProfile(0).extrude( margin )


        return ends +
            middle.centerXY().translateZ(margin) +
            ends.translateZ( boxHeight - margin )
    }

    fun baseProfile( offset : double ) : Shape2d {
        val profile = Square( boxWidth + extra, boxDepth + extra ).center()
            .roundAllCorners( cornerRadius )

        return if ( offset == 0 ) {
            profile
        } else {
            val scale = (profile.size - Vector2( offset, offset )) / profile.size 
            profile.scale( scale )
        }
    }
    
    @Piece
    fun lid() : Shape3d {

        val thickness = 1.2
        val chamfer = 1
        val lipOffset = 2
        val lipInset = 2
        val lipThickness = 2
        val lipHeight = 5

        val lid = ExtrusionBuilder().apply {
            crossSection( baseProfile(chamfer) )
            forward( chamfer )
            crossSection( baseProfile(0) )
            forward( thickness )
            crossSection()
            crossSection( baseProfile( lipInset ) )
            forward( lipHeight )
            crossSection()
            crossSection( baseProfile( lipInset + lipThickness ) )
            forward( - lipHeight )
            crossSection()
        }.build()

        val a = Circle( 12 ).translateX(14)
        val holeP = a.hull( a.mirrorX() )
        val hole = holeP.internalChamferedExtrude( 4, 1, 1 )
        val thicker = (holeP.offset( 2 ) - holeP).extrude( 4 )

        return lid + thicker - hole
    }

    override fun build() : Shape3d {
        val box = Cube( boxWidth, boxDepth, boxHeight ).previewOnly().centerXY()
        val main = body()
        val lid : Shape3d = lid().mirrorZ().bottomTo(main.top)
        return box.translateZ(10) + main + lid
    }
}