initial commit
This commit is contained in:
159
xda_keycap.scad
Normal file
159
xda_keycap.scad
Normal file
@@ -0,0 +1,159 @@
|
||||
// --- Parameters ---
|
||||
$fn = 512;
|
||||
|
||||
// Key Dimensions
|
||||
u_count_x = 1;
|
||||
u_count_y = 1;
|
||||
u_pitch = 19.05;
|
||||
|
||||
width_base_1u = 18.2;
|
||||
width_top_1u = 14.5;
|
||||
height = 9.0;
|
||||
corner_radius = 2.5;
|
||||
|
||||
// Engraving Settings
|
||||
legend_char = "A";
|
||||
legend_depth = 0.5;
|
||||
legend_size = 5;
|
||||
|
||||
// Calculated Dimensions
|
||||
is_2u = (u_count_x >= 2 || u_count_y >= 2);
|
||||
w_base = width_base_1u + (u_count_x - 1) * u_pitch;
|
||||
h_base = width_base_1u + (u_count_y - 1) * u_pitch;
|
||||
w_top = width_top_1u + (u_count_x - 1) * u_pitch;
|
||||
h_top = width_top_1u + (u_count_y - 1) * u_pitch;
|
||||
|
||||
// Dish (Only for 1u)
|
||||
dish_depth = 1;
|
||||
dish_radius = 45;
|
||||
|
||||
// Stem & Stabilizer Dimensions
|
||||
stem_h = 5.0;
|
||||
stem_outer_d = 5.5;
|
||||
cross_l = 4.1;
|
||||
cross_w1 = 1.25;
|
||||
cross_w2 = 1.15;
|
||||
stab_dist = 23.85;
|
||||
|
||||
// Supports
|
||||
support_depth = 5;
|
||||
|
||||
// --- Modules ---
|
||||
|
||||
module rounded_rectangle(w, h, z, r) {
|
||||
hull() {
|
||||
translate([r, r, 0]) cylinder(r=r, h=z);
|
||||
translate([w - r, r, 0]) cylinder(r=r, h=z);
|
||||
translate([r, h - r, 0]) cylinder(r=r, h=z);
|
||||
translate([w - r, h - r, 0]) cylinder(r=r, h=z);
|
||||
}
|
||||
}
|
||||
|
||||
module xda_body() {
|
||||
difference() {
|
||||
hull() {
|
||||
rounded_rectangle(w_base, h_base, 0.1, corner_radius);
|
||||
translate([(w_base - w_top)/2, (h_base - h_top)/2, height - 0.1])
|
||||
rounded_rectangle(w_top, h_top, 0.1, corner_radius);
|
||||
}
|
||||
|
||||
if (!is_2u) {
|
||||
translate([w_base/2, h_base/2, height + dish_radius - dish_depth])
|
||||
sphere(r=dish_radius);
|
||||
}
|
||||
|
||||
translate([0,0,-0.5])
|
||||
hull() {
|
||||
translate([1.5, 1.5, 0])
|
||||
rounded_rectangle(w_base - 3, h_base - 3, 0.1, corner_radius/2);
|
||||
translate([(w_base - w_top)/2 + 1.5, (h_base - h_top)/2 + 1.5, height - 2.5])
|
||||
rounded_rectangle(w_top - 3, h_top - 3, 0.1, corner_radius/2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module single_stem(pos_x, pos_y) {
|
||||
translate([pos_x, pos_y, 0]) {
|
||||
intersection() {
|
||||
cylinder(d=stem_outer_d, h=height - (is_2u ? 1.0 : dish_depth) - 0.5);
|
||||
difference() {
|
||||
cylinder(d=stem_outer_d, h=height);
|
||||
translate([0, 0, -0.1]) {
|
||||
cube([cross_l, cross_w1, stem_h * 2], center=true);
|
||||
cube([cross_w2, cross_l, stem_h * 2], center=true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module all_stems() {
|
||||
center_x = w_base / 2;
|
||||
center_y = h_base / 2;
|
||||
single_stem(center_x, center_y);
|
||||
if (u_count_x >= 2) {
|
||||
single_stem(center_x - stab_dist/2, center_y);
|
||||
single_stem(center_x + stab_dist/2, center_y);
|
||||
}
|
||||
if (u_count_y >= 2) {
|
||||
single_stem(center_x, center_y - stab_dist/2);
|
||||
single_stem(center_x, center_y + stab_dist/2);
|
||||
}
|
||||
}
|
||||
|
||||
module side_engraving() {
|
||||
// Calculate angle based on 1u profile so text sits flush on the slope
|
||||
side_angle = atan((width_base_1u - width_top_1u) / (2 * height));
|
||||
// Offset slightly from the bottom edge
|
||||
y_offset = (width_base_1u - width_top_1u) / 4;
|
||||
|
||||
translate([w_base/2, y_offset, height/2])
|
||||
rotate([90 - side_angle, 0, 0])
|
||||
translate([0, 0, -legend_depth + 0.1])
|
||||
linear_extrude(height = legend_depth + 0.5) {
|
||||
text(legend_char, size = legend_size,
|
||||
halign = "center", valign = "center",
|
||||
font = "Overpass:style=Bold");
|
||||
}
|
||||
}
|
||||
|
||||
module support_rib() {
|
||||
rib_thickness = 1.2;
|
||||
wall_offset = 1.5;
|
||||
stem_radius = stem_outer_d / 2;
|
||||
// Inner wall starts at (width_base_1u/2 - wall_offset)
|
||||
rib_length = (width_base_1u / 2) - wall_offset - stem_radius - 0.1;
|
||||
translate([width_base_1u/2, width_base_1u/2, 0]) {
|
||||
translate([stem_radius- 0.1, -rib_thickness/2, support_depth])
|
||||
cube([rib_length, rib_thickness, height - dish_depth - support_depth]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module supports() {
|
||||
union() {
|
||||
support_rib();
|
||||
rotate([0, 0, 180])
|
||||
translate([-width_base_1u, -width_base_1u, 0])
|
||||
support_rib();
|
||||
rotate([0, 0, 90])
|
||||
translate([0, -width_base_1u, 0])
|
||||
support_rib();
|
||||
rotate([0, 0, 270])
|
||||
translate([-width_base_1u, 0, 0])
|
||||
support_rib();
|
||||
}
|
||||
}
|
||||
|
||||
// Final Assembly
|
||||
difference() {
|
||||
union() {
|
||||
xda_body();
|
||||
all_stems();
|
||||
// Ribs only for 1u
|
||||
if (!is_2u) {
|
||||
supports();
|
||||
}
|
||||
}
|
||||
side_engraving();
|
||||
}
|
||||
Reference in New Issue
Block a user