import static uk.co.nickthecoder.foocad.along.v2.Along.* 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.* import static uk.co.nickthecoder.foocad.screws.v1.Screws.* class SpoolPost : Model { @Custom var bearingD = 22.0 @Custom var bearingD2 = 8.0 @Custom var bearingT = 7.0 @Custom var slack = 0.3 @Custom var guideH = 3 @Custom var rodD = 25.0 @Custom var axisT = 5.0 @Custom var axisLength = 10 @Custom var axisExtra = 2.0 fun bearing() : Shape3d { return (Circle( bearingD/2 ) - Circle( bearingD2 / 2 )).extrude( bearingT ).previewOnly() } @Piece fun endGuide() : Shape3d { val baseHeight = 3 val width = bearingD + axisT*2 var baseP = Circle( width / 2 ) - (Square( width ).centerY().rightTo(0)) + Square( width/2 + guideH, width ).centerY() - Circle( 14/2 ) val guideP = baseP - Square( width + 1 ).centerY().rightTo(0) - Circle( bearingD/2 + slack ) val result = baseP.extrude( baseHeight ) + guideP.extrude( bearingT ).bottomTo( baseHeight ) return result.color( "Red" ) + bearing().bottomTo( baseHeight ) } @Piece fun rodAxis() : Shape3d { return ExtrusionBuilder().apply { forward( axisLength ) crossSection( Circle.hole( rodD / 2 ) ) forward( -axisLength ) crossSection() crossSection( Circle.hole( rodD / 2 + axisT ) ) forward( axisLength + axisExtra ) crossSection() crossSection( Circle( bearingD2/2 + 2 ) ) forward( 1 ) crossSection() crossSection( Circle( bearingD2/2 ) ) forward( bearingT ) crossSection() }.build().color( "Orange" ) } @Piece fun all() : Shape3d { return layoutY( 1, rodAxis().leftTo(1).mirrorX().also(), endGuide().translateX(1).mirrorX().also() ) } var postSize = Vector2( 39, 23 ) var bracketT = 10 var bracketAngle = 2 @Piece fun wallBracket() : Shape3d { val height = bracketT * 2 + postSize.y val backT = bracketT val inset = 35 val width = inset + backT val profile = PolygonBuilder().apply { moveTo(0,0) radius(3) lineTo( backT + inset, 0 ) lineBy( 0, bracketT ) lineBy( -inset, 0 ) lineBy( 0, postSize.y ) lineBy( inset, 0 ) lineBy( 0, bracketT ) lineBy( -inset, 0 ) radius(0) lineBy( -backT, 0 ) }.build() // Tilt it slightly, so that the wood points "upwards", never "downwards". .rotate(bracketAngle) / Square( 100 ) val body = profile.extrude( postSize.x ) val hole = Cylinder(bracketT+5, 7/2).rotateX(90).rotateZ(bracketAngle) .leftTo(body.right-16).frontTo(-1).centerZTo(body.size.z/2) val screwHoles = countersink( 4, 8, 4, 100 ) .rotateY(90)//.centerZTo(body.size.z/2) .tileZ(2,body.size.z*0.4).centerZTo( body.size.z/2 ) .translateY( bracketT + postSize.y/2 ) .rightTo( backT + 1 ) //.centerYTo(profile.size.y - extra/2).also() val end = Hull2d(profile).chamferedExtrude(2,1,0).topTo(0).color("Green") val main = (body - hole - screwHoles) + end return main.bottomTo(0) + end.mirrorZ().bottomTo(0).rightTo(-2) } /** Taper a wooden lolly stick, and insert it to form an end stop, so that the spool can never jump off. */ @Piece fun endStop() : Shape3d { val thickness = 1.2 val main = Square( endStopSize.x + 10, endStopSize.y + thickness *2) .roundCorner(1,3).roundCorner(0,3) .extrude( endStopSize.z ) .centerXY() val hole = Square( endStopSize.x, endStopSize.y ).center().extrude( main.size.z, 0.9 ) return (main - hole) //.rotateX(90).bottomTo(0) } var endStopSize = Vector3( 9.6, 2.6, 14 ) override fun build() : Shape3d { val endGuide = endGuide() val axis = rodAxis().mirrorZ().bottomTo( endGuide.top + 2 ) val rod = Cylinder( 100, rodD/2 ).bottomTo( axis.top + 2 ) val axis2 = axis.mirrorZ().bottomTo( rod.top + 2 ) val endGuide2 = endGuide.bottomTo( axis2.top ) val wood = Cube( 10, endGuide2.size.y, endGuide2.top ) .leftTo( endGuide.right ) .centerY() val spool1 = (Cylinder( 5, 100 ).translateZ( 80 ).also() + Cylinder( 80, 70 )) - Cylinder( 200, 35 ) val spool = spool1.center().alongX().leftTo( rod.left + 10 ).translateZ(-25).previewOnly() return (endGuide + axis + rod + axis2 + endGuide2 + wood).rotateY(90) } }