FooCAD Source Codeimport 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")
}
}