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(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(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(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 ) } }