import static uk.co.nickthecoder.foocad.extend.v1.Extend.* import uk.co.nickthecoder.foocad.hinge.v1.* import uk.co.nickthecoder.foocad.extras.v1.* import static uk.co.nickthecoder.foocad.extras.v1.Extras.* 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 static uk.co.nickthecoder.foocad.layout.v1.Layout2d.* import static uk.co.nickthecoder.foocad.layout.v1.Layout3d.* include ComponentOrganiser.foocad class ComponentOrganiserCase: Model { @Custom var size = Vector2( 4, 4 ) @Custom var baseThickness = 1.2 @Custom var thickness = 1.2 @Custom var lipSize = Vector2(1.2, 6) @Custom var hinge = Hinge( 40 ).chamfer(0.5) @Custom var lidThickness = 1.2 @Custom var lidClearance = 0.2 // The same diameter bolt is also used for the handle (but the length is different). @Custom( about="Defines the bolt length & diameter and the distance of the latch" ) var hingedLatch = HingedLatch() .boltSize( Vector2(20, 3.9) ) .distance( 24 ) // Original was 25. .ribSize( Vector3(3, 6, 35) ) .chamfer(0.5) //.realBolt(true) // Uncomment to test the alignment of the holes. @Custom var handleSize = Vector3( 100, 33, 8 ) meth handleHinge() = Hinge( handleSize.z * 2 ) .innerDiameter( hingedLatch.boltSize.y ) .outerDiameter( handleSize.z + 2 ) .chamfer(0.5) meth componentOrganiser() = ComponentOrganiser().apply { drawerX = size.x drawerY = size.y } meth internalSize() : Vector2 { val co = componentOrganiser() return Vector2( size.x * co.unitWidth + (size.x-1) * co.insertGap, size.y * co.unitDepth + (size.y-1) * co.insertGap ) } meth insideShape() : Shape2d { return Square( internalSize() ) .roundAllCorners(4) .center() } meth hingePositionFromBoxTop() = -1 @Piece meth box() : Shape3d { val co = componentOrganiser() val bottomPattern = co.drawerBottom().centerXY().bottomTo( baseThickness ).color("Green") val inserts = co.insert(1,1) .tileX( size.x, co.insertGap ) .tileY( size.y, co.insertGap ) .centerXY() .previewOnly() .bottomTo( bottomPattern.top ) val inside = insideShape() val outside = inside.offset( thickness ) val lip = ProfileEdge.chamferedStep( lipSize.x, lipSize.y ).reverse() and ProfileEdge.chamfer(0.5) val height = baseThickness + bottomPattern.size.z + co.unitHeight val box = outside .cup( height, thickness ) .baseThickness( baseThickness ) .bottom( Chamfer( 1 ) ) .outsideTop( lip ) .label("plainBox") println( "Plain case = $box" ) val hinges = hinge.forBox( outside.back, height + hingePositionFromBoxTop() ) .centerXTo( inside.left + hinge.length*0.8 ) .mirrorX().also().withCavities() val latchRibs = hingedLatch.ribs() .centerXTo( inside.left + 30 ) .translateZ( height - hingedLatch.distance -2.5) // Positioned by eye. .backTo( outside.front + hingedLatch.chamfer ) .label( "latchRibs" ) .mirrorX().also() //println( "Handle bolt length = ${latchRibs.find("latchRibs").size.x}" ) val handleHinge = handleHinge().forBox( 0, box.top/2 + 6 ) .mirrorY() val handleMount = Square( handleHinge.size.x + 4, height-2 ).centerX() .smartExtrude( lipSize.x ) .top( Chamfer(lipSize.x) ) .rotateX(90) .backTo( outside.front ) .bottomTo( 1 ) .translateX( handleSize.x / 2 - handleSize.z/2 ) val forHandle = ( handleMount + handleHinge .centerXTo( handleMount.middle.x ) .backTo( handleMount.front + handleHinge().chamfer ) ).label("forHandle").mirrorX().also() println( "box and hinges.find = ${(box and hinges).find("plainBox")}" ) return (box and hinges) + latchRibs + bottomPattern + forHandle // + inserts } @Piece meth lid() : Shape3d { val co = componentOrganiser() val inside = insideShape() val outside = inside.offset( thickness ) val boxShape = outside.offset( lipSize.x ) val chamfer = 1 val lip = ProfileEdge.chamferedStep( lipSize.x, lipSize.y ).reverse() and ProfileEdge.chamfer(0.5) val height = lidThickness + lipSize.y val cup = boxShape.offset( lidThickness + 1 ) .cup( height, 1 ) .baseThickness( lidThickness ) .bottom( Chamfer( chamfer ) ) val lid = cup - Cube( cup.size.x, cup.size.y, cup.size.y ) .centerX() .rotateX(45) .translateY( cup.back ) val hinges = hinge.forLid( outside.back, lidThickness + lidClearance - hingePositionFromBoxTop() ) .centerXTo( inside.left + hinge.length*0.8 ) .mirrorX().also().withCavities() val pattern = co.lidPattern() .extrude(2) // Original was 3. .bottomTo( lidThickness ) val latchMount = Square( hingedLatch.hinge().length + 6, 2 + chamfer) .roundCorner( 1, chamfer,1 ) .roundCorner( 0, chamfer,1 ) .centerX() .smartExtrude( height ) //.edges( Chamfer( chamfer/2 ) ) .backTo( lid.front + chamfer ) val latchHinges = ( hingedLatch.forLid( latchMount.front+chamfer, height-2 ) and latchMount ) .centerXTo( inside.left + 30 ) .mirrorX().also() return ((lid and hinges and latchHinges ) + pattern) } @Piece meth handle() : Shape3d { val handleHinge = handleHinge() val shape = PolygonBuilder().apply { moveTo( 0, handleSize.z/2 ) radius(10) lineBy( 0, -handleSize.y + handleSize.z/2 ) lineBy( handleSize.x - handleSize.z, 0 ) radius(0) lineBy( 0, handleSize.y - handleSize.z/2 ) }.buildPath().thickness( handleSize.z ).centerX() val main = shape.smartExtrude( handleSize.z ) .bottom( ProfileEdge.roundedChamfer( handleSize.z/2 ) ) .top( Fillet( handleSize.z/2-1) ) val holes = Circle( handleHinge.innerDiameter/2 + 0.2 ).safeOverhang().rotate(90) .extrude( handleSize.x + 2 ) .rotateY(90) .centerX() .centerZTo( handleSize.z / 2 ) return main - holes } @Piece @Slice( seamPosition="rear" ) meth latch() = hingedLatch.latch() @Piece( printable=false ) override meth build() : Shape3d { val box = box() val plainBox = box.find("plainBox") val axis = Vector3( 0, box.back - hinge.outerDiameter/2, box.size.z - hinge.outerDiameter/2) val lid = lid().mirrorZ() .topTo( plainBox.top + lidThickness + lidClearance ) .color("Green") val latches = latch() .rotateZ(4 - 0) // 4° is the closed position. .rotateX(90).rotateZ(90) .translateY( box.front+4 ) .centerXTo( box.left + 32.5 ) .translateZ( lid.top - 4 ) .mirrorX().also() .color("Violet") val handle = handle().rotateX(90) .backTo( plainBox.front - 1 ) .bottomTo(2) .color("lightBlue") val rotatedLid = (lid + latches).rotateAxisAbout( 60, Vector3( 1,0,0 ), axis ) return box + rotatedLid + handle } }