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