Exit Full View
Up

/Boxes/DrawerSlide.foocad

DrawerSlide

I want a drawer slide for some component organisers containing my electrical components. So the drawer needs to take very little weight, but I do need them to be fully extendable (i.e. the entire drawer+ comes out)

Fine tune the [slack] parameter. Do this while using the same ModelExtensions and print settings as you will for the final product, but print a short (50mm) rod.

Print Notes

Use a high perimeter count, so that the sides of the middle and outer bars are solid.

Use the Ears ModelExtensions to help bed adhesion. Use Rotate ModelExtension by 45° (place it below the Ears extension) for slides longer than your build plate.

Version History

Now using chamderedExtrude as my printer (or my settings) cause right andgle corners to have an extra glob of plastic, which ruins the fit, and needs touching up with a knife. There is still a 90° corner at the internal "stop" (or middle and outer pieces).

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

class DrawerSlide : Model {
    
    @Custom( about="Length when closed" )
    var length = 310

    // Large values will make the slide wobbly and weak, but will allow the drawer to open even more
    // than 100%. 
    // negative values will prevent the drawer opening all the way, but will be stronger.
    @Custom( about="Additional length when open")
    var extra = 10

    // Determines the angle of the dovetail.
    var dovetailRatio = 0.4

    @Custom( about="Additional space between the parts. Fine tune this for your printer" )
    var slack = 0.2 // Was 0.18

    @Custom( about="Extra thickness of the inner bar, so that the draw doesn't rub on the sliders" )
    var raised = 1.2

    // A small chamfer to ensure that the internal corner of the dovetails do not bind
    // Should be AT LEAST the slicer's layer height
    var chamfer = 0.6 // Was 0.4

    @Custom( about="Size of the inner rod" )
    var inner = Vector2(14,4)

    @Custom( about="Size of the middle rod. Both dimensions must be bigger than [inner]" )
    var middle = Vector2(24,7)

    @Custom( about="Size of the outer rod. Both dimension must be bigger than [middle]" )
    var outer = Vector2(32,10)

    @Custom( about="Number of mounting holes for the inner rod" )
    var holeCount = 4

    @Custom( about="Number of mounting tabs of each side of the outer rod" )
    var tabCount = 3

    @Custom( about="Head diameter and shaft diameter of the screws for the inner rod" )
    var screwSize = Vector2(8,4)

    var tabSize = Vector2( 10, 10 )

    fun stopSize() = length/4


    fun dovetail(width : double, thickness : double, addChamfer : bool ) : Shape2d {
        val dovetail = PolygonBuilder().apply {
            moveTo( 0,0 )
            lineBy( width, 0 )
            lineBy( -thickness * dovetailRatio, thickness )
            lineBy( -width + 2 * thickness * dovetailRatio, 0 )
        }.build().centerX()
        return if ( addChamfer) {
            dovetail.roundCorner(1,chamfer,1).roundCorner(0,chamfer,1)
        } else {
            dovetail
        }
    }
    fun fatDovetail(width : double, thickness : double, addChamfer : bool ) : Shape2d {
        return dovetail(width, thickness, addChamfer) +
            Square(width-thickness*dovetailRatio, thickness/2).centerX().backTo(thickness)
    }

    fun extrude( shape : Shape2d, length : double, chamfer : double ) = shape.chamferedExtrude( length, chamfer ).rotateX(90)
    //fun extrude( shape : Shape2d, length : double ) : Shape3d = extrude( shape, length, 0 )

    fun holes( isInner : bool ) : Shape3d {
        val hole = if (isInner) {
            Countersink().holeD(screwSize.y).headD(screwSize.x).mirrorZ()
        } else {
            Cylinder.hole(middle.y*2, screwSize.x/2+1 ).bottomTo(-1)
        }
        return hole.repeatY(holeCount, (length - 20)/(holeCount-1)).centerY()
    }

    @Piece
    fun inner() : Shape3d {
        val dovetail : Shape2d =
            dovetail( inner.x, inner.y, true ) +
            Square( inner.x - inner.y * 2 * dovetailRatio, raised ).frontTo(inner.y).centerX()

        val stop = fatDovetail( inner.x, inner.y, true ) +
            Square( inner.x - inner.y * dovetailRatio, raised ).frontTo(inner.y).centerX()

        return ( extrude(dovetail, length, 1) + extrude( stop, stopSize(), 1 ) ).centerXY() - holes(true)
    }

    @Piece
    fun middle() :Shape3d {
        val dovetail : Shape2d = dovetail( middle.x, middle.y, true )
        val innerDovetail = dovetail( inner.x, inner.y, false ).backTo(middle.y).offset(slack)
        val fatInner = fatDovetail( inner.x, inner.y, false ).backTo(middle.y).offset(slack)
        val stop = fatDovetail( middle.x, middle.y, true ) //- fatInner
        

        return (
                extrude( dovetail,length, 1 ) +
                extrude( stop, stopSize(), 1 ) -
                extrude( innerDovetail, length, -1 ) -
                extrude( fatInner, length/2+stopSize()+extra/2, 0 )
            ).centerXY() - holes(false)
    }

    @Piece
    fun outer() : Shape3d {
        val dovetail : Shape2d = dovetail( outer.x, outer.y, false )

        val middleDovetail = dovetail( middle.x, middle.y, false ).backTo(outer.y).offset(slack)
        val fatMiddle = fatDovetail( middle.x, middle.y, false ).backTo(outer.y).offset(slack)

        val tabs = ( Square( tabSize ).roundAllCorners(2).center() - Circle.hole(screwSize.y/2) )
            .leftTo( outer.x/2 -2)
            .repeatY(tabCount, length/tabCount*1.3).centerY()
            .mirrorX().also().extrude( 4 )

        return (
                extrude(dovetail, length, 1 ) -
                extrude( middleDovetail, length, -1 ) -
                extrude( fatMiddle, length/2+stopSize()+extra/2, 0 )
            ).centerXY() +
            tabs - holes(false)
    }

    @Piece
    fun outerB() : Shape3d {
        val dovetail : Shape2d = dovetail( outer.x, outer.y, false )
        val hole = Countersink().depth(5)
        val holes = hole.rotateY(90).leftTo(dovetail.left).translateZ( 15 )
            .repeatY( tabCount, (length-20)/(tabCount-1) ).mirrorY().translateY(-10)
        val attachment = extrude( Square( 5, 20 ).leftTo( dovetail.left ), length, 1 ) -
            holes

        val middleDovetail = dovetail( middle.x, middle.y, false ).backTo(outer.y).offset(slack)
        val fatMiddle = fatDovetail( middle.x, middle.y, false ).backTo(outer.y).offset(slack)

        return ( extrude(dovetail, length, 1) + attachment -
            extrude( middleDovetail, length, -1 ) -
            extrude( fatMiddle, length/2+stopSize()+extra/2, 0 ) -
            holes(false)
      ).centerXY()
    }

    @Piece
    fun all() : Shape3d {
        val inner : Shape3d = inner()
        val middle : Shape3d = middle()
        val outer : Shape3d = outer()

        return inner.rightTo(middle.left -1) + middle + outer.leftTo(middle.right+1)
    }

    override fun build() : Shape3d {
        return inner().topTo(outer.y+raised).color("Yellow") +
            middle().translateY(length/2).topTo(outer.y).color("Orange") +
            outerB().translateY(length).bottomTo(0).color("Green")
    }
}