From c1bbaed9a29a91cbfa028658b3e9a12e50e83d8b Mon Sep 17 00:00:00 2001 From: Bob Date: Wed, 17 Jun 2020 14:37:00 -0400 Subject: [PATCH 1/8] large key.scad restructuring --- CHANGELOG.md | 15 + customizer.scad | 838 +++++++++++++++++++--------- keys.scad | 29 +- src/dishes/3d_surface.scad | 14 + src/functions.scad | 24 + src/hulls.scad | 19 + src/hulls/hull.scad | 33 ++ src/hulls/linear_extrude.scad | 18 + src/hulls/skin.scad | 34 ++ src/key.scad | 375 ++++--------- src/key_transformations.scad | 11 + src/layouts/lets_split/default.scad | 4 +- src/settings.scad | 9 + 13 files changed, 897 insertions(+), 526 deletions(-) create mode 100644 CHANGELOG.md create mode 100644 src/dishes/3d_surface.scad create mode 100644 src/hulls.scad create mode 100644 src/hulls/hull.scad create mode 100644 src/hulls/linear_extrude.scad create mode 100644 src/hulls/skin.scad diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..8197d44 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,15 @@ +CHANGELOG: + V2.0.0: + * added $fa values for minkowski and shape - so you can customize how much rounding there is + * rejiggered `key.scad` pipeline for more clarity and less shapes + * implemented "3d_surface" dish - still in beta + * super cool though, you can even change the distribution of points on the surface! just make sure you use monotonically increasing functions + * created "hull" folder to house different ways of creating the overall key shape + * promoted "feature" folder to first-class folder with keytext and switch clearance as new residents + * wrote this changelog! + * implemented `$inner_shape_type`, use "flat" for less geometry or "disable" to make a completely solid key easily. didn't help render rounded keys though + * side-printed keycaps are first class! you can use the `sideways()` modifier to set up sideways keycaps that have flat sides to print on. + * it's much easier to make quick artisans now that the inside of the keycap is differenced from any additive features placed on top + * still todo: add a magic scaling variable so you can scale the whole world up, see if that fixes degeneracy + * still todo: rejigger supports + * still todo: rejigger inner shape. maybe just always make it flat diff --git a/customizer.scad b/customizer.scad index 0d0cf72..f940ccb 100644 --- a/customizer.scad +++ b/customizer.scad @@ -52,7 +52,7 @@ $outset_legends = false; // Height in units of key. should remain 1 for most uses $key_height = 1.0; // Keytop thickness, aka how many millimeters between the inside and outside of the top surface of the key -$keytop_thickness = 2; +$keytop_thickness = 1; // Wall thickness, aka the thickness of the sides of the keycap. note this is the total thickness, aka 3 = 1.5mm walls $wall_thickness = 3; // Radius of corners of keycap @@ -199,19 +199,19 @@ $tertiary_color = [1, .6941, .2]; $quaternary_color = [.4078, .3569, .749]; $warning_color = [1,0,0, 0.15]; -// 3d surface variables -// see functions.scad for the surface function -$3d_surface_size = 10; -$3d_surface_step = 1; -// normally the bottom of the keytop looks like the top - curved, at least -// underneath the support structure. This ensures there's a minimum thickness for the -// underside of the keycap, but it's a fair bit of geometry -$flat_keytop_bottom = true; - // how many facets circles will have when used in these features $minkowski_facets = 30; $shape_facets =30; +// 3d surface settings +// unused for now +$3d_surface_size = 100; +// resolution in each axis. 10 = 10 divisions per x/y = 100 points total +$3d_surface_step = 5; + +// "flat" / "dished" / "disable" +$inner_shape_type = "flat"; + // key width functions module u(u=1) { @@ -851,6 +851,17 @@ module debug() { %children(); } + +module display() { + $height_slices = 30; + $minkowski_facets = 64; + $shape_facets = 64; + $stem_type = "disable"; + $support_type = "disable"; + $stem_support_type = "disable"; + + children(); +} module arrows(profile, rows = [4,4,4,3]) { positions = [[0, 0], [1, 0], [2, 0], [1, 1]]; legends = ["←", "↓", "→", "↑"]; @@ -925,6 +936,30 @@ function vertical_inclination_due_to_top_tilt() = sin($top_tilt) * (top_total_ke // of the keycap a flat plane. 1 = front, -1 = back // I derived this through a bunch of trig reductions I don't really understand. function extra_keytop_length_for_flat_sides() = ($width_difference * vertical_inclination_due_to_top_tilt()) / ($total_depth); + +// 3d surface functions (still in beta) + +// monotonically increasing function that distributes the points of the surface mesh +// only for polar_3d_surface right now +// if it's linear it's a grid. sin(dim) * size concentrates detail around the edges +function surface_distribution_function(dim, size) = sin(dim) * size; + +// the function that actually determines what the surface is. +// feel free to override, the last one wins + +// debug +function surface_function(x,y) = 1; +// cylindrical +function surface_function(x,y) = (sin(acos(x/$3d_surface_size))); +// spherical +function surface_function(x,y) = (sin(acos(x/$3d_surface_size))) * sin(acos(y/$3d_surface_size)); +// (statically) random! +// ripples +/* function surface_function(x,y) = cos(pow(pow(x,2)+pow(y,2),0.5)*10)/4+0.75; */ +// Rosenbrock's banana +/* function surface_function(x,y) = (pow(1-(x/100), 2) + 100 * pow((y/100)-pow((x/100),2),2))/200 + 0.1; */ +// y=x revolved around the y axis +/* function surface_function(x,y) = 1/(pow(pow(x,2)+pow(y,2),0.5)/100 + .01); */ $fs=.1; unit = 19.05; @@ -1200,6 +1235,30 @@ function vertical_inclination_due_to_top_tilt() = sin($top_tilt) * (top_total_ke // of the keycap a flat plane. 1 = front, -1 = back // I derived this through a bunch of trig reductions I don't really understand. function extra_keytop_length_for_flat_sides() = ($width_difference * vertical_inclination_due_to_top_tilt()) / ($total_depth); + +// 3d surface functions (still in beta) + +// monotonically increasing function that distributes the points of the surface mesh +// only for polar_3d_surface right now +// if it's linear it's a grid. sin(dim) * size concentrates detail around the edges +function surface_distribution_function(dim, size) = sin(dim) * size; + +// the function that actually determines what the surface is. +// feel free to override, the last one wins + +// debug +function surface_function(x,y) = 1; +// cylindrical +function surface_function(x,y) = (sin(acos(x/$3d_surface_size))); +// spherical +function surface_function(x,y) = (sin(acos(x/$3d_surface_size))) * sin(acos(y/$3d_surface_size)); +// (statically) random! +// ripples +/* function surface_function(x,y) = cos(pow(pow(x,2)+pow(y,2),0.5)*10)/4+0.75; */ +// Rosenbrock's banana +/* function surface_function(x,y) = (pow(1-(x/100), 2) + 100 * pow((y/100)-pow((x/100),2),2))/200 + 0.1; */ +// y=x revolved around the y axis +/* function surface_function(x,y) = 1/(pow(pow(x,2)+pow(y,2),0.5)/100 + .01); */ function sign_x(i,n) = i < n/4 || i > n*3/4 ? 1 : i > n/4 && i < n*3/4 ? -1 : @@ -1367,6 +1426,30 @@ function vertical_inclination_due_to_top_tilt() = sin($top_tilt) * (top_total_ke // I derived this through a bunch of trig reductions I don't really understand. function extra_keytop_length_for_flat_sides() = ($width_difference * vertical_inclination_due_to_top_tilt()) / ($total_depth); +// 3d surface functions (still in beta) + +// monotonically increasing function that distributes the points of the surface mesh +// only for polar_3d_surface right now +// if it's linear it's a grid. sin(dim) * size concentrates detail around the edges +function surface_distribution_function(dim, size) = sin(dim) * size; + +// the function that actually determines what the surface is. +// feel free to override, the last one wins + +// debug +function surface_function(x,y) = 1; +// cylindrical +function surface_function(x,y) = (sin(acos(x/$3d_surface_size))); +// spherical +function surface_function(x,y) = (sin(acos(x/$3d_surface_size))) * sin(acos(y/$3d_surface_size)); +// (statically) random! +// ripples +/* function surface_function(x,y) = cos(pow(pow(x,2)+pow(y,2),0.5)*10)/4+0.75; */ +// Rosenbrock's banana +/* function surface_function(x,y) = (pow(1-(x/100), 2) + 100 * pow((y/100)-pow((x/100),2),2))/200 + 0.1; */ +// y=x revolved around the y axis +/* function surface_function(x,y) = 1/(pow(pow(x,2)+pow(y,2),0.5)/100 + .01); */ + // extra length to the vertical tine of the inside cherry cross // splits the stem into halves - allows easier fitment extra_vertical = 0.6; @@ -1444,6 +1527,30 @@ function vertical_inclination_due_to_top_tilt() = sin($top_tilt) * (top_total_ke // of the keycap a flat plane. 1 = front, -1 = back // I derived this through a bunch of trig reductions I don't really understand. function extra_keytop_length_for_flat_sides() = ($width_difference * vertical_inclination_due_to_top_tilt()) / ($total_depth); + +// 3d surface functions (still in beta) + +// monotonically increasing function that distributes the points of the surface mesh +// only for polar_3d_surface right now +// if it's linear it's a grid. sin(dim) * size concentrates detail around the edges +function surface_distribution_function(dim, size) = sin(dim) * size; + +// the function that actually determines what the surface is. +// feel free to override, the last one wins + +// debug +function surface_function(x,y) = 1; +// cylindrical +function surface_function(x,y) = (sin(acos(x/$3d_surface_size))); +// spherical +function surface_function(x,y) = (sin(acos(x/$3d_surface_size))) * sin(acos(y/$3d_surface_size)); +// (statically) random! +// ripples +/* function surface_function(x,y) = cos(pow(pow(x,2)+pow(y,2),0.5)*10)/4+0.75; */ +// Rosenbrock's banana +/* function surface_function(x,y) = (pow(1-(x/100), 2) + 100 * pow((y/100)-pow((x/100),2),2))/200 + 0.1; */ +// y=x revolved around the y axis +/* function surface_function(x,y) = 1/(pow(pow(x,2)+pow(y,2),0.5)/100 + .01); */ SMALLEST_POSSIBLE = 1/128; // I use functions when I need to compute special variables off of other special variables @@ -1487,6 +1594,30 @@ function vertical_inclination_due_to_top_tilt() = sin($top_tilt) * (top_total_ke // I derived this through a bunch of trig reductions I don't really understand. function extra_keytop_length_for_flat_sides() = ($width_difference * vertical_inclination_due_to_top_tilt()) / ($total_depth); +// 3d surface functions (still in beta) + +// monotonically increasing function that distributes the points of the surface mesh +// only for polar_3d_surface right now +// if it's linear it's a grid. sin(dim) * size concentrates detail around the edges +function surface_distribution_function(dim, size) = sin(dim) * size; + +// the function that actually determines what the surface is. +// feel free to override, the last one wins + +// debug +function surface_function(x,y) = 1; +// cylindrical +function surface_function(x,y) = (sin(acos(x/$3d_surface_size))); +// spherical +function surface_function(x,y) = (sin(acos(x/$3d_surface_size))) * sin(acos(y/$3d_surface_size)); +// (statically) random! +// ripples +/* function surface_function(x,y) = cos(pow(pow(x,2)+pow(y,2),0.5)*10)/4+0.75; */ +// Rosenbrock's banana +/* function surface_function(x,y) = (pow(1-(x/100), 2) + 100 * pow((y/100)-pow((x/100),2),2))/200 + 0.1; */ +// y=x revolved around the y axis +/* function surface_function(x,y) = 1/(pow(pow(x,2)+pow(y,2),0.5)/100 + .01); */ + // extra length to the vertical tine of the inside cherry cross // splits the stem into halves - allows easier fitment extra_vertical = 0.6; @@ -1574,6 +1705,30 @@ function vertical_inclination_due_to_top_tilt() = sin($top_tilt) * (top_total_ke // of the keycap a flat plane. 1 = front, -1 = back // I derived this through a bunch of trig reductions I don't really understand. function extra_keytop_length_for_flat_sides() = ($width_difference * vertical_inclination_due_to_top_tilt()) / ($total_depth); + +// 3d surface functions (still in beta) + +// monotonically increasing function that distributes the points of the surface mesh +// only for polar_3d_surface right now +// if it's linear it's a grid. sin(dim) * size concentrates detail around the edges +function surface_distribution_function(dim, size) = sin(dim) * size; + +// the function that actually determines what the surface is. +// feel free to override, the last one wins + +// debug +function surface_function(x,y) = 1; +// cylindrical +function surface_function(x,y) = (sin(acos(x/$3d_surface_size))); +// spherical +function surface_function(x,y) = (sin(acos(x/$3d_surface_size))) * sin(acos(y/$3d_surface_size)); +// (statically) random! +// ripples +/* function surface_function(x,y) = cos(pow(pow(x,2)+pow(y,2),0.5)*10)/4+0.75; */ +// Rosenbrock's banana +/* function surface_function(x,y) = (pow(1-(x/100), 2) + 100 * pow((y/100)-pow((x/100),2),2))/200 + 0.1; */ +// y=x revolved around the y axis +/* function surface_function(x,y) = 1/(pow(pow(x,2)+pow(y,2),0.5)/100 + .01); */ SMALLEST_POSSIBLE = 1/128; // I use functions when I need to compute special variables off of other special variables @@ -1617,6 +1772,30 @@ function vertical_inclination_due_to_top_tilt() = sin($top_tilt) * (top_total_ke // I derived this through a bunch of trig reductions I don't really understand. function extra_keytop_length_for_flat_sides() = ($width_difference * vertical_inclination_due_to_top_tilt()) / ($total_depth); +// 3d surface functions (still in beta) + +// monotonically increasing function that distributes the points of the surface mesh +// only for polar_3d_surface right now +// if it's linear it's a grid. sin(dim) * size concentrates detail around the edges +function surface_distribution_function(dim, size) = sin(dim) * size; + +// the function that actually determines what the surface is. +// feel free to override, the last one wins + +// debug +function surface_function(x,y) = 1; +// cylindrical +function surface_function(x,y) = (sin(acos(x/$3d_surface_size))); +// spherical +function surface_function(x,y) = (sin(acos(x/$3d_surface_size))) * sin(acos(y/$3d_surface_size)); +// (statically) random! +// ripples +/* function surface_function(x,y) = cos(pow(pow(x,2)+pow(y,2),0.5)*10)/4+0.75; */ +// Rosenbrock's banana +/* function surface_function(x,y) = (pow(1-(x/100), 2) + 100 * pow((y/100)-pow((x/100),2),2))/200 + 0.1; */ +// y=x revolved around the y axis +/* function surface_function(x,y) = 1/(pow(pow(x,2)+pow(y,2),0.5)/100 + .01); */ + // extra length to the vertical tine of the inside cherry cross // splits the stem into halves - allows easier fitment extra_vertical = 0.6; @@ -1723,6 +1902,30 @@ function vertical_inclination_due_to_top_tilt() = sin($top_tilt) * (top_total_ke // I derived this through a bunch of trig reductions I don't really understand. function extra_keytop_length_for_flat_sides() = ($width_difference * vertical_inclination_due_to_top_tilt()) / ($total_depth); +// 3d surface functions (still in beta) + +// monotonically increasing function that distributes the points of the surface mesh +// only for polar_3d_surface right now +// if it's linear it's a grid. sin(dim) * size concentrates detail around the edges +function surface_distribution_function(dim, size) = sin(dim) * size; + +// the function that actually determines what the surface is. +// feel free to override, the last one wins + +// debug +function surface_function(x,y) = 1; +// cylindrical +function surface_function(x,y) = (sin(acos(x/$3d_surface_size))); +// spherical +function surface_function(x,y) = (sin(acos(x/$3d_surface_size))) * sin(acos(y/$3d_surface_size)); +// (statically) random! +// ripples +/* function surface_function(x,y) = cos(pow(pow(x,2)+pow(y,2),0.5)*10)/4+0.75; */ +// Rosenbrock's banana +/* function surface_function(x,y) = (pow(1-(x/100), 2) + 100 * pow((y/100)-pow((x/100),2),2))/200 + 0.1; */ +// y=x revolved around the y axis +/* function surface_function(x,y) = 1/(pow(pow(x,2)+pow(y,2),0.5)/100 + .01); */ + // extra length to the vertical tine of the inside cherry cross // splits the stem into halves - allows easier fitment extra_vertical = 0.6; @@ -1815,6 +2018,30 @@ function vertical_inclination_due_to_top_tilt() = sin($top_tilt) * (top_total_ke // of the keycap a flat plane. 1 = front, -1 = back // I derived this through a bunch of trig reductions I don't really understand. function extra_keytop_length_for_flat_sides() = ($width_difference * vertical_inclination_due_to_top_tilt()) / ($total_depth); + +// 3d surface functions (still in beta) + +// monotonically increasing function that distributes the points of the surface mesh +// only for polar_3d_surface right now +// if it's linear it's a grid. sin(dim) * size concentrates detail around the edges +function surface_distribution_function(dim, size) = sin(dim) * size; + +// the function that actually determines what the surface is. +// feel free to override, the last one wins + +// debug +function surface_function(x,y) = 1; +// cylindrical +function surface_function(x,y) = (sin(acos(x/$3d_surface_size))); +// spherical +function surface_function(x,y) = (sin(acos(x/$3d_surface_size))) * sin(acos(y/$3d_surface_size)); +// (statically) random! +// ripples +/* function surface_function(x,y) = cos(pow(pow(x,2)+pow(y,2),0.5)*10)/4+0.75; */ +// Rosenbrock's banana +/* function surface_function(x,y) = (pow(1-(x/100), 2) + 100 * pow((y/100)-pow((x/100),2),2))/200 + 0.1; */ +// y=x revolved around the y axis +/* function surface_function(x,y) = 1/(pow(pow(x,2)+pow(y,2),0.5)/100 + .01); */ SMALLEST_POSSIBLE = 1/128; // I use functions when I need to compute special variables off of other special variables @@ -1858,6 +2085,30 @@ function vertical_inclination_due_to_top_tilt() = sin($top_tilt) * (top_total_ke // I derived this through a bunch of trig reductions I don't really understand. function extra_keytop_length_for_flat_sides() = ($width_difference * vertical_inclination_due_to_top_tilt()) / ($total_depth); +// 3d surface functions (still in beta) + +// monotonically increasing function that distributes the points of the surface mesh +// only for polar_3d_surface right now +// if it's linear it's a grid. sin(dim) * size concentrates detail around the edges +function surface_distribution_function(dim, size) = sin(dim) * size; + +// the function that actually determines what the surface is. +// feel free to override, the last one wins + +// debug +function surface_function(x,y) = 1; +// cylindrical +function surface_function(x,y) = (sin(acos(x/$3d_surface_size))); +// spherical +function surface_function(x,y) = (sin(acos(x/$3d_surface_size))) * sin(acos(y/$3d_surface_size)); +// (statically) random! +// ripples +/* function surface_function(x,y) = cos(pow(pow(x,2)+pow(y,2),0.5)*10)/4+0.75; */ +// Rosenbrock's banana +/* function surface_function(x,y) = (pow(1-(x/100), 2) + 100 * pow((y/100)-pow((x/100),2),2))/200 + 0.1; */ +// y=x revolved around the y axis +/* function surface_function(x,y) = 1/(pow(pow(x,2)+pow(y,2),0.5)/100 + .01); */ + // extra length to the vertical tine of the inside cherry cross // splits the stem into halves - allows easier fitment extra_vertical = 0.6; @@ -1980,6 +2231,30 @@ function vertical_inclination_due_to_top_tilt() = sin($top_tilt) * (top_total_ke // of the keycap a flat plane. 1 = front, -1 = back // I derived this through a bunch of trig reductions I don't really understand. function extra_keytop_length_for_flat_sides() = ($width_difference * vertical_inclination_due_to_top_tilt()) / ($total_depth); + +// 3d surface functions (still in beta) + +// monotonically increasing function that distributes the points of the surface mesh +// only for polar_3d_surface right now +// if it's linear it's a grid. sin(dim) * size concentrates detail around the edges +function surface_distribution_function(dim, size) = sin(dim) * size; + +// the function that actually determines what the surface is. +// feel free to override, the last one wins + +// debug +function surface_function(x,y) = 1; +// cylindrical +function surface_function(x,y) = (sin(acos(x/$3d_surface_size))); +// spherical +function surface_function(x,y) = (sin(acos(x/$3d_surface_size))) * sin(acos(y/$3d_surface_size)); +// (statically) random! +// ripples +/* function surface_function(x,y) = cos(pow(pow(x,2)+pow(y,2),0.5)*10)/4+0.75; */ +// Rosenbrock's banana +/* function surface_function(x,y) = (pow(1-(x/100), 2) + 100 * pow((y/100)-pow((x/100),2),2))/200 + 0.1; */ +// y=x revolved around the y axis +/* function surface_function(x,y) = 1/(pow(pow(x,2)+pow(y,2),0.5)/100 + .01); */ SMALLEST_POSSIBLE = 1/128; // I use functions when I need to compute special variables off of other special variables @@ -2023,6 +2298,30 @@ function vertical_inclination_due_to_top_tilt() = sin($top_tilt) * (top_total_ke // I derived this through a bunch of trig reductions I don't really understand. function extra_keytop_length_for_flat_sides() = ($width_difference * vertical_inclination_due_to_top_tilt()) / ($total_depth); +// 3d surface functions (still in beta) + +// monotonically increasing function that distributes the points of the surface mesh +// only for polar_3d_surface right now +// if it's linear it's a grid. sin(dim) * size concentrates detail around the edges +function surface_distribution_function(dim, size) = sin(dim) * size; + +// the function that actually determines what the surface is. +// feel free to override, the last one wins + +// debug +function surface_function(x,y) = 1; +// cylindrical +function surface_function(x,y) = (sin(acos(x/$3d_surface_size))); +// spherical +function surface_function(x,y) = (sin(acos(x/$3d_surface_size))) * sin(acos(y/$3d_surface_size)); +// (statically) random! +// ripples +/* function surface_function(x,y) = cos(pow(pow(x,2)+pow(y,2),0.5)*10)/4+0.75; */ +// Rosenbrock's banana +/* function surface_function(x,y) = (pow(1-(x/100), 2) + 100 * pow((y/100)-pow((x/100),2),2))/200 + 0.1; */ +// y=x revolved around the y axis +/* function surface_function(x,y) = 1/(pow(pow(x,2)+pow(y,2),0.5)/100 + .01); */ + // extra length to the vertical tine of the inside cherry cross // splits the stem into halves - allows easier fitment extra_vertical = 0.6; @@ -2414,6 +2713,30 @@ function vertical_inclination_due_to_top_tilt() = sin($top_tilt) * (top_total_ke // of the keycap a flat plane. 1 = front, -1 = back // I derived this through a bunch of trig reductions I don't really understand. function extra_keytop_length_for_flat_sides() = ($width_difference * vertical_inclination_due_to_top_tilt()) / ($total_depth); + +// 3d surface functions (still in beta) + +// monotonically increasing function that distributes the points of the surface mesh +// only for polar_3d_surface right now +// if it's linear it's a grid. sin(dim) * size concentrates detail around the edges +function surface_distribution_function(dim, size) = sin(dim) * size; + +// the function that actually determines what the surface is. +// feel free to override, the last one wins + +// debug +function surface_function(x,y) = 1; +// cylindrical +function surface_function(x,y) = (sin(acos(x/$3d_surface_size))); +// spherical +function surface_function(x,y) = (sin(acos(x/$3d_surface_size))) * sin(acos(y/$3d_surface_size)); +// (statically) random! +// ripples +/* function surface_function(x,y) = cos(pow(pow(x,2)+pow(y,2),0.5)*10)/4+0.75; */ +// Rosenbrock's banana +/* function surface_function(x,y) = (pow(1-(x/100), 2) + 100 * pow((y/100)-pow((x/100),2),2))/200 + 0.1; */ +// y=x revolved around the y axis +/* function surface_function(x,y) = 1/(pow(pow(x,2)+pow(y,2),0.5)/100 + .01); */ // TODO this define doesn't do anything besides tell me I used flat() in this file // is it better than not having it at all? module flat(stem_type, loft, height) { @@ -2555,6 +2878,107 @@ module legends(depth=0) { } } } +// use skin() instead of successive hulls. much more correct, and looks faster +// too, in most cases. successive hull relies on overlapping faces which are +// not good. But, skin works on vertex sets instead of shapes, which makes it +// a lot more difficult to use +module skin_extrude_shape_hull(thickness_difference, depth_difference, extra_slices = 0 ) { + skin([ + for (index = [0:$height_slices + extra_slices]) + let( + progress = (index / $height_slices), + skew_this_slice = $top_skew * progress, + x_skew_this_slice = $top_skew_x * progress, + depth_this_slice = ($total_depth - depth_difference) * progress, + tilt_this_slice = -$top_tilt / $key_height * progress, + y_tilt_this_slice = $double_sculpted ? (-$top_tilt_y / $key_length * progress) : 0 + ) + skin_shape_slice(progress, thickness_difference, skew_this_slice, x_skew_this_slice, depth_this_slice, tilt_this_slice, y_tilt_this_slice) + ]); +} + +function skin_shape_slice(progress, thickness_difference, skew_this_slice, x_skew_this_slice, depth_this_slice, tilt_this_slice, y_tilt_this_slice) = + transform( + translation([x_skew_this_slice,skew_this_slice,depth_this_slice]), + transform( + rotation([tilt_this_slice,y_tilt_this_slice,0]), + skin_key_shape([ + total_key_width(0), + total_key_height(0), + ], + [$width_difference, $height_difference], + progress, + thickness_difference + ) + ) + ); +// corollary is hull_shape_hull +// extra_slices unused, only to match argument signatures +module linear_extrude_shape_hull(thickness_difference, depth_difference, extra_slices = 0){ + height = $total_depth - depth_difference; + width_scale = top_total_key_width() / total_key_width(); + height_scale = top_total_key_height() / total_key_height(); + + translate([0,$linear_extrude_height_adjustment,0]){ + linear_extrude(height = height, scale = [width_scale, height_scale]) { + translate([0,-$linear_extrude_height_adjustment,0]){ + key_shape( + [total_key_width(thickness_difference), total_key_height(thickness_difference)], + [$width_difference, $height_difference] + ); + } + } + } +} +module hull_shape_hull(thickness_difference, depth_difference, extra_slices = 0) { + for (index = [0:$height_slices - 1 + extra_slices]) { + hull() { + shape_slice(index / $height_slices, thickness_difference, depth_difference); + shape_slice((index + 1) / $height_slices, thickness_difference, depth_difference); + } + } +} + +module shape_slice(progress, thickness_difference, depth_difference) { + skew_this_slice = $top_skew * progress; + x_skew_this_slice = $top_skew_x * progress; + + depth_this_slice = ($total_depth - depth_difference) * progress; + + tilt_this_slice = -$top_tilt / $key_height * progress; + y_tilt_this_slice = $double_sculpted ? (-$top_tilt_y / $key_length * progress) : 0; + + translate([x_skew_this_slice, skew_this_slice, depth_this_slice]) { + rotate([tilt_this_slice,y_tilt_this_slice,0]){ + linear_extrude(height = SMALLEST_POSSIBLE + ($rounded_key ? $minkowski_radius : 0), scale = SMALLEST_POSSIBLE){ + key_shape( + [ + total_key_width(thickness_difference), + total_key_height(thickness_difference) + ], + [$width_difference, $height_difference], + progress + ); + } + } + } +} + +// basic key shape, no dish, no inside +// which is only used for dishing to cut the dish off correctly +// $height_difference used for keytop thickness +// extra_slices is a hack to make inverted dishes still work +module shape_hull(thickness_difference, depth_difference, extra_slices = 0){ + render() { + if ($skin_extrude_shape) { + skin_extrude_shape_hull(thickness_difference, depth_difference, extra_slices); + } else if ($linear_extrude_shape) { + linear_extrude_shape_hull(thickness_difference, depth_difference, extra_slices); + } else { + hull_shape_hull(thickness_difference, depth_difference, extra_slices); + } + } +} // from https://www.thingiverse.com/thing:1484333 // public domain license @@ -3499,210 +3923,44 @@ function profile_segment_length(profile,i) = norm(profile[(i+1)%len(profile)] - // Generates an array with n copies of value (default 0) function dup(value=0,n) = [for (i = [1:n]) value]; - /* [Hidden] */ SMALLEST_POSSIBLE = 1/128; -$fs = .1; +// basically disable $fs - though it might be useful for these CGAL problems +$fs = .01; $unit = 19.05; // key shape including dish. used as the ouside and inside shape in hollow_key(). allows for itself to be shrunk in depth and width / height module shape(thickness_difference, depth_difference=0){ dished(depth_difference, $inverted_dish) { - color($primary_color) shape_hull(thickness_difference, depth_difference, $inverted_dish ? 2 : 0); + color($primary_color) shape_hull(thickness_difference, depth_difference, $inverted_dish ? 200 : 0); } } -// shape of the key but with soft, rounded edges. no longer includes dish -// randomly doesnt work sometimes -// the dish doesn't _quite_ reach as far as it should -module rounded_shape() { - dished(-$minkowski_radius, $inverted_dish) { - color($primary_color) minkowski(){ - // half minkowski in the z direction - color($primary_color) shape_hull($minkowski_radius * 2, $minkowski_radius/2, $inverted_dish ? 2 : 0); - /* cube($minkowski_radius); */ - sphere(r=$minkowski_radius, $fn=$minkowski_facets); - } - } - /* %envelope(); */ -} - // this function is more correct, but takes _forever_ // the main difference is minkowski happens after dishing, meaning the dish is // also minkowski'd -/* module rounded_shape() { +module rounded_shape() { color($primary_color) minkowski(){ // half minkowski in the z direction shape($minkowski_radius * 2, $minkowski_radius/2); - difference(){ - sphere(r=$minkowski_radius, $fn=20); - translate([0,0,-$minkowski_radius]){ - cube($minkowski_radius * 2, center=true); - } - } + minkowski_object(); } -} */ +} +// minkowski places this object at every vertex of the other object then mashes +// it all together +module minkowski_object() { + // alternative minkowski shape that needs the bottom of the keycap to be trimmed + /* sphere(1); */ - -// basic key shape, no dish, no inside -// which is only used for dishing to cut the dish off correctly -// $height_difference used for keytop thickness -// extra_slices is a hack to make inverted dishes still work -module shape_hull(thickness_difference, depth_difference, extra_slices = 0){ - render() { - if ($skin_extrude_shape) { - skin_extrude_shape_hull(thickness_difference, depth_difference, extra_slices); - } else if ($linear_extrude_shape) { - linear_extrude_shape_hull(thickness_difference, depth_difference, extra_slices); - } else { - hull_shape_hull(thickness_difference, depth_difference, extra_slices); + difference(){ + sphere(r=$minkowski_radius, $fa=360/$minkowski_facets); + translate([0,0,-$minkowski_radius]){ + cube($minkowski_radius * 2, center=true); } } } -// use skin() instead of successive hulls. much more correct, and looks faster -// too, in most cases. successive hull relies on overlapping faces which are -// not good. But, skin works on vertex sets instead of shapes, which makes it -// a lot more difficult to use -module skin_extrude_shape_hull(thickness_difference, depth_difference, extra_slices = 0 ) { - skin([ - for (index = [0:$height_slices + extra_slices]) - let( - progress = (index / $height_slices), - skew_this_slice = $top_skew * progress, - x_skew_this_slice = $top_skew_x * progress, - depth_this_slice = ($total_depth - depth_difference) * progress, - tilt_this_slice = -$top_tilt / $key_height * progress, - y_tilt_this_slice = $double_sculpted ? (-$top_tilt_y / $key_length * progress) : 0 - ) - skin_shape_slice(progress, thickness_difference, skew_this_slice, x_skew_this_slice, depth_this_slice, tilt_this_slice, y_tilt_this_slice) - ]); -} - -function skin_shape_slice(progress, thickness_difference, skew_this_slice, x_skew_this_slice, depth_this_slice, tilt_this_slice, y_tilt_this_slice) = - transform( - translation([x_skew_this_slice,skew_this_slice,depth_this_slice]), - transform( - rotation([tilt_this_slice,y_tilt_this_slice,0]), - skin_key_shape([ - total_key_width(0), - total_key_height(0), - ], - [$width_difference, $height_difference], - progress, - thickness_difference - ) - ) - ); - -// corollary is hull_shape_hull -// extra_slices unused, only to match argument signatures -module linear_extrude_shape_hull(thickness_difference, depth_difference, extra_slices = 0){ - height = $total_depth - depth_difference; - width_scale = top_total_key_width() / total_key_width(); - height_scale = top_total_key_height() / total_key_height(); - - translate([0,$linear_extrude_height_adjustment,0]){ - linear_extrude(height = height, scale = [width_scale, height_scale]) { - translate([0,-$linear_extrude_height_adjustment,0]){ - key_shape( - [total_key_width(thickness_difference), total_key_height(thickness_difference)], - [$width_difference, $height_difference] - ); - } - } - } -} - -module hull_shape_hull(thickness_difference, depth_difference, extra_slices = 0) { - for (index = [0:$height_slices - 1 + extra_slices]) { - hull() { - shape_slice(index / $height_slices, thickness_difference, depth_difference); - shape_slice((index + 1) / $height_slices, thickness_difference, depth_difference); - } - } -} - -module shape_slice(progress, thickness_difference, depth_difference) { - skew_this_slice = $top_skew * progress; - x_skew_this_slice = $top_skew_x * progress; - - depth_this_slice = ($total_depth - depth_difference) * progress; - - tilt_this_slice = -$top_tilt / $key_height * progress; - y_tilt_this_slice = $double_sculpted ? (-$top_tilt_y / $key_length * progress) : 0; - - translate([x_skew_this_slice, skew_this_slice, depth_this_slice]) { - rotate([tilt_this_slice,y_tilt_this_slice,0]){ - linear_extrude(height = SMALLEST_POSSIBLE){ - key_shape( - [ - total_key_width(thickness_difference), - total_key_height(thickness_difference) - ], - [$width_difference, $height_difference], - progress - ); - } - } - } -} - -// for when you want something to only exist inside the keycap. -// used for the support structure -module inside() { - intersection() { - shape($wall_thickness, $keytop_thickness); - children(); - } -} - -// for when you want something to only exist outside the keycap -module outside() { - difference() { - children(); - shape($wall_thickness, $keytop_thickness); - } -} - -// put something at the top of the key, with no adjustments for dishing -module top_placement(depth_difference=0) { - top_tilt_by_height = -$top_tilt / $key_height; - top_tilt_y_by_length = $double_sculpted ? (-$top_tilt_y / $key_length) : 0; - - minkowski_height = $rounded_key ? $minkowski_radius : 0; - - translate([$top_skew_x + $dish_skew_x, $top_skew + $dish_skew_y, $total_depth - depth_difference + minkowski_height/2]){ - rotate([top_tilt_by_height, top_tilt_y_by_length,0]){ - children(); - } - } -} - -module front_placement() { - // all this math is to take top skew and tilt into account - // we need to find the new effective height and depth of the top, front lip - // of the keycap to find the angle so we can rotate things correctly into place - total_depth_difference = sin(-$top_tilt) * (top_total_key_height()/2); - total_height_difference = $top_skew + (1 - cos(-$top_tilt)) * (top_total_key_height()/2); - - angle = atan2(($total_depth - total_depth_difference), ($height_difference/2 + total_height_difference)); - hypotenuse = ($total_depth -total_depth_difference) / sin(angle); - - translate([0,-total_key_height()/2,0]) { - rotate([-(90-angle), 0, 0]) { - translate([0,0,hypotenuse/2]){ - children(); - } - } - } -} - -// just to DRY up the code -module _dish() { - color($secondary_color) dish(top_total_key_width() + $dish_overdraw_width, top_total_key_height() + $dish_overdraw_height, $dish_depth, $inverted_dish); -} module envelope(depth_difference=0) { s = 1.5; @@ -3714,18 +3972,6 @@ module envelope(depth_difference=0) { } } -// I think this is unused -module dished_for_show() { - difference(){ - union() { - envelope(); - if ($inverted_dish) top_placement(0) _dish(); - } - if (!$inverted_dish) top_placement(0) _dish(); - } -} - - // for when you want to take the dish out of things // used for adding the dish to the key shape and making sure stems don't stick out the top // creates a bounding box 1.5 times larger in width and height than the keycap. @@ -3734,15 +3980,21 @@ module dished(depth_difference = 0, inverted = false) { children(); difference(){ union() { + // envelope is needed to "fill in" the rest of the keycap envelope(depth_difference); - if (inverted) top_placement(depth_difference) _dish(); + if (inverted) top_placement(depth_difference) _dish(inverted); } - if (!inverted) top_placement(depth_difference) _dish(); + if (!inverted) top_placement(depth_difference) _dish(inverted); } } } -// puts it's children at the center of the dishing on the key, including dish height +// just to DRY up the code +module _dish(inverted=$inverted_dish) { + color($secondary_color) dish(top_total_key_width() + $dish_overdraw_width, top_total_key_height() + $dish_overdraw_height, $dish_depth, inverted); +} + +// puts its children at the center of the dishing on the key, including dish height // more user-friendly than top_placement module top_of_key(){ // if there is a dish, we need to account for how much it digs into the top @@ -3755,6 +4007,7 @@ module top_of_key(){ } } +// puts its children at each keystem position provided module keystem_positions(positions) { for (connector_pos = positions) { translate(connector_pos) { @@ -3780,78 +4033,121 @@ module stems_for(positions, stem_type) { } } -// legends / artisan support -module artisan(depth) { - top_of_key() { - // artisan objects / outset shape legends - color($secondary_color) children(); +// put something at the top of the key, with no adjustments for dishing +module top_placement(depth_difference=0) { + top_tilt_by_height = -$top_tilt / $key_height; + top_tilt_y_by_length = $double_sculpted ? (-$top_tilt_y / $key_length) : 0; + + minkowski_height = $rounded_key ? $minkowski_radius : 0; + + translate([$top_skew_x + $dish_skew_x, $top_skew + $dish_skew_y, $total_depth - depth_difference + minkowski_height/2]){ + rotate([top_tilt_by_height, top_tilt_y_by_length,0]){ + children(); + } } } -// key with hollowed inside but no stem -module hollow_key() { - difference(){ - if ($rounded_key) { - rounded_shape(); +module front_of_key() { + // all this math is to take top skew and tilt into account + // we need to find the new effective height and depth of the top, front lip + // of the keycap to find the angle so we can rotate things correctly into place + total_depth_difference = sin(-$top_tilt) * (top_total_key_height()/2); + total_height_difference = $top_skew + (1 - cos(-$top_tilt)) * (top_total_key_height()/2); + + angle = atan2(($total_depth - total_depth_difference), ($height_difference/2 + total_height_difference)); + hypotenuse = ($total_depth -total_depth_difference) / sin(angle); + + translate([0,-total_key_height()/2,0]) { + rotate([-(90-angle), 0, 0]) { + translate([0,0,hypotenuse/2]){ + children(); + } + } + } +} + +module outer_shape() { + shape(0, 0); +} + +module inner_shape(extra_wall_thickness = 0, extra_keytop_thickness = 0) { + translate([0,0,-SMALLEST_POSSIBLE]) { + if ($inner_shape_type == "flat") { + /* $key_shape_type="square"; */ + $height_slices = 1; + color($primary_color) shape_hull($wall_thickness + extra_wall_thickness, $keytop_thickness + extra_keytop_thickness, 0); } else { - shape(0, 0); - } - // translation purely for aesthetic purposes, to get rid of that awful lattice - translate([0,0,-SMALLEST_POSSIBLE]) { - shape($wall_thickness, $keytop_thickness); + shape($wall_thickness + extra_wall_thickness, $keytop_thickness + extra_keytop_thickness); } } } +// additive objects at the top of the key +module additive_features(inset) { + top_of_key() { + if($key_bump) keybump($key_bump_depth, $key_bump_edge); + if(!inset && $children > 0) color($secondary_color) children(); + } + if($outset_legends) legends(0); + // render the clearance check if it's enabled, but don't have it intersect with anything + if ($clearance_check) %clearance_check(); +} + +// subtractive objects at the top of the key +module subtractive_features(inset) { + top_of_key() { + if (inset && $children > 0) color($secondary_color) children(); + } + if(!$outset_legends) legends($inset_legend_depth); + // subtract the clearance check if it's enabled, letting the user see the + // parts of the keycap that will hit the cherry switch + if ($clearance_check) %clearance_check(); +} + +module inside_features() { + translate([0, 0, $stem_inset]) { + // both stem and support are optional + if ($stabilizer_type != "disable") stems_for($stabilizers, $stabilizer_type); + if ($stem_type != "disable") stems_for($stem_positions, $stem_type); + if ($stabilizer_type != "disable") support_for($stabilizers, $stabilizer_type); + // always render stem support even if there isn't a stem. + // rendering flat support w/no stem is much more common than a hollow keycap + // so if you want a hollow keycap you'll have to turn support off entirely + if ($support_type != "disable") support_for($stem_positions, $stem_type); + } +} // The final, penultimate key generation function. // takes all the bits and glues them together. requires configuration with special variables. -module key(inset = false) { - difference() { - union(){ - // the shape of the key, inside and out - hollow_key(); - if($key_bump) top_of_key() keybump($key_bump_depth, $key_bump_edge); - // additive objects at the top of the key - // outside() makes them stay out of the inside. it's a bad name - if(!inset && $children > 0) outside() artisan(0) children(); - if($outset_legends) legends(0); - // render the clearance check if it's enabled, but don't have it intersect with anything - if ($clearance_check) %clearance_check(); +module key(inset=false) { + difference(){ + union() { + outer_shape(); + additive_features(inset) { + children(); + }; } - // subtractive objects at the top of the key - // no outside() - I can't think of a use for it. will save render time - if (inset && $children > 0) artisan($inset_legend_depth) children(); - if(!$outset_legends) legends($inset_legend_depth); - // subtract the clearance check if it's enabled, letting the user see the - // parts of the keycap that will hit the cherry switch - if ($clearance_check) %clearance_check(); - } - - // both stem and support are optional - if ($stem_type != "disable" || ($stabilizers != [] && $stabilizer_type != "disable")) { - dished($keytop_thickness, $inverted_dish) { - translate([0, 0, $stem_inset]) { - if ($stabilizer_type != "disable") stems_for($stabilizers, $stabilizer_type); - - if ($stem_type != "disable") stems_for($stem_positions, $stem_type); - } + if ($inner_shape_type != "disable") difference() { + inner_shape(); + inside_features(); } + + subtractive_features(inset) { + children(); + }; } +} - if ($support_type != "disable"){ - inside() { - translate([0, 0, $stem_inset]) { - if ($stabilizer_type != "disable") support_for($stabilizers, $stabilizer_type); - - // always render stem support even if there isn't a stem. - // rendering flat support w/no stem is much more common than a hollow keycap - // so if you want a hollow keycap you'll have to turn support off entirely - support_for($stem_positions, $stem_type); - } +module display_key(inset=false) { + minkowski() { + outer_shape(); + minkowski_object(); + // minkowski doesn't work with difference + additive_features(false) { + children(); + }; } - } } // actual full key with space carved out and keystem/stabilizer connectors @@ -3896,7 +4192,7 @@ $outset_legends = false; // Height in units of key. should remain 1 for most uses $key_height = 1.0; // Keytop thickness, aka how many millimeters between the inside and outside of the top surface of the key -$keytop_thickness = 2; +$keytop_thickness = 1; // Wall thickness, aka the thickness of the sides of the keycap. note this is the total thickness, aka 3 = 1.5mm walls $wall_thickness = 3; // Radius of corners of keycap @@ -4043,18 +4339,18 @@ $tertiary_color = [1, .6941, .2]; $quaternary_color = [.4078, .3569, .749]; $warning_color = [1,0,0, 0.15]; -// 3d surface variables -// see functions.scad for the surface function -$3d_surface_size = 10; -$3d_surface_step = 1; -// normally the bottom of the keytop looks like the top - curved, at least -// underneath the support structure. This ensures there's a minimum thickness for the -// underside of the keycap, but it's a fair bit of geometry -$flat_keytop_bottom = true; - // how many facets circles will have when used in these features $minkowski_facets = 30; $shape_facets =30; + +// 3d surface settings +// unused for now +$3d_surface_size = 100; +// resolution in each axis. 10 = 10 divisions per x/y = 100 points total +$3d_surface_step = 5; + +// "flat" / "dished" / "disable" +$inner_shape_type = "flat"; key(); } diff --git a/keys.scad b/keys.scad index 768110e..0a80ad0 100644 --- a/keys.scad +++ b/keys.scad @@ -9,7 +9,32 @@ include <./includes.scad> // example key -dcs_row(5) legend("⇪", size=9) key(); +/* $skin_key_shape = true; */ + +difference() { + /* top_of_key() { */ + /* cube(10); */ + /* } */ + /* key(); */ +} + +/* simple_layout(lets_split_layout) { + dcs_row($row) key(); +} */ + +dcs_row(1) legend("h") front_legend("q" +) { + $key_length = 2.75; + key(); +} + +translate_u(0,1) dcs_row(1) { + $key_length = 0.86; + key(); +} + +/* debug() key(); */ + // example row /* for (x = [0:1:4]) { @@ -17,4 +42,4 @@ dcs_row(5) legend("⇪", size=9) key(); } */ // example layout -/* preonic_default("dcs"); */ \ No newline at end of file +/* preonic_default("dcs"); */ diff --git a/src/dishes/3d_surface.scad b/src/dishes/3d_surface.scad new file mode 100644 index 0000000..413c608 --- /dev/null +++ b/src/dishes/3d_surface.scad @@ -0,0 +1,14 @@ +include <../libraries/3d_surface.scad> + +module 3d_surface_dish(width, height, depth, inverted) { + echo(inverted ? "inverted" : "not inverted"); + // scale_factor is dead reckoning + // it doesn't have to be dead reckoning for anything but sculpted sides + // we know the angle of the sides from the width difference, height difference, + // skew and tilt of the top. it's a pain to calculate though + scale_factor = 1.1; + // the edges on this behave differently than with the previous dish implementations + scale([width*scale_factor/$3d_surface_size/2,height*scale_factor/$3d_surface_size/2,depth]) rotate([inverted ? 0:180,0,180]) polar_3d_surface(bottom=-10); + /* %scale([width*scale_factor/$3d_surface_size/2,height*scale_factor/$3d_surface_size/2,depth]) rotate([180,0,0]) polar_3d_surface(bottom=-10); */ + +} diff --git a/src/functions.scad b/src/functions.scad index eabc9c3..376e6c5 100644 --- a/src/functions.scad +++ b/src/functions.scad @@ -40,3 +40,27 @@ function vertical_inclination_due_to_top_tilt() = sin($top_tilt) * (top_total_ke // of the keycap a flat plane. 1 = front, -1 = back // I derived this through a bunch of trig reductions I don't really understand. function extra_keytop_length_for_flat_sides() = ($width_difference * vertical_inclination_due_to_top_tilt()) / ($total_depth); + +// 3d surface functions (still in beta) + +// monotonically increasing function that distributes the points of the surface mesh +// only for polar_3d_surface right now +// if it's linear it's a grid. sin(dim) * size concentrates detail around the edges +function surface_distribution_function(dim, size) = sin(dim) * size; + +// the function that actually determines what the surface is. +// feel free to override, the last one wins + +// debug +function surface_function(x,y) = 1; +// cylindrical +function surface_function(x,y) = (sin(acos(x/$3d_surface_size))); +// spherical +function surface_function(x,y) = (sin(acos(x/$3d_surface_size))) * sin(acos(y/$3d_surface_size)); +// (statically) random! +// ripples +/* function surface_function(x,y) = cos(pow(pow(x,2)+pow(y,2),0.5)*10)/4+0.75; */ +// Rosenbrock's banana +/* function surface_function(x,y) = (pow(1-(x/100), 2) + 100 * pow((y/100)-pow((x/100),2),2))/200 + 0.1; */ +// y=x revolved around the y axis +/* function surface_function(x,y) = 1/(pow(pow(x,2)+pow(y,2),0.5)/100 + .01); */ diff --git a/src/hulls.scad b/src/hulls.scad new file mode 100644 index 0000000..2fb7218 --- /dev/null +++ b/src/hulls.scad @@ -0,0 +1,19 @@ +include +include +include + +// basic key shape, no dish, no inside +// which is only used for dishing to cut the dish off correctly +// $height_difference used for keytop thickness +// extra_slices is a hack to make inverted dishes still work +module shape_hull(thickness_difference, depth_difference, extra_slices = 0){ + render() { + if ($skin_extrude_shape) { + skin_extrude_shape_hull(thickness_difference, depth_difference, extra_slices); + } else if ($linear_extrude_shape) { + linear_extrude_shape_hull(thickness_difference, depth_difference, extra_slices); + } else { + hull_shape_hull(thickness_difference, depth_difference, extra_slices); + } + } +} diff --git a/src/hulls/hull.scad b/src/hulls/hull.scad new file mode 100644 index 0000000..12df0bb --- /dev/null +++ b/src/hulls/hull.scad @@ -0,0 +1,33 @@ +module hull_shape_hull(thickness_difference, depth_difference, extra_slices = 0) { + for (index = [0:$height_slices - 1 + extra_slices]) { + hull() { + shape_slice(index / $height_slices, thickness_difference, depth_difference); + shape_slice((index + 1) / $height_slices, thickness_difference, depth_difference); + } + } +} + +module shape_slice(progress, thickness_difference, depth_difference) { + skew_this_slice = $top_skew * progress; + x_skew_this_slice = $top_skew_x * progress; + + depth_this_slice = ($total_depth - depth_difference) * progress; + + tilt_this_slice = -$top_tilt / $key_height * progress; + y_tilt_this_slice = $double_sculpted ? (-$top_tilt_y / $key_length * progress) : 0; + + translate([x_skew_this_slice, skew_this_slice, depth_this_slice]) { + rotate([tilt_this_slice,y_tilt_this_slice,0]){ + linear_extrude(height = SMALLEST_POSSIBLE + ($rounded_key ? $minkowski_radius : 0), scale = SMALLEST_POSSIBLE){ + key_shape( + [ + total_key_width(thickness_difference), + total_key_height(thickness_difference) + ], + [$width_difference, $height_difference], + progress + ); + } + } + } +} diff --git a/src/hulls/linear_extrude.scad b/src/hulls/linear_extrude.scad new file mode 100644 index 0000000..f62299e --- /dev/null +++ b/src/hulls/linear_extrude.scad @@ -0,0 +1,18 @@ +// corollary is hull_shape_hull +// extra_slices unused, only to match argument signatures +module linear_extrude_shape_hull(thickness_difference, depth_difference, extra_slices = 0){ + height = $total_depth - depth_difference; + width_scale = top_total_key_width() / total_key_width(); + height_scale = top_total_key_height() / total_key_height(); + + translate([0,$linear_extrude_height_adjustment,0]){ + linear_extrude(height = height, scale = [width_scale, height_scale]) { + translate([0,-$linear_extrude_height_adjustment,0]){ + key_shape( + [total_key_width(thickness_difference), total_key_height(thickness_difference)], + [$width_difference, $height_difference] + ); + } + } + } +} diff --git a/src/hulls/skin.scad b/src/hulls/skin.scad new file mode 100644 index 0000000..af8d6d8 --- /dev/null +++ b/src/hulls/skin.scad @@ -0,0 +1,34 @@ +// use skin() instead of successive hulls. much more correct, and looks faster +// too, in most cases. successive hull relies on overlapping faces which are +// not good. But, skin works on vertex sets instead of shapes, which makes it +// a lot more difficult to use +module skin_extrude_shape_hull(thickness_difference, depth_difference, extra_slices = 0 ) { + skin([ + for (index = [0:$height_slices + extra_slices]) + let( + progress = (index / $height_slices), + skew_this_slice = $top_skew * progress, + x_skew_this_slice = $top_skew_x * progress, + depth_this_slice = ($total_depth - depth_difference) * progress, + tilt_this_slice = -$top_tilt / $key_height * progress, + y_tilt_this_slice = $double_sculpted ? (-$top_tilt_y / $key_length * progress) : 0 + ) + skin_shape_slice(progress, thickness_difference, skew_this_slice, x_skew_this_slice, depth_this_slice, tilt_this_slice, y_tilt_this_slice) + ]); +} + +function skin_shape_slice(progress, thickness_difference, skew_this_slice, x_skew_this_slice, depth_this_slice, tilt_this_slice, y_tilt_this_slice) = + transform( + translation([x_skew_this_slice,skew_this_slice,depth_this_slice]), + transform( + rotation([tilt_this_slice,y_tilt_this_slice,0]), + skin_key_shape([ + total_key_width(0), + total_key_height(0), + ], + [$width_difference, $height_difference], + progress, + thickness_difference + ) + ) + ); diff --git a/src/key.scad b/src/key.scad index 8b87f16..06197ff 100644 --- a/src/key.scad +++ b/src/key.scad @@ -6,6 +6,7 @@ include include include include +include include @@ -15,210 +16,44 @@ use use use - /* [Hidden] */ SMALLEST_POSSIBLE = 1/128; -$fs = .1; +// basically disable $fs - though it might be useful for these CGAL problems +$fs = .01; $unit = 19.05; // key shape including dish. used as the ouside and inside shape in hollow_key(). allows for itself to be shrunk in depth and width / height module shape(thickness_difference, depth_difference=0){ dished(depth_difference, $inverted_dish) { - color($primary_color) shape_hull(thickness_difference, depth_difference, $inverted_dish ? 2 : 0); + color($primary_color) shape_hull(thickness_difference, depth_difference, $inverted_dish ? 200 : 0); } } -// shape of the key but with soft, rounded edges. no longer includes dish -// randomly doesnt work sometimes -// the dish doesn't _quite_ reach as far as it should -module rounded_shape() { - dished(-$minkowski_radius, $inverted_dish) { - color($primary_color) minkowski(){ - // half minkowski in the z direction - color($primary_color) shape_hull($minkowski_radius * 2, $minkowski_radius/2, $inverted_dish ? 2 : 0); - /* cube($minkowski_radius); */ - sphere(r=$minkowski_radius, $fn=$minkowski_facets); - } - } - /* %envelope(); */ -} - // this function is more correct, but takes _forever_ // the main difference is minkowski happens after dishing, meaning the dish is // also minkowski'd -/* module rounded_shape() { +module rounded_shape() { color($primary_color) minkowski(){ // half minkowski in the z direction shape($minkowski_radius * 2, $minkowski_radius/2); - difference(){ - sphere(r=$minkowski_radius, $fn=20); - translate([0,0,-$minkowski_radius]){ - cube($minkowski_radius * 2, center=true); - } - } + minkowski_object(); } -} */ +} +// minkowski places this object at every vertex of the other object then mashes +// it all together +module minkowski_object() { + // alternative minkowski shape that needs the bottom of the keycap to be trimmed + /* sphere(1); */ - -// basic key shape, no dish, no inside -// which is only used for dishing to cut the dish off correctly -// $height_difference used for keytop thickness -// extra_slices is a hack to make inverted dishes still work -module shape_hull(thickness_difference, depth_difference, extra_slices = 0){ - render() { - if ($skin_extrude_shape) { - skin_extrude_shape_hull(thickness_difference, depth_difference, extra_slices); - } else if ($linear_extrude_shape) { - linear_extrude_shape_hull(thickness_difference, depth_difference, extra_slices); - } else { - hull_shape_hull(thickness_difference, depth_difference, extra_slices); + difference(){ + sphere(r=$minkowski_radius, $fa=360/$minkowski_facets); + translate([0,0,-$minkowski_radius]){ + cube($minkowski_radius * 2, center=true); } } } -// use skin() instead of successive hulls. much more correct, and looks faster -// too, in most cases. successive hull relies on overlapping faces which are -// not good. But, skin works on vertex sets instead of shapes, which makes it -// a lot more difficult to use -module skin_extrude_shape_hull(thickness_difference, depth_difference, extra_slices = 0 ) { - skin([ - for (index = [0:$height_slices + extra_slices]) - let( - progress = (index / $height_slices), - skew_this_slice = $top_skew * progress, - x_skew_this_slice = $top_skew_x * progress, - depth_this_slice = ($total_depth - depth_difference) * progress, - tilt_this_slice = -$top_tilt / $key_height * progress, - y_tilt_this_slice = $double_sculpted ? (-$top_tilt_y / $key_length * progress) : 0 - ) - skin_shape_slice(progress, thickness_difference, skew_this_slice, x_skew_this_slice, depth_this_slice, tilt_this_slice, y_tilt_this_slice) - ]); -} - -function skin_shape_slice(progress, thickness_difference, skew_this_slice, x_skew_this_slice, depth_this_slice, tilt_this_slice, y_tilt_this_slice) = - transform( - translation([x_skew_this_slice,skew_this_slice,depth_this_slice]), - transform( - rotation([tilt_this_slice,y_tilt_this_slice,0]), - skin_key_shape([ - total_key_width(0), - total_key_height(0), - ], - [$width_difference, $height_difference], - progress, - thickness_difference - ) - ) - ); - -// corollary is hull_shape_hull -// extra_slices unused, only to match argument signatures -module linear_extrude_shape_hull(thickness_difference, depth_difference, extra_slices = 0){ - height = $total_depth - depth_difference; - width_scale = top_total_key_width() / total_key_width(); - height_scale = top_total_key_height() / total_key_height(); - - translate([0,$linear_extrude_height_adjustment,0]){ - linear_extrude(height = height, scale = [width_scale, height_scale]) { - translate([0,-$linear_extrude_height_adjustment,0]){ - key_shape( - [total_key_width(thickness_difference), total_key_height(thickness_difference)], - [$width_difference, $height_difference] - ); - } - } - } -} - -module hull_shape_hull(thickness_difference, depth_difference, extra_slices = 0) { - for (index = [0:$height_slices - 1 + extra_slices]) { - hull() { - shape_slice(index / $height_slices, thickness_difference, depth_difference); - shape_slice((index + 1) / $height_slices, thickness_difference, depth_difference); - } - } -} - -module shape_slice(progress, thickness_difference, depth_difference) { - skew_this_slice = $top_skew * progress; - x_skew_this_slice = $top_skew_x * progress; - - depth_this_slice = ($total_depth - depth_difference) * progress; - - tilt_this_slice = -$top_tilt / $key_height * progress; - y_tilt_this_slice = $double_sculpted ? (-$top_tilt_y / $key_length * progress) : 0; - - translate([x_skew_this_slice, skew_this_slice, depth_this_slice]) { - rotate([tilt_this_slice,y_tilt_this_slice,0]){ - linear_extrude(height = SMALLEST_POSSIBLE){ - key_shape( - [ - total_key_width(thickness_difference), - total_key_height(thickness_difference) - ], - [$width_difference, $height_difference], - progress - ); - } - } - } -} - -// for when you want something to only exist inside the keycap. -// used for the support structure -module inside() { - intersection() { - shape($wall_thickness, $keytop_thickness); - children(); - } -} - -// for when you want something to only exist outside the keycap -module outside() { - difference() { - children(); - shape($wall_thickness, $keytop_thickness); - } -} - -// put something at the top of the key, with no adjustments for dishing -module top_placement(depth_difference=0) { - top_tilt_by_height = -$top_tilt / $key_height; - top_tilt_y_by_length = $double_sculpted ? (-$top_tilt_y / $key_length) : 0; - - minkowski_height = $rounded_key ? $minkowski_radius : 0; - - translate([$top_skew_x + $dish_skew_x, $top_skew + $dish_skew_y, $total_depth - depth_difference + minkowski_height/2]){ - rotate([top_tilt_by_height, top_tilt_y_by_length,0]){ - children(); - } - } -} - -module front_placement() { - // all this math is to take top skew and tilt into account - // we need to find the new effective height and depth of the top, front lip - // of the keycap to find the angle so we can rotate things correctly into place - total_depth_difference = sin(-$top_tilt) * (top_total_key_height()/2); - total_height_difference = $top_skew + (1 - cos(-$top_tilt)) * (top_total_key_height()/2); - - angle = atan2(($total_depth - total_depth_difference), ($height_difference/2 + total_height_difference)); - hypotenuse = ($total_depth -total_depth_difference) / sin(angle); - - translate([0,-total_key_height()/2,0]) { - rotate([-(90-angle), 0, 0]) { - translate([0,0,hypotenuse/2]){ - children(); - } - } - } -} - -// just to DRY up the code -module _dish() { - color($secondary_color) dish(top_total_key_width() + $dish_overdraw_width, top_total_key_height() + $dish_overdraw_height, $dish_depth, $inverted_dish); -} module envelope(depth_difference=0) { s = 1.5; @@ -230,18 +65,6 @@ module envelope(depth_difference=0) { } } -// I think this is unused -module dished_for_show() { - difference(){ - union() { - envelope(); - if ($inverted_dish) top_placement(0) _dish(); - } - if (!$inverted_dish) top_placement(0) _dish(); - } -} - - // for when you want to take the dish out of things // used for adding the dish to the key shape and making sure stems don't stick out the top // creates a bounding box 1.5 times larger in width and height than the keycap. @@ -250,15 +73,21 @@ module dished(depth_difference = 0, inverted = false) { children(); difference(){ union() { + // envelope is needed to "fill in" the rest of the keycap envelope(depth_difference); - if (inverted) top_placement(depth_difference) _dish(); + if (inverted) top_placement(depth_difference) _dish(inverted); } - if (!inverted) top_placement(depth_difference) _dish(); + if (!inverted) top_placement(depth_difference) _dish(inverted); } } } -// puts it's children at the center of the dishing on the key, including dish height +// just to DRY up the code +module _dish(inverted=$inverted_dish) { + color($secondary_color) dish(top_total_key_width() + $dish_overdraw_width, top_total_key_height() + $dish_overdraw_height, $dish_depth, inverted); +} + +// puts its children at the center of the dishing on the key, including dish height // more user-friendly than top_placement module top_of_key(){ // if there is a dish, we need to account for how much it digs into the top @@ -271,6 +100,7 @@ module top_of_key(){ } } +// puts its children at each keystem position provided module keystem_positions(positions) { for (connector_pos = positions) { translate(connector_pos) { @@ -296,78 +126,121 @@ module stems_for(positions, stem_type) { } } -// legends / artisan support -module artisan(depth) { - top_of_key() { - // artisan objects / outset shape legends - color($secondary_color) children(); +// put something at the top of the key, with no adjustments for dishing +module top_placement(depth_difference=0) { + top_tilt_by_height = -$top_tilt / $key_height; + top_tilt_y_by_length = $double_sculpted ? (-$top_tilt_y / $key_length) : 0; + + minkowski_height = $rounded_key ? $minkowski_radius : 0; + + translate([$top_skew_x + $dish_skew_x, $top_skew + $dish_skew_y, $total_depth - depth_difference + minkowski_height/2]){ + rotate([top_tilt_by_height, top_tilt_y_by_length,0]){ + children(); + } } } -// key with hollowed inside but no stem -module hollow_key() { - difference(){ - if ($rounded_key) { - rounded_shape(); +module front_of_key() { + // all this math is to take top skew and tilt into account + // we need to find the new effective height and depth of the top, front lip + // of the keycap to find the angle so we can rotate things correctly into place + total_depth_difference = sin(-$top_tilt) * (top_total_key_height()/2); + total_height_difference = $top_skew + (1 - cos(-$top_tilt)) * (top_total_key_height()/2); + + angle = atan2(($total_depth - total_depth_difference), ($height_difference/2 + total_height_difference)); + hypotenuse = ($total_depth -total_depth_difference) / sin(angle); + + translate([0,-total_key_height()/2,0]) { + rotate([-(90-angle), 0, 0]) { + translate([0,0,hypotenuse/2]){ + children(); + } + } + } +} + +module outer_shape() { + shape(0, 0); +} + +module inner_shape(extra_wall_thickness = 0, extra_keytop_thickness = 0) { + translate([0,0,-SMALLEST_POSSIBLE]) { + if ($inner_shape_type == "flat") { + /* $key_shape_type="square"; */ + $height_slices = 1; + color($primary_color) shape_hull($wall_thickness + extra_wall_thickness, $keytop_thickness + extra_keytop_thickness, 0); } else { - shape(0, 0); - } - // translation purely for aesthetic purposes, to get rid of that awful lattice - translate([0,0,-SMALLEST_POSSIBLE]) { - shape($wall_thickness, $keytop_thickness); + shape($wall_thickness + extra_wall_thickness, $keytop_thickness + extra_keytop_thickness); } } } +// additive objects at the top of the key +module additive_features(inset) { + top_of_key() { + if($key_bump) keybump($key_bump_depth, $key_bump_edge); + if(!inset && $children > 0) color($secondary_color) children(); + } + if($outset_legends) legends(0); + // render the clearance check if it's enabled, but don't have it intersect with anything + if ($clearance_check) %clearance_check(); +} + +// subtractive objects at the top of the key +module subtractive_features(inset) { + top_of_key() { + if (inset && $children > 0) color($secondary_color) children(); + } + if(!$outset_legends) legends($inset_legend_depth); + // subtract the clearance check if it's enabled, letting the user see the + // parts of the keycap that will hit the cherry switch + if ($clearance_check) %clearance_check(); +} + +module inside_features() { + translate([0, 0, $stem_inset]) { + // both stem and support are optional + if ($stabilizer_type != "disable") stems_for($stabilizers, $stabilizer_type); + if ($stem_type != "disable") stems_for($stem_positions, $stem_type); + if ($stabilizer_type != "disable") support_for($stabilizers, $stabilizer_type); + // always render stem support even if there isn't a stem. + // rendering flat support w/no stem is much more common than a hollow keycap + // so if you want a hollow keycap you'll have to turn support off entirely + if ($support_type != "disable") support_for($stem_positions, $stem_type); + } +} // The final, penultimate key generation function. // takes all the bits and glues them together. requires configuration with special variables. -module key(inset = false) { - difference() { - union(){ - // the shape of the key, inside and out - hollow_key(); - if($key_bump) top_of_key() keybump($key_bump_depth, $key_bump_edge); - // additive objects at the top of the key - // outside() makes them stay out of the inside. it's a bad name - if(!inset && $children > 0) outside() artisan(0) children(); - if($outset_legends) legends(0); - // render the clearance check if it's enabled, but don't have it intersect with anything - if ($clearance_check) %clearance_check(); +module key(inset=false) { + difference(){ + union() { + outer_shape(); + additive_features(inset) { + children(); + }; } - // subtractive objects at the top of the key - // no outside() - I can't think of a use for it. will save render time - if (inset && $children > 0) artisan($inset_legend_depth) children(); - if(!$outset_legends) legends($inset_legend_depth); - // subtract the clearance check if it's enabled, letting the user see the - // parts of the keycap that will hit the cherry switch - if ($clearance_check) %clearance_check(); - } - - // both stem and support are optional - if ($stem_type != "disable" || ($stabilizers != [] && $stabilizer_type != "disable")) { - dished($keytop_thickness, $inverted_dish) { - translate([0, 0, $stem_inset]) { - if ($stabilizer_type != "disable") stems_for($stabilizers, $stabilizer_type); - - if ($stem_type != "disable") stems_for($stem_positions, $stem_type); - } + if ($inner_shape_type != "disable") difference() { + inner_shape(); + inside_features(); } + + subtractive_features(inset) { + children(); + }; } +} - if ($support_type != "disable"){ - inside() { - translate([0, 0, $stem_inset]) { - if ($stabilizer_type != "disable") support_for($stabilizers, $stabilizer_type); - - // always render stem support even if there isn't a stem. - // rendering flat support w/no stem is much more common than a hollow keycap - // so if you want a hollow keycap you'll have to turn support off entirely - support_for($stem_positions, $stem_type); - } +module display_key(inset=false) { + minkowski() { + outer_shape(); + minkowski_object(); + // minkowski doesn't work with difference + additive_features(false) { + children(); + }; } - } } // actual full key with space carved out and keystem/stabilizer connectors diff --git a/src/key_transformations.scad b/src/key_transformations.scad index f873a59..e443ae0 100644 --- a/src/key_transformations.scad +++ b/src/key_transformations.scad @@ -177,3 +177,14 @@ module debug() { %children(); } + +module display() { + $height_slices = 30; + $minkowski_facets = 64; + $shape_facets = 64; + $stem_type = "disable"; + $support_type = "disable"; + $stem_support_type = "disable"; + + children(); +} diff --git a/src/layouts/lets_split/default.scad b/src/layouts/lets_split/default.scad index e3824de..c236d43 100644 --- a/src/layouts/lets_split/default.scad +++ b/src/layouts/lets_split/default.scad @@ -1,7 +1,7 @@ include <../layout.scad> // negative numbers are used for spacing -lets_split_mapping = [ +lets_split_layout = [ [1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 1], @@ -9,5 +9,5 @@ lets_split_mapping = [ ]; module lets_split_default(profile) { - layout(lets_split_mapping, profile, row_sculpting_offset=1) children(); + layout(lets_split_layout, profile, row_sculpting_offset=1) children(); } diff --git a/src/settings.scad b/src/settings.scad index cd1fe25..0869c1e 100644 --- a/src/settings.scad +++ b/src/settings.scad @@ -187,3 +187,12 @@ $warning_color = [1,0,0, 0.15]; // how many facets circles will have when used in these features $minkowski_facets = 30; $shape_facets =30; + +// 3d surface settings +// unused for now +$3d_surface_size = 100; +// resolution in each axis. 10 = 10 divisions per x/y = 100 points total +$3d_surface_step = 5; + +// "flat" / "dished" / "disable" +$inner_shape_type = "flat"; From c7168eae688083a9b2a2c8a248b61b4a5c4ce40a Mon Sep 17 00:00:00 2001 From: Bob Date: Thu, 18 Jun 2020 16:54:53 -0400 Subject: [PATCH 2/8] remove unnecessary changes --- customizer.scad | 32 ++++++++++++-------------------- keys.scad | 29 ++--------------------------- src/key_transformations.scad | 11 ----------- 3 files changed, 14 insertions(+), 58 deletions(-) diff --git a/customizer.scad b/customizer.scad index f940ccb..40bc3d4 100644 --- a/customizer.scad +++ b/customizer.scad @@ -851,17 +851,6 @@ module debug() { %children(); } - -module display() { - $height_slices = 30; - $minkowski_facets = 64; - $shape_facets = 64; - $stem_type = "disable"; - $support_type = "disable"; - $stem_support_type = "disable"; - - children(); -} module arrows(profile, rows = [4,4,4,3]) { positions = [[0, 0], [1, 0], [2, 0], [1, 1]]; legends = ["←", "↓", "→", "↑"]; @@ -967,6 +956,7 @@ unit = 19.05; // NOT 3D function unit_length(length) = unit * (length - 1) + 18.16; + module ISO_enter_shape(size, delta, progress){ width = size[0]; height = size[1]; @@ -981,19 +971,21 @@ module ISO_enter_shape(size, delta, progress){ width_ratio = unit_length(1.25) / unit_length(1.5); height_ratio = unit_length(1) / unit_length(2); + delta = delta / 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 + [ 0-delta.x, 0-delta.y], // top right + [ 0-delta.x, -height+delta.y], // bottom right + [-width * width_ratio+delta.x, -height+delta.y], // bottom left + [-width * width_ratio + delta.x,-height * height_ratio+delta.y], // inner middle point + [ -width + delta.x,-height * height_ratio + delta.y], // outer middle point + [ -width + delta.x, 0-delta.y] // top left ]; minkowski(){ - circle(r=corner_size); + circle(r=$corner_radius); // gives us rounded inner corner - offset(r=-corner_size*2) { + offset(r=-$corner_radius*2) { translate([(width * width_ratio)/2, height/2]) polygon(points=pointArray); } } @@ -1192,7 +1184,7 @@ module rounded_square_shape(size, delta, progress, center = true) { // for skin function skin_rounded_square(size, delta, progress, thickness_difference) = - rounded_rectangle_profile(size - (delta * progress), fn=$shape_facets, r=$corner_radius); + rounded_rectangle_profile(size - (delta * progress) - [thickness_difference, thickness_difference], fn=$shape_facets, r=$corner_radius); SMALLEST_POSSIBLE = 1/128; // I use functions when I need to compute special variables off of other special variables diff --git a/keys.scad b/keys.scad index 0a80ad0..768110e 100644 --- a/keys.scad +++ b/keys.scad @@ -9,32 +9,7 @@ include <./includes.scad> // example key -/* $skin_key_shape = true; */ - -difference() { - /* top_of_key() { */ - /* cube(10); */ - /* } */ - /* key(); */ -} - -/* simple_layout(lets_split_layout) { - dcs_row($row) key(); -} */ - -dcs_row(1) legend("h") front_legend("q" -) { - $key_length = 2.75; - key(); -} - -translate_u(0,1) dcs_row(1) { - $key_length = 0.86; - key(); -} - -/* debug() key(); */ - +dcs_row(5) legend("⇪", size=9) key(); // example row /* for (x = [0:1:4]) { @@ -42,4 +17,4 @@ translate_u(0,1) dcs_row(1) { } */ // example layout -/* preonic_default("dcs"); */ +/* preonic_default("dcs"); */ \ No newline at end of file diff --git a/src/key_transformations.scad b/src/key_transformations.scad index e443ae0..f873a59 100644 --- a/src/key_transformations.scad +++ b/src/key_transformations.scad @@ -177,14 +177,3 @@ module debug() { %children(); } - -module display() { - $height_slices = 30; - $minkowski_facets = 64; - $shape_facets = 64; - $stem_type = "disable"; - $support_type = "disable"; - $stem_support_type = "disable"; - - children(); -} From 8b4b9ae6878597f0090b749322396738eb415db8 Mon Sep 17 00:00:00 2001 From: Bob Date: Thu, 18 Jun 2020 17:22:29 -0400 Subject: [PATCH 3/8] hull_shape_type --- CHANGELOG.md | 1 + TIPS_AND_TRICKS.md | 2 +- customizer.scad | 96 +++++++++++++++----------------------- src/hulls.scad | 4 +- src/key.scad | 72 +++++++++++----------------- src/key_profiles/grid.scad | 2 +- src/key_types.scad | 2 +- src/settings.scad | 8 ++-- 8 files changed, 75 insertions(+), 112 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8197d44..6857f25 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ CHANGELOG: * implemented `$inner_shape_type`, use "flat" for less geometry or "disable" to make a completely solid key easily. didn't help render rounded keys though * side-printed keycaps are first class! you can use the `sideways()` modifier to set up sideways keycaps that have flat sides to print on. * it's much easier to make quick artisans now that the inside of the keycap is differenced from any additive features placed on top + * `$linear_extrude_shape` and `$skin_extrude_shape` retired in favor of `$hull_shape_type` * still todo: add a magic scaling variable so you can scale the whole world up, see if that fixes degeneracy * still todo: rejigger supports * still todo: rejigger inner shape. maybe just always make it flat diff --git a/TIPS_AND_TRICKS.md b/TIPS_AND_TRICKS.md index ee0761d..49f96ad 100644 --- a/TIPS_AND_TRICKS.md +++ b/TIPS_AND_TRICKS.md @@ -14,7 +14,7 @@ At the end of the day though, all the columnular sculpting is doing is adding ex ## skin mode -SA, HiPro and DSA keycaps take _forever_ to render. This is a multifaceted issue that I don't want to get into here, but suffice to say _one_ of the reasons it takes so long is how the keycap is constructed from multiple, smaller slices. OpenSCAD takes more time to render the more objects you have, regardless of how they interact. Enter `$skin_extrude_shape = true`. +SA, HiPro and DSA keycaps take _forever_ to render. This is a multifaceted issue that I don't want to get into here, but suffice to say _one_ of the reasons it takes so long is how the keycap is constructed from multiple, smaller slices. OpenSCAD takes more time to render the more objects you have, regardless of how they interact. Enter `$hull_shape_type = "skin"`. `skin()` is a list comprehension function available [here](https://github.com/openscad/list-comprehension-demos/blob/master/skin.scad). The gist of it is that instead of having x number of keycap slices unioned together, we give `skin()` a set of profiles and it makes a single object out of it for us. This reduces the number of objects per keycap, which makes it easier to render them. diff --git a/customizer.scad b/customizer.scad index 40bc3d4..8712e37 100644 --- a/customizer.scad +++ b/customizer.scad @@ -133,12 +133,10 @@ $font="DejaVu Sans Mono:style=Book"; // Whether or not to render fake keyswitches to check clearances $clearance_check = false; // Should be faster, also required for concave shapes -// Use linear_extrude instead of hull slices to make the shape of the key -$linear_extrude_shape = false; -// warns in trajectory.scad but it looks benign -// brand new, more correct, hopefully faster, lots more work -$skin_extrude_shape = false; +// what kind of extrusion we use to create the keycap. "hull" is standard, "linear extrude" is legacy, "skin" is new and not well supported. +$hull_shape_type = "hull"; // ["hull", "linear extrude", "skin"] + // This doesn't work very well, but you can try $rounded_key = false; //minkowski radius. radius of sphere used in minkowski sum for minkowski_key function. 1.75 for G20 @@ -557,7 +555,7 @@ module grid_row(row=3, column = 0) { $dish_skew_x = 0; $dish_skew_y = 0; - $linear_extrude_shape = true; + $hull_shape_type = "linear extrude"; $dish_overdraw_width = -8; @@ -662,7 +660,7 @@ module iso_enter() { $top_tilt = 0; $stem_support_type = "disable"; $key_shape_type = "iso_enter"; - /* $linear_extrude_shape = true; */ + /* $hull_shape_type = "linear extrude"; */ $linear_extrude_height_adjustment = 19.05 * 0.5; // this equals (unit_length(1.5) - unit_length(1.25)) / 2 $dish_overdraw_width = 2.38125; @@ -2962,9 +2960,9 @@ module shape_slice(progress, thickness_difference, depth_difference) { // extra_slices is a hack to make inverted dishes still work module shape_hull(thickness_difference, depth_difference, extra_slices = 0){ render() { - if ($skin_extrude_shape) { + if ($hull_shape_type == "skin") { skin_extrude_shape_hull(thickness_difference, depth_difference, extra_slices); - } else if ($linear_extrude_shape) { + } else if ($hull_shape_type == "linear extrude") { linear_extrude_shape_hull(thickness_difference, depth_difference, extra_slices); } else { hull_shape_hull(thickness_difference, depth_difference, extra_slices); @@ -3928,9 +3926,7 @@ module shape(thickness_difference, depth_difference=0){ } } -// this function is more correct, but takes _forever_ -// the main difference is minkowski happens after dishing, meaning the dish is -// also minkowski'd +// Not currently used due to CGAL errors. Rounds the shape via minkowski module rounded_shape() { color($primary_color) minkowski(){ // half minkowski in the z direction @@ -3953,7 +3949,6 @@ module minkowski_object() { } } - module envelope(depth_difference=0) { s = 1.5; hull(){ @@ -3986,19 +3981,6 @@ module _dish(inverted=$inverted_dish) { color($secondary_color) dish(top_total_key_width() + $dish_overdraw_width, top_total_key_height() + $dish_overdraw_height, $dish_depth, inverted); } -// puts its children at the center of the dishing on the key, including dish height -// more user-friendly than top_placement -module top_of_key(){ - // if there is a dish, we need to account for how much it digs into the top - dish_depth = ($dish_type == "disable") ? 0 : $dish_depth; - // if the dish is inverted, we need to account for that too. in this case we do half, otherwise the children would be floating on top of the dish - corrected_dish_depth = ($inverted_dish) ? -dish_depth / 2 : dish_depth; - - top_placement(corrected_dish_depth) { - children(); - } -} - // puts its children at each keystem position provided module keystem_positions(positions) { for (connector_pos = positions) { @@ -4039,6 +4021,19 @@ module top_placement(depth_difference=0) { } } +// puts its children at the center of the dishing on the key, including dish height +// more user-friendly than top_placement +module top_of_key(){ + // if there is a dish, we need to account for how much it digs into the top + dish_depth = ($dish_type == "disable") ? 0 : $dish_depth; + // if the dish is inverted, we need to account for that too. in this case we do half, otherwise the children would be floating on top of the dish + corrected_dish_depth = ($inverted_dish) ? -dish_depth / 2 : dish_depth; + + top_placement(corrected_dish_depth) { + children(); + } +} + module front_of_key() { // all this math is to take top skew and tilt into account // we need to find the new effective height and depth of the top, front lip @@ -4063,14 +4058,12 @@ module outer_shape() { } module inner_shape(extra_wall_thickness = 0, extra_keytop_thickness = 0) { - translate([0,0,-SMALLEST_POSSIBLE]) { - if ($inner_shape_type == "flat") { - /* $key_shape_type="square"; */ - $height_slices = 1; - color($primary_color) shape_hull($wall_thickness + extra_wall_thickness, $keytop_thickness + extra_keytop_thickness, 0); - } else { - shape($wall_thickness + extra_wall_thickness, $keytop_thickness + extra_keytop_thickness); - } + if ($inner_shape_type == "flat") { + /* $key_shape_type="square"; */ + $height_slices = 1; + color($primary_color) shape_hull($wall_thickness + extra_wall_thickness, $keytop_thickness + extra_keytop_thickness, 0); + } else { + shape($wall_thickness + extra_wall_thickness, $keytop_thickness + extra_keytop_thickness); } } @@ -4096,15 +4089,11 @@ module subtractive_features(inset) { if ($clearance_check) %clearance_check(); } +// features inside the key itself (stem, supports, etc) module inside_features() { translate([0, 0, $stem_inset]) { - // both stem and support are optional if ($stabilizer_type != "disable") stems_for($stabilizers, $stabilizer_type); if ($stem_type != "disable") stems_for($stem_positions, $stem_type); - if ($stabilizer_type != "disable") support_for($stabilizers, $stabilizer_type); - // always render stem support even if there isn't a stem. - // rendering flat support w/no stem is much more common than a hollow keycap - // so if you want a hollow keycap you'll have to turn support off entirely if ($support_type != "disable") support_for($stem_positions, $stem_type); } } @@ -4120,9 +4109,13 @@ module key(inset=false) { }; } - if ($inner_shape_type != "disable") difference() { - inner_shape(); - inside_features(); + if ($inner_shape_type != "disable") { + translate([0,0,-SMALLEST_POSSIBLE]) { + difference() { + inner_shape(); + inside_features(); + } + } } subtractive_features(inset) { @@ -4131,17 +4124,6 @@ module key(inset=false) { } } -module display_key(inset=false) { - minkowski() { - outer_shape(); - minkowski_object(); - // minkowski doesn't work with difference - additive_features(false) { - children(); - }; - } -} - // actual full key with space carved out and keystem/stabilizer connectors // this is an example key with all the fixins from settings.scad module example_key(){ @@ -4265,12 +4247,10 @@ $font="DejaVu Sans Mono:style=Book"; // Whether or not to render fake keyswitches to check clearances $clearance_check = false; // Should be faster, also required for concave shapes -// Use linear_extrude instead of hull slices to make the shape of the key -$linear_extrude_shape = false; -// warns in trajectory.scad but it looks benign -// brand new, more correct, hopefully faster, lots more work -$skin_extrude_shape = false; +// what kind of extrusion we use to create the keycap. "hull" is standard, "linear extrude" is legacy, "skin" is new and not well supported. +$hull_shape_type = "hull"; // ["hull", "linear extrude", "skin"] + // This doesn't work very well, but you can try $rounded_key = false; //minkowski radius. radius of sphere used in minkowski sum for minkowski_key function. 1.75 for G20 diff --git a/src/hulls.scad b/src/hulls.scad index 2fb7218..2698011 100644 --- a/src/hulls.scad +++ b/src/hulls.scad @@ -8,9 +8,9 @@ include // extra_slices is a hack to make inverted dishes still work module shape_hull(thickness_difference, depth_difference, extra_slices = 0){ render() { - if ($skin_extrude_shape) { + if ($hull_shape_type == "skin") { skin_extrude_shape_hull(thickness_difference, depth_difference, extra_slices); - } else if ($linear_extrude_shape) { + } else if ($hull_shape_type == "linear extrude") { linear_extrude_shape_hull(thickness_difference, depth_difference, extra_slices); } else { hull_shape_hull(thickness_difference, depth_difference, extra_slices); diff --git a/src/key.scad b/src/key.scad index 06197ff..388625f 100644 --- a/src/key.scad +++ b/src/key.scad @@ -29,9 +29,7 @@ module shape(thickness_difference, depth_difference=0){ } } -// this function is more correct, but takes _forever_ -// the main difference is minkowski happens after dishing, meaning the dish is -// also minkowski'd +// Not currently used due to CGAL errors. Rounds the shape via minkowski module rounded_shape() { color($primary_color) minkowski(){ // half minkowski in the z direction @@ -54,7 +52,6 @@ module minkowski_object() { } } - module envelope(depth_difference=0) { s = 1.5; hull(){ @@ -87,19 +84,6 @@ module _dish(inverted=$inverted_dish) { color($secondary_color) dish(top_total_key_width() + $dish_overdraw_width, top_total_key_height() + $dish_overdraw_height, $dish_depth, inverted); } -// puts its children at the center of the dishing on the key, including dish height -// more user-friendly than top_placement -module top_of_key(){ - // if there is a dish, we need to account for how much it digs into the top - dish_depth = ($dish_type == "disable") ? 0 : $dish_depth; - // if the dish is inverted, we need to account for that too. in this case we do half, otherwise the children would be floating on top of the dish - corrected_dish_depth = ($inverted_dish) ? -dish_depth / 2 : dish_depth; - - top_placement(corrected_dish_depth) { - children(); - } -} - // puts its children at each keystem position provided module keystem_positions(positions) { for (connector_pos = positions) { @@ -140,6 +124,19 @@ module top_placement(depth_difference=0) { } } +// puts its children at the center of the dishing on the key, including dish height +// more user-friendly than top_placement +module top_of_key(){ + // if there is a dish, we need to account for how much it digs into the top + dish_depth = ($dish_type == "disable") ? 0 : $dish_depth; + // if the dish is inverted, we need to account for that too. in this case we do half, otherwise the children would be floating on top of the dish + corrected_dish_depth = ($inverted_dish) ? -dish_depth / 2 : dish_depth; + + top_placement(corrected_dish_depth) { + children(); + } +} + module front_of_key() { // all this math is to take top skew and tilt into account // we need to find the new effective height and depth of the top, front lip @@ -164,14 +161,12 @@ module outer_shape() { } module inner_shape(extra_wall_thickness = 0, extra_keytop_thickness = 0) { - translate([0,0,-SMALLEST_POSSIBLE]) { - if ($inner_shape_type == "flat") { - /* $key_shape_type="square"; */ - $height_slices = 1; - color($primary_color) shape_hull($wall_thickness + extra_wall_thickness, $keytop_thickness + extra_keytop_thickness, 0); - } else { - shape($wall_thickness + extra_wall_thickness, $keytop_thickness + extra_keytop_thickness); - } + if ($inner_shape_type == "flat") { + /* $key_shape_type="square"; */ + $height_slices = 1; + color($primary_color) shape_hull($wall_thickness + extra_wall_thickness, $keytop_thickness + extra_keytop_thickness, 0); + } else { + shape($wall_thickness + extra_wall_thickness, $keytop_thickness + extra_keytop_thickness); } } @@ -197,15 +192,11 @@ module subtractive_features(inset) { if ($clearance_check) %clearance_check(); } +// features inside the key itself (stem, supports, etc) module inside_features() { translate([0, 0, $stem_inset]) { - // both stem and support are optional if ($stabilizer_type != "disable") stems_for($stabilizers, $stabilizer_type); if ($stem_type != "disable") stems_for($stem_positions, $stem_type); - if ($stabilizer_type != "disable") support_for($stabilizers, $stabilizer_type); - // always render stem support even if there isn't a stem. - // rendering flat support w/no stem is much more common than a hollow keycap - // so if you want a hollow keycap you'll have to turn support off entirely if ($support_type != "disable") support_for($stem_positions, $stem_type); } } @@ -221,9 +212,13 @@ module key(inset=false) { }; } - if ($inner_shape_type != "disable") difference() { - inner_shape(); - inside_features(); + if ($inner_shape_type != "disable") { + translate([0,0,-SMALLEST_POSSIBLE]) { + difference() { + inner_shape(); + inside_features(); + } + } } subtractive_features(inset) { @@ -232,17 +227,6 @@ module key(inset=false) { } } -module display_key(inset=false) { - minkowski() { - outer_shape(); - minkowski_object(); - // minkowski doesn't work with difference - additive_features(false) { - children(); - }; - } -} - // actual full key with space carved out and keystem/stabilizer connectors // this is an example key with all the fixins from settings.scad module example_key(){ diff --git a/src/key_profiles/grid.scad b/src/key_profiles/grid.scad index 2528e11..94f4906 100644 --- a/src/key_profiles/grid.scad +++ b/src/key_profiles/grid.scad @@ -11,7 +11,7 @@ module grid_row(row=3, column = 0) { $dish_skew_x = 0; $dish_skew_y = 0; - $linear_extrude_shape = true; + $hull_shape_type = "linear extrude"; $dish_overdraw_width = -8; diff --git a/src/key_types.scad b/src/key_types.scad index 1b821a1..b867895 100644 --- a/src/key_types.scad +++ b/src/key_types.scad @@ -46,7 +46,7 @@ module iso_enter() { $top_tilt = 0; $stem_support_type = "disable"; $key_shape_type = "iso_enter"; - /* $linear_extrude_shape = true; */ + /* $hull_shape_type = "linear extrude"; */ $linear_extrude_height_adjustment = 19.05 * 0.5; // this equals (unit_length(1.5) - unit_length(1.25)) / 2 $dish_overdraw_width = 2.38125; diff --git a/src/settings.scad b/src/settings.scad index 0869c1e..186a395 100644 --- a/src/settings.scad +++ b/src/settings.scad @@ -118,12 +118,10 @@ $font="DejaVu Sans Mono:style=Book"; // Whether or not to render fake keyswitches to check clearances $clearance_check = false; // Should be faster, also required for concave shapes -// Use linear_extrude instead of hull slices to make the shape of the key -$linear_extrude_shape = false; -// warns in trajectory.scad but it looks benign -// brand new, more correct, hopefully faster, lots more work -$skin_extrude_shape = false; +// what kind of extrusion we use to create the keycap. "hull" is standard, "linear extrude" is legacy, "skin" is new and not well supported. +$hull_shape_type = "hull"; // ["hull", "linear extrude", "skin"] + // This doesn't work very well, but you can try $rounded_key = false; //minkowski radius. radius of sphere used in minkowski sum for minkowski_key function. 1.75 for G20 From 2eed004407e788653341dfeac739a6169d43f8a0 Mon Sep 17 00:00:00 2001 From: Bob Date: Thu, 18 Jun 2020 17:22:39 -0400 Subject: [PATCH 4/8] skin_rounded_square_fix --- src/shapes/rounded_square.scad | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shapes/rounded_square.scad b/src/shapes/rounded_square.scad index e3f5f26..77ffd0a 100644 --- a/src/shapes/rounded_square.scad +++ b/src/shapes/rounded_square.scad @@ -9,4 +9,4 @@ module rounded_square_shape(size, delta, progress, center = true) { // for skin function skin_rounded_square(size, delta, progress, thickness_difference) = - rounded_rectangle_profile(size - (delta * progress), fn=$shape_facets, r=$corner_radius); + rounded_rectangle_profile(size - (delta * progress) - [thickness_difference, thickness_difference], fn=$shape_facets, r=$corner_radius); From 57fbf6044d97099399ce339ac032710a898b90de Mon Sep 17 00:00:00 2001 From: Bob Date: Thu, 18 Jun 2020 17:22:58 -0400 Subject: [PATCH 5/8] ISO enter small fix --- src/shapes/ISO_enter.scad | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/shapes/ISO_enter.scad b/src/shapes/ISO_enter.scad index 8c5730f..9357854 100644 --- a/src/shapes/ISO_enter.scad +++ b/src/shapes/ISO_enter.scad @@ -2,6 +2,7 @@ // NOT 3D function unit_length(length) = unit * (length - 1) + 18.16; + module ISO_enter_shape(size, delta, progress){ width = size[0]; height = size[1]; @@ -16,19 +17,21 @@ module ISO_enter_shape(size, delta, progress){ width_ratio = unit_length(1.25) / unit_length(1.5); height_ratio = unit_length(1) / unit_length(2); + delta = delta / 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 + [ 0-delta.x, 0-delta.y], // top right + [ 0-delta.x, -height+delta.y], // bottom right + [-width * width_ratio+delta.x, -height+delta.y], // bottom left + [-width * width_ratio + delta.x,-height * height_ratio+delta.y], // inner middle point + [ -width + delta.x,-height * height_ratio + delta.y], // outer middle point + [ -width + delta.x, 0-delta.y] // top left ]; minkowski(){ - circle(r=corner_size); + circle(r=$corner_radius); // gives us rounded inner corner - offset(r=-corner_size*2) { + offset(r=-$corner_radius*2) { translate([(width * width_ratio)/2, height/2]) polygon(points=pointArray); } } From e29bb46dfa4e810bc2a3b748961214828657eb6a Mon Sep 17 00:00:00 2001 From: Bob Date: Thu, 18 Jun 2020 20:33:51 -0400 Subject: [PATCH 6/8] hull fix --- customizer.scad | 2 +- src/hulls/hull.scad | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/customizer.scad b/customizer.scad index 8712e37..a481ea5 100644 --- a/customizer.scad +++ b/customizer.scad @@ -2940,7 +2940,7 @@ module shape_slice(progress, thickness_difference, depth_difference) { translate([x_skew_this_slice, skew_this_slice, depth_this_slice]) { rotate([tilt_this_slice,y_tilt_this_slice,0]){ - linear_extrude(height = SMALLEST_POSSIBLE + ($rounded_key ? $minkowski_radius : 0), scale = SMALLEST_POSSIBLE){ + linear_extrude(height = SMALLEST_POSSIBLE, scale = 1){ key_shape( [ total_key_width(thickness_difference), diff --git a/src/hulls/hull.scad b/src/hulls/hull.scad index 12df0bb..af07224 100644 --- a/src/hulls/hull.scad +++ b/src/hulls/hull.scad @@ -18,7 +18,7 @@ module shape_slice(progress, thickness_difference, depth_difference) { translate([x_skew_this_slice, skew_this_slice, depth_this_slice]) { rotate([tilt_this_slice,y_tilt_this_slice,0]){ - linear_extrude(height = SMALLEST_POSSIBLE + ($rounded_key ? $minkowski_radius : 0), scale = SMALLEST_POSSIBLE){ + linear_extrude(height = SMALLEST_POSSIBLE, scale = 1){ key_shape( [ total_key_width(thickness_difference), From 24c80cb735363f950364dca8bdf43befc0389be6 Mon Sep 17 00:00:00 2001 From: Bob Date: Wed, 8 Jul 2020 13:58:05 -0400 Subject: [PATCH 7/8] Couple tweaks for doubleshot --- customizer.scad | 29 ++++++++++++++++++----------- src/features/legends.scad | 2 +- src/key.scad | 27 +++++++++++++++++---------- 3 files changed, 36 insertions(+), 22 deletions(-) diff --git a/customizer.scad b/customizer.scad index a481ea5..3950f77 100644 --- a/customizer.scad +++ b/customizer.scad @@ -2846,7 +2846,7 @@ module keytext(text, position, font_size, depth) { woffset = (top_total_key_width()/3.5) * position[0]; hoffset = (top_total_key_height()/3.5) * -position[1]; translate([woffset, hoffset, -depth]){ - color($tertiary_color) linear_extrude(height=$dish_depth){ + color($tertiary_color) linear_extrude(height=$dish_depth + depth){ text(text=text, font=$font, size=font_size, halign="center", valign="center"); } } @@ -4098,23 +4098,30 @@ module inside_features() { } } +// helpers for doubleshot keycaps for now +module inner_total_shape() { + difference() { + inner_shape(); + inside_features(); + } +} + +module outer_total_shape(inset=false) { + outer_shape(); + additive_features(inset) { + children(); + }; +} + // The final, penultimate key generation function. // takes all the bits and glues them together. requires configuration with special variables. module key(inset=false) { difference(){ - union() { - outer_shape(); - additive_features(inset) { - children(); - }; - } + outer_total_shape(inset); if ($inner_shape_type != "disable") { translate([0,0,-SMALLEST_POSSIBLE]) { - difference() { - inner_shape(); - inside_features(); - } + inner_total_shape(); } } diff --git a/src/features/legends.scad b/src/features/legends.scad index e657218..2f0171a 100644 --- a/src/features/legends.scad +++ b/src/features/legends.scad @@ -2,7 +2,7 @@ module keytext(text, position, font_size, depth) { woffset = (top_total_key_width()/3.5) * position[0]; hoffset = (top_total_key_height()/3.5) * -position[1]; translate([woffset, hoffset, -depth]){ - color($tertiary_color) linear_extrude(height=$dish_depth){ + color($tertiary_color) linear_extrude(height=$dish_depth + depth){ text(text=text, font=$font, size=font_size, halign="center", valign="center"); } } diff --git a/src/key.scad b/src/key.scad index 388625f..1f47db8 100644 --- a/src/key.scad +++ b/src/key.scad @@ -201,23 +201,30 @@ module inside_features() { } } +// helpers for doubleshot keycaps for now +module inner_total_shape() { + difference() { + inner_shape(); + inside_features(); + } +} + +module outer_total_shape(inset=false) { + outer_shape(); + additive_features(inset) { + children(); + }; +} + // The final, penultimate key generation function. // takes all the bits and glues them together. requires configuration with special variables. module key(inset=false) { difference(){ - union() { - outer_shape(); - additive_features(inset) { - children(); - }; - } + outer_total_shape(inset); if ($inner_shape_type != "disable") { translate([0,0,-SMALLEST_POSSIBLE]) { - difference() { - inner_shape(); - inside_features(); - } + inner_total_shape(); } } From e6dd35fca0d090dc4de43fcb367d6c9af2df9d46 Mon Sep 17 00:00:00 2001 From: Bob Date: Tue, 21 Jul 2020 13:51:03 -0400 Subject: [PATCH 8/8] Update linear_extrude.scad mostly for iso enter --- customizer.scad | 4 ++-- src/hulls/linear_extrude.scad | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/customizer.scad b/customizer.scad index 3950f77..7b54da0 100644 --- a/customizer.scad +++ b/customizer.scad @@ -2913,8 +2913,8 @@ module linear_extrude_shape_hull(thickness_difference, depth_difference, extra_s linear_extrude(height = height, scale = [width_scale, height_scale]) { translate([0,-$linear_extrude_height_adjustment,0]){ key_shape( - [total_key_width(thickness_difference), total_key_height(thickness_difference)], - [$width_difference, $height_difference] + [total_key_width(), total_key_height()], + [thickness_difference, thickness_difference] ); } } diff --git a/src/hulls/linear_extrude.scad b/src/hulls/linear_extrude.scad index f62299e..dbe6e8b 100644 --- a/src/hulls/linear_extrude.scad +++ b/src/hulls/linear_extrude.scad @@ -9,8 +9,8 @@ module linear_extrude_shape_hull(thickness_difference, depth_difference, extra_s linear_extrude(height = height, scale = [width_scale, height_scale]) { translate([0,-$linear_extrude_height_adjustment,0]){ key_shape( - [total_key_width(thickness_difference), total_key_height(thickness_difference)], - [$width_difference, $height_difference] + [total_key_width(), total_key_height()], + [thickness_difference, thickness_difference] ); } }