FooCAD Source Codeimport 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 NinePieceJigsaw : Model {
var pieceSize = 30
var cornerRadius = 6
var thickness = 3.0
var tallSize = Vector2( 17, 5 )
var shortSize = Vector2( 7, 16 )
var bobbleRadius = 2.0
var slack = 0.5
var baseThickness = 0.6
var wallSize = Vector2(6,3)
// Pieces are chamfered. The bottom chamfer is larger to account for elephant foot on the first layer.
var chamfer1 = 0.9
var chamfer2 = 0.6
fun piece() = Square( pieceSize -slack ).center().roundAllCorners( cornerRadius )
fun extrude( piece : Shape2d ) = piece.chamferedExtrude( thickness, chamfer1, chamfer2 )
fun tallBobble() = Square( tallSize ).roundAllCorners( bobbleRadius )
.center().centerXTo( pieceSize/2 )
fun tallHole() = tallBobble().offset( slack )
fun shortBobble() = Square( shortSize ).roundAllCorners( bobbleRadius )
.center().centerXTo( pieceSize/2 )
fun shortHole() = shortBobble().offset( slack )
@Piece
fun red() = extrude(
piece() + tallBobble() + tallBobble().rotate(-90)
).color("Red").darker()
@Piece
fun blue() = extrude(
piece() + shortBobble() - shortHole().rotate(-90) - tallHole().rotate(180)
).color("DarkBlue")
@Piece
fun lightBlue() = extrude(
piece() + shortBobble().rotate(90) - shortHole().rotate(-90) - shortHole().rotate(180)
).color("lightBlue")
@Piece
fun white() = extrude(
piece() - shortHole().rotate(180) + tallBobble().rotate(90)
).color("White")
@Piece
fun blues() = blue().tileX(4,2)
@Piece
fun whites() = white().tileX(2,2)
@Piece
fun lightBlues() = lightBlue().tileX(2,2)
@Piece
fun base() : Shape3d {
val inside = Square( pieceSize * 3 ).center().roundAllCorners(cornerRadius+slack)
val outside = inside.offset( wallSize.x )
return outside.extrude( baseThickness )
.color("DimGrey")
}
@Piece
fun wall() : Shape3d {
val inside = Square( pieceSize * 3 ).center().roundAllCorners(cornerRadius+slack)
val outside = inside.offset( wallSize.x )
return (outside - inside).chamferedExtrude( baseThickness + wallSize.y, chamfer1, chamfer2 )
.color("Red").darker()
}
@Piece
fun tray() : Shape3d {
val inside = Square( pieceSize * 3 ).center().roundAllCorners(cornerRadius+slack)
val outside = inside.offset( wallSize.x )
return (outside - inside).chamferedExtrude( baseThickness + wallSize.y, chamfer1, chamfer2 )
.color("Red").darker() +
outside.offset(-chamfer1).extrude( baseThickness )
.color("DimGrey")
}
fun at( piece : Shape3d, x : int, y : int ) =
piece.translate( x * pieceSize, y * pieceSize, 0 )
override fun build() : Shape3d {
return tray().topTo(thickness) +
at(red(), -1, 1 ) +
at(blue(), 0, 1 ) +
at(lightBlue(), 1, 1 ) +
at(blue().rotateZ(-90).mirrorX(), -1, 0 ) +
at(lightBlue().rotateZ(90), 0, 0 ) +
at(blue().rotateZ(90), 1, 0 ) +
at(white().rotateZ(-90), -1, -1 ) +
at(blue(), 0, -1 ) +
at(white(), 1, -1 )
}
@Piece
fun cheat() : Shape3d {
return tray().topTo(thickness) +
at(white().rotateZ(-90).mirrorY(), -1, 1 ) +
at(blue(), 0, 1 ) +
at(blue().rotateZ(-90), 1, 1 ) +
at(blue().rotateZ(90), -1, 0 ) +
at(red().rotateZ(45), 0, 0 ) +
at(lightBlue().mirrorY(), 1, 0 ) +
at(white().mirrorX(), -1, -1 ) +
at(lightBlue().rotateZ(90).mirrorY(), 0, -1 ) +
at(blue().rotateZ(180), 1, -1 )
}
}