Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save cameronkerrnz/c71dcdbfc1a3cbb4bdc45823d9dfbbc8 to your computer and use it in GitHub Desktop.
Save cameronkerrnz/c71dcdbfc1a3cbb4bdc45823d9dfbbc8 to your computer and use it in GitHub Desktop.
Phone case modelled using OpenSCAD suitable for an unknown model of Alcatel phone
body_thickness = 10;
body_width = 71.8;
body_length = 146.2;
body_corner_radius_xy = 7;
glass_width = 67.8;
glass_length = 142.4;
//glass_inset = 2; // TODO: validate // TPU
glass_inset = 0.5; // TODO: validate // PLA
// Side of phone appears to have a radius of about 6mm, tangent
// with the rear face, and wrapping around.
side_profile_radius= 6;
// Rear camera is on the right (when viewed from front) on the rear face
camera_slot_top_offset = 15;
camera_slot_right_offset = 15;
camera_slot_length = 10;
camera_slot_radius = 9.5 / 2; // likely will still need bevel
button_slot_radius = 2;
button_slot_front_offset = 4.5;
//Camera button is on the left side
camera_button_slot_top_offset = 51.5;
camera_button_slot_length = 9.6;
//Volume button is on the right side, to the top of the Sleep button
volume_button_slot_top_offset = 27.6;
volume_button_slot_length = 19.3;
sleep_button_slot_top_offset = 53;
sleep_button_slot_length = 9.2;
//Power receptacle is a USB micro on the bottom, close the the right
//these measurements allow for the plug case to go through
usb_slot_right_offset = 12;
usb_slot_front_offset = 6;
usb_slot_length = 6;
usb_slot_radius = 3;
//Mic hole is on the bottom
mic_hole_right_offset = 29;
mic_hole_front_offset = 5;
mic_hole_diameter = 3;
//Headphone jack is on the top. Allow for plug casing
//Also, does not sit on the centerline.
headphone_hole_right_offset = 30;
headphone_hole_face_offset = 6;
headphone_hole_diameter = 8;
//Front camera is on the front face, top-right corner
front_camera_right_offset = 14.5;
front_camera_diameter = 5; // generous, but will still need bevel
//Ear piece is in top-center on the front face
ear_slot_top_offset = 6;
ear_slot_length = 15;
ear_slot_radius = 1;
//"large enough to punch through the casing"
through = 5;
flare = 1.5; // how much wider a radius would be at 'through' distance; creates bevel
case_wall_thickness = 2; // play with this regarding fuzzy skin settings and perimeters
$fn=32;
module phone_body() {
// Phone is positioned so resulting front face is 0z, on the xy plane
// and the left side of the body is flush with 0x and the bottom (end) side
// of the body is flush with 0y
intersection() {
minkowski() {
translate([
side_profile_radius,
side_profile_radius,
-body_thickness + side_profile_radius])
cube([
body_width - 2*side_profile_radius,
body_length - 2*side_profile_radius,
0.001]);
sphere(r=side_profile_radius);
}
translate([0,0,-body_thickness])
cube([body_width,body_length,body_thickness]);
}
}
module phone_body_exploration() {
// version which just shows the basic elements
translate([
side_profile_radius,
side_profile_radius,
-body_thickness + side_profile_radius]) {
color("green", 0.2) cube([
body_width - 2*side_profile_radius,
body_length - 2*side_profile_radius,
0.01]);
color("red", 0.2) sphere(r=side_profile_radius);
}
color("purple", 0.1)
minkowski() {
translate([
side_profile_radius,
side_profile_radius,
-body_thickness + side_profile_radius])
cube([
body_width - 2*side_profile_radius,
body_length - 2*side_profile_radius,
0.001]);
sphere(r=side_profile_radius);
}
color("black", 0.1)
translate([0,0,-body_thickness])
cube([body_width,body_length,body_thickness]);
}
module case_blank() {
minkowski() {
phone_body();
sphere(d=case_wall_thickness);
}
}
module rear_camera_slot() {
hull() {
translate([
body_width - camera_slot_right_offset,
body_length - camera_slot_top_offset,
-body_thickness+0.1])
rotate([180,0,0])
cylinder(h=through, r1=camera_slot_radius, r2=camera_slot_radius+flare);
translate([
body_width - camera_slot_right_offset,
body_length - camera_slot_top_offset - camera_slot_length,
-body_thickness+0.1])
rotate([180,0,0])
cylinder(h=through, r1=camera_slot_radius, r2=camera_slot_radius+flare);
}
}
module camera_button_slot() {
hull() {
translate([
0.5, // move phone inward so we punch through the entire curvature
body_length - camera_button_slot_top_offset,
-button_slot_front_offset
])
rotate([0, -90, 0])
cylinder(h=through, r1=button_slot_radius, r2=button_slot_radius+flare);
translate([
0.5,
body_length - camera_button_slot_top_offset - camera_button_slot_length,
-button_slot_front_offset
])
rotate([0, -90, 0])
cylinder(h=through, r1=button_slot_radius, r2=button_slot_radius+flare);
}
}
module volume_button_slot() {
hull() {
translate([
body_width-0.5, // move phone inward so we punch through the entire curvature
body_length - volume_button_slot_top_offset,
-button_slot_front_offset
])
rotate([0, 90, 0])
cylinder(h=through, r1=button_slot_radius, r2=button_slot_radius+flare);
translate([
body_width-0.5,
body_length - volume_button_slot_top_offset - volume_button_slot_length,
-button_slot_front_offset
])
rotate([0, 90, 0])
cylinder(h=through, r1=button_slot_radius, r2=button_slot_radius+flare);
}
}
module sleep_button_slot() {
hull() {
translate([
body_width-0.5, // move phone inward so we punch through the entire curvature
body_length - sleep_button_slot_top_offset,
-button_slot_front_offset
])
rotate([0, 90, 0])
cylinder(h=through, r1=button_slot_radius, r2=button_slot_radius+flare);
translate([
body_width-0.5,
body_length - sleep_button_slot_top_offset - sleep_button_slot_length,
-button_slot_front_offset
])
rotate([0, 90, 0])
cylinder(h=through, r1=button_slot_radius, r2=button_slot_radius+flare);
}
}
module usb_slot() {
hull() {
translate([
body_width-usb_slot_right_offset,
5, // move phone inward so we punch through the entire curvature
-usb_slot_front_offset
])
rotate([0, 90, -90])
cylinder(h=through+5, r1=usb_slot_radius, r2=usb_slot_radius+0);
translate([
body_width-usb_slot_right_offset-usb_slot_length,
5, // move phone inward so we punch through the entire curvature
-usb_slot_front_offset
])
rotate([0, 90, -90])
cylinder(h=through+5, r1=usb_slot_radius, r2=usb_slot_radius+0);
}
}
module mic_hole() {
translate([
body_width-mic_hole_right_offset,
5, // move phone inward so we punch through the entire curvature
-mic_hole_front_offset
])
rotate([0, 90, -90])
cylinder(h=through+5, d1=mic_hole_diameter, d2=mic_hole_diameter+flare);
}
module headphone_hole() {
translate([
body_width-mic_hole_right_offset,
body_length-5, // move phone inward so we punch through the entire curvature
-headphone_hole_face_offset
])
rotate([0, 90, 90])
cylinder(h=through+5, d1=headphone_hole_diameter, d2=headphone_hole_diameter+flare);
}
module glass() {
vert_wall = 0.4;
screen_flare = 3;
// This time I want the bezel to include a small vertical as well as mostly angled part
// but the corners have a radius, so route out the design with hull of cylinder and then
// another hull of cylinder/cone.
// vertical wall
hull() {
translate([body_corner_radius_xy, body_corner_radius_xy, 0])
cylinder(h=through, r=body_corner_radius_xy - glass_inset);
translate([body_width - body_corner_radius_xy, body_corner_radius_xy, 0])
cylinder(h=through, r=body_corner_radius_xy - glass_inset);
translate([body_corner_radius_xy, body_length - body_corner_radius_xy, 0])
cylinder(h=through, r=body_corner_radius_xy - glass_inset);
translate([body_width - body_corner_radius_xy, body_length - body_corner_radius_xy, 0])
cylinder(h=through, r=body_corner_radius_xy - glass_inset);
}
// flare, so as not to obstruct touch at side of screen
hull() {
translate([
body_corner_radius_xy - vert_wall,
body_corner_radius_xy - vert_wall,
vert_wall])
cylinder(h=through,
r1=body_corner_radius_xy - glass_inset,
r2=body_corner_radius_xy - glass_inset + screen_flare);
translate([
body_width - body_corner_radius_xy + vert_wall,
body_corner_radius_xy - vert_wall,
vert_wall])
cylinder(h=through,
r1=body_corner_radius_xy - glass_inset,
r2=body_corner_radius_xy - glass_inset + screen_flare);
translate([
body_corner_radius_xy - vert_wall,
body_length - body_corner_radius_xy + + vert_wall,
vert_wall])
cylinder(h=through,
r1=body_corner_radius_xy - glass_inset,
r2=body_corner_radius_xy - glass_inset + screen_flare);
translate([
body_width - body_corner_radius_xy + vert_wall,
body_length - body_corner_radius_xy + vert_wall,
vert_wall])
cylinder(h=through,
r1=body_corner_radius_xy - glass_inset,
r2=body_corner_radius_xy - glass_inset + screen_flare);
}
}
module case_decorative_cutouts() {
// basically a repeat of the rear camera, for rotational symmetry
hull() {
translate([
camera_slot_right_offset,
camera_slot_top_offset,
-body_thickness+0.1])
rotate([180,0,0])
cylinder(h=through, r1=camera_slot_radius, r2=camera_slot_radius+flare);
translate([
camera_slot_right_offset,
camera_slot_top_offset + camera_slot_length,
-body_thickness+0.1])
rotate([180,0,0])
cylinder(h=through, r1=camera_slot_radius, r2=camera_slot_radius+flare);
}
// plus a nice slash, evoking classic playing card design
sash_corner_radius = 2;
sash_corner_side_offset = 20;
sash_width_lengthwise = 10;
// sash_corner_hoisted_end_offset = body_length * 0.29; // flexible version
sash_corner_hoisted_end_offset =
(
body_length
- body_width
+ sash_width_lengthwise
+ sash_corner_side_offset
+ sash_corner_radius
) / 2; // 45 degree version
hull() {
translate([
sash_corner_side_offset + sash_corner_radius,
body_length - sash_corner_hoisted_end_offset,
-body_thickness+0.1])
rotate([180,0,0])
cylinder(h=through, r1=sash_corner_radius, r2=sash_corner_radius+flare);
translate([
// 2* because optical illusion makes it seem much tighter otherwise
sash_corner_side_offset + 2*sash_corner_radius,
body_length - sash_corner_hoisted_end_offset - sash_width_lengthwise,
-body_thickness+0.1])
rotate([180,0,0])
cylinder(h=through, r1=sash_corner_radius*2, r2=sash_corner_radius+flare);
translate([
body_width - sash_corner_side_offset - sash_corner_radius,
sash_corner_hoisted_end_offset,
-body_thickness+0.1])
rotate([180,0,0])
cylinder(h=through, r1=sash_corner_radius, r2=sash_corner_radius+flare);
translate([
// 2* because optical illusion makes it seem much tighter otherwise
body_width - sash_corner_side_offset - 2*sash_corner_radius,
sash_corner_hoisted_end_offset + sash_width_lengthwise,
-body_thickness+0.1])
rotate([180,0,0])
cylinder(h=through, r1=sash_corner_radius*2, r2=sash_corner_radius+flare);
}
}
difference() {
case_blank();
phone_body();
rear_camera_slot();
camera_button_slot();
volume_button_slot();
sleep_button_slot();
usb_slot();
mic_hole();
headphone_hole();
glass();
case_decorative_cutouts();
}
@cameronkerrnz
Copy link
Author

Screenshot 2025-03-07 at 10 05 44 am

Blog post which accompanies this model: DIY Phone Case: as easy as 1, 2, Minkowski!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment