Exit Full View
Up

/Garden/WateringCanSpout.foocad

WateringCanSpout

My spout has degraded in the sun, but the body is still looking good. 3D printer to save a little plastic ;-)

This version comes in two parts, which should be glued together. See version 2, for a single part version (which may be trickier to print on plate slinger printers due to height and small bed contact).

NOTE. I've changed this script since printing it. Check that the rose will fit correctly!

FooCAD Source Code
import uk.co.nickthecoder.foocad.threaded.v1.Threaded

class WateringCanSpout : 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

    @Custom( about="Internal diameter of the tube at the can end" )
    var midD = 24

    @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 bodyL = 23

    val shoulder = 10

    val taper = 1.0

    @Piece
    fun tube() : Shape3d {
        val bodyExternalR = threadD / 2 + thickness + threadDepth 
        val stop = (Circle( bodyExternalR ) - Circle( midD / 2 + thickness ) ).extrude( thickness )
        
        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().bottomTo( stop.top )

        return tube + stop
    }

    @Piece
    fun body() : Shape3d {
        val bodyExternalR = threadD / 2 + thickness + threadDepth 
        val threaded = Threaded.create( threadDepth, threadD, threadPitch ).apply {
            nutProfile = Circle( bodyExternalR )
            nutChamfer = 0
        }

        val rubberT = 4 // the size of the rubber washer

        val stop = (Circle( bodyExternalR ) - Circle( midD / 2 + thickness ) ).extrude( thickness )

        val thread = (
            threaded.nut( bodyL-rubberT)
        ).bottomTo( stop.top )

        return thread + stop
    }

    override fun build() : Shape3d {
        val tube : Shape3d = tube()
        val body : Shape3d = body().mirrorZ()

        return tube + body
    }

}