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