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 NinePieceJigsaw : AbstractModel() { 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 ) @Piece( printable = false ) 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 ) } }