FooCAD Source Codeimport static uk.co.nickthecoder.foocad.layout.v1.Layout2d.*
import static uk.co.nickthecoder.foocad.layout.v1.Layout3d.*
/*
I want a HEAVY phone stand, so that my Mum can use her phone one handed.
The weight is achieved by filling it with plaster / sand / cement / lentils...
Note, the model is almost entirely hollow, apart the the "ledge".
Drill a hold in the back near the top
Add dry plaster or sand & cement.
Add some water,
Plug the drill hole with a (3D printed) bung if you want!
Glue non-slip matt material to the base, and the front, where the phone sits.
Beware PLA will almost certainly crack, if dropped onto a hard surface.
Print Notes
Consider using enough perimeters and top/bottom layers so that
`thickness` is completely solid.
e.g. with a 0.4mm nozzle, and a thickness of 1.6mm, use at least 4 perimeters.
And with a layer height of 0.2, use 8 top/bottom solid layers.
Fill % can be low (remember the model is mostly hollow anyway!)
*/
class HeavyPhoneStand : Model {
// The overall dimensions (width, depth, height)
@Custom
var size = Vector3( 70, 70, 120 )
// The angle of the slope
@Custom
var angle = 20.0
@Custom
var thickness = 1.6
// The height and depth of the ledge, where the phone sits.
@Custom
var ledge = Vector2(14, 14)
// Rounded corners
@Custom
var radius = 2
@Custom
var chamfer = 1.4
@Custom
var internalChamfer = 3.2
@Custom
var dividers = 2
@Piece
fun main() : Shape3d {
val square = Square( size.y, size.z )
val cutAway =
Square( size.y, size.z*2 ).translate( -ledge.x, ledge.y ).also()
.rotate( angle )
.translateX( size.y )
val profile = (square - cutAway).toPolygon()
.roundAllCorners(radius )
val main = extrude( profile, size.x, chamfer )
val cutAwayMiddle =
Square( size.y, size.z*2 ).translateX( -ledge.x )
.rotate( angle )
.translateX( size.y )
val middle2d = (square - cutAwayMiddle)
.offset(-thickness)
.roundAllCorners(internalChamfer, 1)
val middle = extrude( middle2d, size.x - thickness * 2, internalChamfer ).translateZ(thickness)
val divider = profile.extrude(thickness/2).repeatZ( dividers, size.x / (dividers+1) )
val all = (main - middle).centerZ() + divider.centerZ()
val holes = Cylinder( 10, 5 ).sides(6)
.color("Red")
.rotateX(90)
.translateY(1)
.repeatX( dividers + 1, (size.x - thickness * 2)/ (dividers + 1) )
.centerX()
.translateZ( size.z - 20 )
return (all.rotateX(90).rotateZ(-90) - holes)
// Uncoment the following line to look inside!
//.intersection( Cube( 200 ).translate(0,-100, 0) )
}
@Piece
fun cover() : Shape3d {
return (Cylinder( 0.6, 8 ) + Cylinder( 3, 4 ).sides(6)).tileX(3,2)
}
override fun build() = main()
fun extrude( profile : Shape2d, height : double, chamfer : double ) : Shape3d {
return ExtrusionBuilder().apply {
crossSection( profile.offset( -2 ) )
forward( chamfer )
crossSection( profile )
forward( height - chamfer * 2 )
crossSection()
forward( chamfer )
crossSection( -chamfer )
}.build()
}
}