/GardenFurniture/BikeShed.foocad

Rather than moving the bike into the shed, move the whole shed! It runs on a pair of wheels. Lift the shed slightly from the end, wheel it forward, put the bike in place, and wheel the shed back again.
Note to scale - I used random values for size.
The sides will be lined with material (same stuff cheap tents are made from). The roof will be a piece of thin ply, with wooden batterns for strength, covered in roofing felt.
import uk.co.nickthecoder.foocad.screws.v3.*
import uk.co.nickthecoder.foocad.compound.v1.*
import uk.co.nickthecoder.foocad.threaded.v2.*
import uk.co.nickthecoder.foocad.smartextrusion.v1.*
import static uk.co.nickthecoder.foocad.smartextrusion.v1.SmartExtrusion.*
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 BikeShed : Model {
var size = Vector3( 1800, 600, 1100 )
var extraHeight = 150
var wheelSize = Vector2( 30, 50 )
var wheelThreadDiameter = 30
var tyreThickness = 5
var wheelFlangeSize = Vector2( 4, 6 )
var main = Wood( "main", 38, 22 ).color( "Green" )
var half = Wood( "half", 38, 22 ).color( "Orange" )
fun angle() = Math.tan( extraHeight / size.y )
fun back() : Shape3d {
val extra = main.thickness * Math.sin( angle() )
val length = size.z + extraHeight - main.width * 2 + extra
val center = main.cut(length)
.label( "BackCenter" )
.centerX()
.backTo( size.y/2 )
.bottomTo( main.width )
val left = center
.leftTo( -size.x / 2 )
val bottom = main.cut( size.x )
.label( "BackBottom" )
.edgeDownAlongX()
.leftTo( left.right )
.backTo(left.back)
.centerX().darker()
// Top will need to be angled (planing/cutting along the grain).
val topAndBottom = bottom
.bottomTo( center.top ).also()
return center +
left.mirrorX().also() +
topAndBottom
}
fun front() : Shape3d {
val center = main.cut(size.z - main.width * 2)
.label( "FrontCenter" )
.centerX()
.frontTo( -size.y / 2 )
.bottomTo( main.width )
val left = center
.leftTo( -size.x / 2 )
val bottom = main.cut( size.x )
.label( "FrontBottom" )
.edgeDownAlongX()
.leftTo( left.right )
.backTo( left.back )
.centerX().darker()
return center +
left.mirrorX().also() +
// Top will need to be angled (planing/cutting along the grain).
bottom.topTo( size.z ).also()
}
fun side( open : bool ) : Shape3d {
val height = if (open) 100 else size.z
val offsetZ = if (open) size.z - height else 0.0
val angle = angle()
val angleDegrees = angle * 180 / Math.PI
val front = main.cut( height )
.label( "SideFront" )
.rotateZ(90)
.frontTo( -size.y/2 + main.thickness )
.rightTo( size.x / 2 )
.translateZ( offsetZ )
.darker()
val back = main.cut( height + extraHeight - main.width )
.label( "SideBack" )
.rotateZ(90)
.backTo( size.y/2 - main.thickness )
.rightTo( front.right )
.translateZ( offsetZ )
.darker()
val bottom = main.cut( size.y - main.width * 2 - main.thickness * 2 )
.label( "SideBottom" )
.edgeDownAlongY()
.rightTo( front.right )
.centerY()
.translateZ( offsetZ )
val topExtra = main.thickness * Math.sin( angle )
// Will need trimming to size
val top = main.cut( extraHeight/Math.asin(angle) + topExtra)
.label( "SideTop" )
.edgeDownAlongY()
.centerY().translateY(topExtra/2)
.rotateX(angleDegrees)
.translateZ( (back.top + front.top) / 2 - main.width/2 )
.rightTo( front.right )
val across = bottom.translateZ( size.z / 3 )
.topTo( back.top - size.z/3 ).also()
return Compound().apply {
+ front
+ back
+ top
+ bottom
if (! open ) {
+ across
}
}.build()
}
fun rail() : Shape3d {
return half.cut( size.x - 20 - main.thickness )
.label( "Rail" )
.edgeDownAlongX()
.leftTo( -size.x / 2 )
.backTo( size.y / 2 - main.thickness - wheelFlangeSize.x - 3 )
}
fun stop() : Shape3d {
return half.cut( size.y - 2*(main.thickness*2 + wheelFlangeSize.x + 3) )
.label( "Stop" )
.edgeDownAlongY()
.centerY()
.rightTo( size.x / 2 - main.thickness - 20 )
}
fun wheelThread() = Thread( wheelThreadDiameter )
.rodChamfer(1)
@Piece
fun wheel() : Shape3d {
val flange = Circle( wheelSize.y / 2 + wheelFlangeSize.y )
.smartExtrude( wheelFlangeSize.x )
.chamfer( 1 )
val hub = Circle( wheelSize.y / 2 - tyreThickness )
.smartExtrude( wheelSize.x )
.top( Chamfer(1) )
.bottomTo( flange.top )
val bearingHole = Cylinder( 8, 22/2 )
.translateZ(-0.01)
val threadedHole = wheelThread().threadedHole( wheelSize.x/2 + 4 )
.clipped(true)
.topTo( hub.top + 1 )
val shaftHole = Cylinder( 50, 8/2 + 1 )
.bottomTo( bearingHole.top + 1 )
return flange + hub - shaftHole - bearingHole - threadedHole
}
@Piece
fun wheelCover() : Shape3d {
val flange = Circle( wheelSize.y / 2 + wheelFlangeSize.y )
.smartExtrude( wheelFlangeSize.x )
.chamfer( 1 )
val thread = wheelThread()
.threadedRod( wheelSize.x / 2 )
.chamferBottom(false)
.bottomTo( flange.top-0.5 )
val hole = Cylinder( wheelSize.x, wheelThread().coreRadius() - 2 )
.bottomTo( flange.top )
return flange + thread - hole
}
@Piece
fun tyre() : Shape3d {
return (Circle( wheelSize.y / 2 ) - Circle( wheelSize.y / 2 - tyreThickness ))
.smartExtrude( wheelSize.x - 1 )
//.outsideTop( Fillet(3) )
.color( "DimGrey" )
}
@Piece( printable = false )
fun wheelAndTyre() = wheel() +
tyre().translateZ(wheelFlangeSize.x) +
wheelCover().rotateX(180).topTo( wheelSize.x + wheelFlangeSize.y )
.rotateZ(190)
@Piece
fun foot() : Shape3d {
val main = Square( main.thickness, 60 )
.center()
.roundAllCorners(2)
.smartExtrude( 7 ) // How much do we want the shed to be lifter up by?
.top( Chamfer( 2 ) )
val screwHoles = Countersink()
.topTo(main.top)
.centerYTo( main.front * 2/3 )
.mirrorY().also()
return main - screwHoles
}
@Piece( about="TPU at the end of the rails" )
fun endStop2() : Shape3d {
return Square( main.width, main.thickness )
.roundAllCorners(3)
.smartExtrude( 2 )
.top( Chamfer( 1 ) )
}
@Piece( printable = false )
override fun build() : Shape3d {
val foot = foot()
.mirrorZ()
.rightTo( size.x / 2 )
.frontTo( -size.y / 2 )
.topTo(0)
//.translateY(150).also()
.mirrorY().also()
val rail = rail()
.translateZ(-foot.size.z)
val stop = stop()
val wheel = wheelAndTyre().rotateX(90)
.backTo( rail.back + wheelFlangeSize.x + 2 )
.bottomTo( rail.top - wheelFlangeSize.y )
.leftTo( -size.x / 2 + 30 )
return Compound().apply {
+ back()
+ front()
+ side(false)
+ side(true).leftTo(-size.x/2)
+ rail.mirrorY().also()
+ stop
+ wheel.mirrorY().also()
+ foot
}.build()
}
}
