Better full sculpting, preliminary skin extrusion, better supports

This commit is contained in:
Bob 2020-01-01 18:36:23 -05:00
parent 0e3e1a9ecb
commit f0a7b27e8c
22 changed files with 381 additions and 64 deletions

View File

@ -28,3 +28,7 @@ function total_key_height(delta = 0) = $bottom_key_height + $unit * ($key_height
// actual mm key width and height at the top // actual mm key width and height at the top
function top_total_key_width() = $bottom_key_width + ($unit * ($key_length - 1)) - $width_difference; function top_total_key_width() = $bottom_key_width + ($unit * ($key_length - 1)) - $width_difference;
function top_total_key_height() = $bottom_key_height + ($unit * ($key_height - 1)) - $height_difference; function top_total_key_height() = $bottom_key_height + ($unit * ($key_height - 1)) - $height_difference;
function side_tilt(column) = asin($unit * column / $double_sculpt_radius);
// tan of 0 is 0, division by 0 is nan, so we have to guard
function extra_side_tilt_height(column) = side_tilt(column) ? ($double_sculpt_radius - (unit * abs(column)) / tan(abs(side_tilt(column)))) : 0;

View File

@ -9,6 +9,12 @@ include <key_features.scad>
include <libraries/geodesic_sphere.scad> include <libraries/geodesic_sphere.scad>
// for skin hulls
use <libraries/scad-utils/transformations.scad>
use <libraries/scad-utils/lists.scad>
use <libraries/scad-utils/shapes.scad>
use <libraries/skin.scad>
/* [Hidden] */ /* [Hidden] */
SMALLEST_POSSIBLE = 1/128; SMALLEST_POSSIBLE = 1/128;
@ -27,8 +33,25 @@ module shape(thickness_difference, depth_difference){
} }
} }
// shape of the key but with soft, rounded edges. much more realistic, MUCH more complex. orders of magnitude more complex // 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(blue) minkowski(){
// half minkowski in the z direction
color(blue) shape_hull($minkowski_radius * 2, $minkowski_radius/2, $inverted_dish ? 2 : 0);
/* cube($minkowski_radius); */
sphere(r=$minkowski_radius, $fn=48);
}
}
/* %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(blue) minkowski(){ color(blue) 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);
@ -39,7 +62,8 @@ module rounded_shape() {
} }
} }
} }
} } */
// basic key shape, no dish, no inside // basic key shape, no dish, no inside
@ -48,7 +72,9 @@ module rounded_shape() {
// extra_slices is a hack to make inverted dishes still work // extra_slices is a hack to make inverted dishes still work
module shape_hull(thickness_difference, depth_difference, extra_slices = 0){ module shape_hull(thickness_difference, depth_difference, extra_slices = 0){
render() { render() {
if ($linear_extrude_shape) { 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); linear_extrude_shape_hull(thickness_difference, depth_difference, extra_slices);
} else { } else {
hull_shape_hull(thickness_difference, depth_difference, extra_slices); hull_shape_hull(thickness_difference, depth_difference, extra_slices);
@ -56,6 +82,40 @@ module shape_hull(thickness_difference, depth_difference, extra_slices = 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(thickness_difference),
total_key_height(thickness_difference),
],
[$width_difference, $height_difference],
progress
)
)
);
// corollary is hull_shape_hull // corollary is hull_shape_hull
// extra_slices unused, only to match argument signatures // extra_slices unused, only to match argument signatures
module linear_extrude_shape_hull(thickness_difference, depth_difference, extra_slices = 0){ module linear_extrude_shape_hull(thickness_difference, depth_difference, extra_slices = 0){
@ -66,7 +126,10 @@ module linear_extrude_shape_hull(thickness_difference, depth_difference, extra_s
translate([0,$linear_extrude_height_adjustment,0]){ translate([0,$linear_extrude_height_adjustment,0]){
linear_extrude(height = height, scale = [width_scale, height_scale]) { linear_extrude(height = height, scale = [width_scale, height_scale]) {
translate([0,-$linear_extrude_height_adjustment,0]){ translate([0,-$linear_extrude_height_adjustment,0]){
key_shape(total_key_width(thickness_difference), total_key_height(thickness_difference)); key_shape(
[total_key_width(thickness_difference), total_key_height(thickness_difference)],
[$width_difference, $height_difference]
);
} }
} }
} }
@ -120,7 +183,6 @@ module top_placement(depth_difference) {
top_tilt_by_height = -$top_tilt / $key_height; top_tilt_by_height = -$top_tilt / $key_height;
top_tilt_y_by_length = $double_sculpted ? (-$top_tilt_y / $key_length) : 0; top_tilt_y_by_length = $double_sculpted ? (-$top_tilt_y / $key_length) : 0;
translate([$top_skew_x + $dish_skew_x, $top_skew + $dish_skew_y, $total_depth - depth_difference]){ translate([$top_skew_x + $dish_skew_x, $top_skew + $dish_skew_y, $total_depth - depth_difference]){
rotate([top_tilt_by_height, top_tilt_y_by_length,0]){ rotate([top_tilt_by_height, top_tilt_y_by_length,0]){
children(); children();
@ -133,7 +195,7 @@ module _dish() {
dish(top_total_key_width() + $dish_overdraw_width, top_total_key_height() + $dish_overdraw_height, $dish_depth, $inverted_dish); dish(top_total_key_width() + $dish_overdraw_width, top_total_key_height() + $dish_overdraw_height, $dish_depth, $inverted_dish);
} }
module envelope(depth_difference) { module envelope(depth_difference=0) {
s = 1.5; s = 1.5;
hull(){ hull(){
cube([total_key_width() * s, total_key_height() * s, 0.01], center = true); cube([total_key_width() * s, total_key_height() * s, 0.01], center = true);
@ -243,8 +305,7 @@ module clearance_check() {
} }
} }
// legends / artisan support module legends(depth) {
module artisan(depth) {
top_of_key() { top_of_key() {
// outset legend // outset legend
if (len($legends) > 0) { if (len($legends) > 0) {
@ -252,6 +313,12 @@ module artisan(depth) {
keytext($legends[i][0], $legends[i][1], $legends[i][2], depth); 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 // artisan objects / outset shape legends
children(); children();
} }
@ -283,12 +350,14 @@ module key(inset = false) {
if($key_bump) top_of_key() keybump($key_bump_depth, $key_bump_edge); if($key_bump) top_of_key() keybump($key_bump_depth, $key_bump_edge);
// additive objects at the top of the key // additive objects at the top of the key
if(!inset) artisan(0) children(); if(!inset) artisan(0) children();
if($outset_legends) legends(0);
// render the clearance check if it's enabled, but don't have it intersect with anything // render the clearance check if it's enabled, but don't have it intersect with anything
if ($clearance_check) %clearance_check(); if ($clearance_check) %clearance_check();
} }
// subtractive objects at the top of the key // subtractive objects at the top of the key
if (inset) artisan(0.3) children(); if (inset) artisan(0.3) children();
if(!$outset_legends) legends(0.3);
// subtract the clearance check if it's enabled, letting the user see the // subtract the clearance check if it's enabled, letting the user see the
// parts of the keycap that will hit the cherry switch // parts of the keycap that will hit the cherry switch
if ($clearance_check) clearance_check(); if ($clearance_check) clearance_check();

View File

@ -11,3 +11,5 @@ include <layouts/lets_split/default.scad>
include <layouts/project_zen/default.scad> include <layouts/project_zen/default.scad>
include <layouts/60_percent/default.scad> include <layouts/60_percent/default.scad>
include <layouts/gherkin/default.scad>
include <layouts/gherkin/gherkin_bump.scad>

View File

@ -8,6 +8,7 @@ include <key_profiles/dsa.scad>
include <key_profiles/sa.scad> 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>
// 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) {
@ -23,6 +24,8 @@ module key_profile(key_profile_type, row, column=0) {
g20_row(row, column) children(); g20_row(row, column) children();
} else if (key_profile_type == "hipro") { } else if (key_profile_type == "hipro") {
hipro_row(row, column) children(); hipro_row(row, column) children();
} else if (key_profile_type == "grid") {
grid_row(row, column) children();
} else if (key_profile_type == "disable") { } else if (key_profile_type == "disable") {
children(); children();
} else { } else {

View File

@ -5,32 +5,41 @@ module dcs_row(row=3, column=0) {
$width_difference = 6; $width_difference = 6;
$height_difference = 4; $height_difference = 4;
$dish_type = "cylindrical"; $dish_type = "cylindrical";
$dish_depth = 1; $dish_depth = 0.5;
$dish_skew_x = 0; $dish_skew_x = 0;
$dish_skew_y = 0; $dish_skew_y = 0;
$top_skew = 1.75; $top_skew = 1.75;
$top_tilt_y = column * 3.5; $top_tilt_y = side_tilt(column);
extra_height = extra_side_tilt_height(column);
// hack so you can do these in a for loop // this dish depth should match the depth of the uberdishing in fully sculpted mode
// but it doesn't, and it's very slight for any reasonable double sculpting
/* $dish_depth = $double_sculpt_radius - sin(acos(top_total_key_width()/2 /$double_sculpt_radius)) * $double_sculpt_radius; */
/* echo("DISH DEPTH", $dish_depth, "column", column); */
// 5/0 is a hack so you can do these in a for loop
if (row == 5 || row == 0) { if (row == 5 || row == 0) {
$total_depth = 11.5; $total_depth = 11.5 + extra_height;
$top_tilt = -6; $top_tilt = -6;
children(); children();
} else if (row == 1) { } else if (row == 1) {
$total_depth = 8.5; $total_depth = 8.5 + extra_height;
$top_tilt = -1; $top_tilt = -1;
children(); children();
} else if (row == 2) { } else if (row == 2) {
$total_depth = 7.5; $total_depth = 7.5 + extra_height;
$top_tilt = 3; $top_tilt = 3;
children(); children();
} else if (row == 3) { } else if (row == 3) {
$total_depth = 6; $total_depth = 6 + extra_height;
$top_tilt = 7; $top_tilt = 7;
children(); children();
} else if (row == 4) { } else if (row == 4) {
$total_depth = 6; $total_depth = 6 + extra_height;
$top_tilt = 16; $top_tilt = 16;
children(); children();
} else { } else {

View File

@ -14,7 +14,7 @@ module dsa_row(row=3, column = 0) {
$enable_side_sculpting = true; $enable_side_sculpting = true;
$corner_radius = 0.25; $corner_radius = 0.25;
$top_tilt_y = column * 3; $top_tilt_y = column * 3 * $double_sculpt_modifier;
depth_raisers = [0, 3.5, 1, 0, 1, 3]; depth_raisers = [0, 3.5, 1, 0, 1, 3];
if (row == 5) { if (row == 5) {

View File

@ -16,7 +16,7 @@ module g20_row(row=3, column = 0) {
//also, //also,
$rounded_key = true; $rounded_key = true;
$top_tilt_y = column * 3; $top_tilt_y = column * 3 * $double_sculpt_modifier;
$total_depth = 6 + abs((row-3) * 0.5); $total_depth = 6 + abs((row-3) * 0.5);
if (row == 5 || row == 0) { if (row == 5 || row == 0) {

View File

@ -0,0 +1,45 @@
module grid_row(row=3, column = 0) {
$bottom_key_width = 18.16;
$bottom_key_height = 18.16;
$width_difference = 0.2;
$height_difference = 0.2;
$top_tilt = 0;
$top_skew = 0;
$dish_type = "old spherical";
// something weird is going on with this and legends - can't put it below 1.2 or they won't show
$dish_depth = 1;
$dish_skew_x = 0;
$dish_skew_y = 0;
$linear_extrude_shape = true;
$dish_overdraw_width = -8;
$dish_overdraw_height = -8;
$minkowski_radius = 0.5;
//also,
/* $rounded_key = true; */
$top_tilt_y = column * 3 * $double_sculpt_modifier;
$total_depth = 6 + abs((row-3) * 0.5);
if (row == 5 || row == 0) {
/* $top_tilt = -18.55; */
children();
} else if (row == 1) {
/* $top_tilt = (row-3) * 7 + 2.5; */
children();
} else if (row == 2) {
/* $top_tilt = (row-3) * 7 + 2.5; */
children();
} else if (row == 3) {
/* $top_tilt = (row-3) * 7 + 2.5; */
children();
} else if (row == 4) {
/* $top_tilt = (row-3) * 7 + 2.5; */
children();
} else {
children();
}
}

View File

@ -8,7 +8,7 @@ module hipro_row(row=3, column=0) {
$width_difference = ($bottom_key_width - 12.3); $width_difference = ($bottom_key_width - 12.3);
$height_difference = ($bottom_key_height - 12.65); $height_difference = ($bottom_key_height - 12.65);
$dish_type = "spherical"; $dish_type = "spherical";
$dish_depth = 0.9; $dish_depth = 0.75;
$dish_skew_x = 0; $dish_skew_x = 0;
$dish_skew_y = 0; $dish_skew_y = 0;
$top_skew = 0; $top_skew = 0;
@ -17,23 +17,24 @@ module hipro_row(row=3, column=0) {
// do you even minkowski bro // do you even minkowski bro
$corner_radius = 0.25; $corner_radius = 0.25;
$top_tilt_y = column * 3; $top_tilt_y = side_tilt(column);
extra_height = extra_side_tilt_height(column);
if (row == 1){ if (row <= 1){
$total_depth = 12.7; $total_depth = 13.7 + extra_height;
// TODO I didn't change these yet // TODO I didn't change these yet
$top_tilt = -13; $top_tilt = -13;
children(); children();
} else if (row == 2) { } else if (row == 2) {
$total_depth = 10.1; $total_depth = 11.1 + extra_height;
$top_tilt = -7; $top_tilt = -7;
children(); children();
} else if (row == 3) { } else if (row == 3) {
$total_depth = 10.1; $total_depth = 11.1 + extra_height;
$top_tilt = 7; $top_tilt = 7;
children(); children();
} else if (row == 4 || row == 5){ } else if (row == 4 || row == 5){
$total_depth = 11.25; $total_depth = 12.25 + extra_height;
$top_tilt = 13; $top_tilt = 13;
children(); children();
} else { } else {

View File

@ -10,7 +10,7 @@ module oem_row(row=3) {
$top_skew = 1.75; $top_skew = 1.75;
$stem_inset = 1.2; $stem_inset = 1.2;
$top_tilt_y = column * 3; $top_tilt_y = column * 3 * $double_sculpt_modifier;
if (row == 5 || row == 0) { if (row == 5 || row == 0) {
$total_depth = 11.2; $total_depth = 11.2;

View File

@ -1,4 +1,4 @@
module sa_row(n=3) { module sa_row(n=3, column=0) {
$key_shape_type = "sculpted_square"; $key_shape_type = "sculpted_square";
$bottom_key_width = 18.4; $bottom_key_width = 18.4;
$bottom_key_height = 18.4; $bottom_key_height = 18.4;
@ -13,27 +13,36 @@ module sa_row(n=3) {
// might wanna change this if you don't minkowski // might wanna change this if you don't minkowski
// do you even minkowski bro // do you even minkowski bro
$corner_radius = 0.25; $corner_radius = 0.25;
// this is _incredibly_ intensive
/* $rounded_key = true; */
$top_tilt_y = side_tilt(column);
extra_height = extra_side_tilt_height(column);
// 5th row is usually unsculpted or the same as the row below it // 5th row is usually unsculpted or the same as the row below it
// making a super-sculpted top row (or bottom row!) would be real easy // making a super-sculpted top row (or bottom row!) would be real easy
// bottom row would just be 13 tilt and 14.89 total depth // bottom row would just be 13 tilt and 14.89 total depth
// top row would be something new entirely - 18 tilt maybe? // top row would be something new entirely - 18 tilt maybe?
if (n == 1){ if (n <= 1){
$total_depth = 14.89; $total_depth = 14.89 + extra_height;
$top_tilt = -13; $top_tilt = -13;
children(); children();
} else if (n == 2) { } else if (n == 2) {
$total_depth = 12.925; $total_depth = 12.925 + extra_height;
$top_tilt = -7; $top_tilt = -7;
children(); children();
} else if (n == 3 || n == 5) { } else if (n == 3) {
$total_depth = 12.5; $total_depth = 12.5 + extra_height;
$top_tilt = 0; $top_tilt = 0;
children(); children();
} else if (n == 4){ } else if (n == 4){
$total_depth = 12.925; $total_depth = 12.925 + extra_height;
$top_tilt = 7; $top_tilt = 7;
children(); children();
} else { } else {
$total_depth = 12.5 + extra_height;
$top_tilt = 0;
children(); children();
} }
} }

View File

@ -0,0 +1,12 @@
include <../layout.scad>
// negative numbers are used for spacing
gherkin_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],
];
module gherkin_default(profile) {
layout(gherkin_mapping, profile, row_sculpting_offset=1);
}

View File

@ -0,0 +1,20 @@
include <../layout.scad>
// negative numbers are used for spacing
gherkin_bump_mapping = [
[1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1],
[-1, -1, -1, -1, 2, -1, -1, -1, -1],
];
gherkin_bump_legends = [
["q", "w", "e", "r", "t", "", "y", "u", "i", "o", "p"],
["a", "s", "d", "f", "g", "", "h", "j", "k", "l", ";"],
["z", "x", "c", "v", "b", "", "n", "m", ",", ".", "/"],
["", "", "", "", "", "", "", "", ""],
];
module gherkin_bump_layout(profile, row_sculpting_offset=1, column_override=undef) {
layout(gherkin_bump_mapping, profile, legends=gherkin_bump_legends, row_sculpting_offset=row_sculpting_offset, column_override=column_override, column_sculpt_profile="cresting_wave");
}

View File

@ -5,34 +5,49 @@ function abs_sum(list, x=0) =
x + abs(list[0]) : x + abs(list[0]) :
abs_sum([for (x = [1: len(list) - 1]) list[x]], x+abs(list[0])); abs_sum([for (x = [1: len(list) - 1]) list[x]], x+abs(list[0]));
module layout(list, profile="dcs", row_sculpting_offset=0, row_override=undef) { function 2hands(index, total) = ((index+0.5) % (total/2)) - (total/4);
function cresting_wave(index, total, mod=5) = (index < total/2) ? (((index + 0.5) / total)*mod) : -(mod - ((index + 0.5) / total * mod));
function 1hand(index, total) = (index % (total)) - (total/2);
// chooses between all the sculpting options
// checks if column is smack in middle of row - if so, no sculpting
// since we are zero indexed, the 7th row has an index of 6 and is the center of 13. 6*2+1 = 13
function double_sculpted_column(column, row_length, column_sculpt_profile) =
(column*2 + 1 == row_length) ?
0 : (column_sculpt_profile == "2hands") ?
2hands(column, row_length) : (column_sculpt_profile == "1hand") ?
1hand(column, row_length) : (column_sculpt_profile == "cresting_wave") ?
cresting_wave(column, row_length) : 0;
module layout(list, profile="dcs", legends=undef, row_sculpting_offset=0, row_override=undef, column_sculpt_profile="2hands", column_override=undef) {
for (row = [0:len(list)-1]){ for (row = [0:len(list)-1]){
echo("**ROW**:", row); echo("**ROW**:", row);
row_length = len(list[row]); row_length = len(list[row]);
for(column = [0:len(list[row])-1]) {
for(column = column_override ? column_override : [0:len(list[row])-1]) {
row_sculpting = (row_override != undef ? row_override : row) + row_sculpting_offset; row_sculpting = (row_override != undef ? row_override : row) + row_sculpting_offset;
key_length = list[row][column]; key_length = list[row][column];
column_value = double_sculpted_column(column, row_length, column_sculpt_profile);
// check if column is smack in middle of row - if so, no sculpting
// otherwise try to make two half-moon shapes, one for each side of the board
// since we are zero indexed, the 7th row has an index of 6 and is the center of 13. 6*2+1 = 13
double_sculpted_column = (column*2 + 1 == row_length) ? 0 : (column % (row_length/2)) - (row_length/4);
echo("double_sculpted_column", double_sculpted_column);
column_distance = abs_sum([for (x = [0 : column]) list[row][x]]); column_distance = abs_sum([for (x = [0 : column]) list[row][x]]);
echo("\t**COLUMN**", "column_value", column_value, "column_distance", column_distance);
// supports negative values for nonexistent keys
if (key_length >= 1) { if (key_length >= 1) {
translate_u(column_distance - (key_length/2), -row) key_profile(profile, row_sculpting, double_sculpted_column) u(key_length) cherry() { // (row+4) % 5 + 1 translate_u(column_distance - (key_length/2), -row) {
if (key_length == 6.25) { key_profile(profile, row_sculpting, column_value) u(key_length) legend(legends ? legends[row][column] : "") cherry() { // (row+4) % 5 + 1
spacebar() key(); if (key_length == 6.25) {
} else if (key_length == 2.25) { spacebar() key();
lshift() key(); } else if (key_length == 2.25) {
} else if (key_length == 2) { lshift() key();
backspace() key(); } else if (key_length == 2) {
} else if (key_length == 2.75) { backspace() key();
rshift() key(); } else if (key_length == 2.75) {
} else { rshift() key();
key(); } else {
key();
}
} }
} }
} }

View File

@ -8,6 +8,6 @@ preonic_layout_mapping = [
[1, 1, 1, 1, 1, 0, 2, 0, 1, 1, 1, 1, 1] [1, 1, 1, 1, 1, 0, 2, 0, 1, 1, 1, 1, 1]
]; ];
module preonic_default(profile) { module preonic_default(profile, column_sculpt_profile="2hands") {
layout(preonic_layout_mapping, profile); layout(preonic_layout_mapping, profile, column_sculpt_profile=column_sculpt_profile);
} }

View File

@ -0,0 +1,17 @@
function rounded_rectangle_profile(size=[1,1],r=1,fn=32) = [
for (index = [0:fn-1])
let(a = index/fn*360)
r * [cos(a), sin(a)]
+ sign_x(index, fn) * [size[0]/2-r,0]
+ sign_y(index, fn) * [0,size[1]/2-r]
];
function sign_x(i,n) =
i < n/4 || i > n-n/4 ? 1 :
i > n/4 && i < n-n/4 ? -1 :
0;
function sign_y(i,n) =
i > 0 && i < n/2 ? 1 :
i > n/2 ? -1 :
0;

View File

@ -17,6 +17,9 @@ $inverted_dish = false;
// set this to true if you are making double sculpted keycaps // set this to true if you are making double sculpted keycaps
$double_sculpted = false; $double_sculpted = false;
// change aggressiveness of double sculpting
// this is the radius of the cylinder the keytops are placed on
$double_sculpt_radius = 200;
// Support type. default is "flared" for easy FDM printing; bars are more realistic, and flat could be for artisans // Support type. default is "flared" for easy FDM printing; bars are more realistic, and flat could be for artisans
@ -25,6 +28,10 @@ $support_type = "flared"; // [flared, bars, flat, disable]
// Supports for the stem, as it often comes off during printing. Reccommended for most machines // Supports for the stem, as it often comes off during printing. Reccommended for most machines
$stem_support_type = "tines"; // [tines, brim, disabled] $stem_support_type = "tines"; // [tines, brim, disabled]
// enable to have stem support extend past the keycap bottom, to (hopefully) the next
// keycap. only works on tines right now
$extra_long_stem_support = false;
/* [Advanced] */ /* [Advanced] */
/* Key */ /* Key */
@ -110,6 +117,10 @@ $clearance_check = false;
// Use linear_extrude instead of hull slices to make the shape of the key // Use linear_extrude instead of hull slices to make the shape of the key
// Should be faster, also required for concave shapes // Should be faster, also required for concave shapes
$linear_extrude_shape = false; $linear_extrude_shape = false;
// brand new, more correct, hopefully faster, lots more work
// warns in trajectory.scad but it looks benign
$skin_extrude_shape = false;
//should the key be rounded? unnecessary for most printers, and very slow //should the key be rounded? unnecessary for most printers, and very slow
$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
@ -132,6 +143,10 @@ $key_bump_edge = 0.4;
// Currently does not work with thingiverse customizer, and actually breaks it // Currently does not work with thingiverse customizer, and actually breaks it
$legends = []; $legends = [];
// make legends outset instead of inset.
// broken off from artisan support since who wants outset legends?
$outset_legends = false;
// Dimensions of alps stem // Dimensions of alps stem
$alps_stem = [4.45, 2.25]; $alps_stem = [4.45, 2.25];

View File

@ -7,6 +7,10 @@ include <shapes/rounded_square.scad>
include <shapes/square.scad> include <shapes/square.scad>
include <shapes/oblong.scad> include <shapes/oblong.scad>
// size: at progress 0, the shape is supposed to be this size
// delta: at progress 1, the keycap is supposed to be size - delta
// progress: how far along the transition you are.
// it's not always linear - specifically sculpted_square
module key_shape(size, delta, progress = 0) { module key_shape(size, delta, progress = 0) {
if ($key_shape_type == "iso_enter") { if ($key_shape_type == "iso_enter") {
ISO_enter_shape(size, delta, progress); ISO_enter_shape(size, delta, progress);
@ -22,3 +26,10 @@ module key_shape(size, delta, progress = 0) {
echo("Warning: unsupported $key_shape_type"); echo("Warning: unsupported $key_shape_type");
} }
} }
function skin_key_shape(size, delta, progress = 0) =
$key_shape_type == "rounded_square" ?
skin_rounded_square(size, delta, progress) :
$key_shape_type == "sculpted_square" ?
skin_sculpted_square_shape(size, delta, progress) :
echo("Warning: unsupported $key_shape_type for skin shape. disable skin_extrude_shape or pick a new shape");

View File

@ -1,3 +1,5 @@
include <../libraries/rounded_rectangle_profile.scad>
module rounded_square_shape(size, delta, progress, center = true) { module rounded_square_shape(size, delta, progress, center = true) {
width = size[0]; width = size[0];
height = size[1]; height = size[1];
@ -20,3 +22,8 @@ module rounded_square_shape(size, delta, progress, center = true) {
); );
} }
} }
// for skin
function skin_rounded_square(size, delta, progress) =
rounded_rectangle_profile(size - (delta * progress), fn=36, r=$corner_radius);

View File

@ -1,3 +1,5 @@
include <../libraries/rounded_rectangle_profile.scad>
// rounded square shape with additional sculpting functions to better approximate // rounded square shape with additional sculpting functions to better approximate
// When sculpting sides, how much in should the tops come // When sculpting sides, how much in should the tops come
@ -42,6 +44,38 @@ module sculpted_square_shape(size, delta, progress) {
} }
} }
// fudging the hell out of this, I don't remember what the negative-offset-positive-offset was doing in the module above
// also no 'bowed' square shape for now
function skin_sculpted_square_shape(size, delta, progress) =
let(
width = size[0],
height = size[1],
width_difference = delta[0],
height_difference = delta[1],
// makes the sides bow
extra_side_size = side_sculpting(progress),
// makes the rounded corners of the keycap grow larger as they move upwards
extra_corner_size = corner_sculpting(progress),
// computed values for this slice
extra_width_this_slice = (width_difference - extra_side_size) * progress,
extra_height_this_slice = (height_difference - extra_side_size) * progress,
extra_corner_radius_this_slice = ($corner_radius + extra_corner_size),
square_size = [
width - extra_width_this_slice,
height - extra_height_this_slice
]
) rounded_rectangle_profile(square_size - [extra_corner_radius_this_slice, extra_corner_radius_this_slice]/4, fn=36, r=extra_corner_radius_this_slice/1.5 + $more_side_sculpting_factor * progress);
/* offset(r = extra_corner_radius_this_slice) {
offset(r = -extra_corner_radius_this_slice) {
side_rounded_square(square_size, r = $more_side_sculpting_factor * progress);
}
} */
module side_rounded_square(size, r) { module side_rounded_square(size, r) {
iw = size.x - 2 * r; iw = size.x - 2 * r;
ih = size.y - 2 * r; ih = size.y - 2 * r;

View File

@ -1,28 +1,64 @@
include <../functions.scad> include <../functions.scad>
include <../stems/cherry.scad> include <../stems/cherry.scad>
// $wall_thickness/4 to reduce coincident faces
module centered_tines(stem_support_height) { module centered_tines(stem_support_height) {
if ($key_length < 2) translate([0,0,$stem_support_height / 2]) cube([total_key_width($wall_thickness)+$wall_thickness/4, 1, $stem_support_height], center = true); if ($key_length < 2) {
translate([0,0,$stem_support_height / 2]) cube([1, total_key_height($wall_thickness), $stem_support_height], center = true); translate([0,0,$stem_support_height / 2]) {
cube([total_key_width(), 0.5, $stem_support_height], center = true);
}
}
translate([0,0,$stem_support_height / 2]) {
cube([
1,
total_key_height(),
$stem_support_height
],
center = true);
}
} }
module tines_support(stem_type, stem_support_height, slop) { module tines_support(stem_type, stem_support_height, slop) {
extra_height = $extra_long_stem_support ? ($unit - total_key_height()) + 0.1 : 0; // fudge
extra_width = $extra_long_stem_support ? ($unit - total_key_width()) + 0.1 : 0;
if (stem_type == "cherry" || stem_type == "costar_stabilizer") { if (stem_type == "cherry" || stem_type == "costar_stabilizer") {
difference () { difference () {
union() { union() {
if ($key_length < 2) translate([0,0,$stem_support_height / 2]) cube([total_key_width($wall_thickness)+$wall_thickness/4, 1, $stem_support_height], center = true); if ($key_length < 2) {
translate([1.15,0,$stem_support_height / 2]) cube([.5, total_key_height($wall_thickness), $stem_support_height], center = true); translate([0,0,$stem_support_height / 2]) {
translate([-1.15,0,$stem_support_height / 2]) cube([.5, total_key_height($wall_thickness), $stem_support_height], center = true); cube([
total_key_width() + extra_width*2,
0.5,
$stem_support_height
], center = true);
}
}
// 2 vertical tines holding either side of the cruciform
for (x = [1.15, -1.15]) {
translate([x,0,$stem_support_height / 2]) {
cube([
0.5,
total_key_height() + extra_height*2, // this is to extend past
$stem_support_height
], center = true);
}
}
} }
inside_cherry_cross(slop); inside_cherry_cross(slop);
} }
} else if (stem_type == "cherry_stabilizer") { } else if (stem_type == "cherry_stabilizer") {
difference () { difference () {
union() { for (x = [1.15, -1.15]) {
translate([1.15,0,$stem_support_height / 2]) cube([1, total_key_height($wall_thickness), $stem_support_height], center = true); translate([x,0,$stem_support_height / 2]) {
translate([-1.15,0,$stem_support_height / 2]) cube([1, total_key_height($wall_thickness), $stem_support_height], center = true); cube([
1,
total_key_height($wall_thickness),
$stem_support_height
], center = true);
}
} }
inside_cherry_stabilizer_cross(slop); inside_cherry_stabilizer_cross(slop);

View File

@ -1,4 +1,7 @@
include <../functions.scad> include <../functions.scad>
// 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?
include <./flat.scad>
// figures out the scale factor needed to make a 45 degree wall // figures out the scale factor needed to make a 45 degree wall
function scale_for_45(height, starting_size) = (height * 2 + starting_size) / starting_size; function scale_for_45(height, starting_size) = (height * 2 + starting_size) / starting_size;
@ -6,6 +9,11 @@ function scale_for_45(height, starting_size) = (height * 2 + starting_size) / st
// complicated since we want the different stems to work well // complicated since we want the different stems to work well
// also kind of messy... oh well // also kind of messy... oh well
module flared(stem_type, loft, height) { module flared(stem_type, loft, height) {
// flat support. straight flat support has a tendency to shear off; flared support
// all the way to the top has a tendency to warp the outside of the keycap.
// hopefully the compromise is both
flat(stem_type, loft + height/4, height);
translate([0,0,loft]){ translate([0,0,loft]){
if (stem_type == "rounded_cherry") { if (stem_type == "rounded_cherry") {
linear_extrude(height=height, scale = scale_for_45(height, $rounded_cherry_stem_d)){ linear_extrude(height=height, scale = scale_for_45(height, $rounded_cherry_stem_d)){