initial commit
This commit is contained in:
188
case.scad
Normal file
188
case.scad
Normal file
@@ -0,0 +1,188 @@
|
||||
// --- Parameters ---
|
||||
columns = 14;
|
||||
rows = 5;
|
||||
switch_spacing = 19.05;
|
||||
switch_outer_width = 14.2;
|
||||
switch_total_height = 14.2;
|
||||
margin = 5.0;
|
||||
|
||||
plate_w = (columns - 1) * switch_spacing + switch_outer_width + (margin * 2);
|
||||
plate_h = (rows - 1) * switch_spacing + switch_total_height + (margin * 2);
|
||||
|
||||
// --- Plate ---
|
||||
plate_thickness = 1.5;
|
||||
plate_slack = 0.15;
|
||||
recess_depth = 2.5;
|
||||
|
||||
// --- Case Dimensions ---
|
||||
case_angle = 5;
|
||||
wall_thickness = 4.0;
|
||||
front_height = 18.0;
|
||||
clearance = 0.25;
|
||||
floor_thickness = 4.0;
|
||||
rim_extra_height = 3.0;
|
||||
|
||||
pillar_dia = 3;
|
||||
|
||||
case_w = plate_w + (wall_thickness * 2) + (clearance * 2) - 2;
|
||||
case_h = ((plate_h - 2) * cos(case_angle)) + (wall_thickness * 2) + (clearance * 2);
|
||||
|
||||
back_height = front_height + (tan(case_angle) * case_h);
|
||||
|
||||
// --- USB-C and Controller Holder ---
|
||||
usb_w = 12.0;
|
||||
usb_h = 6.5;
|
||||
usb_x_offset = 60.0;
|
||||
usb_z_pos = floor_thickness;
|
||||
|
||||
holder_x = 20.0;
|
||||
holder_y = 35.0;
|
||||
holder_height = 5.0;
|
||||
holder_wall = 2.0;
|
||||
|
||||
// --- Splitting ---
|
||||
joint_clearance = 0.05;
|
||||
tab_size = 10;
|
||||
|
||||
// --- Clips ---
|
||||
clip_width = 10.0;
|
||||
clip_depth = 1.5;
|
||||
clip_height = 1.5;
|
||||
|
||||
module controller_holder() {
|
||||
x_pos = usb_x_offset + (usb_w/2) - (holder_x/2) - holder_wall;
|
||||
y_inner_wall = case_h - wall_thickness;
|
||||
y_pos = y_inner_wall - holder_y - holder_wall;
|
||||
|
||||
translate([x_pos, y_pos, floor_thickness]) {
|
||||
difference() {
|
||||
cube([holder_x + (holder_wall * 2), holder_y + holder_wall, holder_height]);
|
||||
translate([holder_wall, holder_wall, -0.1])
|
||||
cube([holder_x, holder_y + 0.1, holder_height + 0.2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module usb_cutout() {
|
||||
translate([usb_x_offset, case_h - wall_thickness - 1, usb_z_pos])
|
||||
cube([usb_w, wall_thickness + 2, usb_h]);
|
||||
}
|
||||
|
||||
module angled_clip() {
|
||||
color("red")
|
||||
rotate([case_angle, 0, 0])
|
||||
cube([clip_width, clip_depth, clip_height]);
|
||||
}
|
||||
|
||||
module support_pillars() {
|
||||
// Gap indices: x means the gap between column/row x and x+1
|
||||
col_gaps = [3, 6, 8, 11];
|
||||
row_gaps = [1, 2, 3];
|
||||
|
||||
// Plate start positions in case coordinates
|
||||
plate_start_x = (case_w - plate_w)/2 - 2;
|
||||
plate_start_y = (case_h - (plate_h * cos(case_angle)))/2 - 2 * cos(case_angle);
|
||||
|
||||
intersection() {
|
||||
union() {
|
||||
for (c = col_gaps) {
|
||||
for (r = row_gaps) {
|
||||
// X is simple: plate offset + margin + (gap index * spacing)
|
||||
x_pos = plate_start_x + margin + (c * switch_spacing);
|
||||
|
||||
// Y must account for the tilt contraction (cos)
|
||||
y_pos_flat = margin + (r * switch_spacing);
|
||||
y_pos = plate_start_y + (y_pos_flat * cos(case_angle));
|
||||
|
||||
translate([x_pos, y_pos, 0])
|
||||
cylinder(d = pillar_dia, h = back_height + 10, $fn = 32);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clipping volume: Vertical space from floor up to the underside of the tilted plate
|
||||
// This ensures the pillars are vertical but have an angled top surface
|
||||
translate([0, plate_start_y, front_height - recess_depth])
|
||||
rotate([case_angle, 0, 0])
|
||||
translate([-50, 0, -500]) // Big volume below the plate
|
||||
cube([case_w + 100, plate_h, 500]);
|
||||
}
|
||||
}
|
||||
|
||||
module case_full_geometry() {
|
||||
clip_z_offset = plate_thickness + plate_slack;
|
||||
|
||||
// Exact dimensions for the recess
|
||||
recess_w = plate_w + (plate_slack * 2);
|
||||
recess_h = plate_h + (plate_slack * 2);
|
||||
|
||||
union() {
|
||||
difference() {
|
||||
// 1. Shell
|
||||
polyhedron(
|
||||
points=[
|
||||
[0,0,0], [case_w,0,0], [case_w,case_h,0], [0,case_h,0],
|
||||
[0,0,front_height + rim_extra_height], [case_w,0,front_height + rim_extra_height],
|
||||
[0,case_h,back_height + rim_extra_height], [case_w,case_h,back_height + rim_extra_height]
|
||||
],
|
||||
faces=[[0,1,2,3], [4,5,1,0], [7,6,3,2], [5,7,2,1], [6,4,0,3], [4,6,7,5]]
|
||||
);
|
||||
|
||||
// 2. Internal Tub
|
||||
translate([wall_thickness, wall_thickness, floor_thickness])
|
||||
cube([case_w - (wall_thickness * 2), case_h - (wall_thickness * 2), back_height + 20]);
|
||||
|
||||
// 3. The Plate Recess (Hardcode removed, now using plate_slack)
|
||||
translate([(case_w - recess_w)/2, (case_h - (recess_h * cos(case_angle)))/2, front_height - recess_depth])
|
||||
rotate([case_angle, 0, 0])
|
||||
cube([recess_w, recess_h, 20]);
|
||||
}
|
||||
|
||||
support_pillars();
|
||||
|
||||
// 4. Clips
|
||||
for (i = [0:5]) {
|
||||
z_front = (front_height - recess_depth) + clip_z_offset;
|
||||
translate([wall_thickness + (case_w - wall_thickness*2)/7 * (i+1) - clip_width/2, wall_thickness - clip_depth, z_front])
|
||||
angled_clip();
|
||||
|
||||
y_back_wall = case_h - wall_thickness;
|
||||
z_back_shelf = (front_height - recess_depth) + (tan(case_angle) * (y_back_wall - wall_thickness));
|
||||
z_back_clip = z_back_shelf + clip_z_offset;
|
||||
translate([wall_thickness + (case_w - wall_thickness*2)/7 * (i+1) - clip_width/2, y_back_wall - clip_depth * 0.5, z_back_clip])
|
||||
angled_clip();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module jigsaw_cutter(gap) {
|
||||
union() {
|
||||
translate([case_w/2 + gap, -1, -1])
|
||||
cube([case_w, case_h + 2, back_height + 40]);
|
||||
translate([case_w/2 - tab_size + gap, case_h/2 - 15, -1])
|
||||
linear_extrude(back_height + 40)
|
||||
polygon(points=[[gap,0], [tab_size, -5], [tab_size, 35], [gap, 30]]);
|
||||
}
|
||||
}
|
||||
|
||||
// --- Render ---
|
||||
render_part = "both";
|
||||
|
||||
if (render_part == "left" || render_part == "both") {
|
||||
union() {
|
||||
difference() {
|
||||
case_full_geometry();
|
||||
jigsaw_cutter(-joint_clearance);
|
||||
usb_cutout();
|
||||
}
|
||||
controller_holder();
|
||||
}
|
||||
}
|
||||
|
||||
if (render_part == "right" || render_part == "both") {
|
||||
translate([render_part == "both" ? 10 : 0, 0, 0])
|
||||
intersection() {
|
||||
case_full_geometry();
|
||||
jigsaw_cutter(joint_clearance);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user