mirror of
https://github.com/rsheldiii/KeyV2.git
synced 2024-11-22 13:13:40 +00:00
make this library a lot more modular
This commit is contained in:
parent
2368961370
commit
aa795c4958
16
README.md
16
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`:
|
||||
|
||||
```
|
||||
|
@ -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;*/
|
||||
}
|
19
keys.scad
19
keys.scad
@ -11,10 +11,10 @@ unit = 19.05;
|
||||
use <src/key.scad>
|
||||
|
||||
include <src/settings.scad>
|
||||
include <key_sizes.scad>
|
||||
include <key_profiles.scad>
|
||||
include <key_types.scad>
|
||||
include <key_transformations.scad>
|
||||
include <src/key_sizes.scad>
|
||||
include <src/key_profiles.scad>
|
||||
include <src/key_types.scad>
|
||||
include <src/key_transformations.scad>
|
||||
|
||||
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();
|
||||
} */
|
||||
|
@ -1,5 +1,10 @@
|
||||
include <libraries/geodesic_sphere.scad>
|
||||
include <shapes.scad>
|
||||
|
||||
include <dishes/cylindrical.scad>
|
||||
include <dishes/old_spherical.scad>
|
||||
include <dishes/sideways_cylindrical.scad>
|
||||
include <dishes/spherical.scad>
|
||||
|
||||
//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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
19
src/dishes/cylindrical.scad
Normal file
19
src/dishes/cylindrical.scad
Normal file
@ -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);
|
||||
}
|
||||
}
|
25
src/dishes/old_spherical.scad
Normal file
25
src/dishes/old_spherical.scad
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
12
src/dishes/sideways_cylindrical.scad
Normal file
12
src/dishes/sideways_cylindrical.scad
Normal file
@ -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
|
||||
}
|
||||
}
|
26
src/dishes/spherical.scad
Normal file
26
src/dishes/spherical.scad
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
8
src/key_profiles.scad
Normal file
8
src/key_profiles.scad
Normal file
@ -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 <key_profiles/dcs.scad>
|
||||
include <key_profiles/oem.scad>
|
||||
include <key_profiles/dsa.scad>
|
||||
include <key_profiles/sa.scad>
|
||||
include <key_profiles/g20.scad>
|
34
src/key_profiles/dcs.scad
Normal file
34
src/key_profiles/dcs.scad
Normal file
@ -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();
|
||||
}
|
||||
}
|
20
src/key_profiles/dsa.scad
Normal file
20
src/key_profiles/dsa.scad
Normal file
@ -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();
|
||||
}
|
20
src/key_profiles/g20.scad
Normal file
20
src/key_profiles/g20.scad
Normal file
@ -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();
|
||||
}
|
34
src/key_profiles/oem.scad
Normal file
34
src/key_profiles/oem.scad
Normal file
@ -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();
|
||||
}
|
||||
}
|
34
src/key_profiles/sa.scad
Normal file
34
src/key_profiles/sa.scad
Normal file
@ -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();
|
||||
}
|
||||
}
|
@ -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 <shapes/ISO_enter.scad>
|
||||
include <shapes/rounded_square.scad>
|
||||
include <shapes/square.scad>
|
||||
include <shapes/oblong.scad>
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
34
src/shapes/ISO_enter.scad
Normal file
34
src/shapes/ISO_enter.scad
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
11
src/shapes/oblong.scad
Normal file
11
src/shapes/oblong.scad
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
32
src/shapes/rounded_square.scad
Normal file
32
src/shapes/rounded_square.scad
Normal file
@ -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
|
||||
);
|
||||
}
|
||||
}
|
3
src/shapes/square.scad
Normal file
3
src/shapes/square.scad
Normal file
@ -0,0 +1,3 @@
|
||||
module square_shape(size, delta, progress){
|
||||
square(size - delta * progress, center = true);
|
||||
}
|
@ -1,85 +1,20 @@
|
||||
include <stems/cherry.scad>
|
||||
include <stems/rounded_cherry.scad>
|
||||
include <stems/alps.scad>
|
||||
include <stems/filled.scad>
|
||||
|
||||
|
||||
//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);
|
||||
}
|
||||
|
10
src/stems/alps.scad
Normal file
10
src/stems/alps.scad
Normal file
@ -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);
|
||||
}
|
||||
}
|
30
src/stems/cherry.scad
Normal file
30
src/stems/cherry.scad
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
5
src/stems/filled.scad
Normal file
5
src/stems/filled.scad
Normal file
@ -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);
|
||||
}
|
19
src/stems/rounded_cherry.scad
Normal file
19
src/stems/rounded_cherry.scad
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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 <supports/flared.scad>
|
||||
include <supports/flat.scad>
|
||||
include <supports/bars.scad>
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
6
src/supports/bars.scad
Normal file
6
src/supports/bars.scad
Normal file
@ -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);
|
||||
}
|
||||
}
|
26
src/supports/flared.scad
Normal file
26
src/supports/flared.scad
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
5
src/supports/flat.scad
Normal file
5
src/supports/flat.scad
Normal file
@ -0,0 +1,5 @@
|
||||
module flat_support(stem_type, loft, height) {
|
||||
translate([0,0,loft + 500]){
|
||||
cube(1000, center=true);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user