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") } }