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