mirror of
https://github.com/rsheldiii/KeyV2.git
synced 2026-01-14 22:37:56 -05:00
Compare commits
6 Commits
regular-po
...
custom-ste
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fd68c281c3 | ||
|
|
24e280fe3c | ||
|
|
69175f08e4 | ||
|
|
f4f595c651 | ||
|
|
fa49ee0c70 | ||
|
|
9e3f5f4bcd |
16
CHANGELOG.md
16
CHANGELOG.md
@@ -1,16 +0,0 @@
|
|||||||
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
|
|
||||||
* `$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
|
|
||||||
@@ -14,7 +14,7 @@ At the end of the day though, all the columnular sculpting is doing is adding ex
|
|||||||
|
|
||||||
## skin mode
|
## 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 `$hull_shape_type = "skin"`.
|
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`.
|
||||||
|
|
||||||
`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.
|
`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.
|
||||||
|
|
||||||
|
|||||||
1201
customizer.scad
1201
customizer.scad
File diff suppressed because it is too large
Load Diff
@@ -9,7 +9,10 @@ include <./includes.scad>
|
|||||||
|
|
||||||
|
|
||||||
// example key
|
// example key
|
||||||
dcs_row(5) legend("⇪", size=9) key();
|
/* $stem_throw = 1; */
|
||||||
|
$stem_type = "custom";
|
||||||
|
$outset_legends = true;
|
||||||
|
dcs_row(5) front_legend("j") key();
|
||||||
|
|
||||||
// example row
|
// example row
|
||||||
/* for (x = [0:1:4]) {
|
/* for (x = [0:1:4]) {
|
||||||
|
|||||||
@@ -1,4 +1 @@
|
|||||||
// a safe theoretical distance between two vertices such that they don't collapse. hard to use
|
|
||||||
SMALLEST_POSSIBLE = 1/128;
|
SMALLEST_POSSIBLE = 1/128;
|
||||||
$fs=0.1;
|
|
||||||
$unit=19.05;
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ include <dishes/old_spherical.scad>
|
|||||||
include <dishes/sideways_cylindrical.scad>
|
include <dishes/sideways_cylindrical.scad>
|
||||||
include <dishes/spherical.scad>
|
include <dishes/spherical.scad>
|
||||||
include <dishes/flat.scad>
|
include <dishes/flat.scad>
|
||||||
|
include <dishes/3d_surface.scad>
|
||||||
|
|
||||||
//geodesic looks much better, but runs very slow for anything above a 2u
|
//geodesic looks much better, but runs very slow for anything above a 2u
|
||||||
geodesic=false;
|
geodesic=false;
|
||||||
@@ -19,9 +20,10 @@ module dish(width, height, depth, inverted) {
|
|||||||
}
|
}
|
||||||
else if ($dish_type == "sideways cylindrical"){
|
else if ($dish_type == "sideways cylindrical"){
|
||||||
sideways_cylindrical_dish(width, height, depth, inverted);
|
sideways_cylindrical_dish(width, height, depth, inverted);
|
||||||
}
|
} else if ($dish_type == "old spherical") {
|
||||||
else if ($dish_type == "old spherical") {
|
|
||||||
old_spherical_dish(width, height, depth, inverted);
|
old_spherical_dish(width, height, depth, inverted);
|
||||||
|
} else if ($dish_type == "3d_surface") {
|
||||||
|
3d_surface_dish(width, height, depth, inverted);
|
||||||
} else if ($dish_type == "flat") {
|
} else if ($dish_type == "flat") {
|
||||||
flat_dish(width, height, depth, inverted);
|
flat_dish(width, height, depth, inverted);
|
||||||
} else if ($dish_type == "disable") {
|
} else if ($dish_type == "disable") {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ module 3d_surface_dish(width, height, depth, inverted) {
|
|||||||
// skew and tilt of the top. it's a pain to calculate though
|
// skew and tilt of the top. it's a pain to calculate though
|
||||||
scale_factor = 1.1;
|
scale_factor = 1.1;
|
||||||
// the edges on this behave differently than with the previous dish implementations
|
// 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([inverted ? 0:180,0,90]) 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); */
|
/* %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); */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
// features are any premade self-contained objects that go on top or inside
|
|
||||||
|
|
||||||
include <features/key_bump.scad>
|
|
||||||
include <features/clearance_check.scad>
|
|
||||||
include <features/legends.scad>
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
// a fake cherry keyswitch, abstracted out to maybe replace with a better one later
|
|
||||||
module cherry_keyswitch() {
|
|
||||||
union() {
|
|
||||||
hull() {
|
|
||||||
cube([15.6, 15.6, 0.01], center=true);
|
|
||||||
translate([0,1,5 - 0.01]) cube([10.5,9.5, 0.01], center=true);
|
|
||||||
}
|
|
||||||
hull() {
|
|
||||||
cube([15.6, 15.6, 0.01], center=true);
|
|
||||||
translate([0,0,-5.5]) cube([13.5,13.5,0.01], center=true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//approximate (fully depressed) cherry key to check clearances
|
|
||||||
module clearance_check() {
|
|
||||||
if($stem_type == "cherry" || $stem_type == "cherry_rounded"){
|
|
||||||
color($warning_color){
|
|
||||||
translate([0,0,3.6 + $stem_inset - 5]) {
|
|
||||||
cherry_keyswitch();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
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 + depth){
|
|
||||||
text(text=text, font=$font, size=font_size, halign="center", valign="center");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module legends(depth=0) {
|
|
||||||
if (len($front_legends) > 0) {
|
|
||||||
front_of_key() {
|
|
||||||
for (i=[0:len($front_legends)-1]) {
|
|
||||||
rotate([90,0,0]) keytext($front_legends[i][0], $front_legends[i][1], $front_legends[i][2], depth);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (len($legends) > 0) {
|
|
||||||
top_of_key() {
|
|
||||||
for (i=[0:len($legends)-1]) {
|
|
||||||
keytext($legends[i][0], $legends[i][1], $legends[i][2], depth);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -4,8 +4,6 @@ include <constants.scad>
|
|||||||
// functions need to be explicitly included, unlike special variables, which
|
// functions need to be explicitly included, unlike special variables, which
|
||||||
// just need to have been set before they are used. hence this file
|
// just need to have been set before they are used. hence this file
|
||||||
|
|
||||||
function stem_height() = $total_depth - $dish_depth - $stem_inset;
|
|
||||||
|
|
||||||
// cherry stem dimensions
|
// cherry stem dimensions
|
||||||
function outer_cherry_stem(slop) = [7.2 - slop * 2, 5.5 - slop * 2];
|
function outer_cherry_stem(slop) = [7.2 - slop * 2, 5.5 - slop * 2];
|
||||||
|
|
||||||
@@ -60,9 +58,4 @@ function surface_function(x,y) = (sin(acos(x/$3d_surface_size)));
|
|||||||
// spherical
|
// spherical
|
||||||
function surface_function(x,y) = (sin(acos(x/$3d_surface_size))) * sin(acos(y/$3d_surface_size));
|
function surface_function(x,y) = (sin(acos(x/$3d_surface_size))) * sin(acos(y/$3d_surface_size));
|
||||||
// (statically) random!
|
// (statically) random!
|
||||||
// ripples
|
/* function surface_function(x,y) = sin(rands(0,90,1,x+y)[0]); */
|
||||||
/* 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); */
|
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
include <hulls/skin.scad>
|
|
||||||
include <hulls/linear_extrude.scad>
|
|
||||||
include <hulls/hull.scad>
|
|
||||||
|
|
||||||
// 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 ($hull_shape_type == "skin") {
|
|
||||||
skin_extrude_shape_hull(thickness_difference, depth_difference, extra_slices);
|
|
||||||
} 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
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, scale = 1){
|
|
||||||
key_shape(
|
|
||||||
[
|
|
||||||
total_key_width(thickness_difference),
|
|
||||||
total_key_height(thickness_difference)
|
|
||||||
],
|
|
||||||
[$width_difference, $height_difference],
|
|
||||||
progress
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
// 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(), total_key_height()],
|
|
||||||
[thickness_difference, thickness_difference]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,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
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
473
src/key.scad
473
src/key.scad
@@ -5,8 +5,7 @@ include <stems.scad>
|
|||||||
include <stem_supports.scad>
|
include <stem_supports.scad>
|
||||||
include <dishes.scad>
|
include <dishes.scad>
|
||||||
include <supports.scad>
|
include <supports.scad>
|
||||||
include <features.scad>
|
include <key_features.scad>
|
||||||
include <hulls.scad>
|
|
||||||
|
|
||||||
include <libraries/geodesic_sphere.scad>
|
include <libraries/geodesic_sphere.scad>
|
||||||
|
|
||||||
@@ -16,100 +15,173 @@ use <libraries/scad-utils/lists.scad>
|
|||||||
use <libraries/scad-utils/shapes.scad>
|
use <libraries/scad-utils/shapes.scad>
|
||||||
use <libraries/skin.scad>
|
use <libraries/skin.scad>
|
||||||
|
|
||||||
|
|
||||||
/* [Hidden] */
|
/* [Hidden] */
|
||||||
SMALLEST_POSSIBLE = 1/128;
|
SMALLEST_POSSIBLE = 1/128;
|
||||||
// basically disable $fs - though it might be useful for these CGAL problems
|
$fs = .1;
|
||||||
$fs = .01;
|
|
||||||
$unit = 19.05;
|
$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
|
// 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){
|
module shape(thickness_difference, depth_difference=0){
|
||||||
dished(depth_difference, $inverted_dish) {
|
dished(depth_difference, $inverted_dish) {
|
||||||
color($primary_color) shape_hull(thickness_difference, depth_difference, $inverted_dish ? 200 : 0);
|
color($primary_color) shape_hull(thickness_difference, depth_difference, $inverted_dish ? 2 : 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not currently used due to CGAL errors. Rounds the shape via minkowski
|
// 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() {
|
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() {
|
||||||
color($primary_color) minkowski(){
|
color($primary_color) minkowski(){
|
||||||
// half minkowski in the z direction
|
// half minkowski in the z direction
|
||||||
shape($minkowski_radius * 2, $minkowski_radius/2);
|
shape($minkowski_radius * 2, $minkowski_radius/2);
|
||||||
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); */
|
|
||||||
|
|
||||||
difference(){
|
|
||||||
sphere(r=$minkowski_radius, $fa=360/$minkowski_facets);
|
|
||||||
translate([0,0,-$minkowski_radius]){
|
|
||||||
cube($minkowski_radius * 2, center=true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module envelope(depth_difference=0) {
|
|
||||||
s = 1.5;
|
|
||||||
hull(){
|
|
||||||
cube([total_key_width() * s, total_key_height() * s, 0.01], center = true);
|
|
||||||
top_placement(SMALLEST_POSSIBLE + depth_difference){
|
|
||||||
cube([top_total_key_width() * s, top_total_key_height() * s, 0.01], center = true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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.
|
|
||||||
module dished(depth_difference = 0, inverted = false) {
|
|
||||||
intersection() {
|
|
||||||
children();
|
|
||||||
difference(){
|
difference(){
|
||||||
union() {
|
sphere(r=$minkowski_radius, $fn=20);
|
||||||
// envelope is needed to "fill in" the rest of the keycap
|
translate([0,0,-$minkowski_radius]){
|
||||||
envelope(depth_difference);
|
cube($minkowski_radius * 2, center=true);
|
||||||
if (inverted) top_placement(depth_difference) _dish(inverted);
|
|
||||||
}
|
}
|
||||||
if (!inverted) top_placement(depth_difference) _dish(inverted);
|
}
|
||||||
|
}
|
||||||
|
} */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// just to DRY up the code
|
// use skin() instead of successive hulls. much more correct, and looks faster
|
||||||
module _dish(inverted=$inverted_dish) {
|
// too, in most cases. successive hull relies on overlapping faces which are
|
||||||
color($secondary_color) dish(top_total_key_width() + $dish_overdraw_width, top_total_key_height() + $dish_overdraw_height, $dish_depth, inverted);
|
// 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)
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// puts its children at each keystem position provided
|
function skin_shape_slice(progress, thickness_difference, skew_this_slice, x_skew_this_slice, depth_this_slice, tilt_this_slice, y_tilt_this_slice) =
|
||||||
module keystem_positions(positions) {
|
transform(
|
||||||
for (connector_pos = positions) {
|
translation([x_skew_this_slice,skew_this_slice,depth_this_slice]),
|
||||||
translate(connector_pos) {
|
transform(
|
||||||
rotate([0, 0, $stem_rotation]){
|
rotation([tilt_this_slice,y_tilt_this_slice,0]),
|
||||||
children();
|
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 support_for(positions, stem_type) {
|
module hull_shape_hull(thickness_difference, depth_difference, extra_slices = 0) {
|
||||||
keystem_positions(positions) {
|
for (index = [0:$height_slices - 1 + extra_slices]) {
|
||||||
color($tertiary_color) supports($support_type, stem_type, $stem_throw, $total_depth - $stem_throw);
|
hull() {
|
||||||
|
shape_slice(index / $height_slices, thickness_difference, depth_difference);
|
||||||
|
shape_slice((index + 1) / $height_slices, thickness_difference, depth_difference);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module stems_for(positions, stem_type) {
|
module shape_slice(progress, thickness_difference, depth_difference) {
|
||||||
keystem_positions(positions) {
|
skew_this_slice = $top_skew * progress;
|
||||||
color($tertiary_color) stem(stem_type, stem_height(), $stem_slop);
|
x_skew_this_slice = $top_skew_x * progress;
|
||||||
if ($stem_support_type != "disable") {
|
|
||||||
color($quaternary_color) stem_support($stem_support_type, stem_type, $stem_support_height, $stem_slop);
|
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
|
// put something at the top of the key, with no adjustments for dishing
|
||||||
module top_placement(depth_difference=0) {
|
module top_placement(depth_difference=0) {
|
||||||
top_tilt_by_height = -$top_tilt / $key_height;
|
top_tilt_by_height = -$top_tilt / $key_height;
|
||||||
@@ -124,20 +196,7 @@ module top_placement(depth_difference=0) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// puts its children at the center of the dishing on the key, including dish height
|
module front_placement() {
|
||||||
// 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
|
// 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
|
// 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
|
// of the keycap to find the angle so we can rotate things correctly into place
|
||||||
@@ -156,95 +215,215 @@ module front_of_key() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module outer_shape() {
|
// just to DRY up the code
|
||||||
shape(0, 0);
|
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 inner_shape(extra_wall_thickness = 0, extra_keytop_thickness = 0) {
|
module envelope(depth_difference=0) {
|
||||||
if ($inner_shape_type == "flat") {
|
s = 1.5;
|
||||||
/* $key_shape_type="square"; */
|
hull(){
|
||||||
$height_slices = 1;
|
cube([total_key_width() * s, total_key_height() * s, 0.01], center = true);
|
||||||
color($primary_color) shape_hull($wall_thickness + extra_wall_thickness, $keytop_thickness + extra_keytop_thickness, 0);
|
top_placement(SMALLEST_POSSIBLE + depth_difference){
|
||||||
} else {
|
cube([top_total_key_width() * s, top_total_key_height() * s, 0.01], center = true);
|
||||||
shape($wall_thickness + extra_wall_thickness, $keytop_thickness + extra_keytop_thickness);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// additive objects at the top of the key
|
// I think this is unused
|
||||||
module additive_features(inset) {
|
module dished_for_show() {
|
||||||
top_of_key() {
|
difference(){
|
||||||
if($key_bump) keybump($key_bump_depth, $key_bump_edge);
|
union() {
|
||||||
if(!inset && $children > 0) color($secondary_color) children();
|
envelope();
|
||||||
}
|
if ($inverted_dish) top_placement(0) _dish();
|
||||||
if($outset_legends) legends(0);
|
}
|
||||||
// render the clearance check if it's enabled, but don't have it intersect with anything
|
if (!$inverted_dish) top_placement(0) _dish();
|
||||||
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
|
|
||||||
// this is a little confusing as it eats the stem too
|
|
||||||
/* if ($clearance_check) clearance_check(); */
|
|
||||||
}
|
|
||||||
|
|
||||||
// all stems and stabilizers
|
|
||||||
module stems_and_stabilizers() {
|
|
||||||
translate([0, 0, $stem_inset]) {
|
|
||||||
if ($stabilizer_type != "disable") stems_for($stabilizers, $stabilizer_type);
|
|
||||||
if ($stem_type != "disable") stems_for($stem_positions, $stem_type);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// features inside the key itself (stem, supports, etc)
|
|
||||||
module inside_features() {
|
|
||||||
// Stems and stabilizers are not "inside features" unless they are fully
|
|
||||||
// contained inside the cap. otherwise they'd be cut off when they are
|
|
||||||
// differenced with the outside shape
|
|
||||||
if ($stem_inset >= 0) stems_and_stabilizers();
|
|
||||||
if ($support_type != "disable") translate([0, 0, $stem_inset]) support_for($stem_positions, $stem_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
// helpers for doubleshot keycaps for now
|
// for when you want to take the dish out of things
|
||||||
module inner_total_shape() {
|
// used for adding the dish to the key shape and making sure stems don't stick out the top
|
||||||
difference() {
|
// creates a bounding box 1.5 times larger in width and height than the keycap.
|
||||||
inner_shape();
|
module dished(depth_difference = 0, inverted = false) {
|
||||||
inside_features();
|
intersection() {
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module outer_total_shape(inset=false) {
|
|
||||||
outer_shape();
|
|
||||||
additive_features(inset) {
|
|
||||||
children();
|
children();
|
||||||
};
|
difference(){
|
||||||
|
union() {
|
||||||
|
envelope(depth_difference);
|
||||||
|
if (inverted) top_placement(depth_difference) _dish();
|
||||||
|
}
|
||||||
|
if (!inverted) top_placement(depth_difference) _dish();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// puts it's 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 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){
|
||||||
|
text(text=text, font=$font, size=font_size, halign="center", valign="center");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module keystem_positions(positions) {
|
||||||
|
for (connector_pos = positions) {
|
||||||
|
translate(connector_pos) {
|
||||||
|
rotate([0, 0, $stem_rotation]){
|
||||||
|
children();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module support_for(positions, stem_type) {
|
||||||
|
keystem_positions(positions) {
|
||||||
|
color($tertiary_color) supports($support_type, stem_type, $stem_throw, $total_depth - $stem_throw);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module stems_for(positions, stem_type) {
|
||||||
|
keystem_positions(positions) {
|
||||||
|
color($tertiary_color) stem(stem_type, $total_depth, $stem_slop, $stem_throw);
|
||||||
|
if ($stem_support_type != "disable") {
|
||||||
|
color($quaternary_color) stem_support($stem_support_type, stem_type, $stem_support_height, $stem_slop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// a fake cherry keyswitch, abstracted out to maybe replace with a better one later
|
||||||
|
module cherry_keyswitch() {
|
||||||
|
union() {
|
||||||
|
hull() {
|
||||||
|
cube([15.6, 15.6, 0.01], center=true);
|
||||||
|
translate([0,1,5 - 0.01]) cube([10.5,9.5, 0.01], center=true);
|
||||||
|
}
|
||||||
|
hull() {
|
||||||
|
cube([15.6, 15.6, 0.01], center=true);
|
||||||
|
translate([0,0,-5.5]) cube([13.5,13.5,0.01], center=true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//approximate (fully depressed) cherry key to check clearances
|
||||||
|
module clearance_check() {
|
||||||
|
if($stem_type == "cherry" || $stem_type == "cherry_rounded"){
|
||||||
|
color($warning_color){
|
||||||
|
translate([0,0,3.6 + $stem_inset - 5]) {
|
||||||
|
cherry_keyswitch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module legends(depth=0) {
|
||||||
|
if (len($front_legends) > 0) {
|
||||||
|
front_placement() {
|
||||||
|
if (len($front_legends) > 0) {
|
||||||
|
for (i=[0:len($front_legends)-1]) {
|
||||||
|
rotate([90,0,0]) keytext($front_legends[i][0], $front_legends[i][1], $front_legends[i][2], depth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (len($legends) > 0) {
|
||||||
|
top_of_key() {
|
||||||
|
// outset legend
|
||||||
|
if (len($legends) > 0) {
|
||||||
|
for (i=[0:len($legends)-1]) {
|
||||||
|
keytext($legends[i][0], $legends[i][1], $legends[i][2], depth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// legends / artisan support
|
||||||
|
module artisan(depth) {
|
||||||
|
top_of_key() {
|
||||||
|
// artisan objects / outset shape legends
|
||||||
|
color($secondary_color) children();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// key with hollowed inside but no stem
|
||||||
|
module hollow_key() {
|
||||||
|
difference(){
|
||||||
|
if ($rounded_key) {
|
||||||
|
rounded_shape();
|
||||||
|
} 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// The final, penultimate key generation function.
|
// The final, penultimate key generation function.
|
||||||
// takes all the bits and glues them together. requires configuration with special variables.
|
// takes all the bits and glues them together. requires configuration with special variables.
|
||||||
module key(inset=false) {
|
module key(inset = false) {
|
||||||
difference(){
|
difference() {
|
||||||
outer_total_shape(inset);
|
union(){
|
||||||
|
// the shape of the key, inside and out
|
||||||
if ($inner_shape_type != "disable") {
|
hollow_key();
|
||||||
translate([0,0,-SMALLEST_POSSIBLE]) {
|
if($key_bump) top_of_key() keybump($key_bump_depth, $key_bump_edge);
|
||||||
inner_total_shape();
|
// 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();
|
||||||
}
|
}
|
||||||
|
|
||||||
subtractive_features(inset) {
|
// subtractive objects at the top of the key
|
||||||
children();
|
// 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();
|
||||||
}
|
}
|
||||||
|
|
||||||
// if $stem_inset is less than zero, we add the
|
// both stem and support are optional
|
||||||
if ($stem_inset < 0) {
|
if ($stem_type != "disable" || ($stabilizers != [] && $stabilizer_type != "disable")) {
|
||||||
stems_and_stabilizers();
|
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 ($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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ include <key_profiles/sa.scad>
|
|||||||
include <key_profiles/g20.scad>
|
include <key_profiles/g20.scad>
|
||||||
include <key_profiles/hipro.scad>
|
include <key_profiles/hipro.scad>
|
||||||
include <key_profiles/grid.scad>
|
include <key_profiles/grid.scad>
|
||||||
include <key_profiles/regular_polygon.scad>
|
include <key_profiles/cherry.scad>
|
||||||
|
|
||||||
// man, wouldn't it be so cool if functions were first order
|
// man, wouldn't it be so cool if functions were first order
|
||||||
module key_profile(key_profile_type, row, column=0) {
|
module key_profile(key_profile_type, row, column=0) {
|
||||||
@@ -27,10 +27,8 @@ module key_profile(key_profile_type, row, column=0) {
|
|||||||
hipro_row(row, column) children();
|
hipro_row(row, column) children();
|
||||||
} else if (key_profile_type == "grid") {
|
} else if (key_profile_type == "grid") {
|
||||||
grid_row(row, column) children();
|
grid_row(row, column) children();
|
||||||
} else if (key_profile_type == "hexagon") {
|
} else if (key_profile_type == "cherry") {
|
||||||
hexagonal_row(row, column) children();
|
cherry_row(row, column) children();
|
||||||
} else if (key_profile_type == "octagon") {
|
|
||||||
octagonal_row(row, column) children();
|
|
||||||
} else if (key_profile_type == "disable") {
|
} else if (key_profile_type == "disable") {
|
||||||
children();
|
children();
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
48
src/key_profiles/cherry.scad
Normal file
48
src/key_profiles/cherry.scad
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
// based off GMK keycap set
|
||||||
|
|
||||||
|
module cherry_row(row=3, column=0) {
|
||||||
|
$bottom_key_width = 18.16;
|
||||||
|
$bottom_key_height = 18.16;
|
||||||
|
$width_difference = $bottom_key_width - 11.85;
|
||||||
|
$height_difference = $bottom_key_height - 14.64;
|
||||||
|
$dish_type = "cylindrical";
|
||||||
|
$dish_depth = 0.65;
|
||||||
|
$dish_skew_x = 0;
|
||||||
|
$dish_skew_y = 0;
|
||||||
|
$top_skew = 2;
|
||||||
|
|
||||||
|
$top_tilt_y = side_tilt(column);
|
||||||
|
extra_height = $double_sculpted ? extra_side_tilt_height(column) : 0;
|
||||||
|
|
||||||
|
// NOTE: cherry keycaps have this stem inset, but I'm reticent to turn it on
|
||||||
|
// since it'll be surprising to folks. the height has been adjusted accordingly
|
||||||
|
// $stem_inset = 0.6;
|
||||||
|
extra_stem_inset_height = max(0.6 - $stem_inset, 0);
|
||||||
|
|
||||||
|
// <= is a hack so you can do these in a for loop. function row = 0
|
||||||
|
if (row <= 1) {
|
||||||
|
$total_depth = 9.8 - extra_stem_inset_height + extra_height;
|
||||||
|
$top_tilt = 0;
|
||||||
|
|
||||||
|
children();
|
||||||
|
} else if (row == 2) {
|
||||||
|
$total_depth = 7.45 - extra_stem_inset_height + extra_height;
|
||||||
|
$top_tilt = 2.5;
|
||||||
|
|
||||||
|
children();
|
||||||
|
} else if (row == 3) {
|
||||||
|
$total_depth = 6.55 - extra_stem_inset_height + extra_height;
|
||||||
|
$top_tilt = 5;
|
||||||
|
children();
|
||||||
|
} else if (row == 3) {
|
||||||
|
$total_depth = 6.7 + 0.65 - extra_stem_inset_height + extra_height;
|
||||||
|
$top_tilt = 11.5;
|
||||||
|
children();
|
||||||
|
} else if (row >= 4) {
|
||||||
|
$total_depth = 6.7 + 0.65 - extra_stem_inset_height + extra_height;
|
||||||
|
$top_tilt = 11.5;
|
||||||
|
children();
|
||||||
|
} else {
|
||||||
|
children();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@ module grid_row(row=3, column = 0) {
|
|||||||
$dish_skew_x = 0;
|
$dish_skew_x = 0;
|
||||||
$dish_skew_y = 0;
|
$dish_skew_y = 0;
|
||||||
|
|
||||||
$hull_shape_type = "linear extrude";
|
$linear_extrude_shape = true;
|
||||||
|
|
||||||
|
|
||||||
$dish_overdraw_width = -8;
|
$dish_overdraw_width = -8;
|
||||||
|
|||||||
@@ -1,66 +0,0 @@
|
|||||||
include <../constants.scad>
|
|
||||||
// Regular polygon shapes CIRCUMSCRIBE the sphere of diameter $bottom_key_width
|
|
||||||
// This is to make tiling them easier, like in the case of hexagonal keycaps etc
|
|
||||||
|
|
||||||
// this function doesn't set the key shape, so you can't use it directly without some fiddling
|
|
||||||
module regular_polygon_row(n=3, column=0) {
|
|
||||||
$bottom_key_width = $unit - 0.5;
|
|
||||||
$bottom_key_height = $unit - 0.5;
|
|
||||||
$width_difference = 0;
|
|
||||||
$height_difference = 0;
|
|
||||||
$dish_type = "spherical";
|
|
||||||
$dish_depth = 0.85;
|
|
||||||
$dish_skew_x = 0;
|
|
||||||
$dish_skew_y = 0;
|
|
||||||
$top_skew = 0;
|
|
||||||
$height_slices = 1;
|
|
||||||
$corner_radius = 1;
|
|
||||||
|
|
||||||
// this is _incredibly_ intensive
|
|
||||||
/* $rounded_key = true; */
|
|
||||||
|
|
||||||
$top_tilt_y = side_tilt(column);
|
|
||||||
extra_height = $double_sculpted ? extra_side_tilt_height(column) : 0;
|
|
||||||
|
|
||||||
base_depth = 7.5;
|
|
||||||
if (n <= 1){
|
|
||||||
$total_depth = base_depth + 2.5 + extra_height;
|
|
||||||
$top_tilt = -13;
|
|
||||||
|
|
||||||
children();
|
|
||||||
} else if (n == 2) {
|
|
||||||
$total_depth = base_depth + 0.5 + extra_height;
|
|
||||||
$top_tilt = -7;
|
|
||||||
|
|
||||||
children();
|
|
||||||
} else if (n == 3) {
|
|
||||||
$total_depth = base_depth + extra_height;
|
|
||||||
$top_tilt = 0;
|
|
||||||
|
|
||||||
children();
|
|
||||||
} else if (n == 4){
|
|
||||||
$total_depth = base_depth + 0.5 + extra_height;
|
|
||||||
$top_tilt = 7;
|
|
||||||
|
|
||||||
children();
|
|
||||||
} else {
|
|
||||||
$total_depth = base_depth + extra_height;
|
|
||||||
$top_tilt = 0;
|
|
||||||
|
|
||||||
children();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module hexagonal_row(n=3, column=0) {
|
|
||||||
$key_shape_type = "hexagon";
|
|
||||||
regular_polygon_row(n,column) {
|
|
||||||
children();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module octagonal_row(n=3, column=0) {
|
|
||||||
$key_shape_type = "octagon";
|
|
||||||
regular_polygon_row(n, column) {
|
|
||||||
children();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
// kind of a catch-all at this point for any directive that doesn't fit in the other files
|
// kind of a catch-all at this point for any directive that doesn't fit in the other files
|
||||||
|
|
||||||
include <constants.scad>
|
//TODO duplicate def to not make this a special var. maybe not worth it
|
||||||
|
unit = 19.05;
|
||||||
|
|
||||||
module translate_u(x=0, y=0, z=0){
|
module translate_u(x=0, y=0, z=0){
|
||||||
translate([x * $unit, y*$unit, z*$unit]) children();
|
translate([x * unit, y*unit, z*unit]) children();
|
||||||
}
|
}
|
||||||
|
|
||||||
module no_stem_support() {
|
module no_stem_support() {
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ module iso_enter() {
|
|||||||
$top_tilt = 0;
|
$top_tilt = 0;
|
||||||
$stem_support_type = "disable";
|
$stem_support_type = "disable";
|
||||||
$key_shape_type = "iso_enter";
|
$key_shape_type = "iso_enter";
|
||||||
/* $hull_shape_type = "linear extrude"; */
|
/* $linear_extrude_shape = true; */
|
||||||
$linear_extrude_height_adjustment = 19.05 * 0.5;
|
$linear_extrude_height_adjustment = 19.05 * 0.5;
|
||||||
// this equals (unit_length(1.5) - unit_length(1.25)) / 2
|
// this equals (unit_length(1.5) - unit_length(1.25)) / 2
|
||||||
$dish_overdraw_width = 2.38125;
|
$dish_overdraw_width = 2.38125;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
include <../layout.scad>
|
include <../layout.scad>
|
||||||
|
|
||||||
// negative numbers are used for spacing
|
// negative numbers are used for spacing
|
||||||
lets_split_layout = [
|
lets_split_mapping = [
|
||||||
[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],
|
[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_layout = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
module lets_split_default(profile) {
|
module lets_split_default(profile) {
|
||||||
layout(lets_split_layout, profile, row_sculpting_offset=1) children();
|
layout(lets_split_mapping, profile, row_sculpting_offset=1) children();
|
||||||
}
|
}
|
||||||
|
|||||||
79
src/libraries/3d_surface.scad
Normal file
79
src/libraries/3d_surface.scad
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
// thanks Paul https://github.com/openscad/list-comprehension-demos/
|
||||||
|
|
||||||
|
include <../functions.scad>
|
||||||
|
|
||||||
|
module 3d_surface(size=$3d_surface_size, step=$3d_surface_step, bottom=-SMALLEST_POSSIBLE){
|
||||||
|
function p(x, y) = [ x, y, max(0,surface_function(x, y)) ];
|
||||||
|
function p0(x, y) = [ x, y, bottom ];
|
||||||
|
function rev(b, v) = b ? v : [ v[3], v[2], v[1], v[0] ];
|
||||||
|
function face(x, y) = [ p(x, y + step), p(x + step, y + step), p(x + step, y), p(x + step, y), p(x, y), p(x, y + step) ];
|
||||||
|
function fan(a, i) =
|
||||||
|
a == 0 ? [ [ 0, 0, bottom ], [ i, -size, bottom ], [ i + step, -size, bottom ] ]
|
||||||
|
: a == 1 ? [ [ 0, 0, bottom ], [ i + step, size, bottom ], [ i, size, bottom ] ]
|
||||||
|
: a == 2 ? [ [ 0, 0, bottom ], [ -size, i + step, bottom ], [ -size, i, bottom ] ]
|
||||||
|
: [ [ 0, 0, bottom ], [ size, i, bottom ], [ size, i + step, bottom ] ];
|
||||||
|
function sidex(x, y) = [ p0(x, y), p(x, y), p(x + step, y), p0(x + step, y) ];
|
||||||
|
function sidey(x, y) = [ p0(x, y), p(x, y), p(x, y + step), p0(x, y + step) ];
|
||||||
|
|
||||||
|
points = flatten(concat(
|
||||||
|
// top surface
|
||||||
|
[ for (x = [ -size : step : size - step ], y = [ -size : step : size - step ]) face(x, y) ],
|
||||||
|
// bottom surface as triangle fan
|
||||||
|
[ for (a = [ 0 : 3 ], i = [ -size : step : size - step ]) fan(a, i) ],
|
||||||
|
// sides
|
||||||
|
[ for (x = [ -size : step : size - step ], y = [ -size, size ]) rev(y < 0, sidex(x, y)) ],
|
||||||
|
[ for (y = [ -size : step : size - step ], x = [ -size, size ]) rev(x > 0, sidey(x, y)) ]
|
||||||
|
));
|
||||||
|
|
||||||
|
tcount = 2 * pow(2 * size / step, 2) + 8 * size / step;
|
||||||
|
scount = 8 * size / step;
|
||||||
|
|
||||||
|
tfaces = [ for (a = [ 0 : 3 : 3 * (tcount - 1) ] ) [ a, a + 1, a + 2 ] ];
|
||||||
|
sfaces = [ for (a = [ 3 * tcount : 4 : 3 * tcount + 4 * scount ] ) [ a, a + 1, a + 2, a + 3 ] ];
|
||||||
|
faces = concat(tfaces, sfaces);
|
||||||
|
|
||||||
|
polyhedron(points, faces, convexity = 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
module polar_3d_surface(size=$3d_surface_size, step=$3d_surface_step, bottom=-SMALLEST_POSSIBLE){
|
||||||
|
function to_polar(q, size) = q * (90 / size);
|
||||||
|
|
||||||
|
function p(x, y) = [
|
||||||
|
surface_distribution_function(to_polar(x, size), size),
|
||||||
|
surface_distribution_function(to_polar(y, size), size),
|
||||||
|
max(0,surface_function(surface_distribution_function(to_polar(x, size), size), surface_distribution_function(to_polar(y, size), size)))
|
||||||
|
];
|
||||||
|
function p0(x, y) = [ x, y, bottom ];
|
||||||
|
function rev(b, v) = b ? v : [ v[3], v[2], v[1], v[0] ];
|
||||||
|
function face(x, y) = [ p(x, y + step), p(x + step, y + step), p(x + step, y), p(x + step, y), p(x, y), p(x, y + step) ];
|
||||||
|
function fan(a, i) =
|
||||||
|
a == 0 ? [ [ 0, 0, bottom ], [ i, -size, bottom ], [ i + step, -size, bottom ] ]
|
||||||
|
: a == 1 ? [ [ 0, 0, bottom ], [ i + step, size, bottom ], [ i, size, bottom ] ]
|
||||||
|
: a == 2 ? [ [ 0, 0, bottom ], [ -size, i + step, bottom ], [ -size, i, bottom ] ]
|
||||||
|
: [ [ 0, 0, bottom ], [ size, i, bottom ], [ size, i + step, bottom ] ];
|
||||||
|
function sidex(x, y) = [ p0(x, y), p(x, y), p(x + step, y), p0(x + step, y) ];
|
||||||
|
function sidey(x, y) = [ p0(x, y), p(x, y), p(x, y + step), p0(x, y + step) ];
|
||||||
|
|
||||||
|
points = flatten(concat(
|
||||||
|
// top surface
|
||||||
|
[ for (x = [ -size : step : size - step ], y = [ -size : step : size - step ]) face(x, y) ],
|
||||||
|
// bottom surface as triangle fan
|
||||||
|
[ for (a = [ 0 : 3 ], i = [ -size : step : size - step ]) fan(a, i) ],
|
||||||
|
// sides
|
||||||
|
[ for (x = [ -size : step : size - step ], y = [ -size, size ]) rev(y < 0, sidex(x, y)) ],
|
||||||
|
[ for (y = [ -size : step : size - step ], x = [ -size, size ]) rev(x > 0, sidey(x, y)) ]
|
||||||
|
));
|
||||||
|
|
||||||
|
tcount = 2 * pow(2 * size / step, 2) + 8 * size / step;
|
||||||
|
scount = 8 * size / step;
|
||||||
|
|
||||||
|
tfaces = [ for (a = [ 0 : 3 : 3 * (tcount - 1) ] ) [ a, a + 1, a + 2 ] ];
|
||||||
|
sfaces = [ for (a = [ 3 * tcount : 4 : 3 * tcount + 4 * scount ] ) [ a, a + 1, a + 2, a + 3 ] ];
|
||||||
|
faces = concat(tfaces, sfaces);
|
||||||
|
|
||||||
|
polyhedron(points, faces, convexity = 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
// defaults, overridden in functions.scad
|
||||||
|
function surface_distribution_function(dim, size) = sin(dim) * size;
|
||||||
|
function surface_function(x,y) = (sin(acos(x/$3d_surface_size))) * sin(acos(y/$3d_surface_size));
|
||||||
@@ -74,7 +74,6 @@ $rounded_cherry_stem_d = 5.5;
|
|||||||
|
|
||||||
// How much higher the stem is than the bottom of the keycap.
|
// How much higher the stem is than the bottom of the keycap.
|
||||||
// Inset stem requires support but is more accurate in some profiles
|
// Inset stem requires support but is more accurate in some profiles
|
||||||
// can be negative to make outset stems!
|
|
||||||
$stem_inset = 0;
|
$stem_inset = 0;
|
||||||
// How many degrees to rotate the stems. useful for sideways keycaps, maybe
|
// How many degrees to rotate the stems. useful for sideways keycaps, maybe
|
||||||
$stem_rotation = 0;
|
$stem_rotation = 0;
|
||||||
@@ -119,10 +118,12 @@ $font="DejaVu Sans Mono:style=Book";
|
|||||||
// Whether or not to render fake keyswitches to check clearances
|
// Whether or not to render fake keyswitches to check clearances
|
||||||
$clearance_check = false;
|
$clearance_check = false;
|
||||||
// Should be faster, also required for concave shapes
|
// 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;
|
||||||
|
|
||||||
// what kind of extrusion we use to create the keycap. "hull" is standard, "linear extrude" is legacy, "skin" is new and not well supported.
|
// warns in trajectory.scad but it looks benign
|
||||||
$hull_shape_type = "hull"; // ["hull", "linear extrude", "skin"]
|
// brand new, more correct, hopefully faster, lots more work
|
||||||
|
$skin_extrude_shape = false;
|
||||||
// This doesn't work very well, but you can try
|
// This doesn't work very well, but you can try
|
||||||
$rounded_key = false;
|
$rounded_key = false;
|
||||||
//minkowski radius. radius of sphere used in minkowski sum for minkowski_key function. 1.75 for G20
|
//minkowski radius. radius of sphere used in minkowski sum for minkowski_key function. 1.75 for G20
|
||||||
@@ -191,7 +192,4 @@ $shape_facets =30;
|
|||||||
// unused for now
|
// unused for now
|
||||||
$3d_surface_size = 100;
|
$3d_surface_size = 100;
|
||||||
// resolution in each axis. 10 = 10 divisions per x/y = 100 points total
|
// resolution in each axis. 10 = 10 divisions per x/y = 100 points total
|
||||||
$3d_surface_step = 5;
|
$3d_surface_step = 10;
|
||||||
|
|
||||||
// "flat" / "dished" / "disable"
|
|
||||||
$inner_shape_type = "flat";
|
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
include <constants.scad>
|
$fs=.1;
|
||||||
|
unit = 19.05;
|
||||||
|
|
||||||
include <shapes/ISO_enter.scad>
|
include <shapes/ISO_enter.scad>
|
||||||
include <shapes/sculpted_square.scad>
|
include <shapes/sculpted_square.scad>
|
||||||
include <shapes/rounded_square.scad>
|
include <shapes/rounded_square.scad>
|
||||||
include <shapes/square.scad>
|
include <shapes/square.scad>
|
||||||
include <shapes/oblong.scad>
|
include <shapes/oblong.scad>
|
||||||
include <shapes/regular_polygon.scad>
|
|
||||||
|
|
||||||
// size: at progress 0, the shape is supposed to be this size
|
// size: at progress 0, the shape is supposed to be this size
|
||||||
// delta: at progress 1, the keycap is supposed to be size - delta
|
// delta: at progress 1, the keycap is supposed to be size - delta
|
||||||
@@ -24,10 +25,6 @@ module key_shape(size, delta, progress = 0) {
|
|||||||
square_shape(size, delta, progress);
|
square_shape(size, delta, progress);
|
||||||
} else if ($key_shape_type == "oblong") {
|
} else if ($key_shape_type == "oblong") {
|
||||||
oblong_shape(size, delta, progress);
|
oblong_shape(size, delta, progress);
|
||||||
} else if ($key_shape_type == "hexagon") {
|
|
||||||
regular_polygon_shape(size, delta, progress);
|
|
||||||
} else if ($key_shape_type == "octagon") {
|
|
||||||
regular_polygon_shape(size, delta, progress, sides=8);
|
|
||||||
} else {
|
} else {
|
||||||
echo("Warning: unsupported $key_shape_type");
|
echo("Warning: unsupported $key_shape_type");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
// NOT 3D
|
// NOT 3D
|
||||||
function unit_length(length) = unit * (length - 1) + 18.16;
|
function unit_length(length) = unit * (length - 1) + 18.16;
|
||||||
|
|
||||||
|
|
||||||
module ISO_enter_shape(size, delta, progress){
|
module ISO_enter_shape(size, delta, progress){
|
||||||
width = size[0];
|
width = size[0];
|
||||||
height = size[1];
|
height = size[1];
|
||||||
@@ -17,21 +16,19 @@ module ISO_enter_shape(size, delta, progress){
|
|||||||
width_ratio = unit_length(1.25) / unit_length(1.5);
|
width_ratio = unit_length(1.25) / unit_length(1.5);
|
||||||
height_ratio = unit_length(1) / unit_length(2);
|
height_ratio = unit_length(1) / unit_length(2);
|
||||||
|
|
||||||
delta = delta / 2;
|
|
||||||
|
|
||||||
pointArray = [
|
pointArray = [
|
||||||
[ 0-delta.x, 0-delta.y], // top right
|
[ 0, 0], // top right
|
||||||
[ 0-delta.x, -height+delta.y], // bottom right
|
[ 0, -height], // bottom right
|
||||||
[-width * width_ratio+delta.x, -height+delta.y], // bottom left
|
[-width * width_ratio, -height], // bottom left
|
||||||
[-width * width_ratio + delta.x,-height * height_ratio+delta.y], // inner middle point
|
[-width * width_ratio,-height * height_ratio], // inner middle point
|
||||||
[ -width + delta.x,-height * height_ratio + delta.y], // outer middle point
|
[ -width,-height * height_ratio], // outer middle point
|
||||||
[ -width + delta.x, 0-delta.y] // top left
|
[ -width, 0] // top left
|
||||||
];
|
];
|
||||||
|
|
||||||
minkowski(){
|
minkowski(){
|
||||||
circle(r=$corner_radius);
|
circle(r=corner_size);
|
||||||
// gives us rounded inner corner
|
// gives us rounded inner corner
|
||||||
offset(r=-$corner_radius*2) {
|
offset(r=-corner_size*2) {
|
||||||
translate([(width * width_ratio)/2, height/2]) polygon(points=pointArray);
|
translate([(width * width_ratio)/2, height/2]) polygon(points=pointArray);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
// we do this weird key_shape_type check here because rounded_square uses
|
|
||||||
// square_shape, and we want flat sides to work for that too.
|
|
||||||
// could be refactored, idk
|
|
||||||
module regular_polygon_shape(size, delta, progress, sides=6){
|
|
||||||
// https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/undersized_circular_objects
|
|
||||||
fudge = 1/cos(180/sides);
|
|
||||||
diameter = (size.x - delta.x * progress - $corner_radius*2) * fudge;
|
|
||||||
offset(r=$corner_radius) rotate([0,0,360/sides/2]) circle(d = diameter, $fn=sides);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// TODO not implemented
|
|
||||||
function skin_regular_polygon_shape(size, delta, progress, thickness_difference, sides=6) = echo("skin regular polygon not implemented");
|
|
||||||
@@ -9,4 +9,4 @@ module rounded_square_shape(size, delta, progress, center = true) {
|
|||||||
// for skin
|
// for skin
|
||||||
|
|
||||||
function skin_rounded_square(size, delta, progress, thickness_difference) =
|
function skin_rounded_square(size, delta, progress, thickness_difference) =
|
||||||
rounded_rectangle_profile(size - (delta * progress) - [thickness_difference, thickness_difference], fn=$shape_facets, r=$corner_radius);
|
rounded_rectangle_profile(size - (delta * progress), fn=$shape_facets, r=$corner_radius);
|
||||||
|
|||||||
@@ -4,22 +4,25 @@ include <stems/box_cherry.scad>
|
|||||||
include <stems/alps.scad>
|
include <stems/alps.scad>
|
||||||
include <stems/filled.scad>
|
include <stems/filled.scad>
|
||||||
include <stems/cherry_stabilizer.scad>
|
include <stems/cherry_stabilizer.scad>
|
||||||
|
include <stems/custom.scad>
|
||||||
|
|
||||||
|
|
||||||
//whole stem, alps or cherry, trimmed to fit
|
//whole stem, alps or cherry, trimmed to fit
|
||||||
module stem(stem_type, depth, slop){
|
module stem(stem_type, depth, slop, throw){
|
||||||
if (stem_type == "alps") {
|
if (stem_type == "alps") {
|
||||||
alps_stem(depth, slop);
|
alps_stem(depth, slop, throw);
|
||||||
} else if (stem_type == "cherry" || stem_type == "costar_stabilizer") {
|
} else if (stem_type == "cherry" || stem_type == "costar_stabilizer") {
|
||||||
cherry_stem(depth, slop);
|
cherry_stem(depth, slop, throw);
|
||||||
} else if (stem_type == "rounded_cherry") {
|
} else if (stem_type == "rounded_cherry") {
|
||||||
rounded_cherry_stem(depth, slop);
|
rounded_cherry_stem(depth, slop, throw);
|
||||||
} else if (stem_type == "box_cherry") {
|
} else if (stem_type == "box_cherry") {
|
||||||
box_cherry_stem(depth, slop);
|
box_cherry_stem(depth, slop, throw);
|
||||||
} else if (stem_type == "filled") {
|
} else if (stem_type == "filled") {
|
||||||
filled_stem();
|
filled_stem();
|
||||||
} else if (stem_type == "cherry_stabilizer") {
|
} else if (stem_type == "cherry_stabilizer") {
|
||||||
cherry_stabilizer_stem(depth, slop);
|
cherry_stabilizer_stem(depth, slop, throw);
|
||||||
|
} else if (stem_type == "custom") {
|
||||||
|
custom_stem(depth, slop, throw);
|
||||||
} else if (stem_type == "disable") {
|
} else if (stem_type == "disable") {
|
||||||
children();
|
children();
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
module alps_stem(depth, has_brim, slop){
|
module alps_stem(depth, slop, throw){
|
||||||
linear_extrude(height=depth) {
|
linear_extrude(height=depth) {
|
||||||
square($alps_stem, center = true);
|
square($alps_stem, center = true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
include <../functions.scad>
|
include <../functions.scad>
|
||||||
include <cherry.scad>
|
include <cherry.scad>
|
||||||
|
|
||||||
module box_cherry_stem(depth, slop) {
|
module box_cherry_stem(depth, slop, throw) {
|
||||||
difference(){
|
difference(){
|
||||||
// outside shape
|
// outside shape
|
||||||
linear_extrude(height = depth) {
|
linear_extrude(height = depth) {
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ module inside_cherry_cross(slop) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module cherry_stem(depth, slop) {
|
module cherry_stem(depth, slop, throw) {
|
||||||
difference(){
|
difference(){
|
||||||
// outside shape
|
// outside shape
|
||||||
linear_extrude(height = depth) {
|
linear_extrude(height = depth) {
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ module inside_cherry_stabilizer_cross(slop) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module cherry_stabilizer_stem(depth, slop) {
|
module cherry_stabilizer_stem(depth, slop, throw) {
|
||||||
difference(){
|
difference(){
|
||||||
// outside shape
|
// outside shape
|
||||||
linear_extrude(height = depth) {
|
linear_extrude(height = depth) {
|
||||||
|
|||||||
12
src/stems/custom.scad
Normal file
12
src/stems/custom.scad
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
thickness = .84;
|
||||||
|
inner_stem_size = [6,4];
|
||||||
|
outer_stem_size = inner_stem_size + [thickness, thickness];
|
||||||
|
|
||||||
|
module custom_stem(depth, slop, throw){
|
||||||
|
linear_extrude(height=depth) {
|
||||||
|
difference() {
|
||||||
|
square(outer_stem_size + [slop,slop], center = true);
|
||||||
|
square(inner_stem_size + [slop,slop], center = true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
module filled_stem() {
|
module filled_stem(_depth, _slop, _throw) {
|
||||||
// I broke the crap out of this stem type due to the changes I made around how stems are differenced
|
// I broke the crap out of this stem type due to the changes I made around how stems are differenced
|
||||||
// now that we just take the dish out of stems in order to support stuff like
|
// now that we just take the dish out of stems in order to support stuff like
|
||||||
// bare stem keycaps (and buckling spring eventually) we can't just make a
|
// bare stem keycaps (and buckling spring eventually) we can't just make a
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
include <../functions.scad>
|
include <../functions.scad>
|
||||||
include <cherry.scad>
|
include <cherry.scad>
|
||||||
|
|
||||||
module rounded_cherry_stem(depth, slop) {
|
module rounded_cherry_stem(depth, slop, throw) {
|
||||||
difference(){
|
difference(){
|
||||||
cylinder(d=$rounded_cherry_stem_d, h=depth);
|
cylinder(d=$rounded_cherry_stem_d, h=depth);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user