From aa795c4958f3036901d415c4d54b9b69039352f1 Mon Sep 17 00:00:00 2001 From: Bob - Home - Windows Date: Sun, 4 Feb 2018 15:43:17 -0500 Subject: [PATCH] make this library a lot more modular --- README.md | 16 +- key_profiles.scad | 147 ------------------ keys.scad | 19 ++- src/dishes.scad | 95 +---------- src/dishes/cylindrical.scad | 19 +++ src/dishes/old_spherical.scad | 25 +++ src/dishes/sideways_cylindrical.scad | 12 ++ src/dishes/spherical.scad | 26 ++++ src/key_profiles.scad | 8 + src/key_profiles/dcs.scad | 34 ++++ src/key_profiles/dsa.scad | 20 +++ src/key_profiles/g20.scad | 20 +++ src/key_profiles/oem.scad | 34 ++++ src/key_profiles/sa.scad | 34 ++++ key_sizes.scad => src/key_sizes.scad | 0 .../key_transformations.scad | 0 key_types.scad => src/key_types.scad | 0 src/shapes.scad | 93 ++--------- src/shapes/ISO_enter.scad | 34 ++++ src/shapes/oblong.scad | 11 ++ src/shapes/rounded_square.scad | 32 ++++ src/shapes/square.scad | 3 + src/stems.scad | 79 +--------- src/stems/alps.scad | 10 ++ src/stems/cherry.scad | 30 ++++ src/stems/filled.scad | 5 + src/stems/rounded_cherry.scad | 19 +++ src/supports.scad | 48 +----- src/supports/bars.scad | 6 + src/supports/flared.scad | 26 ++++ src/supports/flat.scad | 5 + 31 files changed, 467 insertions(+), 443 deletions(-) delete mode 100644 key_profiles.scad create mode 100644 src/dishes/cylindrical.scad create mode 100644 src/dishes/old_spherical.scad create mode 100644 src/dishes/sideways_cylindrical.scad create mode 100644 src/dishes/spherical.scad create mode 100644 src/key_profiles.scad create mode 100644 src/key_profiles/dcs.scad create mode 100644 src/key_profiles/dsa.scad create mode 100644 src/key_profiles/g20.scad create mode 100644 src/key_profiles/oem.scad create mode 100644 src/key_profiles/sa.scad rename key_sizes.scad => src/key_sizes.scad (100%) rename key_transformations.scad => src/key_transformations.scad (100%) rename key_types.scad => src/key_types.scad (100%) create mode 100644 src/shapes/ISO_enter.scad create mode 100644 src/shapes/oblong.scad create mode 100644 src/shapes/rounded_square.scad create mode 100644 src/shapes/square.scad create mode 100644 src/stems/alps.scad create mode 100644 src/stems/cherry.scad create mode 100644 src/stems/filled.scad create mode 100644 src/stems/rounded_cherry.scad create mode 100644 src/supports/bars.scad create mode 100644 src/supports/flared.scad create mode 100644 src/supports/flat.scad diff --git a/README.md b/README.md index 7af66ea..26ed0ed 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Relevant links: ## Let's Go! I wanna make a keycap! -At the highest level this library supports Cherry and Alps switches, and has pre-defined key profiles for SA, DSA, DCS, and (some form of) OEM keycaps. `keys.scad` is meant as an entry point for everything but the most technical use; there should already be an example at the bottom to get you started! Pre-programmed key profiles can be found at `key_profiles.scad`. +At the highest level this library supports Cherry and Alps switches, and has pre-defined key profiles for SA, DSA, DCS, and (some form of) OEM keycaps. `keys.scad` is meant as an entry point for everything but the most technical use; there should already be an example at the bottom to get you started! Pre-programmed key profiles can be found at the `key_profiles` directory. Every key starts with defaults that are overridden by each function call. The simplest cherry key you can make would be: @@ -29,7 +29,7 @@ sa_row(2) 2u() cherry() key(); ## What if I want to customize my keycaps? -There is a bevy of supporting functions to customize your keycaps. You can add a brim to more easily print the stem, switch up the stem support type, make 2x2 keycaps for a POS system, add legends, rotate stems, and more. These functions can be found in `key_profiles.scad`, `key_sizes.scad`, `key_transformations.scad`, and `key_types.scad` currently, and can be referenced directly in `keys.scad`. +There is a bevy of supporting functions to customize your keycaps. You can add a brim to more easily print the stem, switch up the stem support type, make 2x2 keycaps for a POS system, add legends, rotate stems, and more. These functions can be found in `key_profiles/`, `key_sizes.scad`, `key_transformations.scad`, and `key_types.scad` currently, and can be referenced directly in `keys.scad`. If you wanted to generate some 2u stabilized keycaps for an Ergodox for instance, you could do something like this: @@ -64,7 +64,7 @@ At the base level this library should function well as a key profile design libr Now we're talkin! -This library should be abstract enough to handle new dish types, keystems, and key shapes, in case you want to design your own Typewriter-style keycaps, support buckling spring keyboards or design some kind of triangular dished profile. `src/shapes.scad` `src/stems.scad` and `src/dishes.scad` all have a 'selector' module at the top that should allow you to implement your own creations alongside what already exists. +This library should be abstract enough to handle new dish types, keystems, and key shapes, in case you want to design your own Typewriter-style keycaps, support buckling spring keyboards or design some kind of triangular dished profile. `src/shapes.scad` `src/stems.scad` and `src/dishes.scad` all have a 'selector' module that should allow you to implement your own creations alongside what already exists in their constituent folders. Here's an example of tweaking the settings and code to make a 'stop sign' key profile: @@ -72,10 +72,18 @@ In `key_shape()` in `shapes.scad`: ``` else if ($key_shape_type == "stop_sign") { - rotate([0,0,22.5]) circle(d=size[0] - delta[0], $fn=8); + stop_sign_shape(size, delta, progress); } ``` +in `src/shapes/stop_sign.scad`: + +``` +module stop_sign_shape(size, delta, progress){ + rotate([0,0,22.5]) circle(d=size[0] - delta[0], $fn=8); +} +``` + In `keys.scad`: ``` diff --git a/key_profiles.scad b/key_profiles.scad deleted file mode 100644 index 23a0487..0000000 --- a/key_profiles.scad +++ /dev/null @@ -1,147 +0,0 @@ -// key profile definitions - -module dcs_row(n=1) { - // names, so I don't go crazy - $bottom_key_width = 18.16; - $bottom_key_height = 18.16; - $width_difference = 6; - $height_difference = 4; - $dish_type = "cylindrical"; - $dish_depth = 1; - $dish_skew_x = 0; - $dish_skew_y = 0; - $top_skew = 1.75; - - if (n == 5) { - $total_depth = 11.5; - $top_tilt = -6; - children(); - } else if (n == 1) { - $total_depth = 8.5; - $top_tilt = -1; - children(); - } else if (n == 2) { - $total_depth = 7.5; - $top_tilt = 3; - children(); - } else if (n == 3) { - $total_depth = 6; - $top_tilt = 7; - children(); - } else if (n == 4) { - $total_depth = 6; - $top_tilt = 16; - children(); - } -} - -module oem_row(n=1) { - $bottom_key_width = 18.05; - $bottom_key_height = 18.05; - $width_difference = 5.8; - $height_difference = 4; - $dish_type = "cylindrical"; - $dish_depth = 1; - $dish_skew_x = 0; - $dish_skew_y = 0; - $top_skew = 1.75; - $stem_inset = 1.2; - - if (n == 5) { - $total_depth = 11.2; - $top_tilt = -3; - children(); - } else if (n == 1) { - $total_depth = 9.45; - $top_tilt = 1; - children(); - } else if (n == 2) { - $total_depth = 9; - $top_tilt = 6; - children(); - } else if (n == 3) { - $total_depth = 9.25; - $top_tilt = 9; - children(); - } else if (n == 4) { - $total_depth = 9.25; - $top_tilt = 10; - children(); - } -} - -module dsa_row(n=3) { - $bottom_key_width = 18.24; // 18.4; - $bottom_key_height = 18.24; // 18.4; - $width_difference = 6; // 5.7; - $height_difference = 6; // 5.7; - $total_depth = 8.1; - $top_tilt = (n-1) * 7 - 14; - $top_skew = 0; - $dish_type = "spherical"; - $dish_depth = 1.2; - $dish_skew_x = 0; - $dish_skew_y = 0; - $height_slices = 10; - $enable_side_sculpting = true; - // might wanna change this if you don't minkowski - // do you even minkowski bro - $corner_radius = 0.25; - - children(); -} - -module sa_row(n=1) { - $bottom_key_width = 18.4; - $bottom_key_height = 18.4; - $width_difference = 5.7; - $height_difference = 5.7; - $dish_type = "spherical"; - $dish_depth = 0.85; - $dish_skew_x = 0; - $dish_skew_y = 0; - $top_skew = 0; - $height_slices = 10; - $enable_side_sculpting = true; - // might wanna change this if you don't minkowski - // do you even minkowski bro - $corner_radius = 0.25; - - if (n == 1){ - $total_depth = 14.89; - $top_tilt = -13; - children(); - } else if (n == 2) { - $total_depth = 12.925; - $top_tilt = -7; - children(); - } else if (n == 3) { - $total_depth = 12.5; - $top_tilt = 0; - children(); - } else if (n == 4){ - $total_depth = 12.925; - $top_tilt = 7; - children(); - } -} - -module g20() { - $bottom_key_width = 18.16; - $bottom_key_height = 18.16; - $width_difference = 2; - $height_difference = 2; - $total_depth = 6; - $top_tilt = 2.5; - $top_skew = 0.75; - $dish_type = "no dish"; - $dish_depth = 0; - $dish_skew_x = 0; - $dish_skew_y = 0; - $minkowski_radius = 1.75; - - - children(); - //also, - /*$rounded_key = true;*/ -} diff --git a/keys.scad b/keys.scad index b99700f..4cecd6a 100644 --- a/keys.scad +++ b/keys.scad @@ -11,10 +11,10 @@ unit = 19.05; use include -include -include -include -include +include +include +include +include module translate_u(x=0, y=0, z=0){ translate([x * unit, y*unit, z*unit]) children(); @@ -25,7 +25,7 @@ cherry() key(); translate_u(1) sa_row(2) cherry() key("q"); translate_u(2) oem_row(2) alps() key("q", inset=true); -translate_u(3) dsa_row() rounded_cherry() key(); +translate_u(3) dsa_row() flat_support() rounded_cherry() key(); translate_u(1, 1) sa_row(3) lshift() cherry() key(inset=true) { sphere(1); @@ -34,8 +34,15 @@ translate_u(1, 1) sa_row(3) lshift() cherry() key(inset=true) { translate_u(3, 2) sa_row(3) bar_support() spacebar() cherry() key("space bar"); translate_u(3,1) sa_row(3) 2u() cherry() { - $key_shape_type = "spherical"; + $key_shape_type = "oblong"; $support_type = false; $inverted_dish = true; key(); } + + +/* // g20 / dsa sculpting test +for (x = [1:5]) { + translate_u(0, x) dsa_row(x) cherry() key(); + translate_u(1, x) g20_row(x) cherry() key(); +} */ diff --git a/src/dishes.scad b/src/dishes.scad index e6ebe3d..39c1ab4 100644 --- a/src/dishes.scad +++ b/src/dishes.scad @@ -1,5 +1,10 @@ include -include + +include +include +include +include + //geodesic looks much better, but runs very slow for anything above a 2u geodesic=false; @@ -18,93 +23,7 @@ module dish(width, height, depth, inverted) { old_spherical_dish(width, height, depth, inverted); } else { // else no dish, "no dish" is the value - // switchted to actually diffing a cube here due to (hopeful) changes to stems being differenced from the dish instead of the inside + // switchted to actually diffing a cube here due to changes to stems being differenced from the dish instead of the inside translate([0,0,500]) cube([width, height, 1000], center=true); } } - -module cylindrical_dish(width, height, depth, inverted){ - // .5 has problems starting around 3u - $fa=.25; - /* we do some funky math here - * basically you want to have the dish "dig in" to the keycap x millimeters - * in order to do that you have to solve a small (2d) system of equations - * where the chord of the spherical cross section of the dish is - * the width of the keycap. - */ - // the distance you have to move the dish so it digs in depth millimeters - chord_length = (pow(width, 2) - 4 * pow(depth, 2)) / (8 * depth); - //the radius of the dish - rad = (pow(width, 2) + 4 * pow(depth, 2)) / (8 * depth); - direction = inverted ? -1 : 1; - - translate([0,0, chord_length * direction]){ - rotate([90, 0, 0]) cylinder(h=height + 20, r=rad, center=true); - } -} - -module sideways_cylindrical_dish(width, height, depth, inverted){ - $fa=1; - chord_length = (pow(height, 2) - 4 * pow(depth, 2)) / (8 * depth); - rad = (pow(height, 2) + 4 * pow(depth, 2)) / (8 * depth); - - direction = inverted ? -1 : 1; - - translate([0,0, chord_length * direction]){ - // cylinder is rendered facing up, so we rotate it on the y axis first - rotate([0,90,0]) cylinder(h = width + 20,r=rad, center=true); // +20 for fudge factor - } -} - -module spherical_dish(width, height, depth, inverted){ - - //same thing as the cylindrical dish here, but we need the corners to just touch - so we have to find the hypotenuse of the top - chord = pow((pow(width,2) + pow(height, 2)),0.5); //getting diagonal of the top - - // the distance you have to move the dish up so it digs in depth millimeters - chord_length = (pow(chord, 2) - 4 * pow(depth, 2)) / (8 * depth); - //the radius of the dish - rad = (pow(chord, 2) + 4 * pow(depth, 2)) / (8 * depth); - direction = inverted ? -1 : 1; - - translate([0,0,0 * direction]){ - if (geodesic){ - $fa=20; - scale([chord/2/depth, chord/2/depth]) { - geodesic_sphere(r=depth); - } - } else { - $fa=7; - // rotate 1 because the bottom of the sphere looks like trash. - scale([chord/2/depth, chord/2/depth]) { - geodesic_sphere(r=depth); - } - } - } -} - -//the older, 'more accurate', and MUCH slower spherical dish. -// generates the largest sphere possible that still contains the chord we are looking for -// much more graduated curvature at an immense cost -module old_spherical_dish(width, height, depth, inverted){ - - //same thing as the cylindrical dish here, but we need the corners to just touch - so we have to find the hypotenuse of the top - chord = pow((pow(width,2) + pow(height, 2)),0.5); //getting diagonal of the top - - // the distance you have to move the dish up so it digs in depth millimeters - chord_length = (pow(chord, 2) - 4 * pow(depth, 2)) / (8 * depth); - //the radius of the dish - rad = (pow(chord, 2) + 4 * pow(depth, 2)) / (8 * depth); - direction = inverted ? -1 : 1; - - translate([0,0,chord_length * direction]){ - if (geodesic){ - $fa=7; - geodesic_sphere(r=rad); - } else { - $fa=1; - // rotate 1 because the bottom of the sphere looks like trash - sphere(r=rad); - } - } -} diff --git a/src/dishes/cylindrical.scad b/src/dishes/cylindrical.scad new file mode 100644 index 0000000..5040865 --- /dev/null +++ b/src/dishes/cylindrical.scad @@ -0,0 +1,19 @@ +module cylindrical_dish(width, height, depth, inverted){ + // .5 has problems starting around 3u + $fa=.25; + /* we do some funky math here + * basically you want to have the dish "dig in" to the keycap x millimeters + * in order to do that you have to solve a small (2d) system of equations + * where the chord of the spherical cross section of the dish is + * the width of the keycap. + */ + // the distance you have to move the dish so it digs in depth millimeters + chord_length = (pow(width, 2) - 4 * pow(depth, 2)) / (8 * depth); + //the radius of the dish + rad = (pow(width, 2) + 4 * pow(depth, 2)) / (8 * depth); + direction = inverted ? -1 : 1; + + translate([0,0, chord_length * direction]){ + rotate([90, 0, 0]) cylinder(h=height + 20, r=rad, center=true); + } +} diff --git a/src/dishes/old_spherical.scad b/src/dishes/old_spherical.scad new file mode 100644 index 0000000..c2726fe --- /dev/null +++ b/src/dishes/old_spherical.scad @@ -0,0 +1,25 @@ +//the older, 'more accurate', and MUCH slower spherical dish. +// generates the largest sphere possible that still contains the chord we are looking for +// much more graduated curvature at an immense cost +module old_spherical_dish(width, height, depth, inverted){ + + //same thing as the cylindrical dish here, but we need the corners to just touch - so we have to find the hypotenuse of the top + chord = pow((pow(width,2) + pow(height, 2)),0.5); //getting diagonal of the top + + // the distance you have to move the dish up so it digs in depth millimeters + chord_length = (pow(chord, 2) - 4 * pow(depth, 2)) / (8 * depth); + //the radius of the dish + rad = (pow(chord, 2) + 4 * pow(depth, 2)) / (8 * depth); + direction = inverted ? -1 : 1; + + translate([0,0,chord_length * direction]){ + if (geodesic){ + $fa=7; + geodesic_sphere(r=rad); + } else { + $fa=1; + // rotate 1 because the bottom of the sphere looks like trash + sphere(r=rad); + } + } +} diff --git a/src/dishes/sideways_cylindrical.scad b/src/dishes/sideways_cylindrical.scad new file mode 100644 index 0000000..6d357b1 --- /dev/null +++ b/src/dishes/sideways_cylindrical.scad @@ -0,0 +1,12 @@ +module sideways_cylindrical_dish(width, height, depth, inverted){ + $fa=1; + chord_length = (pow(height, 2) - 4 * pow(depth, 2)) / (8 * depth); + rad = (pow(height, 2) + 4 * pow(depth, 2)) / (8 * depth); + + direction = inverted ? -1 : 1; + + translate([0,0, chord_length * direction]){ + // cylinder is rendered facing up, so we rotate it on the y axis first + rotate([0,90,0]) cylinder(h = width + 20,r=rad, center=true); // +20 for fudge factor + } +} diff --git a/src/dishes/spherical.scad b/src/dishes/spherical.scad new file mode 100644 index 0000000..9dfbd7c --- /dev/null +++ b/src/dishes/spherical.scad @@ -0,0 +1,26 @@ +module spherical_dish(width, height, depth, inverted){ + + //same thing as the cylindrical dish here, but we need the corners to just touch - so we have to find the hypotenuse of the top + chord = pow((pow(width,2) + pow(height, 2)),0.5); //getting diagonal of the top + + // the distance you have to move the dish up so it digs in depth millimeters + chord_length = (pow(chord, 2) - 4 * pow(depth, 2)) / (8 * depth); + //the radius of the dish + rad = (pow(chord, 2) + 4 * pow(depth, 2)) / (8 * depth); + direction = inverted ? -1 : 1; + + translate([0,0,0 * direction]){ + if (geodesic){ + $fa=20; + scale([chord/2/depth, chord/2/depth]) { + geodesic_sphere(r=depth); + } + } else { + $fa=7; + // rotate 1 because the bottom of the sphere looks like trash. + scale([chord/2/depth, chord/2/depth]) { + geodesic_sphere(r=depth); + } + } + } +} diff --git a/src/key_profiles.scad b/src/key_profiles.scad new file mode 100644 index 0000000..d906c6e --- /dev/null +++ b/src/key_profiles.scad @@ -0,0 +1,8 @@ +// key profile definitions + +// unlike the other files with their own dedicated folders, this one doesn't need a selector. it just collects all the functions +include +include +include +include +include diff --git a/src/key_profiles/dcs.scad b/src/key_profiles/dcs.scad new file mode 100644 index 0000000..fcb0312 --- /dev/null +++ b/src/key_profiles/dcs.scad @@ -0,0 +1,34 @@ +module dcs_row(n=1) { + // names, so I don't go crazy + $bottom_key_width = 18.16; + $bottom_key_height = 18.16; + $width_difference = 6; + $height_difference = 4; + $dish_type = "cylindrical"; + $dish_depth = 1; + $dish_skew_x = 0; + $dish_skew_y = 0; + $top_skew = 1.75; + + if (n == 5) { + $total_depth = 11.5; + $top_tilt = -6; + children(); + } else if (n == 1) { + $total_depth = 8.5; + $top_tilt = -1; + children(); + } else if (n == 2) { + $total_depth = 7.5; + $top_tilt = 3; + children(); + } else if (n == 3) { + $total_depth = 6; + $top_tilt = 7; + children(); + } else if (n == 4) { + $total_depth = 6; + $top_tilt = 16; + children(); + } +} diff --git a/src/key_profiles/dsa.scad b/src/key_profiles/dsa.scad new file mode 100644 index 0000000..904c00e --- /dev/null +++ b/src/key_profiles/dsa.scad @@ -0,0 +1,20 @@ +module dsa_row(n=3) { + $bottom_key_width = 18.24; // 18.4; + $bottom_key_height = 18.24; // 18.4; + $width_difference = 6; // 5.7; + $height_difference = 6; // 5.7; + $total_depth = 8.1 + abs((n-3) * 1); + $top_tilt = (n-3) * -7; + $top_skew = 0; + $dish_type = "spherical"; + $dish_depth = 1.2; + $dish_skew_x = 0; + $dish_skew_y = 0; + $height_slices = 10; + $enable_side_sculpting = true; + // might wanna change this if you don't minkowski + // do you even minkowski bro + $corner_radius = 0.25; + + children(); +} diff --git a/src/key_profiles/g20.scad b/src/key_profiles/g20.scad new file mode 100644 index 0000000..9629cc9 --- /dev/null +++ b/src/key_profiles/g20.scad @@ -0,0 +1,20 @@ +module g20_row(n=3) { + $bottom_key_width = 18.16; + $bottom_key_height = 18.16; + $width_difference = 2; + $height_difference = 2; + $total_depth = 6; + $top_tilt = 2.5; + $top_tilt = (n-3) * -7 + 2.5; + $top_skew = 0.75; + $dish_type = "no dish"; + $dish_depth = 0; + $dish_skew_x = 0; + $dish_skew_y = 0; + $minkowski_radius = 1.75; + //also, + /*$rounded_key = true;*/ + + + children(); +} diff --git a/src/key_profiles/oem.scad b/src/key_profiles/oem.scad new file mode 100644 index 0000000..c3d78e1 --- /dev/null +++ b/src/key_profiles/oem.scad @@ -0,0 +1,34 @@ +module oem_row(n=1) { + $bottom_key_width = 18.05; + $bottom_key_height = 18.05; + $width_difference = 5.8; + $height_difference = 4; + $dish_type = "cylindrical"; + $dish_depth = 1; + $dish_skew_x = 0; + $dish_skew_y = 0; + $top_skew = 1.75; + $stem_inset = 1.2; + + if (n == 5) { + $total_depth = 11.2; + $top_tilt = -3; + children(); + } else if (n == 1) { + $total_depth = 9.45; + $top_tilt = 1; + children(); + } else if (n == 2) { + $total_depth = 9; + $top_tilt = 6; + children(); + } else if (n == 3) { + $total_depth = 9.25; + $top_tilt = 9; + children(); + } else if (n == 4) { + $total_depth = 9.25; + $top_tilt = 10; + children(); + } +} diff --git a/src/key_profiles/sa.scad b/src/key_profiles/sa.scad new file mode 100644 index 0000000..0808cfc --- /dev/null +++ b/src/key_profiles/sa.scad @@ -0,0 +1,34 @@ +module sa_row(n=1) { + $bottom_key_width = 18.4; + $bottom_key_height = 18.4; + $width_difference = 5.7; + $height_difference = 5.7; + $dish_type = "spherical"; + $dish_depth = 0.85; + $dish_skew_x = 0; + $dish_skew_y = 0; + $top_skew = 0; + $height_slices = 10; + $enable_side_sculpting = true; + // might wanna change this if you don't minkowski + // do you even minkowski bro + $corner_radius = 0.25; + + if (n == 1){ + $total_depth = 14.89; + $top_tilt = -13; + children(); + } else if (n == 2) { + $total_depth = 12.925; + $top_tilt = -7; + children(); + } else if (n == 3) { + $total_depth = 12.5; + $top_tilt = 0; + children(); + } else if (n == 4){ + $total_depth = 12.925; + $top_tilt = 7; + children(); + } +} diff --git a/key_sizes.scad b/src/key_sizes.scad similarity index 100% rename from key_sizes.scad rename to src/key_sizes.scad diff --git a/key_transformations.scad b/src/key_transformations.scad similarity index 100% rename from key_transformations.scad rename to src/key_transformations.scad diff --git a/key_types.scad b/src/key_types.scad similarity index 100% rename from key_types.scad rename to src/key_types.scad diff --git a/src/shapes.scad b/src/shapes.scad index c463b76..5a496d0 100644 --- a/src/shapes.scad +++ b/src/shapes.scad @@ -1,96 +1,21 @@ $fs=.1; unit = 19.05; -// side sculpting functions -// bows the sides out on stuff like SA and DSA keycaps -function side_sculpting(progress) = (1 - progress) * 2.5; -// makes the rounded corners of the keycap grow larger as they move upwards -function corner_sculpting(progress) = pow(progress, 2); +include +include +include +include module key_shape(size, delta, progress = 0) { if ($key_shape_type == "iso_enter") { - ISO_enter(size, delta, progress); + ISO_enter_shape(size, delta, progress); } else if ($key_shape_type == "rounded_square") { - roundedSquare(size, delta, progress); + rounded_square_shape(size, delta, progress); } else if ($key_shape_type == "square") { - square(size - delta, center = true); - } else if ($key_shape_type == "spherical") { - spherical(size, delta, progress); + square_shape(size, delta, progress); + } else if ($key_shape_type == "oblong") { + oblong_shape(size, delta, progress); } else { echo("Warning: unsupported $key_shape_type"); } } - -module spherical(size, delta, progress) { - // .05 is because of offset. if we set offset to be half the height of the shape, and then subtract height from the shape, the height of the shape will be zero (because the shape would be [width - height, height - height]). that doesn't play well with openSCAD (understandably), so we add this tiny fudge factor to make sure the shape we offset has a positive width - height = size[1] - delta[1] * progress - .05; - - if (progress < 0.5) { - } else { - offset(r=height / 2) { - square(size - [height, height] - delta * progress, center=true); - } - } -} - -module roundedSquare(size, delta, progress, center = true) { - width = size[0]; - height = size[1]; - - width_difference = delta[0]; - height_difference = delta[1]; - // makes the sides bow - extra_side_size = $enable_side_sculpting ? side_sculpting(progress) : 0; - // makes the rounded corners of the keycap grow larger as they move upwards - extra_corner_size = $enable_side_sculpting ? corner_sculpting(progress) : 0; - - // computed values for this slice - extra_width_this_slice = (width_difference - extra_side_size) * progress; - extra_height_this_slice = (height_difference - extra_side_size) * progress; - extra_corner_radius_this_slice = ($corner_radius + extra_corner_size); - - offset(r=extra_corner_radius_this_slice){ - square( - [ - width - extra_width_this_slice - extra_corner_radius_this_slice * 2, - height - extra_height_this_slice - extra_corner_radius_this_slice * 2 - ], - center=center - ); - } -} - -// corollary is roundedSquare -// NOT 3D -module ISO_enter(size, delta, progress){ - width = size[0]; - height = size[1]; - function unit_length(length) = unit * (length - 1) + 18.16; - - - // in order to make the ISO keycap shape generic, we are going to express the - // 'elbow point' in terms of ratios. an ISO enter is just a 1.5u key stuck on - // top of a 1.25u key, but since our key_shape function doesnt understand that - // and wants to pass just width and height, we make these ratios to know where - // to put the elbow joint - - width_ratio = unit_length(1.25) / unit_length(1.5); - height_ratio = unit_length(1) / unit_length(2); - - pointArray = [ - [ 0, 0], // top right - [ 0, -height], // bottom right - [-width * width_ratio, -height], // bottom left - [-width * width_ratio,-height * height_ratio], // inner middle point - [ -width,-height * height_ratio], // outer middle point - [ -width, 0] // top left - ]; - - minkowski(){ - circle(r=corner_size); - // gives us rounded inner corner - offset(r=-corner_size*2) { - translate([(width * width_ratio)/2, height/2]) polygon(points=pointArray); - } - } -} diff --git a/src/shapes/ISO_enter.scad b/src/shapes/ISO_enter.scad new file mode 100644 index 0000000..b70adaa --- /dev/null +++ b/src/shapes/ISO_enter.scad @@ -0,0 +1,34 @@ +// corollary is rounded_square +// NOT 3D +module ISO_enter_shape(size, delta, progress){ + width = size[0]; + height = size[1]; + function unit_length(length) = unit * (length - 1) + 18.16; + + + // in order to make the ISO keycap shape generic, we are going to express the + // 'elbow point' in terms of ratios. an ISO enter is just a 1.5u key stuck on + // top of a 1.25u key, but since our key_shape function doesnt understand that + // and wants to pass just width and height, we make these ratios to know where + // to put the elbow joint + + width_ratio = unit_length(1.25) / unit_length(1.5); + height_ratio = unit_length(1) / unit_length(2); + + pointArray = [ + [ 0, 0], // top right + [ 0, -height], // bottom right + [-width * width_ratio, -height], // bottom left + [-width * width_ratio,-height * height_ratio], // inner middle point + [ -width,-height * height_ratio], // outer middle point + [ -width, 0] // top left + ]; + + minkowski(){ + circle(r=corner_size); + // gives us rounded inner corner + offset(r=-corner_size*2) { + translate([(width * width_ratio)/2, height/2]) polygon(points=pointArray); + } + } +} diff --git a/src/shapes/oblong.scad b/src/shapes/oblong.scad new file mode 100644 index 0000000..fff567a --- /dev/null +++ b/src/shapes/oblong.scad @@ -0,0 +1,11 @@ +module oblong_shape(size, delta, progress) { + // .05 is because of offset. if we set offset to be half the height of the shape, and then subtract height from the shape, the height of the shape will be zero (because the shape would be [width - height, height - height]). that doesn't play well with openSCAD (understandably), so we add this tiny fudge factor to make sure the shape we offset has a positive width + height = size[1] - delta[1] * progress - .05; + + if (progress < 0.5) { + } else { + offset(r=height / 2) { + square(size - [height, height] - delta * progress, center=true); + } + } +} diff --git a/src/shapes/rounded_square.scad b/src/shapes/rounded_square.scad new file mode 100644 index 0000000..4beca23 --- /dev/null +++ b/src/shapes/rounded_square.scad @@ -0,0 +1,32 @@ +// side sculpting functions +// bows the sides out on stuff like SA and DSA keycaps +function side_sculpting(progress) = (1 - progress) * 2.5; +// makes the rounded corners of the keycap grow larger as they move upwards +function corner_sculpting(progress) = pow(progress, 2); + +module rounded_square_shape(size, delta, progress, center = true) { + width = size[0]; + height = size[1]; + + width_difference = delta[0]; + height_difference = delta[1]; + // makes the sides bow + extra_side_size = $enable_side_sculpting ? side_sculpting(progress) : 0; + // makes the rounded corners of the keycap grow larger as they move upwards + extra_corner_size = $enable_side_sculpting ? corner_sculpting(progress) : 0; + + // computed values for this slice + extra_width_this_slice = (width_difference - extra_side_size) * progress; + extra_height_this_slice = (height_difference - extra_side_size) * progress; + extra_corner_radius_this_slice = ($corner_radius + extra_corner_size); + + offset(r=extra_corner_radius_this_slice){ + square( + [ + width - extra_width_this_slice - extra_corner_radius_this_slice * 2, + height - extra_height_this_slice - extra_corner_radius_this_slice * 2 + ], + center=center + ); + } +} diff --git a/src/shapes/square.scad b/src/shapes/square.scad new file mode 100644 index 0000000..f62a192 --- /dev/null +++ b/src/shapes/square.scad @@ -0,0 +1,3 @@ +module square_shape(size, delta, progress){ + square(size - delta * progress, center = true); +} diff --git a/src/stems.scad b/src/stems.scad index bcb7f5e..82e64cb 100644 --- a/src/stems.scad +++ b/src/stems.scad @@ -1,85 +1,20 @@ +include +include +include +include + + //whole stem, alps or cherry, trimmed to fit module stem(stem_type, depth, has_brim){ if (stem_type == "alps") { alps_stem(depth, has_brim); } else if (stem_type == "cherry_rounded") { - cherry_stem_rounded(depth, has_brim); + rounded_cherry_stem(depth, has_brim); } else if (stem_type == "cherry") { cherry_stem(depth, has_brim); } else if (stem_type == "filled") { - // just a cube, so no args filled_stem(); } else { echo("Warning: unsupported $stem_type"); } } - -module cherry_stem(depth, has_brim) { - difference(){ - union() { - // outside shape - linear_extrude(height = depth) { - offset(r=1){ - square($cherry_stem - [2,2], center=true); - } - } - - // brim, if applicable - if(has_brim) { - linear_extrude(height = brim_height){ - offset(r=1){ - square($cherry_stem - [2,2], center=true); - } - } - } - } - - // inside cross - // translation purely for aesthetic purposes, to get rid of that awful lattice - translate([0,0,-0.005]) { - linear_extrude(height = $stem_throw) { - square($cherry_cross[0], center=true); - square($cherry_cross[1], center=true); - } - } - } -} - -module cherry_stem_rounded(depth, has_brim) { - - - difference(){ - union(){ - cylinder(d=$rounded_cherry_stem_d, h=depth); - if(has_brim) { - cylinder(d=$rounded_cherry_stem_d * 2, h=brim_height); - } - } - - // inside cross - // translation purely for aesthetic purposes, to get rid of that awful lattice - translate([0,0,-0.005]) { - linear_extrude(height = $stem_throw) { - square($cherry_cross[0], center=true); - square($cherry_cross[1], center=true); - } - } - } -} - -module alps_stem(depth, has_brim){ - if(has_brim) { - linear_extrude(h=brim_height) { - square($alps_stem * [2,2], center = true); - } - } - linear_extrude(h=depth) { - square($alps_stem, center = true); - } -} - -module filled_stem() { - // this is mostly for testing. we don't pass the size of the keycp in here - // so we can't make this work for all keys - cube(1000, center=true); -} diff --git a/src/stems/alps.scad b/src/stems/alps.scad new file mode 100644 index 0000000..2babe63 --- /dev/null +++ b/src/stems/alps.scad @@ -0,0 +1,10 @@ +module alps_stem(depth, has_brim){ + if(has_brim) { + linear_extrude(h=brim_height) { + square($alps_stem * [2,2], center = true); + } + } + linear_extrude(h=depth) { + square($alps_stem, center = true); + } +} diff --git a/src/stems/cherry.scad b/src/stems/cherry.scad new file mode 100644 index 0000000..a02df73 --- /dev/null +++ b/src/stems/cherry.scad @@ -0,0 +1,30 @@ +module cherry_stem(depth, has_brim) { + difference(){ + union() { + // outside shape + linear_extrude(height = depth) { + offset(r=1){ + square($cherry_stem - [2,2], center=true); + } + } + + // brim, if applicable + if(has_brim) { + linear_extrude(height = brim_height){ + offset(r=1){ + square($cherry_stem - [2,2], center=true); + } + } + } + } + + // inside cross + // translation purely for aesthetic purposes, to get rid of that awful lattice + translate([0,0,-0.005]) { + linear_extrude(height = $stem_throw) { + square($cherry_cross[0], center=true); + square($cherry_cross[1], center=true); + } + } + } +} diff --git a/src/stems/filled.scad b/src/stems/filled.scad new file mode 100644 index 0000000..80248f4 --- /dev/null +++ b/src/stems/filled.scad @@ -0,0 +1,5 @@ +module filled_stem() { + // this is mostly for testing. we don't pass the size of the keycp in here + // so we can't make this work for all keys + cube(1000, center=true); +} diff --git a/src/stems/rounded_cherry.scad b/src/stems/rounded_cherry.scad new file mode 100644 index 0000000..265b0d2 --- /dev/null +++ b/src/stems/rounded_cherry.scad @@ -0,0 +1,19 @@ +module rounded_cherry_stem(depth, has_brim) { + difference(){ + union(){ + cylinder(d=$rounded_cherry_stem_d, h=depth); + if(has_brim) { + cylinder(d=$rounded_cherry_stem_d * 2, h=brim_height); + } + } + + // inside cross + // translation purely for aesthetic purposes, to get rid of that awful lattice + translate([0,0,-0.005]) { + linear_extrude(height = $stem_throw) { + square($cherry_cross[0], center=true); + square($cherry_cross[1], center=true); + } + } + } +} diff --git a/src/supports.scad b/src/supports.scad index 0579fbd..4cd0d1f 100644 --- a/src/supports.scad +++ b/src/supports.scad @@ -1,51 +1,15 @@ -// figures out the scale factor needed to make a 45 degree wall -function scale_for_45(height, starting_size) = (height * 2 + starting_size) / starting_size; +include +include +include module supports(type, stem_type, loft, height) { if (type == "flared") { - flared(stem_type, loft, height); + flared_support(stem_type, loft, height); } else if (type == "flat") { - flat(stem_type, loft, height); + flat_support(stem_type, loft, height); } else if (type == "bars") { - bars(stem_type, loft, height); + bars_support(stem_type, loft, height); } else { echo("Warning: unsupported $support_type"); } } - -// complicated since we want the different stems to work well -// also kind of messy... oh well -module flared(stem_type, loft, height) { - translate([0,0,loft]){ - if(stem_type == "cherry") { - cherry_scale = [scale_for_45(height, $cherry_stem[0]), scale_for_45(height, $cherry_stem[1])]; - linear_extrude(height=height, scale = cherry_scale){ - offset(r=1){ - square($cherry_stem - [2,2], center=true); - } - } - } else if (stem_type == "cherry_rounded") { - linear_extrude(height=height, scale = scale_for_45(height, $rounded_cherry_stem_d)){ - circle(d=$rounded_cherry_stem_d); - } - } else if (stem_type == "alps") { - alps_scale = [scale_for_45(height, $alps_stem[0]), scale_for_45(height, $alps_stem[1])]; - linear_extrude(height=height, scale = alps_scale){ - square($alps_stem, center=true); - } - } - } -} - -module flat(stem_type, loft, height) { - translate([0,0,loft + 500]){ - cube(1000, center=true); - } -} - -module bars(stem_type, loft, height) { - translate([0,0,loft + height / 2]){ - cube([2, 100, height], center = true); - cube([100, 2, height], center = true); - } -} diff --git a/src/supports/bars.scad b/src/supports/bars.scad new file mode 100644 index 0000000..66266a0 --- /dev/null +++ b/src/supports/bars.scad @@ -0,0 +1,6 @@ +module bars_support(stem_type, loft, height) { + translate([0,0,loft + height / 2]){ + cube([2, 100, height], center = true); + cube([100, 2, height], center = true); + } +} diff --git a/src/supports/flared.scad b/src/supports/flared.scad new file mode 100644 index 0000000..f43749e --- /dev/null +++ b/src/supports/flared.scad @@ -0,0 +1,26 @@ +// figures out the scale factor needed to make a 45 degree wall +function scale_for_45(height, starting_size) = (height * 2 + starting_size) / starting_size; + +// complicated since we want the different stems to work well +// also kind of messy... oh well +module flared_support(stem_type, loft, height) { + translate([0,0,loft]){ + if(stem_type == "cherry") { + cherry_scale = [scale_for_45(height, $cherry_stem[0]), scale_for_45(height, $cherry_stem[1])]; + linear_extrude(height=height, scale = cherry_scale){ + offset(r=1){ + square($cherry_stem - [2,2], center=true); + } + } + } else if (stem_type == "cherry_rounded") { + linear_extrude(height=height, scale = scale_for_45(height, $rounded_cherry_stem_d)){ + circle(d=$rounded_cherry_stem_d); + } + } else if (stem_type == "alps") { + alps_scale = [scale_for_45(height, $alps_stem[0]), scale_for_45(height, $alps_stem[1])]; + linear_extrude(height=height, scale = alps_scale){ + square($alps_stem, center=true); + } + } + } +} diff --git a/src/supports/flat.scad b/src/supports/flat.scad new file mode 100644 index 0000000..524870e --- /dev/null +++ b/src/supports/flat.scad @@ -0,0 +1,5 @@ +module flat_support(stem_type, loft, height) { + translate([0,0,loft + 500]){ + cube(1000, center=true); + } +}