import static uk.co.nickthecoder.foocad.layout.v1.Layout2d.* import static uk.co.nickthecoder.foocad.layout.v1.Layout3d.* import uk.co.nickthecoder.foocad.smartextrusion.v1.* import static uk.co.nickthecoder.foocad.smartextrusion.v1.SmartExtrusion.* import uk.co.nickthecoder.foocad.threaded.v2.* import uk.co.nickthecoder.foocad.screws.v3.* class BikeRackQuickRelease : Model { @Custom var camSize = Vector3( 50, 25, 3 ) @Custom var rackDiameter = 9 @Custom var blockSize = Vector2( 40, 20 ) @Custom var clearance = 0.5 @Custom var leverSize = Vector2( 10, 60 ) //35 ) // was ,60 @Custom var countersink = Countersink( 5, 10 ) @Custom var thread = Thread( 10 ) .headSize( Vector2( 18, 3 ) ) var runnerSize = Vector3( 70, 12, 2 ) var runnerBlockSize = Vector3( 0, 14, 4 ) meth stop( height : float ) : Shape3d { return Square( 10, 5 ) .roundAllCorners(1) .backTo(0) .smartExtrude( height ) .top( Fillet( 1 ) ) .bottom( Fillet( -2, 3 ) ) .bottomTo( camSize.z ) } meth cam( plain : bool ) : Shape3d { val holeRadius = if (plain) 2 else shaftDiameter()/2 + clearance val distance = blockSize.y/2 val leverAngle = 40 val centerP = Circle( distance ) val holeP = Circle( holeRadius ) val camP = Square( camSize.x, camSize.y ) .roundAllCorners( 8 ) .rightTo( distance ) .hull( centerP ) val leverEnd = Circle(leverSize.x/2) .translateY(-leverSize.y) .rotate(-leverAngle) val leverP = centerP.hull( leverEnd ) val main = (camP + leverP - holeP ) .smartExtrude( camSize.z ) .edges( Chamfer( Math.min( 1, camSize.z/3 ) ) ) val stop = stop( 5 ) .rotateZ(-90) .translate( -blockSize.y/2-clearance, -blockSize.y/2 - clearance, 0 ) return if (plain) main else main + stop } @Piece meth cam() = cam( false ) @Piece meth cam2() = cam( true ) meth shaftDiameter() = thread.diameter + 4 @Piece meth block() = blockUpright().rotateX(180).bottomTo(0) @Piece( print="block" ) meth blockUpright() : Shape3d { val countersink = countersink.recess( rackDiameter - 4 ) val main = Square( blockSize ) .roundAllCorners(3) .center() .smartExtrude( rackDiameter - clearance ) .bottom( Fillet(2) ) val holes = countersink .mirrorZ() .translateX( blockSize.x * 0.3 ) .mirrorX().also() val threadedHole = thread.threadedHole( main.size.z ) return (main - holes - threadedHole).color("Green") } @Piece( about="In case `block` is too short, use this to make it taller by 1mm" ) fun shim() = block().intersection( Cube( 100, 100, 0.1 ).centerXY() ) .scaleZ(10) @Piece meth bolt() : Shape3d { val bolt = thread.bolt( rackDiameter + camSize.z -clearance ) .bareLength( camSize.z + clearance ) val collar = Cylinder( camSize.z + clearance, shaftDiameter()/2 ) .bottomTo( thread.headSize.y ) return (bolt + collar).color("Orange") } @Piece meth runner() : Shape3d { val profile = Square( runnerSize.z + runnerBlockSize.z, runnerSize.y + runnerBlockSize.y ) - Square( runnerBlockSize.z, runnerSize.y ) .roundCorner(2,runnerBlockSize.z) .toPolygon() val main = profile .extrude( runnerSize.x ) .rotateY(90) .bottomTo(0) .centerXY() val envelope = Square( runnerSize.x, runnerSize.y + runnerBlockSize.y ) .roundAllCorners( 4 ) .extrude( runnerSize.z + runnerBlockSize.z + 2 ) .centerXY().bottomTo(-1) val holes = countersink.mirrorZ() .spreadX(3,main.size.x, 0.25) .centerX() //.centerYTo(main.back - runnerBlockSize.y/2) .frontTo( main.front + runnerSize.y ) return main.intersection( envelope ) - holes } override fun build() : Shape3d { val cam = cam() val cam2 = cam.rotateZ(90).translateZ(0.1).previewOnly() val rack = Cylinder( 100, rackDiameter/2 ) .center() .rotateY(90) .frontTo( blockSize.y/2 ) .bottomTo( camSize.z ) .previewOnly() val block = blockUpright().topTo(rack.top) val bolt = bolt().bottomTo( -thread.headSize.y )//.translateZ(-30) val board = Cube( 100, 50, 12 ) .centerXY().bottomTo(rack.top) .previewOnly() return cam + block + bolt + cam2 // + rack + board } }