Exit Full View
Up

/Bike/FlatBed.foocad

FlatBed

See also

Requirements

  • Carry lots of shopping on my ebike.
  • Carry bulkier items by tying down to a flat bed (e.g. bags of compost)
  • Easy to take on/off without tools.

Solution

Attach a piece of plywood to the pannier rack. It slots in place, and is secured by three bolts. The bolt head is plastic, and overlaps the pannier rack. They are weak(ish), and hopefully, they will snap off if the bike is knocked over. I'd prefer these reprintable bolts to break, rather than the box!

The box has a threaded inserts at each corner. The plywood base has holes in these positions, so the box can be screwed to the plywood. To make positioning the box easier, I also added some plastic guides to the top surface of the plywood.

Note. I ended up using plywood which was sturdy enough without the extra battonning around the edges. So only the three thinner pieces of wood remain.

Before entering the house, I can unscrew the 3 bolts, and lift the box and the base together. The box will only be unscrewed from the base when I buy compost, or other bulky items.

FooCAD Source Code
import uk.co.nickthecoder.foocad.woodworking.v1.*
import static uk.co.nickthecoder.foocad.woodworking.v1.Woodworking.*
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.*
import static uk.co.nickthecoder.foocad.along.v2.Along.*
import static uk.co.nickthecoder.foocad.extras.v1.Extras.*

class FlatBed : Model {

    @Custom
    val rackSize = Vector3( 180, 450, 10 )

    // The unused part of the rack near the seat.
    // Remember that the bag overlaps the bed by strut.thickness (so add it )
    val nonOverlap = 80

    // The "square" part of the bed
    val bedSize1 = Vector3( 400, 300, 8 )
    // The width of the "pointy" end, and the length from the square part.
    val bedSize2 = Vector2( 230, 200 )

    val strut = Wood( "strut", 38, 22 ).color("Green")
    val thinner = Wood( "strut", 38, rackSize.z, "OliveDrab" )
    val ply = Plywood( "ply", bedSize1.z, "LightGreen" )

    val slack = 2
    
    val roundRadius = 20

    fun pannier() : Shape3d {
        val outside = Square( rackSize.x, rackSize.y ).roundAllCorners(20).center()
        return (outside - outside.offset(-rackSize.z )).extrude( rackSize.z )
            .previewOnly()
    }

    fun bagBase() : Shape3d {

        val pannier = pannier()

        val size = Vector2(
            bedSize1.x + strut.thickness*2 + slack*2,
            bedSize1.y + bedSize2.y + strut.thickness*2 + slack*2
        )

        val base = ply.cut( Square( size.x, size.y ).roundAllCorners( roundRadius ) )
            .label("bagBase")
            .centerX()
            .backTo( pannier.back - nonOverlap )

        val sides = strut.cut( size.y )
            .round( OPPOSITE_EDGE, roundRadius ).bothEnds()
            .label("bagSides")
            .alongY().centerY().topTo(0)
            .leftTo(base.left)
            .frontTo(base.front)
            .mirrorX().also()

        val back = strut.cut( size.x - strut.thickness * 2 )
            .brighter()
            .label("bagBack")
            .alongX2().centerX().topTo(0)
            .frontTo(base.front)

        val fronts = strut.cut( (back.size.x - pannier.size.x )/2 - slack )
            .round( OPPOSITE_SIDE, roundRadius ).otherEnd()
            .brighter()
            .label("bagFronts")
            .alongX2().topTo(0)
            .rightTo( base.right - strut.thickness )
            .backTo(base.back)
            .mirrorX().also()

        val sidesOfRack = thinner.cut( bedSize2.y )
            .label("bedMiddleAlong")
            .alongY2()
            .topTo(0)
            .backTo( fronts.front )
            .rightTo( pannier.left - slack )
            .mirrorX().also()

        val endOfRack = thinner.cut( pannier.size.x )
            .label("bedStop")
            .alongX()
            .centerX()
            .backTo( pannier.front - slack )
            .topTo(0)

        val ramp = thinner.cut( 80 )
            .mitre( OPPOSITE_EDGE )
            .label("bedRamp")
            .alongY2()
            .mirrorY()
            .centerX()
            .frontTo( pannier.front + rackSize.z + slack )
            .topTo(base.bottom-0.1)

        return base + sides + back + fronts + sidesOfRack + endOfRack + ramp
    }

    override fun build() : Shape3d {
        val pannier = pannier().topTo(0)
        val bag = bagBase()//.topTo( 20 )

        return (pannier + bag).mirrorZ()
    }
}