FooCAD Source Codeimport static uk.co.nickthecoder.foocad.extras.v1.Extras.*
import static uk.co.nickthecoder.foocad.layout.v1.Layout2d.*
import static uk.co.nickthecoder.foocad.layout.v1.Layout3d.*
class PowerSupply : Model {
var size = Vector3( 150, 140, 42 )
var slack = 0.3
var ribSize = Vector2( 1.2, 6 )
var rim = Vector2( 5, 10 )
var thickness = 2.0
var topThickness = 2
var chamfer = 3.0
var meterSize = Vector2( 45.5, 26 )
var barrelD = 4
var potD = 7
var powerD = 12.5
var onD = 16.8
var usbSize = Vector3( 14.9, 18, 15.7 )
var bananaD = 4.5
var jackD = 8.5
fun hole( shape : Shape2d ) = shape.extrude( topThickness + 2 ).bottomTo(-1).color("Red")
@Piece fun testFront() = frontHole( Circle(10) ) + Cube(17)
fun frontHole( shape : Shape2d ) = shape.extrude( thickness + 2 )
.rotateX(90)
.centerZTo( size.z *0.5 - 3 )
.backTo( -size.y / 2 + 1 )
.color("Blue")
override fun build() : Shape3d {
val case : Shape3d = case().rotateY(180).bottomTo(0)
val power = powerLabel().rightTo( 50 ).centerYTo( 55 ).bottomTo( case.top )
val twelve = twelveLabel().rotateX(90).centerXTo( 45 ).centerZTo( size.z/4 ).backTo(case.front)
val usb = usbLabel().centerYTo(60).centerXTo(-30).bottomTo( case.top )
return case + power + twelve + usb
}
fun label( str : String ) : Shape3d {
val text = Text( str )
return text.extrude( 1.2 ).color("Black") + text.offset(1).extrude(0.8).color("White")
}
@Piece
fun powerLabel() = label( "Power" )
@Piece
fun twelveLabel() = label( "12V" )
@Piece
fun usbLabel() = label( "USB" )
/**
Glue this to the tiny pot on the buck/boost module, so that a regular knob can be attached.
*/
@Piece
fun potAdaptor() : Shape3d {
val r = 5.5
val scale = 1.07
val rounded = Octagon( r/scale ).extrude( 1, 0.75 ).mirrorZ().bottomTo(0)
val rod = Octagon( r/scale ).extrude(13+6+topThickness, scale).bottomTo( rounded.top )
val hole = Octagon(2.6+0.5).extrude(10).bottomTo(rod.top-1.5)
val whole = rounded + rod - hole
// We could print it upright, but it will be stronger printing it in 2 parts laying down.
val halves = (whole.rotateX(90) / Cube( 50 ).centerXY()).tileX(2,0.4).centerXY()
val hinge = Square( halves.size.x, halves.size.y/2).center().frontTo(halves.front+2).extrude(0.2)
return hinge + halves
}
@Piece
fun potMount() : Shape3d {
val base = Square( 25, 16 ).centerY().translateX(-4).extrude(6.0)//0.8)
val main = (Square( 16, 10 ).centerY().translateX(-2) -
Square( 11.5, 4.9 ).centerY().translateY(-1.2)).extrude( 9 ).bottomTo(base.top)
val hole = Cylinder( 20, 3.4 ).sides(20).bottomTo(-1).centerXTo(9.3)
return main + base - hole
}
@Piece
fun usbMount() : Shape3d {
val t = 1.5
val mount = Cube( usbSize + Vector3( t*2, t - thickness, 0 ) ).centerX().remove(
Cube( usbSize ).centerX().bottomTo(1.5).frontTo(-thickness)
)
val pair = (mount and mount.translateX(30)).centerX()
val front = Cube( 60, t, mount.size.z ).centerX()
.backTo(mount.back).also()
val base = Cube( front.size.x, mount.size.y, t ).centerX()
.topTo( mount.top ).also()
return pair and front + base
}
@Piece
fun case() : Shape3d {
val internal = Square( size.x + slack*2, size.y+slack*2 )
.roundAllCorners(0.1, 5)
.center()
val external = internal.offset(thickness)
//.roundAllCorners(thickness)
val case = ExtrusionBuilder().apply {
// touching bed (the top of the case)
crossSection( external.offset( -chamfer ) )
forward( chamfer )
crossSection( external ) // Finished the chamfer
forward( size.z - chamfer )
crossSection() // At the highest point
crossSection( internal ) // Ready to head down the inside
forward( -rim.y )
crossSection() // Fininshed the overhang
crossSection( -rim.x )
forward( -1 )
crossSection() // A flat part of the rim
forward( -rim.x + 1 )
crossSection( rim.x ) // Slanted part
moveTo(Vector3(0, 0, topThickness + chamfer) )
crossSection() // The main wall inside
forward( -chamfer )
crossSection( - chamfer )
}.build()
val ribsH = Cube( case.size.x - thickness*2, ribSize.x, ribSize.y )
.repeatY(2, 58).centerXY().centerYTo(0).bottomTo(topThickness)
val ribsV = Cube( ribSize.x, case.size.y - thickness*2, ribSize.y )
.centerXY().bottomTo(topThickness)
val ribs = ( ribsH + ribsV).color("Green" )
val bananaHoles = frontHole( Octagon( bananaD ).repeatX(3,25) )
.rightTo(-4)
val jackHole = frontHole( Octagon( jackD ) )
.repeatX( 2, 25 )
.leftTo(bananaHoles.left + bananaD/2 -jackD/2 )
.mirrorY()
// BEGIN Variable Voltage
val meterHole = hole( Square( meterSize ).center() )
.centerYTo( 12 )
.centerXTo( bananaHoles.middle.x )
val potHole = hole( Circle( potD / 2 ) )
.centerXTo( bananaHoles.middle.x )
.centerYTo( -20 )
val mockPot = Cylinder( 17, 14/2 )
.centerXTo( potHole.middle.x )
.centerYTo( potHole.middle.y )
.topTo(0)
.previewOnly()
// The 12V line is always connected to the buck/boost, but the output from the buck/boost
// is switched with an LED-lit button.
// This lets us adjust the voltage while the banana jack is not powered.
val onHole = hole( Circle( onD / 2 ) )
.centerYTo( -50 )
.centerXTo( potHole.middle.x )
// END Variable Voltage
val powerHole = frontHole( Octagon( powerD ) ).mirrorY()
val usbHole = frontHole( Square( usbSize.x, usbSize.z ) )
.backTo( case.back + 1 )
.bottomTo( 8 )
// A pair of double sockets at the front and the back.
val usbHoles = usbHole.repeatX(2, 30).centerXTo(size.x/4).mirrorY().also()
// The back ones are switched. The front are always on.
val mockUSB = (Cube( usbSize.x, usbSize.y, usbSize.z ).centerXY() +
Cube( usbSize.x - 3, 8, usbSize.z + 5 ).centerX()
)
.repeatX(2, 30)
.leftTo(usbHoles.left).bottomTo(usbHoles.bottom).frontTo(case.front)
.mirrorY().also()
.previewOnly()
val usbSwitches = hole( Circle( onD / 2 ) )
.repeatX( 2, 30 )
.centerXTo( usbHoles.middle.x )
.centerYTo( 42 )
val topHoles =
meterHole + potHole + powerHole + onHole + usbSwitches
val lines =
Cube( 1, size.y, 0.6 ).centerXTo( meterHole.middle.x ).centerY() +
Cube( 1, 0.6, size.z ).centerXTo( meterHole.middle.x )
.topTo( jackHole.middle.z )
.backTo(case.front)
.mirrorY().also() +
Cube( 1, size.y, 0.6 ).repeatX(2, 30).centerXTo( size.x/4 ).frontTo( usbSwitches.back )
val all = case - topHoles - usbHoles - bananaHoles - jackHole -lines + ribs + mockUSB
return all + mockPot
}
}