summaryrefslogtreecommitdiff
path: root/cubbies.scad
diff options
context:
space:
mode:
Diffstat (limited to 'cubbies.scad')
-rw-r--r--cubbies.scad209
1 files changed, 209 insertions, 0 deletions
diff --git a/cubbies.scad b/cubbies.scad
new file mode 100644
index 0000000..9497c5e
--- /dev/null
+++ b/cubbies.scad
@@ -0,0 +1,209 @@
1include <BOSL2/std.scad>; // https://github.com/revarbat/BOSL2
2include <BOSL2/walls.scad>;
3include <BOSL2/fnliterals.scad>;
4include <BOSL2/joiners.scad>;
5
6$fn=20;
7
8part="both"; // [bottom::Bottom Only,side:Side Only,female_tabs:Holes only from side,male_tabs:Tabs only from bottom,view_fit:Debugging view to confirm tab fit,both:Bottom + Side]
9
10/* [Cubby dimensions] */
11cubby_width=40;
12cubby_depth=120;
13cubby_height=90;
14
15// thickness of bottom and side
16thickness=5;
17
18// thickness of struts (used in both bottom and side)
19strut_thickness=5;
20
21// If set (to non zero), this is used in the max_bridge paramater for the
22// sparse_struct BOSL 2 function (which generates the wireframe rectangles). By
23// default, it is calculated as max_bridge=(cubby_height + cubby_width)/5.
24max_bridge=0;
25
26/* [Tab Dimensions] */
27// width of each tab
28tab_width=10;
29// material between tabs
30tab_padding=5;
31// this value will be added to the mortises for additional tolerance
32tab_tolerance=0.5;
33
34/* [Screw Tabs] */
35screw_tabs=true;
36
37/* [Hidden] */
38tab_depth=thickness;
39tab_height=thickness;
40default_max_bridge=(cubby_height + cubby_width) / 5;
41
42if ( part == "both" ) {
43 both();
44} else if ( part =="bottom") {
45 cubby_bottom(cubby_width, cubby_depth);
46} else if ( part == "side" ) {
47 cubby_side(cubby_depth, cubby_height, screw_tabs);
48} else if ( part == "view_fit") {
49 view_tab_fit(cubby_width, cubby_depth, cubby_height);
50} else if ( part == "male_tabs" ) {
51 male_tabs(cubby_width, cubby_depth);
52} else if ( part == "female_tabs" ) {
53 female_tabs(cubby_depth, cubby_height);
54}
55
56function assert_cubby_width() =
57 let (min_width = strut_thickness + 1) // I'm not sure why I need the +1
58 assert(cubby_width >= min_width,
59 str("Cubby width must be atleast ", min_width, "mm"));
60
61function assert_cubby_depth() =
62 let (min_depth = tab_width * 2)
63 assert(cubby_depth >= min_depth,
64 str("Cubby width must be atleast ", min_depth, "mm"));
65
66function assert_cubby_height() =
67 let (min_height = cubby_side_bracket_height())
68 assert(cubby_height >= min_height,
69 str("Cubby width must be atleast ", min_height, "mm"));
70
71function double (x) = x * 2;
72function half (x) = x / 2;
73
74module both () {
75 gap=5;
76 cubby_bottom(cubby_width, cubby_depth);
77 left(((cubby_width + cubby_height) / 2) + (tab_height * 2) + gap)
78 cubby_side(cubby_depth, cubby_height, screw_tabs);
79}
80
81module cubby_bottom (width, depth) {
82 let (_=assert_cubby_width());
83 let (_=assert_cubby_depth());
84
85 rot(90) yrot(90) color("blue") bottom_wall() yrot(90) down(tab_height / 2) {
86 move_dist=(width / 2) + (tab_depth / 2);
87 fwd(move_dist)
88 alternating_tabs(false, "male", depth, tab_width,
89 tab_depth, tab_height, tab_padding, tab_tolerance);
90 back(move_dist)
91 alternating_tabs(true, "male", depth, tab_width,
92 tab_depth, tab_height, tab_padding, tab_tolerance);
93 }
94 children();
95 module bottom_wall () {
96 strut_wall(width, depth) children();
97 }
98}
99
100// this calculation needs to be referenced by the view_tab_fit function
101function cubby_side_bracket_height() = double(tab_height) + tab_tolerance;
102module cubby_side (depth, height, screw_tabs=true) {
103 let (_=assert_cubby_depth());
104 let (_=assert_cubby_height());
105
106 screw_tab_width=15;
107 screw_tab_height=20;
108 screw_tab_thickness=thickness;
109
110 yrot(-90) color("red") side_wall() {
111 if ( screw_tabs ) {
112 position(TOP+FRONT+LEFT) screw_tab();
113 up(screw_tab_height) position(BOTTOM+FRONT+LEFT) screw_tab();
114 }
115 attach(BOTTOM, TOP) zrot(90) tab_bracket();
116 attach(TOP, BOTTOM) zrot(90) tab_bracket();
117 }
118 children();
119
120 module side_wall () {
121 strut_wall(depth, height - cubby_side_bracket_height() * 2) children();
122 }
123
124 module tab_bracket () {
125 difference() {
126 cuboid([depth,thickness,cubby_side_bracket_height()]);
127 alternating_tabs(true, "female", depth, tab_width, tab_depth,
128 tab_height, tab_padding, tab_tolerance);
129 alternating_tabs(false, "female", depth, tab_width, tab_depth,
130 tab_height, tab_padding, tab_tolerance);
131 }
132 children();
133 }
134
135 module screw_tab () {
136 difference() {
137 cuboid([screw_tab_width, screw_tab_thickness,screw_tab_height],
138 anchor=LEFT+TOP);
139 right(screw_tab_width * (2 / 3)) zrot(90) yrot(90) {
140 right(screw_tab_height * (1 / 3)) cyl(l=15, r=2, anchor=RIGHT);
141 right(screw_tab_height * (2 / 3)) cyl(l=15, r=2, anchor=LEFT);
142 }
143 }
144 children();
145 }
146}
147
148module strut_wall(w, h) {
149 bridge=max_bridge ? max_bridge : default_max_bridge;
150 sparse_strut(
151 l=w,
152 h=h,
153 thick=thickness,
154 maxang=45,
155 strut=5,
156 max_bridge=bridge
157 ) children();
158}
159
160module male_tabs (w, d) {
161 keep=(w / 2) - thickness;
162 left_half(x=-keep) cubby_bottom(cubby_width, cubby_depth);
163}
164
165module female_tabs (d, h) {
166 // text inscribed (when printing tolerances)
167 text_inscription_depth=0.6;
168 text_size=thickness * 0.9;
169 text=str(tab_tolerance);
170 text_pos=[-h/2 + (thickness * 0.95),
171 -d / 2 + (thickness / 2),
172 (thickness / 2)];
173
174 xrot(180) left_half(x=(h / -2 + (thickness * 3)))
175 cubby_side(d, h, screw_tabs=false);
176 translate(text_pos) zrot(90) linear_extrude(text_inscription_depth)
177 color("green") text(size=text_size, text, font="Bitstream Vera Sans:style=Bold");
178}
179
180module view_tab_fit (w, d, h) {
181 // position for testing tab fit
182 module position_fit_test (left=true) {
183 cubby_bottom(w, d);
184 dist=(w / 2) + (thickness / -2) + tab_depth - 2;
185 down=half(h) - half(thickness) -
186 tab_height - half(tab_tolerance);
187 yflip() yrot(90) down(dist * (left ? 1 : -1)) left(down)
188 cubby_side(d, h, screw_tabs);
189 }
190
191 position_fit_test(left=true);
192 yrot(180) up(h) position_fit_test(left=false);
193}
194
195module alternating_tabs (first, gender, length, tab_width, tab_depth,
196 tab_height, tab_padding, tolerance) {
197 dist=length - (tab_padding * 2);
198 total_tabs=dist / (tab_width + tab_padding + tolerance);
199 half_tabs=total_tabs / 2;
200 tab_qty = total_tabs % 2 == 0 ? half_tabs : first ?
201 ceil(half_tabs) : floor(half_tabs);
202 start = first ? tab_padding : (tab_padding * 2) + tab_width;
203 spacing = (tab_width + tab_padding) * 2;
204 xcopies(spacing, tab_qty, dist, sp=((dist / -2) + start))
205 dovetail(gender, angle=0, slide=add_tol(tab_depth),
206 width=add_tol(tab_width), height=add_tol(tab_height));
207
208 function add_tol (x) = gender == "male" ? x : x + tolerance;
209}