import static uk.co.nickthecoder.foocad.arrange.v1.Arrange.* import static uk.co.nickthecoder.foocad.layout.v1.Layout2d.* import static uk.co.nickthecoder.foocad.layout.v1.Layout3d.* class TubeTidy() : Model { val hookSize = Vector2( 30, 5 ) val hookThickness = 3 val indent = 4 @Custom( about="Diameter of the tube/wire" ) var tubeDiameter = 8 @Slice( brimWidth=5 ) fun hook( tubeDiameter : double ) : Shape3d { val radius = hookSize.x/2 + hookThickness/2 val tubeRadius = tubeDiameter/2 + hookThickness/2 val foo = radius*0.4 val profile = PolygonBuilder().apply { circularArcBy( foo, foo, foo, false, true ) bezierBy( Vector2( 0, foo ), Vector2( 0, foo ), Vector2(-indent, radius ) ) lineBy( 0, radius*0.1 ) circularArcBy( radius *2, 0, radius, true, false ) bezierBy( Vector2( 0, -foo ), Vector2( 0, -foo ), Vector2(-indent, -radius ) ) lineBy(0,-tubeRadius*2) circularArcBy( foo, -foo, foo, false, true ) lineBy(tubeRadius,0) circularArcBy( 0, tubeRadius*2, tubeRadius, false, true ) lineBy(-1,0) }.buildPath().thickness( hookThickness ).leftTo(0).frontTo(0) val handle = Square( 2, 20 ) .frontTo(profile.back -1) .centerXTo( hookSize.x/2 + hookThickness ) val bulge = Circle( 4 ).centerXTo( handle.middle.x ).translateY( handle.back ) val withHandle = profile + handle + bulge val hook = ExtrusionBuilder().apply { crossSection( withHandle ) //direction( Vector3( 1, 0, 2 ) ) forward( hookSize.y ) crossSection() }.build() return hook } override fun build() = hook( tubeDiameter ) @Piece fun hook8() = hook(8) @Piece fun hook10() = hook(10) @Piece fun hook12() = hook(12) @Piece fun hook16() = hook(16) @Piece fun many() = arrange( 3, hook(8), hook(10), hook(12), hook(16) ) }