import uk.co.nickthecoder.foocad.smartextrusion.v1.* import static uk.co.nickthecoder.foocad.smartextrusion.v1.SmartExtrusion.* import static uk.co.nickthecoder.foocad.layout.v1.Layout2d.* import static uk.co.nickthecoder.foocad.layout.v1.Layout3d.* import uk.co.nickthecoder.foocad.extras.v1.* import static uk.co.nickthecoder.foocad.extras.v1.Extras.* import uk.co.nickthecoder.foocad.cup.v1.* import static uk.co.nickthecoder.foocad.cup.v1.Cup.* class JigsawOrganiser : Model { @Custom var unitSize = Vector2( 55/2, 40 ) @Custom var lugDepth = 4 @Custom var round = 1 @Custom var thickness = 1.2 @Custom var baseThickness = thickness // 0.20 for a VERY tight fit - slight elephant's foot makes it too tight. @Custom var clearance = 0.30 @Custom var height = 50.0 @Custom var flatSides = "" @Custom var lipSize = Vector2(1,2) meth maleShape() = maleShape( 12 ) meth maleShape( width : double ) = lugShape( width, true ) meth femaleShape( width : double ) = lugShape( width, false ) meth lugShape( width : double, isMale : bool ) : Shape2d { val femaleOffset = if (isMale) 0 else clearance val inside = Square( width + lugDepth*2, 4 ).backTo(0).centerX() val outside = Trapezium( width + femaleOffset*2, lugDepth ).angle(20).centerX() val both = (inside + outside).toPolygon() val round1 = lugDepth*0.15 - femaleOffset/2 val round2 = lugDepth*0.2 + femaleOffset/4 return both .roundCorner( 3, round1,4 ) .roundCorner( 2, round2 ) .roundCorner( 1, round2 ) .roundCorner( 0, round1,4 ) } meth bin( across : int, down : int, height : double ) = bin( across, down, height, "" ) meth bin( across : int, down : int, height : double, flatSides : String ) : Shape3d { val basic = Square( unitSize.x * across, unitSize.y * down ) .center() .roundAllCorners(round) val back = if (flatSides.contains("b")) null else maleShape( unitSize.x/3 ).repeatX(across, unitSize.x).centerX().translateY(basic.back) val front = if (flatSides.contains("f")) null else femaleShape( unitSize.x/3 ).repeatX(across, unitSize.x).centerX().translateY(basic.front) val right = if (flatSides.contains("r")) null else maleShape( unitSize.y/3 ).rotate(-90).repeatY(down, unitSize.y).centerY().translateX(basic.right) val left = if (flatSides.contains("l")) null else femaleShape(unitSize.y/3).rotate(-90).repeatY(down, unitSize.y).centerY().translateX( basic.left ) val shape = (basic + back + right - front - left).toPolygon() val topEdge = ProfileEdge.chamfer(lipSize.x/2).reverse() .and( ProfileEdge.flat(lipSize.y) ) .and( ProfileEdge.chamfer(lipSize.x/2) ) val cup = shape.cup( height, thickness ) .baseThickness(baseThickness) .insideBottom( Fillet(0.5) ) .outsideBottom( Chamfer(0.5) ) .insideTop( topEdge ) .outsideTop( Chamfer(lipSize.x/2) ) return cup } @Piece meth bin1x1() = bin( 1,1, height, flatSides) @Piece meth bin1x2() = bin( 1,2, height, flatSides ) @Piece meth bin1x3() = bin( 1,3, height, flatSides ) @Piece meth bin1x4() = bin( 1,4, height, flatSides ) @Piece meth bin1x5() = bin( 1,5, height, flatSides ) @Piece meth bin1x6() = bin( 1,6, height, flatSides ) @Piece meth bin2x1() = bin( 2,1, height, flatSides ) @Piece meth bin2x2() = bin( 2,2, height, flatSides ) @Piece meth bin2x3() = bin( 2,3, height, flatSides ) @Piece meth bin2x4() = bin( 2,4, height, flatSides ) @Piece meth bin2x5() = bin( 2,5, height, flatSides ) @Piece meth bin2x6() = bin( 2,6, height, flatSides ) @Piece meth bin3x1() = bin( 3,1, height, flatSides ) @Piece meth bin3x2() = bin( 3,2, height, flatSides ) @Piece meth bin3x3() = bin( 3,3, height, flatSides ) @Piece meth bin3x4() = bin( 3,4, height, flatSides ) @Piece meth bin3x5() = bin( 3,5, height, flatSides ) @Piece meth bin3x6() = bin( 3,6, height, flatSides ) @Piece meth bin4x1() = bin( 4,1, height, flatSides ) @Piece meth bin4x2() = bin( 4,2, height, flatSides ) @Piece meth bin4x3() = bin( 4,3, height, flatSides ) @Piece meth bin4x4() = bin( 4,4, height, flatSides ) @Piece meth bin4x5() = bin( 4,5, height, flatSides ) @Piece meth bin4x6() = bin( 4,6, height, flatSides ) @Piece meth bin5x1() = bin( 5,1, height, flatSides ) @Piece meth bin5x2() = bin( 5,2, height, flatSides ) @Piece meth bin5x3() = bin( 5,3, height, flatSides ) @Piece meth bin5x4() = bin( 5,4, height, flatSides ) @Piece meth bin5x5() = bin( 5,5, height, flatSides ) @Piece meth bin5x6() = bin( 5,6, height, flatSides ) @Piece meth bin6x1() = bin( 6,1, height, flatSides ) @Piece meth bin6x2() = bin( 6,2, height, flatSides ) @Piece meth bin6x3() = bin( 6,3, height, flatSides ) @Piece meth bin6x4() = bin( 6,4, height, flatSides ) @Piece meth bin6x5() = bin( 6,5, height, flatSides ) @Piece meth bin6x6() = bin( 6,6, height, flatSides ) @Piece meth bin7x1() = bin( 7,1, height, flatSides ) @Piece meth bin7x2() = bin( 7,2, height, flatSides ) override fun build() : Shape3d { val big = bin(2,2, 60) val thin = bin(1,2, 50, "l") val shallow = bin(2,1, 50, "f") val bigFour = big .translateX( unitSize.x*2 + clearance/2 ).also() .translateY( unitSize.y*2 + clearance/2 ).also() val thinTwo = thin.translateX( - unitSize.x*1.5 - clearance/2 ) .translateY(unitSize.y*2 + clearance/2 ).also() val shallowTwo = shallow .translateY( -unitSize.y * 1.5 - clearance/2 ) .translateX( unitSize.x*2 + clearance/2 ).also() val unit = bin(1,1, 40, "lf").leftTo( thinTwo.left ).frontTo( shallowTwo.front ) return bigFour + thinTwo + shallowTwo + unit } }