/Garden/SeedlingSupport.foocad

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.
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
}
}