/Bottles/Funnel.foocad

A funnel which screws onto the top of a container.
The default thread is compatable with UK milk bottles.
import uk.co.nickthecoder.foocad.smartextrusion.v1.*
import static uk.co.nickthecoder.foocad.smartextrusion.v1.SmartExtrusion.*
import uk.co.nickthecoder.foocad.cup.v1.*
import static uk.co.nickthecoder.foocad.cup.v1.Cup.*
import uk.co.nickthecoder.foocad.threaded.v2.*
include Bottle.foocad
class Funnel : Model {
@Custom
val size = Vector3( 160, 100, 120 )
@Custom
var length : double = 10
@Custom
var round = 20
@Custom( about="The default thread is compatible with the UK milk bottles" )
var thread = Thread( 39, 5 )
@Custom
var wallThickness = 1.8
meth cap() : Shape3d {
val capHeight = 12
val solid = Circle( thread.diameter/2 + 3 )
.cup( capHeight, 6 ).baseThickness(wallThickness)
.outsideBottom( ProfileEdge.roundedChamfer(3) )
.insideBottom( Chamfer(wallThickness) )
.outsideTop( Chamfer(1) )
val hole = thread.threadedHole( solid.top - wallThickness*1.5 )
.chamferStart(false)
.chamferEnd(true)
.bottomTo( wallThickness*1.5 )
return solid - hole
}
@Piece
@Slice( brimWidthInterior = 5 )
meth funnel() : Shape3d {
val rimHeight = 6
val neckDiameter = thread.coreRadius()*2 - 4
var throatDiameter = neckDiameter - wallThickness*2
val size2d = Vector2( size.x, size.y )
val cap = cap().topTo( size.z - length )
val wideNeck = (Circle( cap.size.x/2 - 0.55 ) - Circle( throatDiameter/2 ) )
.smartExtrude( 30 )
//.offsetBottom( 0 )
.topTo( cap.bottom + wallThickness*1.5 )
val lip = (Circle( neckDiameter/2 ) - Circle( throatDiameter/2 ))
.smartExtrude( cap.size.z + length )
.outsideTop( Chamfer(1) )
.bottomTo( cap.bottom )
val capHole = Circle( throatDiameter/2 )
.extrude( wallThickness *2 )
.bottomTo( cap.bottom-0.01 )
val squarish = Square( size2d ).center().roundAllCorners(round )
val rim = (squarish - squarish.offset( -wallThickness ))
.smartExtrude(rimHeight)
.outsideBottom( ProfileEdge.chamfer(1).reverse() and ProfileEdge.flat(4) and ProfileEdge.chamfer(0.6) )
val main = Bottle.extrudeRoundedSquareToCircle( cap.bottom - rim.top, size2d, round, neckDiameter )
.bottomTo( rim.top )
//.color("Orange")
val insideMain = Bottle.extrudeRoundedSquareToCircle( cap.bottom - rim.top +0.02, size2d, round, neckDiameter, -wallThickness )
.bottomTo( rim.top - 0.01 )
return rim + main + cap + wideNeck - insideMain - capHole + lip
}
@Piece( about="Test fit for the cap." )
meth test() : Shape3d {
length = -5
val all = funnel()
return all.translateZ( 4- size.z ) - Cube( 1000 ).centerXY().topTo(0)
}
override fun build() : Shape3d {
return funnel()
}
}

