Exit Full View
Up

/Phone/HeavyPhoneStand.foocad

HeavyPhoneStand
FooCAD Source Code
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()

    }
}