chiark / gitweb /
fairphone-case: struts adj from cura
[reprap-play.git] / fairphone-case.scad
1 // -*- C -*-
2
3 phone_height = 146.5 - .80;
4 phone_width = 76.75;
5
6 phone_cnr_rad = 6.0;
7
8 phone_edge_thick = 9.0;
9 phone_total_thick = 12.0;
10 phone_backside_slope_inner = 1.5; // larger means shallower
11 phone_backside_slope_outer = 1.0; // larger means shallower
12
13 camera_pos_tl = [  7.0, 13.0 ]; // measured from tl corner
14 camera_pos_br = [ 24.0, 39.5 ]; // tl/br as seen from back
15
16 case_th_bottom = 2.5;
17 case_th_lid = 2.5;
18 case_th_side = 2;
19 case_th_lip = 1.2;
20
21 case_struts_count = 6;
22 case_struts_solid_below = 0.75;
23 case_struts_solid_above = 1.00;
24 case_struts_width = 0.10;
25
26 keeper_th_z = 0.75;
27 keeper_th_x = 0.75;
28 keeper_inner_width = 1.75;
29 keeper_inner_height = 1.75;
30
31 keeper_gap_z_top = 0.25;
32 keeper_gap_z_bot = 0.75;
33 keeper_gap_x     = 0.25;
34 keeper_gap_x_holes = 0.75;
35
36 case_lip = 1.25;
37
38 lid_gap_x = 0.25;
39 lid_gap_z = 0.25;
40 lid_lip = 1.75;
41
42 $fa = 5;
43 $fs = 0.1;
44
45 // calculated
46
47 phone_backside_slope_thick = phone_total_thick - phone_edge_thick;
48
49 //lid_lip_overlap_width xxx bad name = ;
50 //lid_lip_inner_slope = [ 5, 5 ]; // xxx
51
52 epp0 = [0,0];
53 epp1 = [0, -phone_edge_thick];
54 epp2i = epp1 + phone_backside_slope_thick * [ phone_backside_slope_inner, -1 ];
55 epp2o = epp1 + phone_backside_slope_thick * [ phone_backside_slope_outer, -1 ];
56 epp3 = epp2i + [10, 0];
57 epp5 = epp0 + [0,1] * (keeper_th_z + keeper_gap_z_top + case_lip);
58 epp4 = epp5 + [-1,0] * case_th_side;
59
60 kppe = [0,0];
61 kppd = kppe + [1,0] * keeper_inner_width;
62 kppc = kppd + [0,1] * keeper_th_z;
63 kppb = [ kppe[0] - keeper_th_x, kppc[1] ];
64 kppf = kppe - [0,1] * keeper_inner_height;
65 kppa = [ kppb[0], kppf[1] ];
66
67 lpp10 = [ epp5[0] + lid_gap_x, kppc[1] + lid_gap_z ];
68 lpp11 = [ lpp10[0],            epp5[1] + lid_gap_z ];
69 lpp12 = [ epp4[0] + lid_lip,   lpp11[1] ];
70 lpp13 = [ lpp12[0],            lpp12[1] + lid_lip ];
71
72 module rectfromto(a,b) {
73   ab = b - a;
74   translate([min(a[0], b[0]), min(a[1], b[1])])
75     square([abs(ab[0]), abs(ab[1])]);
76 }
77 module circleat(c,r) { translate(c) circle(r); }
78
79 module KeeperProfile(){
80   polygon([kppe, kppd, kppc, kppb, kppa, kppf]);
81 }
82
83 module EdgeProfile(){
84   difference(){
85     hull(){
86       translate(epp3) square(case_th_bottom*2, center=true);
87       circleat(epp2o, r=case_th_bottom);
88       circleat(epp1, r=case_th_side);
89       rectfromto(epp0, epp4);
90     }
91     polygon([ epp5 + [0,10],
92               epp1,
93               epp2i,
94               epp3 + [10,0] ]);
95   }
96 }
97
98 module LidEdgeProfile(){
99   polygon([ lpp10,
100             lpp11,
101             lpp12,
102             lpp13,
103             lpp13 + [10, 0],
104             lpp10 + [10, 0]
105             ]);
106   intersection(){
107     circleat(lpp12, r=lid_lip);
108     rectfromto( lpp12 + [-10,   0],
109                 lpp12 + [+10, +10] );
110   }
111 }
112
113 module CaseBase_rhsflip(yn=[0,1]) {
114   for (rhs=yn) {
115     translate([phone_width/2, 0, 0])
116       mirror([rhs,0,0])
117       translate([-phone_width/2, 0, 0])
118       children();
119   }
120 }
121
122 module CaseBase_botflip() {
123   for (bot=[0,1]) {
124     translate([0, -phone_height/2, 0])
125       mirror([0, bot, 0])
126       translate([0, phone_height/2, 0])
127       children();
128   }
129 }  
130
131 module AroundEdges(fill_zstart, fill_th, fill_downwards=0){
132   // sides
133   CaseBase_rhsflip(){
134     translate([0, -phone_cnr_rad, 0])
135       rotate([90,0,0])
136       linear_extrude(height = phone_height - phone_cnr_rad*2)
137       children(0);
138   }
139   // corners
140   CaseBase_rhsflip() CaseBase_botflip() {
141     translate([+1,-1] * phone_cnr_rad)
142       intersection(){
143         rotate_extrude()
144           intersection(){
145             mirror([1,0,0])
146               translate([-1,0] * phone_cnr_rad)
147               children(0);
148             rectfromto([0,-20],[10,20]);
149           }
150         translate([-10, 0, -20] + 0.01 * [+1,-1, 0] )
151           cube([10,10,40]);
152       }
153   }
154   // top and bottom
155   CaseBase_botflip(){
156     translate([ phone_width - phone_cnr_rad, 0,0 ])
157       rotate([90,0,-90])
158       linear_extrude(height = phone_width - phone_cnr_rad*2)
159       children(0);
160   }
161   // fill
162   translate([0,0, fill_zstart])
163     mirror([0,0, fill_downwards])
164     linear_extrude(height = fill_th)
165     rectfromto([+1,-1] * phone_cnr_rad,
166                [phone_width, -phone_height] + [-1,+1] * phone_cnr_rad);
167 }
168
169 module CaseBase(){
170   AroundEdges(epp3[1], case_th_bottom, 1)
171     EdgeProfile();
172 }
173
174 module Case(){ ////toplevel
175   difference(){
176     union(){
177       CaseBase();
178
179       // ledge (fixed keeper)
180       intersection(){
181         rotate([90, 0, 0])
182           linear_extrude(height = phone_height + phone_cnr_rad * 2)
183           KeeperProfile();
184
185         // outline of the whole case, to stop it protruding
186         translate([0,0, -25])
187           linear_extrude(height = 50)
188           hull()
189           // CaseBase_rhsflip() // actually, we only care about the LH
190           CaseBase_botflip()
191           circleat([+1,-1] * phone_cnr_rad, phone_cnr_rad + case_th_side/2);
192       }
193     }
194
195     // slot for keeper
196     CaseBase_rhsflip(1)
197       translate([0, -phone_cnr_rad, 0])
198       rotate([90, 0, 0])
199       linear_extrude(height = phone_height + phone_cnr_rad * 2)
200       minkowski(){
201         KeeperProfile();
202         rectfromto([ -keeper_gap_x,    -keeper_gap_z_bot ],
203                    [ keeper_gap_x_holes,    +keeper_gap_z_top ]);
204       }
205
206     // front camera
207     CaseBase_rhsflip([1])
208       mirror([0, 0, 1])
209       linear_extrude(height = 20)
210       mirror([0, 1, 0])
211       rectfromto(camera_pos_tl, camera_pos_br);
212
213     // struts (invisible, because they're buried in the case)
214     for (i= [1 : 1 : case_struts_count]) {
215       translate([0,
216                  -phone_height * i / (case_struts_count+1),
217                  epp2i[1] - case_th_bottom + case_struts_solid_below])
218         linear_extrude(height= case_th_bottom
219                        -(case_struts_solid_below+case_struts_solid_above))
220         rectfromto([               epp2i[0], -0.5 * case_struts_width ],
221                    [ phone_width - epp2i[0], +0.5 * case_struts_width ]);
222     }
223   }
224 }
225
226 module Lid(){ ////toplevel
227   AroundEdges(lpp10[1], lpp13[1] - lpp10[1], 0)
228     LidEdgeProfile();
229 }
230
231 module TestLength(){ ////toplevel
232   intersection(){
233     Case();
234     translate([-30, -200, -20])
235     cube([30 + 15, 250, 40]);
236   }
237 }
238
239 module TestWidth(){ ////toplevel
240   intersection(){
241     Case();
242     translate([-30, -(phone_height - 25), -20])
243       mirror([0, 1, 0])
244       cube([200, 50, 40]);
245   }
246 }
247
248 module TestCamera(){ ////toplevel
249   intersection(){
250     Case();
251     CaseBase_rhsflip(1)
252       translate([0,0,-25])
253       linear_extrude(height = 50)
254       mirror([0, 1, 0])
255       rectfromto([-20, -20],
256                  camera_pos_br + [ 5, 5 ]);
257   }
258 }
259
260 module OneKeeper(){ ////toplevel
261   translate([0, -phone_cnr_rad, 0])
262     rotate([90, 0, 0])
263     linear_extrude(height = phone_height - phone_cnr_rad * 2)
264     KeeperProfile();
265 }
266
267 module OneKeeperPrint(){ ////toplevel
268   rotate([0,180,0])
269     OneKeeper();
270 }
271
272 module Keeper(){ ////toplevel
273   CaseBase_rhsflip()
274     OneKeeper();
275 }
276
277 module DemoProfiles(){ ////toplevel
278   LidEdgeProfile();
279   %EdgeProfile();
280   KeeperProfile();
281 }
282
283 //EdgeProfile();
284 //KeeperProfile();
285 //CaseBase();
286 //%Case();
287 //Keeper();
288 //LidEdgeProfile();
289 //KeeperProfile();
290 //DemoProfiles();