FooCAD Source Codeimport static uk.co.nickthecoder.foocad.chamferedextrude.v1.ChamferedExtrude.*
class Floodlight : Model {
val size = Vector3(120,80,16)
val thickness = 2
val margin = 5
val slack = 0.3
val recessT = 5
var radius = 6
var postChamfer = 1
var frontChamfer = 3
val postDist = 92
var postT = 5
var postHeight = 30
var heatSize = Vector3( 80.5, 61.5, 39 )
// I'm using old heat sinks from CPUs, which have a lip on one edge.
var heatLip = 1.1
@Custom
var apeture = Vector2(55, 45)
@Custom
var led = Vector2( 27, 27 )
@Custom
var board = Vector2(79, 45 )
var caseScrews = Vector2( 104, 64 )
var cablePos = 44
fun heatSink() : Shape3d {
return Cube(heatSize).centerXY().previewOnly()
}
@Piece
fun back() : Shape3d {
val backP = (
Square( size.x, size.y ).center().roundAllCorners(radius) -
Square( board ).center()
)
val backP2 = (
Square( size.x, size.y ).center().roundAllCorners(radius)
)
val back = backP.extrude( thickness ) +
(backP2 - backP2.offset( -thickness )).extrude(thickness*3)
val recess = (
Square( heatSize.x + thickness *2, heatSize.y + thickness* 2 ).center() -
Square( heatSize.x + slack*2, heatSize.y + slack*2 ).center()
).extrude( recessT ).translateZ(thickness)
val lip = Cube( heatSize.x, 5, heatLip ).centerX().bottomTo( thickness ).frontTo(recess.front).color("Red")
val postP = Circle( 7 ).translateY(postHeight).hull(
Square( 30, 0.1 ).centerX()
)
val postP2 = postP - Circle( 10 ).translateY(postHeight)
val post = postP
.chamferedExtrude( postT, postChamfer ) -
Cylinder( postT*3, 2).translateY(postHeight).centerZ() +
postP2.chamferedExtrude( postT*2, postChamfer )
val posts = post
.rotateX(90).rotateZ(90)
.translateX( postDist/2 )
.mirrorX().also().withCavities()
val screwPost = Cylinder( 6, 5 ).remove(Cylinder( 12, 2 ).center()).remove(Cylinder( 4, 0, 4 ).topTo(6.01))
val screwPosts = screwPost.translate( caseScrews.x/2, caseScrews.y/2, 0 )
.mirrorX().also().withCavities().mirrorY().also().withCavities()
return (back + recess + lip + posts).and( screwPosts )
}
@Piece
fun bracket() : Shape3d {
val backP = (
Square( size.x, 50 ).center()-
Square( 40, 30 ).center()
)
.translateY(6)
.roundAllCorners(radius)
val back = backP.extrude(thickness) +
(backP - backP.offset( -thickness )).extrude(thickness*3)
val postP = Circle( 7 ).translateY(postHeight).hull(
Square( 30, 0.1 ).centerX()
)
val postP2 = postP - Circle( 10 ).translateY(postHeight)
val gap = 0.5 // Space for a locking washer (has teeth which aids friction).
val post = postP.chamferedExtrude(postT, postChamfer).bottomTo( postT ) +
postP2.chamferedExtrude( postT*2, postChamfer ) -
Cylinder( 10, 2 ).translateY( postHeight )
val posts = post
.rotateX(90).rotateZ(90)
.translateX( postDist/2)
.mirrorX().also().withCavities()
val screwPost = Cylinder( 6, 5 ).remove(Cylinder( 12, 2 ).center()).remove(Cylinder( 4, 0, 4 ).topTo(6.01))
val screwPosts = screwPost.translateX( postDist/2 ).mirrorX().also().withCavities().translateY(22)
return (back + posts) .and ( screwPosts )
}
var cableD = 8
var grometT = 2
@Piece
fun front() : Shape3d {
val profile = Square( size.x, size.y )
.roundAllCorners( radius )
.offset( thickness + slack )
.center()
val overlap = 5
val front = ExtrusionBuilder().apply {
crossSection( profile.offset(-frontChamfer) )
forward( frontChamfer )
crossSection( profile )
forward( size.z + thickness * 3 - frontChamfer )
crossSection()
crossSection( -thickness )
forward(-thickness*3)
crossSection()
crossSection( -overlap )
forward( -overlap )
crossSection( overlap )
forward( -size.z + thickness + overlap +frontChamfer )
crossSection()
forward( -frontChamfer )
crossSection( -frontChamfer )
}.build()
val holeP = Square( apeture ).roundAllCorners( 1, 10 )
val hole = holeP.extrude( thickness*3 ).center()
val screwPost = Cylinder( size.z, 5 ) - Cylinder( 12, 2 ).translateZ(size.z-10)
val screwPosts = screwPost.translate( caseScrews.x/2, caseScrews.y/2, 0 )
.mirrorX().also().mirrorY().also()
val gripPostDist = 13
val gripD = 8
val gripHoleD = 1.5
val gripPost = ( Cylinder( 6, gripD/2 ) - Cylinder( 12, gripHoleD ) ).translateX(-gripPostDist/2)
val gripPosts = (
gripPost.mirrorX().also().translateZ(4) +
gripPost.hull( gripPost.mirrorX() )
).translate(cablePos,16,0)
val gripBar = (
Circle( gripD/2 ).hull( Circle( gripD/2 ).translateX( -gripPostDist ) ) -
Circle( gripHoleD+0.5 ) - Circle( gripHoleD+0.5 ).translateX(-gripPostDist)
).extrude( 2 ) +
// A little nub, that can grip the cable, if the cable is thin.
// Flip over the out of the way if not needed.
Square( gripPostDist - gripD -0.5, 2).center().translateX(-gripPostDist/2)
.chamferedExtrude( 4, 0.6 )
val cableHole = Cylinder( 8, cableD/2 + grometT/2 )
.center()
.rotateX(90)
.translate( cablePos, size.y/2, cableD/2+6)
return front + screwPosts + gripPosts - hole - cableHole + gripBar
}
@Piece
fun gromet() : Shape3d {
val h = 8
return (
Cylinder( h, cableD/2 + grometT ) +
Cylinder( grometT*2, 10 ) -
Cylinder( h, cableD/2+1, cableD/2 )
)
}
override fun build() : Shape3d {
return back().color("Orange") +
front().translateZ(-50)+
bracket().mirrorZ().translateZ(postHeight*2).color("Yellow") +
heatSink().bottomTo(thickness) +
gromet().translateX(-80)
}
}