mirror of
https://github.com/rsheldiii/KeyV2.git
synced 2025-09-13 23:59:49 +00:00
make this library a lot more modular
This commit is contained in:
parent
2368961370
commit
aa795c4958
31 changed files with 467 additions and 443 deletions
|
@ -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();
|
||||
}
|
||||
}
|
69
src/key_sizes.scad
Normal file
69
src/key_sizes.scad
Normal file
|
@ -0,0 +1,69 @@
|
|||
// key width functions
|
||||
|
||||
module u(u=1) {
|
||||
$key_length = u;
|
||||
children();
|
||||
}
|
||||
|
||||
module 1u() {
|
||||
u(1) children();
|
||||
}
|
||||
|
||||
module 1_25u() {
|
||||
u(1.25) children();
|
||||
}
|
||||
|
||||
module 1_5u() {
|
||||
u(1.5) children();
|
||||
}
|
||||
|
||||
module 2u() {
|
||||
u(2) children();
|
||||
}
|
||||
|
||||
module 2_25u() {
|
||||
u(2.25) children();
|
||||
}
|
||||
|
||||
module 2_75u() {
|
||||
u(2.75) children();
|
||||
}
|
||||
|
||||
module 6_25u() {
|
||||
u(6.25) children();
|
||||
}
|
||||
|
||||
// key height functions
|
||||
|
||||
module uh(u=1) {
|
||||
$key_height = u;
|
||||
children();
|
||||
}
|
||||
|
||||
module 1uh() {
|
||||
uh(1) children();
|
||||
}
|
||||
|
||||
module 2uh() {
|
||||
uh(2) children();
|
||||
}
|
||||
|
||||
module 1_25uh() {
|
||||
uh(1.25) children();
|
||||
}
|
||||
|
||||
module 1_5uh() {
|
||||
uh(1.5) children();
|
||||
}
|
||||
|
||||
module 2_25uh() {
|
||||
uh(2.25) children();
|
||||
}
|
||||
|
||||
module 2_75uh() {
|
||||
uh(2.75) children();
|
||||
}
|
||||
|
||||
module 6_25uh() {
|
||||
uh(6.25) children();
|
||||
}
|
94
src/key_transformations.scad
Normal file
94
src/key_transformations.scad
Normal file
|
@ -0,0 +1,94 @@
|
|||
// kind of a catch-all at this point for any directive that doesn't fit in the other files
|
||||
|
||||
module brimmed() {
|
||||
$has_brim = true;
|
||||
children();
|
||||
}
|
||||
|
||||
module rounded() {
|
||||
$rounded_key = true;
|
||||
children();
|
||||
}
|
||||
|
||||
module inverted() {
|
||||
$inverted_dish = true;
|
||||
children();
|
||||
}
|
||||
|
||||
module rotated() {
|
||||
$stem_rotation = 90;
|
||||
children();
|
||||
}
|
||||
|
||||
module stabilized(mm=12, vertical = false) {
|
||||
if (vertical) {
|
||||
$connectors = [
|
||||
[0, 0],
|
||||
[0, mm],
|
||||
[0, -mm]
|
||||
];
|
||||
|
||||
children();
|
||||
} else {
|
||||
$connectors = [
|
||||
[0, 0],
|
||||
[mm, 0],
|
||||
[-mm, 0]
|
||||
];
|
||||
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
module dishless() {
|
||||
$dish_type = "no dish";
|
||||
children();
|
||||
}
|
||||
|
||||
module inset(val=1) {
|
||||
$stem_inset = val;
|
||||
children();
|
||||
}
|
||||
|
||||
module filled() {
|
||||
$stem_type = "filled";
|
||||
children();
|
||||
}
|
||||
|
||||
module blank() {
|
||||
$stem_type = "blank";
|
||||
children();
|
||||
}
|
||||
|
||||
module cherry(slop = 0.3) {
|
||||
$stem_slop = slop;
|
||||
$stem_type = "cherry";
|
||||
children();
|
||||
}
|
||||
|
||||
module alps(slop = 0.3) {
|
||||
$stem_slop = slop;
|
||||
$stem_type = "alps";
|
||||
children();
|
||||
}
|
||||
|
||||
module rounded_cherry(slop = 0.3) {
|
||||
$stem_slop = slop;
|
||||
$stem_type = "cherry_rounded";
|
||||
children();
|
||||
}
|
||||
|
||||
module flared_support() {
|
||||
$support_type = "flared";
|
||||
children();
|
||||
}
|
||||
|
||||
module bar_support() {
|
||||
$support_type = "bars";
|
||||
children();
|
||||
}
|
||||
|
||||
module flat_support() {
|
||||
$support_type = "flat";
|
||||
children();
|
||||
}
|
59
src/key_types.scad
Normal file
59
src/key_types.scad
Normal file
|
@ -0,0 +1,59 @@
|
|||
module spacebar() {
|
||||
$inverted_dish = true;
|
||||
$dish_type = "sideways cylindrical";
|
||||
6_25u() stabilized(mm=50) children();
|
||||
}
|
||||
|
||||
module lshift() {
|
||||
2_25u() stabilized() children();
|
||||
}
|
||||
|
||||
module rshift() {
|
||||
2_75u() stabilized() children();
|
||||
}
|
||||
|
||||
module backspace() {
|
||||
2u() stabilized() children();
|
||||
}
|
||||
|
||||
module enter() {
|
||||
2_25u() stabilized() children();
|
||||
}
|
||||
|
||||
module numpad_enter() {
|
||||
2uh() stabilized(vertical=true) children();
|
||||
}
|
||||
|
||||
module numpad_plus() {
|
||||
numpad_enter() children();
|
||||
}
|
||||
|
||||
module numpad_0() {
|
||||
backspace() children();
|
||||
}
|
||||
|
||||
module stepped_caps_lock() {
|
||||
u(1.75) {
|
||||
$connectors = [
|
||||
[-5, 0]
|
||||
];
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
module iso_enter() {
|
||||
$key_length = 1.5;
|
||||
$key_height = 2;
|
||||
|
||||
$top_tilt = 0;
|
||||
$key_shape_type = "iso_enter";
|
||||
$linear_extrude_shape = true;
|
||||
$linear_extrude_height_adjustment = 19.05 * 0.5;
|
||||
// (unit_length(1.5) - unit_length(1.25)) / 2
|
||||
$dish_overdraw_width = 2.38125;
|
||||
|
||||
|
||||
stabilized(vertical=true) {
|
||||
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…
Add table
Add a link
Reference in a new issue