Exit Full View
Up

/Garden/SeedlingSupport.foocad

SeedlingSupport

I grow squashes, cucumbers etc. indoors (for warmth), but the light is far from ideal. The net result, they start off leggy, needing support.

So, I add small stakes (bamboo BBQ skewers). Tieing to the stakes is a PITA.

Instead, I want to use TPU to grip the stakes, and support the plants without damaging them.

FooCAD Source Code
import static uk.co.nickthecoder.foocad.layout.v1.Layout2d.*
import static uk.co.nickthecoder.foocad.layout.v1.Layout3d.*
import uk.co.nickthecoder.foocad.smartextrusion.v1.*
import static uk.co.nickthecoder.foocad.smartextrusion.v1.SmartExtrusion.*
import uk.co.nickthecoder.foocad.extras.v1.*
import static uk.co.nickthecoder.foocad.extras.v1.Extras.*

class SeedlingSupport : Model {

    @Custom( about="Diameter of the hole" )
    var diameter = 2.9

    @Custom( about="Width and thickness" )
    var triSize = Vector2(2, 3)

    @Custom( about="Diameter, width, thickness" )
    var clawSize = Vector3(16, 2, 3)

    @Custom( about="How open/closed the claw piece is. " )
    var clawAngle = 280

    @Custom
    var teepeePoles = 5

    @Custom
    var teepeeDiameter = 80

    meth triShape() : Shape2d {
        val inside = Circle( diameter ).sides(3)
        val outside = inside.offset(triSize.x)
            .roundAllCorners(1,1)
        return outside - inside
    }

    meth tri() = tri ( triSize.y )

    meth tri( height : double ) : Shape3d {
        return triShape()
            .smartExtrude(height)
                .edges( Chamfer(triSize.y/8) )
    }

    @Piece
    meth claw() : Shape3d {
        val tri = tri()
        val claw = RoundedCircularArc( clawSize.x/2+clawSize.y, clawSize.x/2, -90, -90 + clawAngle )
            .translateY( clawSize.x/2 + clawSize.y/2 )
            .rotate(-30)
            .smartExtrude(clawSize.z)
                .edges( Chamfer(clawSize.y/8) )
            .translate( tri.right -1, 0.3, 0 )

        return tri + claw

    }

    @Piece
    meth clawBatch() = claw()
        .translateX( (diameter + triSize.x) * 2.5 )
        .repeatAroundZ( 6 )

    @Piece
    meth pincer() : Shape3d {
        val tri = tri()

        val shape = RoundedCircularArc( clawSize.x/2 + clawSize.y, clawSize.x/2, -20, 180 ) +
            RoundedCircularArc( clawSize.x/2 + clawSize.y*1.5 + 0.5, clawSize.x/2 + clawSize.y/2 + 0.5, 180, 380 )
                .translateX( clawSize.y/2 + 0.5 )

        val pincer = shape.leftTo( tri.right -1 )
            .smartExtrude(clawSize.z)
                .edges( Chamfer(clawSize.y/8) )

        return tri + pincer
    }

    @Piece
    meth pincerBatch() = pincer()
        .translateX( (diameter + triSize.x) * 2.5 )
        .repeatAroundZ( 6 )

    @Piece( about="Ends of stakes can be an eye hazzard. Makes them less pointy!" )
    meth tip() : Shape3d {
        val tri = tri( triSize.y * 2 )
        val base = Hull2d( triShape() )
            .smartExtrude( triSize.y / 2 )
                .bottom( Chamfer(clawSize.y/8) )

        return tri + base
    }

    @Piece( about="Holds 3 stakes togther at the top of the teepee shape" )
    meth teepeeTop() = teepeeTop( triSize.x/2 )

    meth teepeeTop( distance : double ) : Shape3d {

        val tri = tri().rightTo(0).translateX(  triSize.x/2 ).translateX(-distance/2-triSize.y/2)
        val around = tri.repeatAroundZ(teepeePoles)
        val ring = Ring( distance/2 + triSize.x, distance/2 )
        val connection = ring
            .smartExtrude( triSize.y )
            .edges( Chamfer(clawSize.y/8) )

        return around + connection
    }

    /**
    One stake goes in the two end holes.
    */
    @Piece
    meth teepeeBottom() = teepee( teepeeDiameter/2 )

    meth teepee( distance : double ) : Shape3d {
        val deltaAngle = 11
        val tri = tri().rightTo(0).translateX( -distance/2 - triSize.x/2 ).rotateZ(180+deltaAngle)
        val around = tri.repeatAroundZ(teepeePoles+1, (360-deltaAngle*2)/teepeePoles)
        
        val foo = Vector2(distance/2 + triSize.x/2, 0)
        val turnPerPole = (360-deltaAngle*2)/(teepeePoles)
        val path = PolygonBuilder().apply {
            moveTo( foo.rotateDegrees(deltaAngle) + Vector2(1,0))
            lineBy( -1,0 )
            for ( p in 1 .. teepeePoles ) {
                lineTo( foo.rotateDegrees(deltaAngle + p * turnPerPole ) )
            }
            lineBy( 1,0 )
        }.buildPath()

        val connection = path.thickness( triSize.x )
            .smartExtrude( triSize.y )
            .edges( Chamfer(clawSize.y/8) )

        return around + connection
    }

    @Piece( print="claw" )
    override meth build() : Shape3d {
        val claws = claw()
            .translateZ(10).rotateZ(-40)
                .mirrorY().translateZ(3).also(2)

        val pincer = pincer().translateZ(40)

        val stake = Cylinder( 60, diameter/2 )
            .previewOnly()


        return stake + claws + pincer
    }

}