Exit Full View
Up

/Christmas/SpringoSnoman.foocad

SpringoSnoman

A slinky spring in the shape of a snowman. The snowman is cut into a spring from his neck to the base. However, I like to leave the first few loops fused, as it is nicer to play with when the spring stops short of the base. I also leave the brim on!

You will need to separate the layers using using a blade.

##Print Notes

I used PETG for the spring(s).

I strongly recommend printing the "test" piece first, because you may need to adjust the "gap", or your printer if your prints are fused.

I used a gap of 0.39mm, and a layer height of 0.2mm. If you use a different layer height, also adjust the gap.

If you turn the part cooling fan off when printing the hat, the center sags quite nicely!

FooCAD Source Code
import static uk.co.nickthecoder.foocad.chamferedextrude.v1.ChamferedExtrude.*
import static uk.co.nickthecoder.foocad.layout.v1.Layout2d.*
import static uk.co.nickthecoder.foocad.layout.v1.Layout3d.*
import uk.co.nickthecoder.foocad.threaded.v1.Threaded
import static uk.co.nickthecoder.foocad.threaded.v1.Threaded.*

class SpringoSnowman : Model {
    
    // If the layers fuse together too much, adjust the gap.
    // I believe there is "aliasing" between the gap and the layer height.
    // The gap should be slightly less than a multiple of your layer height.
    // Look at the print, and you may see some parts have a clear gap, whereas
    // other places look fused. You want a very small "fused" section.
    // NOTE. Each slicer may give different results. I use slic3r.
    @Custom
    var gap = 0.39

    // The height of one piece of the slinky spring (including the gap).
    // If this is an exact multiple of the layer height, then the alias
    // artifacts described above line up.
    // I haven't investigated adjusing this.
    @Custom
    var pitch = 2.0

    // The difference between the outer and inner radius.
    @Custom
    var thickness = 2

    @Custom
    var slack = 0.3

    // False if you want to drill holes for facial features yourself.
    @Custom
    var includeHoles = true

    // A small springo to help tune the gap and other settings before printing
    // the complete snowman.
    @Piece
    fun test() = Cylinder( 10, 20 ) - Cylinder( 12, 20-thickness ).translateZ(-1) -
            Threaded.springo( 60, 10, pitch, gap )

    @Piece
    fun springoSnowman() = snowman() - Threaded.springo( 70, 72, pitch, gap )

    @Piece
    fun printNode() = nose().mirrorZ()

    @Piece
    fun eyes() = eye().tileX(2, 1)

    @Piece
    fun springoHat() = hat() - Threaded.springo( 30, 8, pitch, gap ).translateZ(2)


    fun nose() : Shape3d {
        return Cylinder( 4, 2 ) + Cylinder( 12, 3, 1 ).translate(0,1,4)
            .color("Orange")
    }

    fun eye() : Shape3d {
        return Cylinder( 4, 2 ) + Sphere( 2.5 ).translateZ( 4 ).color("DarkSlateGray")
    }

    fun hat() : Shape3d {
        val brim = Circle( 17 ).chamferedExtrude(2,0,0.5).color( "DimGray" )
        val main = Circle( 12 ).chamferedExtrude( 12,0,1 ).color( "DimGray" )
        val hole = Circle( 10 ).internalChamferedExtrude( 11,1,0 ).color("Red")

        return (brim + main - hole)
    }

    fun snowman() : Shape3d {
        var head : Shape3d = Sphere( 16 ).translateZ(84)
        if ( includeHoles ) {
            val eyeHoles = Cylinder( 10, 2 )
                    .translateZ(-3).rotateX(-88).translateY(14).rotateZ(200)
                    .translateZ(88)
                    .mirrorX().also()
            val noseHole = Cylinder( 10, 2 )
                .translateZ(-3).rotateX(90).translate( 0, -16, 83 )
            head = head - eyeHoles - noseHole
        }
        val body = 
            Sphere( 30 ).translateZ(20)/Cube(80).centerXY() +
            Sphere( 22 ).translateZ( 53 ) -
            Sphere( 30-thickness ).translateZ(20) -
            Sphere( 22-thickness ).translateZ(53)

        val snowman = body + head - Cylinder( 25, 12 -thickness ).translateZ(84-16)

        val springo = snowman

        return springo
    }


    override fun build() : Shape3d {
       return snowman() +
            nose().translateZ(-3).rotateX(90).translate( 0, -14, 83 ) +
            eye().translateZ(-3).rotateX(-90).translateY(14).rotateZ(200)
                .translateZ(88)
                .mirrorX().also() +
            hat().translateZ( 96 )
    }
}