import static uk.co.nickthecoder.foocad.extras.v1.Extras.* import static uk.co.nickthecoder.foocad.chamferedextrude.v1.ChamferedExtrude.* import static uk.co.nickthecoder.foocad.arrange.v1.Arrange.* import static uk.co.nickthecoder.foocad.layout.v1.Layout2d.* import static uk.co.nickthecoder.foocad.layout.v1.Layout3d.* import uk.co.nickthecoder.foocad.threaded.v2.* import static uk.co.nickthecoder.foocad.threaded.v2.Thread.* // used to make the collet nut narrower as we increase in the Z direction. class NarrorWithZ( val factor : double ) : Transform3d { override fun transform( point : Vector3 ) = Vector3( point.x - point.x * point.z*factor, point.y - point.y * point.z*factor, point.z ) } class ScrewDriver : Model { // When not using a collet, the diameter must be really accurate! // Test with a very stubby screwdriver first! // Note. This is the distance between opposite vertices of the hex, not the // easy to measure 1/4 inch :-( // The conversion factor is Sin(60) 0.866 // So the tight fit value is 25.4 / 4 / 0.866 = 7.3 // Therefore I've included 0.5mm of clearance. YMMV. @Custom( about="Internal length and diameter of the collet to accomodate the driver bit" ) var bitSize = Vector2( 7.8, 12 ) @Custom( about="X : Diameter. Y : At least 10mm, then 25mm for every bit you wish to store" ) var handleSize = Vector2( 14, 3*25 + 10 ) @Custom( about="Diameter of the hole to hold spare bits" ) var insideDiameter = 8 @Custom var useCollet = true // Too large, and the collect won't tighten around the screwdriver bit. // Too small, and the collect won't screw very far onto the screwdriver. // This may need adjusting to suit your printer / print settings. @Custom( about="The amount of taper in the collet nut" ) var snug = 0.8 @Custom( about="Set this to 0 if you wish to use the slicer's brim" ) var brimSize = 25 @Piece fun test() : Shape3d { return Square( 7.0, 1 ).center().extrude(2).color("Green") + Circle( bitSize.x / 2 ).sides(6).extrude(1).color( "Yellow") + collet().mirrorZ().topTo(-2) } fun colletThread() : Thread { val d : int = bitSize.x + 5 return Thread( d ).clearance(0.3) } fun endThread() : Thread = Thread( insideDiameter + 1 ).rodChamfer(0.5) @Piece fun nut() : Shape3d { val hex = Circle( colletThread().diameter / 2 + 3 ) .sides(6).roundAllCorners(2) val outside = ExtrusionBuilder().apply { crossSection( hex ) forward(7) crossSection( Circle( colletThread().diameter / 2 + 2 ) ) forward(5) crossSection(-1) }.build() val threadedHole = colletThread().threadedHole( 10 ) .chamferEnd(false) .clipped() val hole = Circle( bitSize.x / 2 + 0.5 ).extrude(3).bottomTo(-1) val factor = snug / threadedHole.size.z / colletThread().diameter val narrowed = (outside - threadedHole).transform( NarrorWithZ( factor ) ) val brim = if (brimSize > 0) { Triangle( brimSize + 1 ) .backTo( -colletThread().diameter / 2 +1) .repeatAround(4) .extrude(0.2) .color("White").opacity(0.2) } else { null } return narrowed.rotateY(180).bottomTo(0) + brim - hole } fun brim( innerRadius : double ) : Shape3d { val outerRadius = innerRadius + brimSize return if (brimSize > 0) { ( Circle( outerRadius ).extrude(0.2) + ( Circle( outerRadius ) - Circle(outerRadius - 1) + Square( outerRadius - innerRadius - 1, 1.2 ).centerY().translateX( innerRadius + 1 ).repeatAround(4) ) .extrude(2.4) ).color( "White" ).opacity(0.2) } else { null } } fun collet() : Shape3d { val rod = colletThread().threadedRod( bitSize.y + 1 ) .chamferTop(false) val hex = Circle( bitSize.x / 2 ).sides(6) .extrude( bitSize.y ).bottomTo(-0.01) val split = Cube( 1, handleSize.x, colletThread().diameter ).centerXY().bottomTo(-0.01) .rotateZ(30) .bottomTo(0.2) return rod + brim( colletThread().diameter/2 ) - hex - split } @Piece fun magneticBitHolder() : Shape3d { val outside = ExtrusionBuilder().apply { crossSection( Circle(bitSize.x/2 + 1.5) ) forward( bitSize.y + 4 ) crossSection( bodyShape() ) }.build() val hex = Circle( bitSize.x / 2 ).sides(6) .extrude( bitSize.y + 2 ).bottomTo(-0.01) return outside + brim( bitSize.x/2 + 1.5 ) - hex } fun bodyShape() : Shape2d { return Circle( handleSize.x / 2 ).sides(6) .roundAllCorners(2) } // The Solid part of the body, not including the collect, or end thread etc. // You could add writing to the side(s), or add extra shaped parts for better grip etc. fun plainBody() : Shape3d { return bodyShape().extrude( handleSize.y ) } @Piece fun body() : Shape3d { val collet = if (useCollet) { collet() } else { magneticBitHolder() } val delta = handleSize.x/2 - colletThread().coreRadius() val transition = if ( useCollet ) { ExtrusionBuilder().apply { crossSection( Circle( colletThread().coreRadius() ) ) forward( Math.abs(delta) ) crossSection( bodyShape() ) }.build() } else { Cube(0) }.bottomTo(collet.top-0.1) val body = plainBody().bottomTo(transition.top - 0.01) val end = ExtrusionBuilder().apply { crossSection( bodyShape() ) forward(2) crossSection( Circle( handleSize.x / 2 ) ) forward(2) crossSection() }.build().bottomTo( body.top ) val endThreadHole = endThread().threadedHole( 10 ) .chamferEnd(false) .chamferStart(false) .clipped(true) .topTo(end.top) val hole = Circle( insideDiameter/2 ) .chamferedExtrude( end.top - transition.top, 0, (insideDiameter - handleSize.x )/2 ) .topTo( end.top+ 0.01 ) .color("Blue") return collet + body + transition + end - endThreadHole - hole } @Piece fun fixedEnd() : Shape3d { val end = Circle( handleSize.x/2 ).chamferedExtrude(8, 1, 4) val threaded = endThread().threadedRod(6) .chamferBottom(false) .chamferTop(false) .bottomTo( end.top-2 ) return end + threaded } @Piece fun swivelEnd() : Shape3d { val fixedEnd = fixedEnd().rotateY(180).bottomTo(0).color("Green") val start = Circle(3).chamferedExtrude(1,0,1).bottomTo(-0.02) val slack = 0.6 val diagonal = handleSize.x/2 - 2 val bar = 9 - diagonal val profile = PolygonBuilder().apply { moveTo(0,0) lineBy( 1.5, 0 ) lineBy( 0, bar ) lineBy( 1.5, 1.5 ) lineBy( -1, 1 ) lineBy( diagonal, diagonal ) lineBy( 0, 2 ) lineTo( 0, 13.5 ) }.build() val remove = (profile.translateX(slack) + Square(0.3, profile.size.y)) .revolve() .color("Orange") val swivel = profile.revolve().color("Yellow") val whiskers = Cube( 0.4, 6, 0.2 ).centerXY().rotateZ(90).also() val brim = if (brimSize > 0) { Circle( endThread().diameter / 2 + brimSize ).extrude(0.2).color( "White" ).opacity(0.2) } else { null } return fixedEnd + brim - start - remove + swivel + whiskers } @Piece override fun preview() : Shape3d { brimSize = 0 val body = body().rotateY(90) val nut = nut().rotateY(90).leftTo( body.left ) val end = swivelEnd().rotateY(90).rightTo( body.right + 6 ) return body + end + nut } override fun build() : Shape3d { return arrangeX( 2, body(), if (useCollet) nut() else Cube(0), swivelEnd() ).centerX() } }