/Tools/ZipTie.foocad

Zip ties inspired by SunShine : https://www.youtube.com/watch?v=AJyiSVeIEqY
Thread some TPU through the holes to complete the zip tie.
NOTE. Do NOT try to print one at a time, as the small size will probably prevent one layer cooling before the next layer starts.
import static uk.co.nickthecoder.foocad.layout.v1.Layout2d.* import static uk.co.nickthecoder.foocad.layout.v1.Layout3d.* import static uk.co.nickthecoder.foocad.chamferedextrude.v1.ChamferedExtrude.* class ZipTie : AbstractModel() { val size = Vector3( 9.5, 5.5, 2.8 ) val diameter = 2.15 val overhang = 2.0 val offset = 2.75 val anvilHeight = 2 val across = 4 val down = 4 fun one(diameter : float, overhang : float) : Shape3d { val base = Square( size.x, size.y ) .center().roundAllCorners( size.y / 6 ) .extrude( size.z ) val hole = Circle( diameter / 2 ).sides(20) .chamferedExtrude(size.z+1, -0.8, 0) .translate(offset, 0, -0.001) val holes = hole.mirrorX().also().translateZ(-0.01) val chamfer = 1 val anvil = ExtrusionBuilder().apply { crossSection(Square( offset *2 - diameter, size.y ).center()) forward( anvilHeight *0.25) crossSection(Square( offset *2 - diameter, (size.y + diameter)/2).center()) forward( anvilHeight *0.75) crossSection(Square( offset *2 - diameter + overhang, diameter ).center()) }.build() .bottomTo(base.top) return (base + anvil) - holes } /** * 7 clips, each with a different diameters * NOTE. The speed and layer height will probably affect the finish result, * The center item uses "diameter". * Once you have worked out the best diameter (the filament should just fit in the hole), * move on to "overhangVariations" */ @Piece fun diameterVariations() : Shape3d { val variation = 0.05 val overhangVariation = 0.2 val items = listOf<Shape3d>() for (i in 0 .. 6) { items.add( one( diameter + variation * (i-3), 0 ) .translateY( i * (size.y + 1) ) ) } items.add( Cube( 1.5, (size.y + 1)* 6, 0.4 ).centerX() ) return Union3d( items ) } @Piece fun overhangVariations() : Shape3d { val variation = 0.2 val items = listOf<Shape3d>() for (i in 0 .. 6) { items.add( one( diameter, overhang + variation * (i-3) ) .translateY( i * (size.y + 1) ) ) } items.add( Cube( 1.5, (size.y + 1)* 6, 0.4 ).centerX() ) return Union3d( items ) } /** * 16 clips in a 4x4 grid */ @Piece fun many() : Shape3d { val one = one( diameter, overhang ) val many = one .tileX(across, 1).tileY(4, 1).centerXY() val lineY = Square( 1, many.size.y ) .repeatX( across, many.size.x/across ) .center() .extrude(0.4) val lineX = Square( many.size.x-1, 1 ) .repeatY( down, one.size.y + 1 ) .center().frontTo(many.front+0.1) .extrude(0.4) return many + lineX + lineY } override fun build() : Shape3d { return one(diameter, overhang) } }