1 Commits

Author SHA1 Message Date
Bob
6845923913 actually force skin extrusion too 2022-02-19 21:07:18 -05:00
29 changed files with 637 additions and 921 deletions

View File

@@ -25,19 +25,7 @@ If you are technically inclined at all, this is definitely the best way to run t
First, you'll need OpenSCAD: http://www.openscad.org/downloads.html. I highly recommend installing the development snapshot, as they generally support more features and are relatively stable. Development snapshots are listed in their own section on the downloads page.
After you have openSCAD installed, you need to download the code and run it. running `git clone https://github.com/rsheldiii/openSCAD-projects.git` if you have git, or downloading [this zip](https://github.com/rsheldiii/openSCAD-projects/archive/master.zip) and extracting the directory should do it.
To make your own key, all you need to do is open `keys.scad` with openSCAD and modify this line:
```
dcs_row(5) legend("⇪", size=9) key();
```
To be whatever you want. For example, this is for a ctrl key on an OEM keyboard:
```u(1.25) oem_row(3) legend("ctrl", size=4.5) key();```
It is possible to edit this project with an external editor by checking off Design => 'Automatic Reload and Preview' in OpenSCAD.
After you have openSCAD installed, you need to download the code and run it. running `git clone https://github.com/rsheldiii/KeyV2.git` if you have git, or downloading [this zip](https://github.com/rsheldiii/KeyV2/archive/master.zip) and extracting the directory should do it. Then all you need to do is open `keys.scad` with openSCAD and you are set! It is possible to edit this project with an external editor by checking off Design => 'Automatic Reload and Preview' in OpenSCAD.
All examples below assume you are running the library on your computer with OpenSCAD.
@@ -90,7 +78,7 @@ These modifier functions may not cover every use case; in that case, you may hav
new to the library and still in a beta state, layouts allows you to generate an entire layout for a keyboard!
It is recommended to print layouts with a brim that extends to the next key.
It is recommended to use tined stem support and set `$extra_long_stem_support = true` if you plan on printing these keycaps.
```
60_percent_default("dcs") key();
@@ -198,7 +186,9 @@ Prints from this library are still challenging, despite all efforts to the contr
That's it, if you have any questions feel free to open an issue or leave a comment on thingiverse!
## TODO:
moved to [TODO doc](./TODO.md)
* replace linear_extrude_shape_hull with skin_extrude_shape_hull or something, to enable concave extrusions
* replace current ISO enter shape with one that works for `skin()`
* generate dishes via math?
## Contributions welcome

View File

@@ -1,5 +1,7 @@
TODO:
* Make flat stem support default
* make flat inner shape default
* support repositioning to print on the back surface of the keycap
* implement regular polygon for skin extrusions
* switch to skin-shaped extrusions by default
* kailh choc has a non-square key unit; should I get that working for layouts etc?

File diff suppressed because it is too large Load Diff

View File

@@ -17,4 +17,4 @@ dcs_row(5) legend("⇪", size=9) key();
} */
// example layout
/* preonic_default("dcs") key(); */
/* preonic_default("dcs"); */

View File

@@ -4,8 +4,6 @@ include <dishes/cylindrical.scad>
include <dishes/old_spherical.scad>
include <dishes/sideways_cylindrical.scad>
include <dishes/spherical.scad>
include <dishes/squared_spherical.scad>
include <dishes/squared_scoop.scad>
include <dishes/flat.scad>
include <dishes/3d_surface.scad>
@@ -16,22 +14,20 @@ geodesic=false;
module dish(width, height, depth, inverted) {
if($dish_type == "cylindrical"){
cylindrical_dish(width, height, depth, inverted);
} else if ($dish_type == "spherical") {
}
else if ($dish_type == "spherical") {
spherical_dish(width, height, depth, inverted);
} else if ($dish_type == "sideways cylindrical"){
}
else if ($dish_type == "sideways cylindrical"){
sideways_cylindrical_dish(width, height, depth, inverted);
} else if ($dish_type == "old spherical") {
old_spherical_dish(width, height, depth, inverted);
} else if ($dish_type == "3d surface") {
} else if ($dish_type == "3d_surface") {
3d_surface_dish(width, height, depth, inverted);
} else if ($dish_type == "flat") {
flat_dish(width, height, depth, inverted);
} else if ($dish_type == "disable") {
// else no dish
} else if ($dish_type == "squared spherical") {
squared_spherical_dish(width, height, depth, inverted=inverted);
} else if ($dish_type == "squared scoop") {
squared_scoop_dish(width, height, depth, inverted=inverted);
} else {
echo("WARN: $dish_type unsupported");
}

View File

@@ -6,11 +6,9 @@ module 3d_surface_dish(width, height, depth, inverted) {
// it doesn't have to be dead reckoning for anything but sculpted sides
// we know the angle of the sides from the width difference, height difference,
// skew and tilt of the top. it's a pain to calculate though
scale_factor = 1.11;
scale_factor = 1.1;
// the edges on this behave differently than with the previous dish implementations
scale([width*scale_factor/$3d_surface_size/2,height*scale_factor/$3d_surface_size/2,depth])
rotate([inverted ? 0:180,0,180])
polar_3d_surface(size=$3d_surface_size, step=$3d_surface_step, bottom=-10);
scale([width*scale_factor/$3d_surface_size/2,height*scale_factor/$3d_surface_size/2,depth]) rotate([inverted ? 0:180,0,180]) polar_3d_surface(bottom=-10);
/* %scale([width*scale_factor/$3d_surface_size/2,height*scale_factor/$3d_surface_size/2,depth]) rotate([180,0,0]) polar_3d_surface(bottom=-10); */
}

View File

@@ -1,34 +0,0 @@
module squared_scoop_dish(height, width, depth, r=0.5, inverted=false, num=4, den=5){
// changable numerator/denoninator on where to place the square's corners
// for example, num=2, den=3 means the dish will happen at 1/3 and 2/3 the
// width and the height. Defaults to 4/5. Customizable when calling
// this module
//
// This was initially intended for the scoop on the HiPro, since that's what
// it uses. Use "hipro_row()" if that's what you'd like. However, I do NOT
// know how close the inner square is for the HiPro keycaps. In fact, it could
// just be a sphere, in which the "squared spherical" scoop is more appropriate.
// If, however, it the "squared scoop" makes sense, you can adjust where the square
// lands with the num (numerator) and den (denominator) variables. For instance,
// "3" and "4" mean 3/4 of the width/height is where the flat part starts.
chord = pow(pow(height/2, 2) + pow(width/2, 2),0.5);
direction = inverted ? -1 : 1;
//This is the set of points to hull around for the scoop
points=[
[height/den - height/2, width/den - width/2, -chord],
[num*height/den - height/2, width/den - width/2, -chord],
[height/den - height/2, num*width/den - width/2, -chord],
[num*height/den - height/2, num*width/den - width/2, -chord]
];
resize([height,width,depth])
hull() {
shape_slice(1,0,0);
for(i=[0:len(points)-1]) {
translate(points[i])
sphere(r=r,$fn=64);
}
}
}

View File

@@ -1,22 +0,0 @@
module squared_spherical_dish(width, height, depth, inverted=false) {
chord = pow(pow(height / 2, 2) + pow(width / 2, 2),0.5);
direction = inverted ? -1 : 1;
r=max(height,width,chord) / 5;
// ^^^^^ Nothing special about this code to figure out r.
// I just modeled up 1u, 1.25u, 1.5u, 2u, 2.25u, and 2.75u
// keys and messed around until I came up with something that
// looked reasonable for all key sizes. This just seems to work
// well for all sizes
translate([-width / 2, -height / 2, 0 * direction]) {
resize([width, height, depth])
hull() {
cube([chord,chord,0.001]);
// Use something larger in this translate than -depth
// (like -chord) if you want more of a defined circle
// in the keywell
translate([chord/2, chord/2, -depth])
sphere(r=r, $fn=128);
}
}
}

View File

@@ -33,7 +33,7 @@ function top_total_key_height() = $bottom_key_height + ($unit * ($key_height - 1
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;
function extra_side_tilt_height(column) = side_tilt(column) ? ($double_sculpt_radius - (unit * abs(column)) / tan(abs(side_tilt(column)))) : 0;
// (I think) extra length of the side of the keycap due to the keytop being tilted.
// necessary for calculating flat sided keycaps
@@ -43,6 +43,29 @@ function vertical_inclination_due_to_top_tilt() = sin($top_tilt) * (top_total_ke
// I derived this through a bunch of trig reductions I don't really understand.
function extra_keytop_length_for_flat_sides() = ($width_difference * vertical_inclination_due_to_top_tilt()) / ($total_depth);
// 3d surface functions (still in beta)
// monotonically increasing function that distributes the points of the surface mesh
// only for polar_3d_surface right now
// if it's linear it's a grid. sin(dim) * size concentrates detail around the edges
function surface_distribution_function(dim, size) = sin(dim) * size;
// the function that actually determines what the surface is.
// feel free to override, the last one wins
// debug
function surface_function(x,y) = 1;
// cylindrical
function surface_function(x,y) = (sin(acos(x/$3d_surface_size)));
// spherical
function surface_function(x,y) = (sin(acos(x/$3d_surface_size))) * sin(acos(y/$3d_surface_size));
// ripples
/* function surface_function(x,y) = cos(pow(pow(x,2)+pow(y,2),0.5)*10)/4+0.75; */
// Rosenbrock's banana
/* function surface_function(x,y) = (pow(1-(x/100), 2) + 100 * pow((y/100)-pow((x/100),2),2))/200 + 0.1; */
// y=x revolved around the y axis
/* function surface_function(x,y) = 1/(pow(pow(x,2)+pow(y,2),0.5)/100 + .01); */
/* function surface_function(x,y) = sin(rands(0,90,1,x+y)[0]); */
// adds uniform rounding radius for round-anything polyRound
function add_rounding(p, radius)=[for(i=[0:len(p)-1])[p[i].x,p[i].y, radius]];
// computes millimeter length from unit length

View File

@@ -1,13 +1,13 @@
module hull_shape_hull(thickness_difference, depth_difference, extra_slices = 0) {
for (index = [0:$height_slices - 1 + extra_slices]) {
hull() {
placed_shape_slice(index / $height_slices, thickness_difference, depth_difference);
placed_shape_slice((index + 1) / $height_slices, thickness_difference, depth_difference);
shape_slice(index / $height_slices, thickness_difference, depth_difference);
shape_slice((index + 1) / $height_slices, thickness_difference, depth_difference);
}
}
}
module placed_shape_slice(progress, 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;
@@ -18,20 +18,16 @@ module placed_shape_slice(progress, thickness_difference, depth_difference) {
translate([x_skew_this_slice, skew_this_slice, depth_this_slice]) {
rotate([tilt_this_slice,y_tilt_this_slice,0]){
shape_slice(progress, thickness_difference, depth_difference);
linear_extrude(height = SMALLEST_POSSIBLE, scale = 1){
key_shape(
[
total_key_width(thickness_difference),
total_key_height(thickness_difference)
],
[$width_difference, $height_difference],
progress
);
}
}
}
}
module shape_slice(progress, thickness_difference, depth_difference) {
linear_extrude(height = SMALLEST_POSSIBLE, scale = 1){
key_shape(
[
total_key_width(thickness_difference),
total_key_height(thickness_difference)
],
[$width_difference, $height_difference],
progress
);
}
}

View File

@@ -24,6 +24,7 @@ module shape(thickness_difference, depth_difference=0){
}
}
// Not currently used due to CGAL errors. Rounds the shape via minkowski
module rounded_shape() {
color($primary_color) minkowski(){
// half minkowski in the z direction
@@ -112,9 +113,9 @@ module top_placement(depth_difference=0) {
top_tilt_by_height = -$top_tilt / $key_height;
top_tilt_y_by_length = $double_sculpted ? (-$top_tilt_y / $key_length) : 0;
// minkowski_height = $rounded_key ? $minkowski_radius : 0;
minkowski_height = $rounded_key ? $minkowski_radius : 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 + minkowski_height/2]){
rotate([top_tilt_by_height, top_tilt_y_by_length,0]){
children();
}
@@ -234,9 +235,7 @@ module outer_total_shape(inset=false) {
// takes all the bits and glues them together. requires configuration with special variables.
module key(inset=false) {
difference(){
outer_total_shape(inset) {
children();
};
outer_total_shape(inset);
if ($inner_shape_type != "disable") {
translate([0,0,-SMALLEST_POSSIBLE]) {

View File

@@ -8,13 +8,10 @@ include <key_profiles/dsa.scad>
include <key_profiles/sa.scad>
include <key_profiles/g20.scad>
include <key_profiles/hipro.scad>
include <key_profiles/mt3.scad>
include <key_profiles/grid.scad>
include <key_profiles/regular_polygon.scad>
include <key_profiles/cherry.scad>
include <key_profiles/dss.scad>
include <key_profiles/asa.scad>
include <key_profiles/typewriter.scad>
// man, wouldn't it be so cool if functions were first order
module key_profile(key_profile_type, row, column=0) {
@@ -28,24 +25,18 @@ module key_profile(key_profile_type, row, column=0) {
dss_row(row, column) children();
} else if (key_profile_type == "sa") {
sa_row(row, column) children();
} else if (key_profile_type == "asa") {
asa_row(row, column) children();
} else if (key_profile_type == "g20") {
g20_row(row, column) children();
} else if (key_profile_type == "hipro") {
hipro_row(row, column) children();
} else if (key_profile_type == "grid") {
grid_row(row, column) children();
} else if (key_profile_type == "typewriter") {
typewriter_row(row, column) children();
} else if (key_profile_type == "hexagon") {
hexagonal_row(row, column) children();
} else if (key_profile_type == "octagon") {
octagonal_row(row, column) children();
} else if (key_profile_type == "cherry") {
cherry_row(row, column) children();
} else if (key_profile_type == "mt3") {
mt3_row(row, column) children();
} else if (key_profile_type == "disable") {
children();
} else {

View File

@@ -1,42 +0,0 @@
module asa_row(row=3, column = 0) {
$key_shape_type = "sculpted_square";
$bottom_key_height = 18.06;
$bottom_key_width = 18.05; // Default (R3)
$total_depth = 10.35; // Default (R3)
$top_tilt = 1.5; // Default (R3)
$width_difference = 5.05;
$height_difference = 5.56;
$dish_type = "spherical";
$dish_depth = 1.2;
$dish_skew_x = 0;
$dish_skew_y = 0;
$top_skew = 1.75;
$stem_inset = 1.2;
$height_slices = 10;
$corner_radius = 1;
// this is _incredibly_ intensive
//$rounded_key = true;
if (row == 1){
$bottom_key_width = 17.95;
$width_difference = 4.95;
$total_depth = 10.65;
$top_tilt = 7;
children();
} else if (row == 2) {
$bottom_key_width = 18.17;
$width_difference = 5.17;
$total_depth = 9.65;
$top_tilt = 3.25;
children();
} else if (row == 4){
$bottom_key_width = 18.02;
$width_difference = 5.02;
$total_depth = 11.9;
$top_tilt = 0.43;
children();
} else {
children();
}
}

View File

@@ -1,3 +1,4 @@
// my own measurements
module hipro_row(row=3, column=0) {
$key_shape_type = "sculpted_square";
@@ -6,7 +7,7 @@ module hipro_row(row=3, column=0) {
$width_difference = ($bottom_key_width - 12.3);
$height_difference = ($bottom_key_height - 12.65);
$dish_type = "squared scoop";
$dish_type = "spherical";
$dish_depth = 0.75;
$dish_skew_x = 0;
$dish_skew_y = 0;

View File

@@ -1,53 +0,0 @@
// This is an imperfect attempt to clone the MT3 profile
module mt3_row(row=3, column=0, deep_dish=false) {
$key_shape_type = "sculpted_square";
$bottom_key_width = 18.35;
$bottom_key_height = 18.6;
$width_difference = ($bottom_key_width - 13.0);
$height_difference = ($bottom_key_height - 13.0);
$dish_type = "squared spherical";
$dish_depth = deep_dish ? 1.6 : 1.2;
$dish_skew_x = 0;
$dish_skew_y = 0;
$top_skew = 0;
$height_slices = 10;
$corner_sculpting_factor = 2;
$corner_radius = 0.0125;
$more_side_sculpting_factor = 0.75;
$top_tilt_y = side_tilt(column);
extra_height = $double_sculpted ? extra_side_tilt_height(column) : 0;
if (row == 0){
// TODO I didn't change these yet
$total_depth = 14.7 + extra_height;
$top_tilt = -12.5;
children();
} else if (row == 1) {
$total_depth = 13.1 + extra_height;
$top_tilt = -6;
children();
} else if (row == 2) {
$total_depth = 10.7 + extra_height;
$top_tilt = -6;
children();
} else if (row == 3) {
$total_depth = 10.7 + extra_height;
$top_tilt = 6;
children();
} else if (row == 4){
$total_depth = 11.6 + extra_height;
$top_tilt = 12;
children();
} else if (row >= 5) {
$total_depth = 11.6 + extra_height;
$top_tilt = 0;
children();
} else {
children();
}
}

View File

@@ -1,57 +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 typewriter_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";
$key_shape_type = "circular";
$inverted_dish = true;
$stem_inset = -4.5;
$stem_throw = 5;
$dish_depth = 1;
$dish_skew_x = 0;
$dish_skew_y = 0;
$top_skew = 0;
$height_slices = 1;
$stem_support_type = "disable";
// $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 = 3.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();
}
}

View File

@@ -193,68 +193,13 @@ module upside_down() {
}
module sideways() {
$stem_support_type = "disable";
$key_shape_type = "flat_sided_square";
$dish_overdraw_width = abs(extra_keytop_length_for_flat_sides());
extra_y_rotation = atan2($width_difference/2,$total_depth); // TODO assumes centered top
extra_y_rotation = atan2($width_difference/2,$total_depth);
translate([0,0,cos(extra_y_rotation) * total_key_width()/2])
rotate([0,90 + extra_y_rotation ,0]) children();
}
/* this is hard to explain. we want the angle of the back of the keycap.
* first we draw a line at the back of the keycap perpendicular to the ground.
* then we extend the line created by the slope of the keytop to that line
* the angle of the latter line off the ground is $top_tilt, and
* you can create a right triangle with the adjacent edge being $bottom_key_height/2
* raised up $total_depth. this gets you x, the component of the extended
* keytop slope line, and y, a component of the first perpendicular line.
* by a very similar triangle you get r and s, where x is the hypotenuse of that
* right triangle and the right angle is again against the first perpendicular line
* s is the opposite line in the right triangle required to find q, the angle
* of the back. if you subtract r from $total_depth plus y you can now use these
* two values in atan to find the angle of interest.
*/
module backside() {
$stem_support_type = "disable";
// $key_shape_type = "flat_sided_square";
a = $bottom_key_height;
b = $total_depth;
c = top_total_key_height();
x = (a / 2 - $top_skew) / cos(-$top_tilt) - c / 2;
y = sin(-$top_tilt) * (x + c/2);
r = sin(-$top_tilt) * x;
s = cos(-$top_tilt) * x;
q = atan2(s, (y + b - r));
translate([0,0,cos(q) * total_key_height()/2])
rotate([-90 - q, 0,0]) children();
}
// this is just backside with a few signs switched
module frontside() {
$stem_support_type = "disable";
// $key_shape_type = "flat_sided_square";
a = $bottom_key_height;
b = $total_depth;
c = top_total_key_height();
x = (a / 2 + $top_skew) / cos($top_tilt) - c / 2;
y = sin($top_tilt) * (x + c/2);
r = sin($top_tilt) * x;
s = cos($top_tilt) * x;
q = atan2(s, (y + b - r));
translate([0,0,cos(q) * total_key_height()/2])
rotate([90 + q, 0,0]) children();
}
// emulating the % modifier.
// since we use custom colors, just using the % modifier doesn't work
module debug() {
@@ -278,11 +223,3 @@ module auto_place() {
translate_u(x,-y) children(child_index);
}
}
// suggested settings for resin prints
module resin() {
$stem_slop = 0;
$stem_inner_slop = 0;
$stem_support_type = "disable";
children();
}

View File

@@ -17,5 +17,5 @@ include <../layout.scad>
];
module 60_percent_default(profile) {
layout(60_percent_default_layout, profile, 60_percent_legends, row_sculpting_offset=1) children();
layout(60_percent_default_layout, profile, 60_percent_legends) children();
}

View File

@@ -3,7 +3,7 @@
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 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) ];
@@ -35,13 +35,13 @@ module 3d_surface(size=$3d_surface_size, step=$3d_surface_step, bottom=-SMALLEST
polyhedron(points, faces, convexity = 8);
}
module polar_3d_surface(size, step, bottom=-SMALLEST_POSSIBLE){
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)))
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] ];
@@ -75,5 +75,5 @@ module polar_3d_surface(size, step, bottom=-SMALLEST_POSSIBLE){
}
// defaults, overridden in functions.scad
// $surface_distribution_function = function(dim, size) sin(dim) * size;
// $surface_function = function(x,y) (sin(acos(x/$3d_surface_size))) * sin(acos(y/$3d_surface_size));
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));

View File

@@ -79,6 +79,10 @@ $stem_inset = 0;
// How many degrees to rotate the stems. useful for sideways keycaps, maybe
$stem_rotation = 0;
// 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;
/* [Shape] */
// Key shape type, determines the shape of the key. default is 'rounded square'
@@ -190,56 +194,11 @@ $warning_color = [1,0,0, 0.15];
$minkowski_facets = 30;
$shape_facets =30;
// 3d surface settings
// unused for now
$3d_surface_size = 100;
// resolution in each axis. 10 = 10 divisions per x/y = 100 points total
$3d_surface_step = 10;
// "flat" / "dished" / "disable"
$inner_shape_type = "flat";
// When sculpting sides using sculpted_square, how much in should the tops come
$side_sculpting_factor = 4.5;
// When sculpting corners, how much extra radius should be added
$corner_sculpting_factor = 1;
// When doing more side sculpting corners, how much extra radius should be added
$more_side_sculpting_factor = 0.4;
// 3d surface functions (still in beta)
// 3d surface settings
// unused for now
$3d_surface_size = 20;
// resolution in each axis. 10 = 10 divisions per x/y = 100 points total.
// 5 = 20 divisions per x/y
$3d_surface_step = 1;
// monotonically increasing function that distributes the points of the surface mesh
// only for polar_3d_surface right now
// if it's linear it's a grid. sin(dim) * size concentrates detail around the edges
sinusoidal_surface_distribution = function(dim,size) sin(dim) * size;
linear_surface_distribution = function(dim,size) sin(dim) * size;
$surface_distribution_function = linear_surface_distribution;
// the function that actually determines what the surface is.
// feel free to override, the last one wins
// debug
// $surface_function = function(x,y) 1;
cylindrical_surface = function(x,y) (sin(acos(x/$3d_surface_size)));
spherical_surface = function(x,y) (1 - (x/$3d_surface_size)^2)^0.5 * (1 - (y/$3d_surface_size)^2)^0.5;
// looks a lot like mt3
quartic_surface = function(x,y) (1 - (x/$3d_surface_size)^4)^0.5 * (1 - (y/$3d_surface_size)^4)^0.5;
ripple_surface = function(x,y) cos((x^2+y^2)^0.5 * 50)/4 + 0.75;
rosenbrocks_banana_surface = function(x,y) (pow(1-(x/$3d_surface_size))^2 + 100 * pow((y/$3d_surface_size)-(x/$3d_surface_size)^2)^2)/200 + 0.1;
spike_surface = function(x,y) 1/(((x/$3d_surface_size)^2+(y/$3d_surface_size)^2)^0.5) + .01;
random_surface = function(x,y) sin(rands(0,90,1,x+y)[0]);
bumps_surface = function(x,y) sin(20*x)*cos(20*y)/3+1;
$surface_function = bumps_surface; // bumps_surface;
// ripples
/*
// Rosenbrock's banana
/* $
// y=x revolved around the y axis
/* $surface_function = */
/* $surface_function = */

View File

@@ -28,8 +28,6 @@ module key_shape(size, delta, progress = 0) {
regular_polygon_shape(size, delta, progress);
} else if ($key_shape_type == "octagon") {
regular_polygon_shape(size, delta, progress, sides=8);
} else if ($key_shape_type == "circular") {
regular_polygon_shape(size, delta, progress, sides=36);
} else {
echo("Warning: unsupported $key_shape_type");
}

View File

@@ -38,12 +38,12 @@ module ISO_enter_shape(size, delta, progress){
}
function iso_enter_vertices(size, delta, progress, thickness_difference) = [
[ 0-delta.x/2 * progress - thickness_difference/8, 0 - delta.y / 2 * progress - thickness_difference/8], // top right
[ 0-delta.x/2 * progress - thickness_difference/8, -size[1] + delta.y / 2 * progress + thickness_difference/8], // bottom right
[-size[0] * width_ratio + delta.x/2 * progress + thickness_difference/8, -size[1] + delta.y / 2 * progress + thickness_difference/8], // bottom left
[-size[0] * width_ratio + delta.x/2 * progress + thickness_difference/8,-size[1] * height_ratio + delta.y / 2 * progress + thickness_difference/2], // inner middle point
[ -size[0] + delta.x/2 * progress + thickness_difference/8,-size[1] * height_ratio + delta.y / 2 * progress + thickness_difference/2], // outer middle point
[ -size[0] + delta.x/2 * progress + thickness_difference/8, 0 - delta.y / 2 * progress - thickness_difference/8] // top left
[ 0-delta.x/2 * progress - thickness_difference/2, 0 - delta.y / 2 * progress - thickness_difference/2], // top right
[ 0-delta.x/2 * progress - thickness_difference/2, -size[1] + delta.y / 2 * progress + thickness_difference/2], // bottom right
[-size[0] * width_ratio + delta.x/2 * progress + thickness_difference/2, -size[1] + delta.y / 2 * progress + thickness_difference/2], // bottom left
[-size[0] * width_ratio + delta.x/2 * progress + thickness_difference/2,-size[1] * height_ratio + delta.y / 2 * progress + thickness_difference/2], // inner middle point
[ -size[0] + delta.x/2 * progress + thickness_difference/2,-size[1] * height_ratio + delta.y / 2 * progress + thickness_difference/2], // outer middle point
[ -size[0] + delta.x/2 * progress + thickness_difference/2, 0 - delta.y / 2 * progress - thickness_difference/2] // top left
] + [
[(size[0] * width_ratio)/2, size[1]/2 ],
[(size[0] * width_ratio)/2, size[1]/2 ],

View File

@@ -1,10 +1,18 @@
// rounded square shape with additional sculpting functions to better approximate
// When sculpting sides, how much in should the tops come
side_sculpting_factor = 4.5;
// When sculpting corners, how much extra radius should be added
corner_sculpting_factor = 1;
// When doing more side sculpting corners, how much extra radius should be added
more_side_sculpting_factor = 0.4;
// side sculpting functions
// bows the sides out on stuff like SA and DSA keycaps
function side_sculpting(progress) = (1 - progress) * $side_sculpting_factor;
function side_sculpting(progress) = (1 - progress) * side_sculpting_factor;
// makes the rounded corners of the keycap grow larger as they move upwards
function corner_sculpting(progress) = pow(progress, 2) * $corner_sculpting_factor;
function corner_sculpting(progress) = pow(progress, 2) * corner_sculpting_factor;
module sculpted_square_shape(size, delta, progress) {
width = size[0];
@@ -29,7 +37,7 @@ module sculpted_square_shape(size, delta, progress) {
offset(r = extra_corner_radius_this_slice, $fa=360/$shape_facets) {
offset(r = -extra_corner_radius_this_slice) {
side_rounded_square(square_size, r = $more_side_sculpting_factor * progress);
side_rounded_square(square_size, r = more_side_sculpting_factor * progress);
}
}
}
@@ -84,7 +92,7 @@ function skin_sculpted_square_shape(size, delta, progress, thickness_difference)
width - extra_width_this_slice - thickness_difference,
height - extra_height_this_slice - thickness_difference
]
) new_side_rounded_square(square_size, $more_side_sculpting_factor * progress, extra_corner_radius_this_slice);
) new_side_rounded_square(square_size, more_side_sculpting_factor * progress, extra_corner_radius_this_slice);
module side_rounded_square(size, r) {

View File

@@ -16,12 +16,12 @@ module brim_support(stem_type, stem_support_height, slop) {
}
}
inside_cherry_cross($stem_inner_slop);
inside_cherry_cross(slop);
}
} else if (stem_type == "rounded_cherry") {
difference() {
cylinder(d=$rounded_cherry_stem_d * 2, h=stem_support_height);
inside_cherry_cross($stem_inner_slop);
inside_cherry_cross(slop);
}
} else if (stem_type == "box_cherry") {
difference() {
@@ -31,7 +31,7 @@ module brim_support(stem_type, stem_support_height, slop) {
}
}
inside_cherry_cross($stem_inner_slop);
inside_cherry_cross(slop);
}
} else if (stem_type == "cherry_stabilizer") {
difference() {
@@ -41,7 +41,7 @@ module brim_support(stem_type, stem_support_height, slop) {
}
}
inside_cherry_cross($stem_inner_slop);
inside_cherry_cross(slop);
}
} else if(stem_type == "choc") {
translate([-5.7/2,0,0]) linear_extrude(height=stem_support_height) {

View File

@@ -1,20 +1,17 @@
include <../functions.scad>
include <../stems/cherry.scad>
/* NOTE: every reference to total_key_width and total_key_height
* is multiplied by two in order to account for offset stems
*/
module centered_tines(stem_support_height) {
if ($key_length < 2) {
translate([0,0,$stem_support_height / 2]) {
cube([total_key_width()*2, 0.5, $stem_support_height], center = true);
cube([total_key_width(), 0.5, $stem_support_height], center = true);
}
}
translate([0,0,$stem_support_height / 2]) {
cube([
1,
total_key_height()*2,
total_key_height(),
$stem_support_height
],
center = true);
@@ -22,13 +19,16 @@ module centered_tines(stem_support_height) {
}
module tines_support(stem_type, stem_support_height, slop) {
extra_height = $extra_long_stem_support ? ($unit - total_key_height()) + 0.1 : -$wall_thickness/4; // fudge
extra_width = $extra_long_stem_support ? ($unit - total_key_width()) + 0.1 : -$wall_thickness/4;
if (stem_type == "cherry" || stem_type == "costar_stabilizer") {
difference () {
union() {
if ($key_length < 2) {
translate([0,0,$stem_support_height / 2]) {
cube([
total_key_width()*2,
total_key_width() + extra_width*2,
0.5,
$stem_support_height
], center = true);
@@ -36,18 +36,18 @@ module tines_support(stem_type, stem_support_height, slop) {
}
// 2 vertical tines holding either side of the cruciform
for (x = [2, -2]) {
for (x = [1.15, -1.15]) {
translate([x,0,$stem_support_height / 2]) {
cube([
0.5,
total_key_height()*2, // this is to extend past
total_key_height() + extra_height*2, // this is to extend past
$stem_support_height
], center = true);
}
}
}
inside_cherry_cross($stem_inner_slop);
inside_cherry_cross(slop);
}
} else if (stem_type == "cherry_stabilizer") {
difference () {
@@ -55,7 +55,7 @@ module tines_support(stem_type, stem_support_height, slop) {
translate([x,0,$stem_support_height / 2]) {
cube([
1,
total_key_height()*2,
total_key_height($wall_thickness),
$stem_support_height
], center = true);
}
@@ -67,19 +67,19 @@ module tines_support(stem_type, stem_support_height, slop) {
difference () {
centered_tines(stem_support_height);
inside_cherry_cross($stem_inner_slop);
inside_cherry_cross(slop);
}
} else if (stem_type == "rounded_cherry") {
difference () {
centered_tines(stem_support_height);
inside_cherry_cross($stem_inner_slop);
inside_cherry_cross(slop);
}
} else if (stem_type == "alps"){
centered_tines(stem_support_height);
} else if (stem_type == "choc"){
if ($key_length < 2) translate([0,0,$stem_support_height / 2]) cube([total_key_width(), 0.42, $stem_support_height], center = true);
/* translate([-5.7/2,0,$stem_support_height / 2]) cube([0.5, total_key_height(), $stem_support_height], center = true); */
/* translate([5.7/2,0,$stem_support_height / 2]) cube([0.5, total_key_height(), $stem_support_height], center = true); */
if ($key_length < 2) translate([0,0,$stem_support_height / 2]) cube([total_key_width($wall_thickness)+$wall_thickness/4, 0.42, $stem_support_height], center = true);
/* translate([-5.7/2,0,$stem_support_height / 2]) cube([0.5, total_key_height($wall_thickness), $stem_support_height], center = true); */
/* translate([5.7/2,0,$stem_support_height / 2]) cube([0.5, total_key_height($wall_thickness), $stem_support_height], center = true); */
}
}

View File

@@ -11,6 +11,6 @@ module box_cherry_stem(depth, slop, throw) {
}
// inside cross
inside_cherry_cross($stem_inner_slop);
inside_cherry_cross(slop);
}
}

View File

@@ -2,7 +2,7 @@ include <../functions.scad>
// extra length to the vertical tine of the inside cherry cross
// splits the stem into halves - allows easier fitment
extra_vertical = 100;
extra_vertical = 0.6;
module inside_cherry_cross(slop) {
// inside cross

View File

@@ -7,6 +7,6 @@ module rounded_cherry_stem(depth, slop, throw) {
// inside cross
// translation purely for aesthetic purposes, to get rid of that awful lattice
inside_cherry_cross($stem_inner_slop);
inside_cherry_cross(slop);
}
}

View File

@@ -445,12 +445,12 @@ copy-descriptor@^0.1.0:
integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=
copy-props@^2.0.1:
version "2.0.5"
resolved "https://registry.yarnpkg.com/copy-props/-/copy-props-2.0.5.tgz#03cf9ae328d4ebb36f8f1d804448a6af9ee3f2d2"
integrity sha512-XBlx8HSqrT0ObQwmSzM7WE5k8FxTV75h1DX1Z3n6NhQ/UYYAvInWYmG06vFt7hQZArE2fuO62aihiWIVQwh1sw==
version "2.0.4"
resolved "https://registry.yarnpkg.com/copy-props/-/copy-props-2.0.4.tgz#93bb1cadfafd31da5bb8a9d4b41f471ec3a72dfe"
integrity sha512-7cjuUME+p+S3HZlbllgsn2CDwS+5eCCX16qBgNC4jgSTf49qR1VKy/Zhl400m0IQXl/bPGEVqncgUUMjrr4s8A==
dependencies:
each-props "^1.3.2"
is-plain-object "^5.0.0"
each-props "^1.3.0"
is-plain-object "^2.0.1"
core-util-is@~1.0.0:
version "1.0.2"
@@ -538,7 +538,7 @@ duplexify@^3.6.0:
readable-stream "^2.0.0"
stream-shift "^1.0.0"
each-props@^1.3.2:
each-props@^1.3.0:
version "1.3.2"
resolved "https://registry.yarnpkg.com/each-props/-/each-props-1.3.2.tgz#ea45a414d16dd5cfa419b1a81720d5ca06892333"
integrity sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==
@@ -1013,9 +1013,9 @@ homedir-polyfill@^1.0.1:
parse-passwd "^1.0.0"
hosted-git-info@^2.1.4:
version "2.8.9"
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9"
integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==
version "2.8.8"
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488"
integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==
inflight@^1.0.4:
version "1.0.6"
@@ -1178,11 +1178,6 @@ is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4:
dependencies:
isobject "^3.0.1"
is-plain-object@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344"
integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==
is-relative@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-1.0.0.tgz#a1bb6935ce8c5dba1e8b9754b9b2dcc020e2260d"
@@ -1629,9 +1624,9 @@ path-is-absolute@^1.0.0:
integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
path-parse@^1.0.6:
version "1.0.7"
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
version "1.0.6"
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==
path-root-regex@^0.1.0:
version "0.1.2"
@@ -2353,9 +2348,9 @@ xtend@~4.0.0, xtend@~4.0.1:
integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
y18n@^3.2.1:
version "3.2.2"
resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.2.tgz#85c901bd6470ce71fc4bb723ad209b70f7f28696"
integrity sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==
version "3.2.1"
resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41"
integrity sha1-bRX7qITAhnnA136I53WegR4H+kE=
yargs-parser@^5.0.0:
version "5.0.1"