Exit Full View
Up

/Furniture/LaptopBase.foocad

LaptopBase

I have a laptop, and want to place it on top of my lap. However, in summer under heavy load, it gets too hot.

So, I want a "tray" for the laptop to sit on, with plenty of air-flow below it, instead of it sitting directly on my lap.

Bolt the four piece to a piece of plywood, which is approximately the same size as the laptop. Either use round-head wood screws, or machine screws with metal insert placed into the plywood. I prefer the latter, but my inserts are slightly too long, so I cover them up with piece holeCover.

FooCAD Source Code
import uk.co.nickthecoder.foocad.smartextrusion.v1.*
import static uk.co.nickthecoder.foocad.smartextrusion.v1.SmartExtrusion.*
import static uk.co.nickthecoder.foocad.extend.v1.Extend.*
import uk.co.nickthecoder.foocad.extras.v1.*
import static uk.co.nickthecoder.foocad.extras.v1.Extras.*

class LaptopBase : Model {

    @Custom( about="Size of the blocks (z does not include the walls)" )
    var cornerSize = Vector3( 20, 40, 12 )

    @Custom( about="Size of the blocks (z does not include the walls)" )
    var edgeSize = Vector3( 14, 40, 12 )

    @Custom( about="Thickness and height of the walls" )
    var cornerWallSize = Vector2( 4, 2 )

    @Custom( about="width and depth of an extra chamfer for the laptop to sit within" )
    var cornerChamfer = Vector2( 8, 5 )

    @Custom( about="Thickness and height of the walls" )
    var edgeWallSize = Vector2( 6, 4 )

    @Custom( about="width and depth of an extra chamfer for the laptop to sit within" )
    var edgeChamfer = Vector2( 1, 1 )

    @Custom( about="Diameter of the bolts e.g. 6.0 for M6 bolts" )
    var boltDiameter = 6.0

    @Custom( about="Length, thickness and height of the sloted part" )
    var slotSize = Vector3( 10, 7, 6 )

    @Custom
    var radius = 4

    meth corner() : Shape3d {
        val shape = Square( cornerSize.x, cornerSize.y )
            .roundCorner(2, Math.min( cornerSize.x, cornerSize.y )*0.8, 1 )
        val roundedShape = shape.roundAllCorners(radius)

        val main = roundedShape
            .extrude( cornerSize.z + cornerWallSize.y + cornerChamfer.y )

        val remove = Square( 100 ).translate( cornerWallSize.x, cornerWallSize.x )
            .smartExtrude( cornerWallSize.y + cornerChamfer.y )
                .bottom( Chamfer(cornerChamfer.x, cornerChamfer.y) )
            .topTo( main.top + 0.01 )

        val slotShape = Hull2d( Circle( boltDiameter/2 ).translateX( slotSize.x + cornerSize.x ).also())
        
        val slot = slotShape.ring( slotSize.y )
            .smartExtrude( slotSize.z )
                .top(Fillet(1))
                .bottom(Chamfer(0.5))
            .leftTo( 0 ).centerYTo( main.middle.y )

        return main -remove + slot
    }

    meth edge() : Shape3d {
        val width = Math.max( edgeSize.x, edgeSize.y )
        val depth = Math.min( edgeSize.x, edgeSize.y )

        val main = Square( width, depth ).centerX()
            .roundAllCorners(radius)
            .extrude( edgeSize.z + edgeWallSize.y + edgeChamfer.y )

        val remove = Square( 100 )
            .centerX().backTo( main.back - edgeWallSize.x )
            .smartExtrude( edgeWallSize.y + edgeChamfer.y )
                .bottom(Chamfer(edgeChamfer.x,edgeChamfer.y))
            .topTo( main.top + 0.01 )


        val slotShape = Circle( boltDiameter/2 ).extendY( slotSize.x/2 + depth/2 )
        
        val slot = slotShape.ring( slotSize.y )
            .smartExtrude( slotSize.z )
                .top(Fillet(1))
                .bottom(Chamfer(0.5))
            .backTo( main.back )

        return main - remove + slot
    }

    @Custom
    var coverSize = Vector2( 30, 2 )

    @Custom
    var coverRecess = Vector2( 20, 1 )

    @Piece
    meth holeCover() : Shape3d {
        val main = Circle( coverSize.x/2 )
            .smartExtrude( coverSize.y )
                .bottom( Chamfer( coverSize.y/3 ) )
        val recess = if (coverRecess.x > 0 && coverRecess.y > 0) {
            Circle( coverRecess.x/2 )
                .smartExtrude( coverRecess.y )
                .top( Chamfer( coverRecess.y/3 ).reverse() )
                .topTo( main.top + 0.01 )
        } else {
            null
        }

        return main - recess
    }

    override fun build() : Shape3d {
        val board = Cube( 300, 200, 12 )
            .centerXY()
            .previewOnly()

        val corners = corner()
            .leftTo( board.left )
            .frontTo( board.front )
            .mirrorX().also()
            .bottomTo( board.top )

        val edges = edge()
            .backTo( board.back )
            .centerXTo( board.size.x * 0.35 )
            .mirrorX().also()
            .bottomTo( board.top )

        val holeCover = holeCover()
            .topTo( board.bottom - 0.01 )

        return board + corners + edges + holeCover
    }

}