import static uk.co.nickthecoder.foocad.layout.v1.Layout2d.* import static uk.co.nickthecoder.foocad.layout.v1.Layout3d.* import uk.co.nickthecoder.foocad.threaded.v1.Threaded class WateringCanSpout2 : Model { @Custom( about="Diameter of the end, where the rose attaches" ) var endD = 23.5 @Custom( about="Length of the slightly tapered region where the rose attaches" ) var endL = 20.0 // Don't make it too large, or there won't be enough of a lip for the sealing washer. @Custom( about="Internal diameter of the tube at the can end" ) var midD = 26 @Custom( about="Length of the shaft, not including the threaded part or the rose attachment" ) var length = 180 @Custom( about="Thread depth" ) var threadDepth = 1.0 @Custom( about="Thread pitch" ) var threadPitch = 5.0 @Custom( about="Thread diameter" ) var threadD = 39.5 @Custom( about="Thickness of all the parts" ) var thickness = 1.2 @Custom( about="Length of the threaded portion" ) var connectorL = 19 val shoulder = 10 // Cut the fins off after printing! @Custom( about="Helps support the wobbly tube while printing. Only needed for plater slingers?" ) var includeFins = true val taper = 1.0 fun tube() : Shape3d { val bodyExternalR = threadD / 2 + thickness + threadDepth val tube = ExtrusionBuilder().apply { crossSection( Circle( bodyExternalR ) ) forward( shoulder ) crossSection( Circle( midD /2 + thickness*2 ) ) forward( length - shoulder ) crossSection( Circle( endD/2 )) forward( endL ) crossSection( -taper ) crossSection( - thickness ) forward( -endL ) crossSection( taper ) forward( -length + shoulder) crossSection( Circle( midD /2 + thickness ) ) forward( -shoulder ) crossSection() }.buildClosed() return tube } fun body() : Shape3d { val bodyExternalR = threadD / 2 + thickness + threadDepth val threaded = Threaded.create( threadDepth, threadD, threadPitch ).apply { nutProfile = Circle( bodyExternalR ) nutChamfer = 0 } val stop = (Circle( bodyExternalR ) - Circle( midD / 2 + thickness ) ).extrude( thickness ) val thread = ( threaded.nut( connectorL ) ).bottomTo( stop.top ) return thread + stop } override fun build() : Shape3d { val tube = tube().mirrorZ().bottomTo(0) val body = body().bottomTo( tube.top ) val fins = if ( includeFins ) { val rect = Square( 20, 0.8 ).centerY() ExtrusionBuilder().apply { crossSection( rect.leftTo( endD/2 - taper ) ) forward( endL ) crossSection( rect.leftTo( endD/2 ) ) forward( (length- shoulder) * 0.5 ) crossSection( rect.scaleX(0.01).leftTo((endD/2 + midD/2+thickness)/2 ) ) }.build() .color("Green") .repeatAroundZ(4) } else { null } return tube + body + fins } }