/Christmas/SpringoSnowman.foocad

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!
import uk.co.nickthecoder.foocad.threaded.v2.*
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.*
class SpringoSnowman : AbstractModel() {
// 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) +
Thread.springo( 40, 40-thickness*4, 10, pitch, gap ).color("Red")
@Piece
fun springoSnowman() : Shape3d {
val snowman = snowman()
return snowman - Thread.springo( snowman.size.x, 20, 72, pitch, gap )
}
@Piece
fun printNode() = nose().mirrorZ()
@Piece
fun eyes() = eye().tileX(2, 1)
@Piece
fun springoHat() = hat() - Thread.springo( 30, 10, 8, pitch, gap ).translateZ(2.5)
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 ).chamferedExtrude( 11.2,-1,0 ).translateZ(-0.1).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
}
@Piece( printable = false )
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 )
}
}

