chiark / gitweb /
76427b1706217200f7c48e14faf7af475881e4d4
[reprap-play.git] / fairphone-case.scad
1 // -*- C -*-
2
3 phone_height = 146.5;
4 phone_width = 76.75;
5
6 phone_cnr_rad = 4.0;
7
8 phone_edge_thick = 9.0;
9 phone_total_thick = 12.0;
10 phone_backside_slope = 1.0; // larger means shallower
11
12 camera_pos_tl = [  7.5, 13.5 ]; // measured from tl corner
13 camera_pos_br = [ 24.0, 39.5 ]; // tl/br as seen from back
14
15 case_th_bottom = 2;
16 case_th_lid = 2;
17 case_th_side = 2;
18 case_th_lip = 1.2;
19
20 keeper_th_z = 0.75;
21 keeper_th_x = 0.75;
22 keeper_inner_width = 1.75;
23 keeper_inner_height = 1.75;
24
25 keeper_gap_z_top = 0.25;
26 keeper_gap_z_bot = 0.25;
27 keeper_gap_x     = 0.25;
28 keeper_gap_x_holes = 0.75;
29
30 case_lip = 1.25;
31
32 $fa = 5;
33 $fs = 0.1;
34
35 // calculated
36
37 phone_backside_slope_thick = phone_total_thick - phone_edge_thick;
38
39 //lid_lip_overlap_width xxx bad name = ;
40 //lid_lip_inner_slope = [ 5, 5 ]; // xxx
41
42 epp0 = [0,0];
43 epp1 = [0, -phone_edge_thick];
44 epp2 = epp1 + phone_backside_slope_thick * [ phone_backside_slope, -1 ];
45 epp3 = epp2 + [10, 0];
46 epp5 = epp0 + [0,1] * (keeper_th_z + keeper_gap_z_top + case_lip);
47 epp4 = epp5 + [-1,0] * case_th_side;
48
49 kppe = [0,0];
50 kppd = kppe + [1,0] * keeper_inner_width;
51 kppc = kppd + [0,1] * keeper_th_z;
52 kppb = [ kppe[0] - keeper_th_x, kppc[1] ];
53 kppf = kppe - [0,1] * keeper_inner_height;
54 kppa = [ kppb[0], kppf[1] ];
55
56 module rectfromto(a,b) {
57   ab = b - a;
58   translate([min(a[0], b[0]), min(a[1], b[1])])
59     square([abs(ab[0]), abs(ab[1])]);
60 }
61 module circleat(c,r) { translate(c) circle(r); }
62
63 module KeeperProfile(){
64   polygon([kppe, kppd, kppc, kppb, kppa, kppf]);
65 }
66
67 module EdgeProfile(){
68   difference(){
69     hull(){
70       circleat(epp3, r=case_th_bottom);
71       circleat(epp2, r=case_th_bottom);
72       circleat(epp1, r=case_th_side);
73       rectfromto(epp0, epp4);
74     }
75     polygon([ epp5 + [0,10],
76               epp1,
77               epp2,
78               epp3 + [10,0] ]);
79   }
80 }
81
82 module CaseBase_rhsflip(yn=[0,1]) {
83   for (rhs=yn) {
84     translate([phone_width/2, 0, 0])
85       mirror([rhs,0,0])
86       translate([-phone_width/2, 0, 0])
87       children();
88   }
89 }
90
91 module CaseBase_botflip() {
92   for (bot=[0,1]) {
93     translate([0, -phone_height/2, 0])
94       mirror([0, bot, 0])
95       translate([0, phone_height/2, 0])
96       children();
97   }
98 }  
99
100 module CaseBase(){
101   // sides
102   CaseBase_rhsflip(){
103     translate([0, -phone_cnr_rad, 0])
104       rotate([90,0,0])
105       linear_extrude(height = phone_height - phone_cnr_rad*2)
106       EdgeProfile();
107   }
108   // corners
109   CaseBase_rhsflip() CaseBase_botflip() {
110     translate([+1,-1] * phone_cnr_rad)
111       intersection(){
112         rotate_extrude()
113           intersection(){
114             mirror([1,0,0])
115               translate([-1,0] * phone_cnr_rad)
116               EdgeProfile();
117             rectfromto([0,-20],[10,20]);
118           }
119         translate([-10, 0, -20] + 0.01 * [+1,-1, 0] )
120           cube([10,10,40]);
121       }
122   }
123   // top and bottom
124   CaseBase_botflip(){
125     translate([ phone_width - phone_cnr_rad, 0,0 ])
126       rotate([90,0,-90])
127       linear_extrude(height = phone_width - phone_cnr_rad*2)
128       EdgeProfile();
129   }
130   // fill
131   translate([0,0, epp3[1]])
132     mirror([0,0, 1])
133     linear_extrude(height = case_th_bottom)
134     rectfromto([+1,-1] * phone_cnr_rad,
135                [phone_width, -phone_height] + [-1,+1] * phone_cnr_rad);
136 }
137
138 module Case(){ ////toplevel
139   difference(){
140     CaseBase();
141
142     // slots for keeper
143     CaseBase_rhsflip()
144       translate([0, -phone_cnr_rad, 0])
145       rotate([90, 0, 0])
146       linear_extrude(height = phone_height + phone_cnr_rad * 2)
147       minkowski(){
148         KeeperProfile();
149         rectfromto([ -keeper_gap_x,    -keeper_gap_z_bot ],
150                    [ keeper_gap_x_holes,    +keeper_gap_z_top ]);
151       }
152
153     // front camera
154     CaseBase_rhsflip([1])
155       mirror([0, 0, 1])
156       linear_extrude(height = 20)
157       mirror([0, 1, 0])
158       rectfromto(camera_pos_tl, camera_pos_br);
159   }
160 }
161
162 module TestLength(){ ////toplevel
163   intersection(){
164     Case();
165     translate([-30, -200, -20])
166     cube([30 + 15, 250, 40]);
167   }
168 }
169
170 module TestWidth(){ ////toplevel
171   intersection(){
172     Case();
173     translate([-30, -(phone_height - 25), -20])
174       mirror([0, 1, 0])
175       cube([200, 50, 40]);
176   }
177 }
178
179 module OneKeeper(){ ////toplevel
180   translate([0, -phone_cnr_rad, 0])
181     rotate([90, 0, 0])
182     linear_extrude(height = phone_height - phone_cnr_rad * 2)
183     KeeperProfile();
184 }
185
186 module OneKeeperPrint(){ ////toplevel
187   rotate([0,180,0])
188     OneKeeper();
189 }
190
191 module Keeper(){ ////toplevel
192   CaseBase_rhsflip()
193     OneKeeper();
194 }
195
196 //EdgeProfile();
197 //KeeperProfile();
198 //CaseBase();
199 //%Case();
200 //Keeper();