FooCAD Source Codeimport static uk.co.nickthecoder.foocad.extras.v1.Extras.*
import uk.co.nickthecoder.foocad.threaded.v1.Threaded
/**
Sometimes, I want to attach things to a plywood sheet, which can be undone by hand (no tools)
Drill a large hole through the plywood, and glue in the `nut`.
Cap the other side of the wood with the optional `trim`.
*/
class NutAndBoltForWood : Model {
@Custom( about="Thickness of the plywood" )
var woodThickness = 8
@Custom
var holeDiameter = 14.7 // Actually 15mm, but adding clearance.
@Custom( about="The size of the square part on the opposite side of the wood" )
var nutSize = Vector3( 30, 30, 5 )
@Custom
var threadSize = 2
@Custom
var threadDiameter = 10
@Custom
var threadPitch = 6
@Custom
var washerThickness = 2.0
@Custom( about="Extra length to add to the bolt (the thickness of the thing being attached")
var boltExtra = 10
@Custom( about="Thickness and depth of the trim" )
var trimSize = Vector2( 1, 2 )
fun boltLength() = woodThickness + nutSize.z + boltExtra + washerThickness
fun threaded() = Threaded.create( threadSize, threadDiameter, threadPitch )
// If you need a different shape, create a subclass, and override this method.
fun nutProfile() : Shape2d = Square( nutSize.x, nutSize.y ).center().roundAllCorners(4)
// If you need a different shape, create a subclass, and override this method.
fun trimProfile() : Shape2d = Circle( holeDiameter/2 + 2 )
@Piece
fun nut() : Shape3d {
// On the opposite side of the wood.
val block = nutProfile().extrude( nutSize.z )
// Inside the hole drilled through the plywood.
val neck = Cylinder( woodThickness, holeDiameter / 2 )
.bottomTo( block.top )
// Recess for the `trim` piece.
val forTrim = Cylinder( trimSize.y+0.3, holeDiameter / 2 - trimSize.x )
.topTo(neck.top+0.1)
.color("Red")
val thread = threaded().hole( nutSize.z + woodThickness + 4 ).translateZ(-2)
return block + neck - thread - forTrim
}
@Piece
fun trim() : Shape3d {
val r = holeDiameter / 2 - trimSize.x - 0.3
val neck = (Circle( r ) - Circle( r - trimSize.x))
.extrude( trimSize.x + trimSize.y )
val flat = (trimProfile() - Circle( r ))
.extrude( trimSize.x )
return neck + flat
}
@Custom
var boltHeadHeight = 4
@Piece
fun bolt() : Shape3d {
val bolt = threaded().bolt( boltLength() + boltHeadHeight, boltHeadHeight )
// For a slot for a screwdriver, so we can get the bolt out, if it snaps.
val slot = Cube( 20, 20, 1 ).centerZ()
.center()
.rotateX(90)
.bottomTo( bolt.top - 1 )
return bolt - slot
}
/**
Print using TPU
*/
@Piece
fun washer() : Shape3d {
val bolt = bolt()
return (Circle( bolt.size.x * 0.45 ) - Circle( threadDiameter/2 ) )
.extrude( 1.6 )
}
override fun build() : Shape3d {
// Set to 0 for the pieces in the final posision.
// Set to 10 ish so that each piece is separated.
val explode = 10
val nut = nut().color("Green")
val trim = trim().mirrorZ().topTo( nut.top + trimSize.x + explode ).color("LightGreen")
val attachment = (Square( 30 ).center() - Circle( threadDiameter/2 + 1))
.extrude( boltExtra )
.bottomTo( trim.top + explode )
.previewOnly()
val washer = washer(). bottomTo( attachment.top + explode ).color( "DarkBlue" )
val bolt = bolt().mirrorZ().topTo( washer.top + boltHeadHeight + explode )
return nut + trim + bolt + washer + attachment
}
}