Exit Full View
Up

/Garden/SeedModuleGrid2.foocad

SeedModuleGrid2

This is very similar to SeedModuleGrid, but the patten of the ribbing is different. I'm not sure which is better yet, so I'm keeping both scripts for now.

I want a grid, which fits over a "standard" half size gravel tray. The grid will hole SimplePlantPots, made to the appropriate size.

The default values work well with Wilko's half size gravel trays, and the "module" sized SimplePlantPot. Alas, SimplePlantPot was sized so that it fit into a "full sized" gravel tray (3x5), and they only just fint into a half size tray (3x2). Therefore the inner "ring" part is removed, leaving the item weaker than I would like. (Because the central rib doesn't attach to the outside edge).

Parameters

  • cutAt Cuts the final model into two parts, for a tray wider than the printer. cutAt is in the range 0..gridAcross - 1 Use pieces cutA and cutB instead of the default.

  • outerSize If outerSize is set, then it will raise the grid off the ground, making a tray (without a bottom) which helps keep pots together, not falling over, and is easy to move the whole tray, rather than individual pots. Alas, these trays are not stackable (but do not need to be very tall). Do NOT use outerSize and cutAt together.

FooCAD Source Code
import static uk.co.nickthecoder.foocad.layout.v1.Layout2d.*
import static uk.co.nickthecoder.foocad.layout.v1.Layout3d.*

class SeedModuleGrid2 : Model {

    @Custom( about="Width of the holes (slightly bigger than the pot width, excluding the rim" )
    var width = 67.0 // Was 65

    @Custom( about="Gap bewteen the holes" )
    var gap = Vector2(5.0, 9.0) // was 4

    @Custom( about= "Radius of the pots" )
    var cornerRadius = 8

    @Custom( about="Quantity of pots in the X direction" )
    var gridAcross = 3

    @Custom( about="Quantity of pots in the Y direction" )
    var gridDown = 2

    @Custom( about="External size of the tray" )
    var traySize = Vector2( 221, 164)

    @Custom( about="Radius of the tray's corners")
    var trayRadius = 18

    @Custom( about="Used for an 'exclusion' area where no ribs can be created. Often not needed!" )
    var trayLip = 5.0

    @Custom( about="Thickness of the top sheet" )
    var sheetThickness = 0.9

    @Custom( about="Thickness of the ribbing, which gives the grid strength" )
    var gridThickness = 1.2

    @Custom( about="Height of the ribbing, which gives the grid strength" )
    var gridHeight = 6.0

    @Custom( about="Print in two halves, and then glue them together" )
    var cutAt = 3

    @Custom( about="The size of the outer rim. Use a large Y value, to hold pots steady, without a tray" )
    var outerSize = Vector2( 1.2, 0 )

    fun build( cutAt : int ) : Shape3d {

        val hole = Square( width ).roundAllCorners( cornerRadius ).center()
        val holes = hole
            .tileX( gridAcross, gap.x )
            .tileY( gridDown, gap.y )
            .center()

        val sheet = Square( traySize + Vector2( gridThickness, gridThickness ) * 2 )
            .roundAllCorners( trayRadius + gridThickness )
            .center()

        val top = (sheet - holes).extrude( sheetThickness )

        
        val edge = (sheet - sheet.offset(-outerSize.x))
        val outer = if (outerSize.y > gridHeight ) {
            val expand = -outerSize.y * 0.15 // Determines the angle. Was 0.172
            val outerEdge = ExtrusionBuilder().apply {
                crossSection( sheet )
                forward( outerSize.y )
                crossSection(expand)
                crossSection( -outerSize.x * 3 )
                forward( -outerSize.x )
                crossSection()
                forward( -outerSize.x * 3 )
                crossSection( outerSize.x * 2)
                forward( -outerSize.y + outerSize.x * 4 )
                crossSection(-expand)
            }.buildClosed()

            val handles = Cube( 70, outerEdge.size.y + 2, outerSize.y * 0.7 ).centerXY().centerZTo( outerSize.y / 2 ) +
                Cube( outerEdge.size.x + 2, 70, outerSize.y * 0.7 ).centerXY().centerZTo( outerSize.y / 2 )

            outerEdge - handles
        } else {
            Cube(0)
        }

        val exclusion : Shape2d = (
            Square( traySize ).roundAllCorners(trayRadius).center() -
            Square( traySize - Vector2( trayLip, trayLip ) * 2 ).roundAllCorners(trayRadius-trayLip).center()
        )

        val rings = (hole.offset(gridThickness) - hole)
            .repeatX( gridAcross, hole.size.x + gap.x )
            .repeatY( gridDown, hole.size.y + gap.y )
            .center()
        val across = Square( gap.x, gridThickness )
            .backTo( hole.back - cornerRadius )
            .leftTo( hole.right )
            .mirrorY().also()
            .repeatX( gridAcross-1, hole.size.x + gap.x )
            .repeatY( gridDown, hole.size.y + gap.y )
            .center()
        val down = Square( gridThickness, gap.y )
            .rightTo( hole.right - cornerRadius )
            .frontTo( hole.back )
            .mirrorX().also()
            .repeatX( gridAcross, hole.size.x + gap.x )
            .repeatY( gridDown-1, hole.size.y + gap.y )
            .center()

      
        val tray = exclusion.extrude( 2 ).bottomTo( sheetThickness ).previewOnly()


        val solid = (edge + rings + across + down - exclusion ).extrude( gridHeight )
            .bottomTo(0.01)
            .color("Orange")

        if (cutAt > 0) {
            val overlap = Cube( top.size.x, top.size.y + 2, solid.size.z + 2 )
                .centerY().bottomTo(-1).rightTo( (cutAt - gridAcross/2) * (width + gap.x) )

            val cut = (top + solid) / overlap 
            val extra = Cube( gridThickness*2, holes.size.y + gridThickness, gridHeight*2 )
                .centerY().rightTo(overlap.right )
                .color("Red")

            return cut + extra
        }

        return top + solid + tray + outer

    }

    @Piece
    fun cutA() = build( cutAt )

    @Piece
    fun cutB() = build( gridAcross - cutAt )

    override fun build() = build( 0 )


}