/GardenFurniture/NoobWoodworker.foocad

Can we build garden furniture using just straight cuts?
I'm also testing the use of fabric for side panels (i.e. either canvas, or the thinner plastic tent fabrics).
import uk.co.nickthecoder.foocad.woodworking.v1.*
import static uk.co.nickthecoder.foocad.woodworking.v1.Woodworking.*
import uk.co.nickthecoder.foocad.screws.v3.*
import static uk.co.nickthecoder.foocad.layout.v1.Layout2d.*
import static uk.co.nickthecoder.foocad.layout.v1.Layout3d.*
import static uk.co.nickthecoder.foocad.along.v3.Along.*
import uk.co.nickthecoder.foocad.woodworking.v1.*
import static uk.co.nickthecoder.foocad.woodworking.v1.Woodworking.*
class DemoNoobWoodworker : Model {
@Custom
var noob = NoobWoodworker()
@Custom
var wood = Wood( "wood", 45, 16 )
@Custom
var angleRadius = 20
@Piece
meth guideShim() = noob.guideShim( wood.size )
meth preview() = wood.cut( 100 ).previewOnly()
@Piece
meth angle() = noob.angle( wood.size.x, angleRadius ) +
preview().edgeDownAlongX().mirrorY() +
preview().edgeDownAlongY().rightTo(0).frontTo(-wood.thickness)
@Piece
meth angle2() = noob.angle2( wood.width, wood.thickness, angleRadius ) +
preview().edgeDownAlongX().backTo(0).bottomTo( noob.flatThickness ) +
preview().edgeDownAlongY().leftTo(-wood.thickness).frontTo(-wood.thickness).bottomTo( noob.flatThickness )
@Piece
meth corner() = noob.corner( wood ) +
preview().sideDownAlongX().bottomTo( noob.flatThickness ).leftTo( noob.betweenThickness ) +
preview().sideDownAlongY().bottomTo( noob.flatThickness ).rightTo( 0 )
@Piece
meth doubleCorner() = noob.doubleCorner( wood )
@Piece
meth tConnector() = noob.tConnector( wood ) +
preview().sideDownAlongX().bottomTo( noob.flatThickness ) +
preview().sideDownAlongY().bottomTo( noob.flatThickness ).rightTo( -noob.betweenThickness ).centerYTo( wood.width/2 )
@Piece
meth simpleConnector() = noob.simpleConnector( wood.size )
override fun build() : Shape3d {
return guideShim()
}
}
class NoobWoodworker {
@Custom
var betweenThickness = 2
@Custom
var edgeThickness = 3
@Custom
var flatThickness = 1
@Custom
var betweenCountersink = Countersink()
@Custom
var outsideCountersink = Countersink()
@Custom
var guideCountersink = Countersink()
@Custom
var rounding = 4
var color = "Orange"
// Set to true when rendering the large-scale, so that the plastic hardware
// is greatly simplified. i.e. no holes, no threads etc.
var mock = false
meth guideShim( size : Vector2 ) : Shape3d {
val shim = Square( size ).center()
.roundAllCorners(rounding)
.extrude( edgeThickness )
val hole = outsideCountersink.topTo( shim.top )
return if ( mock ) {
shim
} else {
shim - hole
}.color( color )
}
meth angle( width : double ) = angle( width, width*0.7 )
meth angle( width : double, radius : double ) : Shape3d {
val shape = Square( width, edgeThickness )
.rotate(90).leftTo(0).also(2)
.roundCorner(3, radius)
val holes = outsideCountersink
.depth( width )
.recess( width - outsideCountersink.recessDiameter/4 - 1 )
.rotateX(-90)
.backTo( width )
.centerXTo( width *0.75 )
.centerZTo( width/2 )
.rotateZ(90).mirrorX().also(2)
return if (mock) {
shape.extrude( width )
} else {
val roundMask = Square( width )
.roundCorner(2, rounding)
.roundCorner(1, rounding)
.extrude( width*3 )
.rotateX(90)
.centerY()
.bottomTo(0)
(shape.extrude( width ) - holes)
.intersection(roundMask)
.intersection(roundMask.rotateZ(90))
}
}
meth angle2( width : double, thickness : double ) = angle2( width, thickness, width*0.7 )
meth angle2( width : double, thickness : double, radius : double ) : Shape3d {
val shape = Square( width, edgeThickness )
.rotate(90).leftTo(0).also(2)
.roundCorner(3, radius)
val holes = outsideCountersink
.depth( width )
.recess( width - outsideCountersink.recessDiameter/4 - 1 )
.rotateX(-90)
.backTo( width )
.centerXTo( width *0.75 )
.centerZTo( width/2 )
.rotateZ(90).mirrorX().also(2)
val baseShape = (
Square( width + thickness ).leftTo(-thickness).frontTo(-thickness) -
Square( width * 2 ).translate(edgeThickness, edgeThickness )
).toPolygon()
val base = baseShape
.roundCorner(5, rounding )
.roundCorner(4, rounding )
.roundCorner(3, rounding )
.extrude( flatThickness )
return if (mock) {
base + shape.extrude( width + flatThickness )
} else {
val roundMask = Square( width, width + flatThickness )
.roundCorner(2, rounding)
.extrude( width*3 )
.rotateX(90)
.centerY()
.bottomTo(0)
base + (shape.extrude( width + flatThickness ) - holes)
.intersection(roundMask)
.intersection(roundMask.rotateZ(90))
}
}
meth corner( wood : Wood ) = corner( wood.width, wood.thickness )
meth corner( width : double, thickness : double ) : Shape3d {
val back = Square( width * 2 + betweenThickness, width )
.roundCorners( listOf<int>(2, 3), rounding )
.extrude( flatThickness )
.leftTo(-width)
val between = Cube( betweenThickness, width, thickness )
.bottomTo( back.top )
val betweenHole = betweenCountersink.rotateY(-90)
.leftTo( between.left )
.centerYTo( between.middle.y )
.centerZTo( between.middle.z )
val end = Square( back.size.x, between.size.z + edgeThickness )
.roundCorners( listOf<int>(2, 3), rounding )
.leftTo( back.left )
.extrude( edgeThickness )
.rotateX(90)
val endHoles = guideCountersink
.rotateX(90)
.frontTo( end.front )
.centerZTo( end.middle.z )
.translateX( -width / 4 )
.translateX( -width / 2 ).also()
.translateX( width + betweenThickness ).also()
return if ( mock ) {
back + between + end
} else {
(back + between - betweenHole + end - endHoles )
}.color( color )
}
meth doubleCorner( wood : Wood ) = doubleCorner( wood.width, wood.thickness )
meth doubleCorner( width : double, thickness : double ) : Shape3d {
val between1 = Square( width + edgeThickness, thickness)
.extrude(betweenThickness)
.rotateY(-90)
.leftTo(0)
.frontTo(-thickness)
val between2 = Square( width + betweenThickness, width + edgeThickness)
.extrude( edgeThickness )
.rotateX(90)
.frontTo(0)
.leftTo(-width)
val guide1 = Square( width*2 + betweenThickness, thickness )
.roundCorners( listOf<int>(2, 3), rounding )
.leftTo( between2.left )
.extrude( edgeThickness )
.mirrorY()
val guide2 = Square( thickness, width )
.roundCorner( 3, rounding )
.leftTo( between2.left )
.frontTo( betweenThickness )
.extrude( edgeThickness )
val guide3 = Square( width + edgeThickness, width )
.roundCorner(2, rounding)
.extrude( edgeThickness )
.rotateY(-90)
.leftTo(guide2.right)
.translateY(betweenThickness)
val guide4 = guide3.rotateZ(-90)
.leftTo(between2.right)
.frontTo(0)
val twoHoles = outsideCountersink
.mirrorZ()
.translateX(width/2).also()
.centerXTo( - width/2 )
.centerYTo( - thickness/2 )
val bottomHoles = twoHoles.translateX(width + betweenThickness ).also() +
twoHoles.rotateZ(90)
.centerXTo( guide2.middle.x )
.centerYTo( guide2.middle.y )
val guide4Hole = outsideCountersink
.rotateX(-90)
.centerXTo( guide4.middle.x )
.centerZTo( guide4.middle.z )
.backTo( guide4.back )
val guide3Hole = outsideCountersink
.rotateY(90)
.centerYTo( guide3.middle.y )
.centerZTo( guide3.middle.z )
.rightTo( guide3.right )
val between1Hole = betweenCountersink
.rotateY(-90)
.centerYTo( between1.middle.y )
.centerZTo( width*0.8 )
.leftTo( between1.left )
var between2Hole : Shape3d = betweenCountersink
.rotateX(-90)
.centerXTo( between2.middle.x )
.centerZTo( width*0.8 )
.backTo( between2.back )
between2Hole = if ( false ) {
between2Hole.centerXTo( -width + thickness/2 )
} else {
between2Hole.centerXTo( -(width-thickness)/2 )
}
return if ( mock ) {
between1 + between2 +
guide1 + guide2 + guide3 + guide4
} else {
between1 + between2 +
guide1 + guide2 + guide3 + guide4 -
guide3Hole - guide4Hole - bottomHoles - between1Hole - between2Hole
}.color( color )
}
meth tConnector( wood : Wood ) = tConnector( wood.width, wood.thickness )
meth tConnector( wood : Wood, overlap : double ) = tConnector( wood.width, wood.thickness, overlap )
meth tConnector( width : double, thickness : double ) = tConnector( width, thickness, width * 2/3 )
meth tConnector( width : double, thickness : double, overlap : double ) : Shape3d {
val back = Square( width + overlap + betweenThickness, width + edgeThickness )
.roundAllCorners(rounding)
.extrude( flatThickness )
.leftTo(-overlap)
val between = Cube( betweenThickness, width, thickness )
.bottomTo( back.top )
.frontTo( edgeThickness )
val guide = Cube( width + betweenThickness - rounding, edgeThickness, thickness + flatThickness )
val betweenHole = betweenCountersink
.rotateY(90)
.centerYTo( between.middle.y )
.centerZTo( between.middle.z )
.rightTo( between.right )
val guideHole = outsideCountersink
.rotateX(90)
.centerXTo( guide.middle.x )
.centerZTo( guide.middle.z )
.frontTo( guide.front )
return if (mock) {
back + between + guide
} else {
back + between + guide - betweenHole - guideHole
}.color( color ).translate( -betweenThickness, -edgeThickness, 0 )
}
meth simpleConnector( size : Vector2 ) = simpleConnector( size.x, size.y )
meth simpleConnector( width : double, thickness : double ) : Shape3d {
val back = Square( width * 1.5 + betweenThickness, width )
.extrude( edgeThickness )
.leftTo(-width)
val between = Cube( betweenThickness, width, thickness )
.bottomTo( back.top )
return (back + between).color( color )
}
}
