+module OrdinaryRearAperture(rhs,bot, pos){
+ Flip_rhs(rhs) Flip_bot(bot)
+ linextr(-20, 20)
+ mirror([0,1])
+ translate(pos + bumper)
+ children();
+}
+
+module OrdinaryRearApertures(){
+ // rear speaker
+ OrdinaryRearAperture(1,1, rearspeaker_pos_bl)
+ rectfromto(-rearspeaker_gap,
+ rearspeaker_size + rearspeaker_gap);
+
+ // finger hole to remove phone
+ OrdinaryRearAperture(1,0, [ fingerpushhole_dias[0]/2 + epp2i[0],
+ phone[1]/2 ])
+ scale(fingerpushhole_dias)
+ circle(r= 0.5 );
+}
+
+module RearCameraAperture(){
+ Flip_rhs(1)
+ mirror([0, 0, 1])
+ linear_extrude(height = 20)
+ mirror([0, 1, 0])
+ translate(bumper)
+ rectfromto(camera_pos_tl, camera_pos_br);
+}
+
+module HingeLidProfile(){
+ hull(){
+ circleat(hppT, hp_r1);
+ circleat(lpp12, lp_r12);
+ polygon([lpp10,
+ lpp13 + [2,0],
+ lpp12,
+ hppT]);
+ }
+}
+
+module HingeBaseProfile(){
+ difference(){
+ hull(){
+ circleat(hppB, hp_r1);
+ circleat(epp2o, case_th_bottom);
+ circleat(hppB + [10,0], hp_r1);
+ }
+ polygon([epp5, epp1, epp2i, epp3, bppL]);
+ }
+}
+
+module HingeLeverOuterProfile(){
+ hull(){
+ circleat(hppT, hp_r2);
+ circleat(hppB, hp_r2);
+ }
+}
+
+module HingeLeverInnerProfile(){
+ for (c = [hppT, hppB]) {
+ hull()
+ for (x=[0,20])
+ translate([x,0])
+ circleat(c, hp_rn);
+ circleat(hppB, hp_rn);
+ }
+}
+
+module HingePortion(x0,x1){
+ Flip_rhs() Flip_bot(1)
+ translate([x0,0,0])
+ mirror([1,0,0])
+ rotate([90,0,-90])
+ linear_extrude(height=x1-x0)
+ children(0);
+}
+
+module CaseBase(){
+ AroundEdges(epp3[1], case_th_bottom, 1)
+ EdgeProfile();
+}
+
+module Case(){ ////toplevel
+ difference(){
+ union(){
+ CaseBase();
+
+ // ledge (fixed keeper)
+ intersection(){
+ rotate([90, 0, 0])
+ linear_extrude(height = phone_height + phone_cnr_rad * 2)
+ KeeperProfile(1);
+
+ // outline of the whole case, to stop it protruding
+ translate([0,0, -25])
+ linear_extrude(height = 50)
+ hull()
+ // Flip_rhs() // actually, we only care about the LH
+ Flip_bot()
+ circleat([+1,-1] * phone_cnr_rad, phone_cnr_rad + case_th_side/2);
+ }
+
+ // hinge
+ HingePortion(hex20, hex21) HingeBaseProfile();
+ }
+
+ // slot for keeper
+ Flip_rhs(1)
+ translate([0, -phone_cnr_rad, 0])
+ rotate([90, 0, 0])
+ linear_extrude(height = phone_height + phone_cnr_rad * 2)
+ minkowski(){
+ KeeperProfile();
+ rectfromto([ -keeper_gap_x, -keeper_gap_z_bot ],
+ [ keeper_gap_x_holes, +keeper_gap_z_top ]);
+ }
+
+ // front camera
+ RearCameraAperture();
+
+ // struts (invisible, because they're buried in the case)
+ Struts(epp2i[0], epp2i[1] - case_th_bottom, case_th_bottom);
+
+ Buttons(){
+ mirror([1,0,0])
+ rotate([90,0,90]) {
+ intersection(){
+ translate([0,0,-10])
+ linear_extrude(height= 20)
+ ButtonPlan($button_l, 0,1);
+ if ($button_leg_only)
+ rotate([-90,90,0])
+ translate([phone_width/2, -400, kppe[1]])
+ mirror([$rhsflip,0,0]) cube([400, 800, 50]);
+ }
+ translate([0,0, -bppR[0]])
+ linear_extrude(height= 20)
+ ButtonPlan($button_l, 1,1);
+ }
+ }
+
+ // apertures along top edge
+ CaseAperture(jack_pos, jack_dia, 8);
+ Flip_rhs(1)
+ CaseAperture(noisecancelmic_pos, noisecancelmic_dia, 20);
+
+ OrdinaryRearApertures();
+
+ // gaps for the lid's hinge arms
+ HingePortion(hex20 - hinge_x_arms_gap,
+ hex21 + hinge_x_arms_gap)
+ minkowski(){
+ HingeLidProfile();
+ circle(r= hinge_r_arms_gap, $fn= 8);
+ }
+
+ // screw holes in the hinge arms
+ DemoHingeScrews();
+ }
+}
+
+module Lid(){ ////toplevel
+ difference(){
+ union(){
+ AroundEdges(lpp10[1], lpp13[1] - lpp10[1], 0)
+ LidEdgeProfile();
+
+ // button covers
+ Buttons(){
+ intersection(){
+ rotate([90,0,90])
+ translate([0,0,-10])
+ linear_extrude(height= 20)
+ ButtonPlan($button_l, 1,0);
+ rotate([90,0,0])
+ translate([0,0,-100])
+ linear_extrude(height= 200)
+ ButtonCoverProfile();
+ }
+ }
+
+ // hinge arms
+ HingePortion(hex20, hex21) HingeLidProfile();
+ }
+ Struts(lpp10[0] + strut_min_at_end, lpp13[1], -case_th_lid);
+
+ // screw holes in the hinge arms
+ DemoHingeScrews();
+ }
+}
+
+module HingeLever(){ ////toplevel
+ difference() {
+ // outer body, positive
+ HingePortion(hex22, hex22 + phone_width/2)
+ HingeLeverOuterProfile();
+
+ // space for the screws
+ HingePortion(hex23, hex24)
+ HingeLeverInnerProfile();
+
+ // bores for the screws
+ DemoHingeScrews();
+ }
+}
+
+module HingeLeverPrint(){ ////toplevel
+ rotate([90,0,0])
+ HingeLever();
+}
+
+module TestSelectLength(){
+ translate([-30, -200, -20])
+ cube([30 + 15, 250, 40]);
+}
+
+module TestLength(){ ////toplevel
+ intersection(){
+ Case();
+ TestSelectLength();
+ }
+}
+
+module TestLengthRight(){ ////toplevel
+ intersection(){
+ Case();
+ Flip_rhs(1)
+ TestSelectLength();
+ }
+}
+
+module TestSelectWidth(){
+ translate([-30, -(phone_height - 25), -20])
+ mirror([0, 1, 0])
+ cube([200, 50, 40]);
+}
+
+module TestWidth(){ ////toplevel
+ intersection(){
+ Case();
+ TestSelectWidth();
+ }
+}
+
+module TestLidWidthPrint(){ ////toplevel
+ rotate([0,180.0]) intersection(){
+ Lid();
+ TestSelectWidth();
+ }
+}
+
+module TestSelectRearAperture(){
+ minkowski(){
+ union() children();
+ translate([20, 0,0])
+ cube([42, 2, 1], center=true);
+ }
+}
+
+module TestSelectCamera(){
+ minkowski(){
+ TestSelectRearAperture()
+ RearCameraAperture();
+ cube([0.1, 50, 0.1]);
+ }
+}
+
+module TestSelectOrdinaryRearApertures(){
+ TestSelectRearAperture()
+ OrdinaryRearApertures();
+}
+
+module TestCamera(){ ////toplevel
+ intersection(){
+ Case();
+ TestSelectCamera();
+ }
+}
+
+module TestLidByCamera(){ ////toplevel
+ intersection(){
+ Lid();
+ TestSelectCamera();
+ }
+}
+
+module TestLidByCameraPrint(){ ////toplevel
+ rotate([180,0,0]) TestLidByCamera();
+}
+
+module DemoByCamera(){ ////toplevel
+ color("blue") TestLidByCamera();
+ color("red") TestCamera();
+}
+
+module OneKeeper(){ ////toplevel
+ translate([0, -phone_cnr_rad, 0])
+ rotate([90, 0, 0])
+ linear_extrude(height = phone_height - phone_cnr_rad * 2)
+ KeeperProfile();
+}
+
+module OneKeeperPrint(){ ////toplevel
+ rotate([0,180,0])
+ OneKeeper();
+}
+
+module LidPrint(){ ////toplevel
+ rotate([0,180,0])
+ Lid();
+}
+
+module TestSelectFrame(){
+ include = [1,-1] * (epp2i[0] + 4);
+
+ difference(){
+ cube(1000, center=true);
+ translate([0,0, -100])
+ linear_extrude(height=200)
+ rectfromto(include, inside_br - include);
+ }
+}
+
+module TestFrameCase(){ ////toplevel
+ intersection(){
+ Case();
+ union(){
+ TestSelectFrame();
+ TestSelectCamera();
+ TestSelectOrdinaryRearApertures();
+ }
+ }
+}
+
+module TestFrameLidPrint(){ ////toplevel
+ rotate([0,180,0]) intersection(){
+ Lid();
+ TestSelectFrame();
+ }
+}
+
+module Keeper(){ ////toplevel
+ Flip_rhs()
+ OneKeeper();
+}
+
+module ButtonPlanForDemo(z, deep, cut){
+ translate([0,0,z])
+ ButtonPlan(8, deep, cut);
+}
+
+module DemoHingeScrews(){
+ Flip_rhs() Flip_bot(1){
+ for (c= [ hppT, hppB ])
+ translate([ hex20,
+ -c[0],
+ c[1] ]){
+ rotate([0,90,0])
+ translate([0,0,-.2])
+ cylinder( r= hingescrew_shaft_dia/2,
+ h = hingescrew_shaft_len+0.2 );
+ rotate([0,-90,0])
+ translate([0,0,+.1])
+ cylinder( r= hingescrew_head_dia/2, h = hingescrew_head_th );
+ }
+ }
+}
+
+module DemoFrame(){ ////toplevel
+ color("red") TestFrameCase();
+ color("blue") intersection(){ Lid(); TestSelectFrame(); }
+ color("black") DemoHingeScrews();
+ %HingeLever();
+}
+
+module DemoHingedFrame(){ ///toplevel
+ hinge_origin = [0, -(phone_height - hppB[0]), hppB[1]];
+
+ color("red") TestFrameCase();
+ translate([0,0, -2*hp_k])
+ color("blue") intersection(){ Lid(); TestSelectFrame(); }
+
+ translate(hinge_origin)
+ rotate([180,0,0])
+ translate(-hinge_origin) {
+ color("orange") HingeLever();
+ color("black") DemoHingeScrews();
+ }
+}
+
+module DemoHinge(){ ////toplevel
+ DemoFrame();
+ translate([0,0, -hp_k*3])
+ DemoHingedFrame();
+}
+
+module DemoProfiles(){ ////toplevel
+ LidEdgeProfile();
+ %EdgeProfile();
+ KeeperProfile();
+ translate([0,0,-1]) color("black") KeeperProfile(1);
+
+ translate([20,0]) {
+ LidEdgeProfile();
+ %EdgeProfile();
+
+ demopoint_QR = [ bppS[0], bppQ[1] - 0.1];
+
+ color("blue") ButtonCoverProfile();
+ color("red") {
+ rectfromto(bppQ, demopoint_QR);
+ rectfromto(bppR, demopoint_QR);
+ }
+ }
+
+ translate([-20,0]) {
+ color("black") ButtonPlanForDemo(-2, 0,1);
+ color("red" ) ButtonPlanForDemo(-4, 1,1);
+ color("blue") ButtonPlanForDemo(-6, 1,0);
+ }
+
+ translate([0, -30]) {
+ %LidEdgeProfile();
+ %EdgeProfile();
+ color("blue") HingeLidProfile();
+ color("red") HingeBaseProfile();
+ color("black") translate([0,0,-2]) HingeLeverOuterProfile();
+ color("orange") translate([0,0,-1]) HingeLeverInnerProfile();
+ }
+}
+
+//EdgeProfile();