cassetta_atrezzi_auto/cassetta_atrezzi_auto.py
1from cadquery import Assembly, Workplane, Color, Vertex, Vector
2from cadquery.selectors import AreaNthSelector
3
4BOX_LENGTH = 240
5BOX_WIDTH = 180
6BOX_DEPTH = 20
7BORDER_RADIUS = 20
8CHAMFER_SIZE = 2
9WALL_THICKNESS = 2
10EDGE_DEPTH = 5
11REINFORCEMENT_WIDTH = 20
12TOL = 0.001
13LATCH_CANTILEVER = 12
14LATCH_WIDTH = 6
15SCREW_LENGTH = 40
16SCREW_DIAMETER = 4
17SCREW_NUT_DIAMETER = 7
18SCREW_NUT_DEPTH = 3
19
20
21def box_walls(
22 length: float,
23 width: float,
24 depth: float,
25 border_radius: float,
26 thickness: float = 0,
27 chamfer_size: float = 0,
28) -> Workplane:
29 box = Workplane("XY").box(length, width, depth).edges("|Z").fillet(border_radius)
30 if chamfer_size > 0:
31 box = box.edges("<Z").chamfer(chamfer_size)
32 if thickness > 0:
33 box = box.faces(">Z").shell(-thickness)
34 return box
35
36
37def box_edge(
38 length: float,
39 width: float,
40 depth: float,
41 thickness: float,
42 border_radius: float,
43 chamfer_size: float,
44 inset_depth: float = 2,
45) -> Workplane:
46 inset = (
47 Workplane("XY")
48 .box(length + chamfer_size, width + chamfer_size, inset_depth)
49 .edges("|Z")
50 .fillet(border_radius + chamfer_size)
51 .faces(">Z or <Z")
52 .shell(-thickness)
53 .translate((0, 0, depth / 2))
54 .faces("<Z")
55 .chamfer(thickness / 2 - TOL)
56 )
57 return (
58 Workplane("XY")
59 .box(length + 2 * chamfer_size, width + 2 * chamfer_size, depth)
60 .edges("|Z")
61 .fillet(border_radius + chamfer_size)
62 .faces(">Z or <Z")
63 .shell(-(thickness + chamfer_size))
64 .faces("<Z")
65 .wires(AreaNthSelector(1))
66 .chamfer(chamfer_size)
67 - inset
68 )
69
70
71def latch_side(
72 depth: float,
73 height: float,
74 width: float,
75 screw_length: float,
76 screw_diameter: float,
77 screw_nut_diameter: float,
78 screw_nut_depth: float,
79) -> Workplane:
80 return (
81 Workplane("YZ")
82 .lineTo(0, height)
83 .lineTo(depth, height)
84 .lineTo(depth, depth)
85 .close()
86 .extrude(width)
87 .edges("|X and >Y and >Z")
88 .fillet(depth / 5)
89 .edges("|X and >Y and (not >Z)")
90 .fillet(depth / 2)
91 .edges("|Z and (not <Y)")
92 .chamfer(depth / 10)
93 .faces("<X")
94 .workplane()
95 .center(-depth / 2, height - screw_nut_diameter / 2 - 1.5)
96 .cboreHole(screw_diameter, screw_nut_diameter, screw_nut_depth)
97 )
98
99
100def latch_holder(
101 cantilever: float,
102 height: float,
103 width: float,
104 screw_length: float,
105 screw_diameter: float,
106 screw_nut_diameter: float,
107 screw_nut_depth: float,
108) -> Workplane:
109 separation = screw_length + screw_nut_depth - width
110 return (
111 latch_side(
112 cantilever,
113 height,
114 width,
115 screw_length,
116 screw_diameter,
117 screw_nut_diameter,
118 screw_nut_depth,
119 )
120 + latch_side(
121 cantilever,
122 height,
123 width,
124 screw_length,
125 screw_diameter,
126 screw_nut_diameter,
127 screw_nut_depth,
128 )
129 .mirror("YZ")
130 .translate((separation, 0, 0))
131 ).translate((-separation / 2, 0, 0))
132
133
134def assembly() -> Assembly:
135 _box_walls = box_walls(
136 BOX_LENGTH,
137 BOX_WIDTH,
138 BOX_DEPTH - EDGE_DEPTH,
139 BORDER_RADIUS,
140 WALL_THICKNESS,
141 CHAMFER_SIZE,
142 )
143 _box_edge = box_edge(
144 BOX_LENGTH,
145 BOX_WIDTH,
146 EDGE_DEPTH,
147 WALL_THICKNESS,
148 BORDER_RADIUS,
149 CHAMFER_SIZE,
150 )
151 _latch = latch_holder(
152 LATCH_CANTILEVER,
153 BOX_DEPTH - CHAMFER_SIZE,
154 LATCH_WIDTH,
155 SCREW_LENGTH,
156 SCREW_DIAMETER,
157 SCREW_NUT_DIAMETER,
158 SCREW_NUT_DEPTH,
159 )
160
161 front_center = _box_walls.faces(">Y").val().Center()
162 return (
163 Assembly()
164 .add(_box_walls, name="box_walls", color=Color("gray90"))
165 .add(_box_edge, name="box_edge", color=Color("gray70"))
166 # .add(reinforcements, name="reinforcements", color=Color("gray50"))
167 .add(_latch, name="latch", color=Color("gray30"))
168 # Fix edge on top of box
169 .constrain("box_walls@faces@>Z", "box_edge@faces@<Z", "Plane")
170 .constrain("box_edge@faces@<Z", "FixedRotation", (0, 0, 0))
171 # Fix latch-holder on front of box
172 .constrain(
173 "box_walls",
174 Vertex.makeVertex(*front_center + Vector(0, 0, EDGE_DEPTH)),
175 "latch",
176 _latch.faces("<Y").val(),
177 "Point",
178 )
179 .constrain("box_walls@faces@>Y", "latch@faces@<Y", "Plane")
180 .constrain("latch@faces@<Y", "FixedRotation", (0, 0, 0))
181 .solve()
182 )
183
184
185bottom_part = assembly()