import 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() } }