18 Commits

Author SHA1 Message Date
Bob
92c1856712 Increase polygonal tolerance
the caps are a little tight after testing
2020-09-29 15:35:39 -04:00
Bob
78a69feff1 add regular polygon shape
also tweak a few things to get them to work
2020-09-29 15:25:20 -04:00
Bob
8a7a302ac8 Merge pull request #52 from rsheldiii/new-key-structure
key.scad restructuring
2020-09-29 12:05:54 -04:00
Bob
e6dd35fca0 Update linear_extrude.scad
mostly for iso enter
2020-07-21 13:51:04 -04:00
Bob
24c80cb735 Couple tweaks for doubleshot 2020-07-08 13:58:06 -04:00
Bob
e29bb46dfa hull fix 2020-06-18 20:33:51 -04:00
Bob
57fbf6044d ISO enter small fix 2020-06-18 17:22:58 -04:00
Bob
2eed004407 skin_rounded_square_fix 2020-06-18 17:22:39 -04:00
Bob
8b4b9ae687 hull_shape_type 2020-06-18 17:22:29 -04:00
Bob
c7168eae68 remove unnecessary changes 2020-06-18 16:54:54 -04:00
Bob
c1bbaed9a2 large key.scad restructuring 2020-06-17 14:37:00 -04:00
Bob
a523c45f4a Merge pull request #44 from rsheldiii/key-features
Key features are a full feature
2020-05-12 16:46:10 -04:00
Bob
b29a5f3c5f Merge branch 'v2.0.0' into key-features 2020-05-12 16:43:50 -04:00
Bob
c7602e2ce9 Merge pull request #45 from rsheldiii/improving-shapes-a-bit
Add rounding facets and more skin shapes
2020-05-12 16:22:38 -04:00
Bob
f98c0d4a4f update link in readme
to point to sha so it's perpetually right, even if I update the code
2020-05-12 14:01:06 -04:00
Bob
18892c02b0 add minkowski facets 2020-05-12 12:02:07 -04:00
Bob
9cb3e12b9b Add rounding facets and more skin shapes 2020-05-12 11:57:40 -04:00
Bob
a61411258b break features into their own dir 2020-05-12 10:52:19 -04:00
29 changed files with 1352 additions and 652 deletions

16
CHANGELOG.md Normal file
View File

@@ -0,0 +1,16 @@
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

View File

@@ -60,7 +60,7 @@ You can chain as many modifier functions as you like!
## Modifier functions
There is a bevy of supporting functions to customize your keycaps. You can add a brim to more easily print the stem with `brimmed_stem_support`, make 2x2 keycaps with `2u() 2uh()`, add legends, rotate stems, and more. All these functions manipulate the settings available to you in [`settings.scad`](https://github.com/rsheldiii/KeyV2/blob/master/src/settings.scad), though [some of them](https://github.com/rsheldiii/KeyV2/blob/master/src/key_transformations.scad#L128) are quite complex.
There is a bevy of supporting functions to customize your keycaps. You can add a brim to more easily print the stem with `brimmed_stem_support`, make 2x2 keycaps with `2u() 2uh()`, add legends, rotate stems, and more. All these functions manipulate the settings available to you in [`settings.scad`](https://github.com/rsheldiii/KeyV2/blob/master/src/settings.scad), though [some of them](https://github.com/rsheldiii/KeyV2/blob/851ececdb297c77bfbcd0a7cb4cdbc5e21970396/src/key_transformations.scad#L128) are quite complex.
These modifier functions can be found in [`key_profiles/`](https://github.com/rsheldiii/KeyV2/blob/master/src/key_profiles) for different keycap profiles, [`key_types.scad`](https://github.com/rsheldiii/KeyV2/blob/master/src/key_types.scad) for predefined settings for common keys (spacebar, left shift, etc), [`key_sizes.scad`](https://github.com/rsheldiii/KeyV2/blob/master/src/key_sizes.scad) for common unit sizes, and [`key_transformations.scad`](https://github.com/rsheldiii/KeyV2/blob/master/src/key_transformations.scad) for everything else. I encourage you to do some sleuthing but for a list of (most) helper functions with explanations, [Check out the wiki!](https://github.com/rsheldiii/KeyV2/wiki/KeyV2-Helper-Documentation)

View File

@@ -14,7 +14,7 @@ At the end of the day though, all the columnular sculpting is doing is adding ex
## skin mode
SA, HiPro and DSA keycaps take _forever_ to render. This is a multifaceted issue that I don't want to get into here, but suffice to say _one_ of the reasons it takes so long is how the keycap is constructed from multiple, smaller slices. OpenSCAD takes more time to render the more objects you have, regardless of how they interact. Enter `$skin_extrude_shape = true`.
SA, HiPro and DSA keycaps take _forever_ to render. This is a multifaceted issue that I don't want to get into here, but suffice to say _one_ of the reasons it takes so long is how the keycap is constructed from multiple, smaller slices. OpenSCAD takes more time to render the more objects you have, regardless of how they interact. Enter `$hull_shape_type = "skin"`.
`skin()` is a list comprehension function available [here](https://github.com/openscad/list-comprehension-demos/blob/master/skin.scad). The gist of it is that instead of having x number of keycap slices unioned together, we give `skin()` a set of profiles and it makes a single object out of it for us. This reduces the number of objects per keycap, which makes it easier to render them.

File diff suppressed because it is too large Load Diff

View File

@@ -5,88 +5,11 @@
// without having to rely on this file. Unfortunately that means setting tons of
// special variables, but that's a limitation of SCAD we have to work around
echo($fa);
echo("WHERES THE BEEF");
include <./includes.scad>
dsa_row(3) {
union() {
$key_shape_type="sculpted_square";
$dish_type="disabled";
$skin_extrude_shape = true;
key();
}
}
/* $inverted_dish = true; */
/* $rounded_key = true; */
/* $linear_extrude_shape=true; */
/* $rounded_key=true; */
/* $outset_legends = true; */
/* $inverted_dish =true; */
/* $dish_type = "pyramid"; */
/* legend("q") key(); */
/* $outset_legends = true; */
dcs_row(3) {
/* iso_enter() */
union() {
union() {
/* $minkowski_radius = 10; */
/* $minkowski_radius = 0.12; */
/* $key_shape_type = "iso_enter"; */
$key_shape_type="sculpted_square";
/* $dish_type ="disable"; */
/* $inverted_dish = true; */
/* $stem_type = "disable"; */
/* $dish_type="3d_surface"; */
/* $support_type = "disable"; */
/* $stabilizer_type = "disable"; */
/* rounded_shape(); */
/* minkowski() { */
/* rounded_key(); */
/* translate([0,0,-200]) cube(10); */
/* difference(){ */
/* key(); */
/* cube(100); */
/* } */
/* minkowski_shape(); */
/* } */
}
}
}
/* translate_u(1,0) {
oem_row(3) {
cherry() legend("q")
union() {
key();
}
}
} */
/* difference() {
translate([0,0,-.1]) cube(1.1);
translate([0.5,0.5,-0.5]) polar_3d_surface(step=0.1);
} */
// Written in 2015 by Torsten Paul <Torsten.Paul@gmx.de>
//
// To the extent possible under law, the author(s) have dedicated all
// copyright and related and neighboring rights to this software to the
// public domain worldwide. This software is distributed without any
// warranty.
//
// For details of the CC0 Public Domain Dedication see
// <http://creativecommons.org/publicdomain/zero/1.0/>.
// example key
dcs_row(5) legend("⇪", size=9) key();
// example row
/* for (x = [0:1:4]) {
@@ -94,4 +17,4 @@ dsa_row(3) {
} */
// example layout
/* preonic_default("dcs"); */
/* preonic_default("dcs"); */

View File

@@ -1 +1,4 @@
// a safe theoretical distance between two vertices such that they don't collapse. hard to use
SMALLEST_POSSIBLE = 1/128;
$fs=0.1;
$unit=19.05;

View File

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

5
src/features.scad Normal file
View File

@@ -0,0 +1,5 @@
// 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>

View File

@@ -0,0 +1,24 @@
// 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();
}
}
}
}

26
src/features/legends.scad Normal file
View File

@@ -0,0 +1,26 @@
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);
}
}
}
}

View File

@@ -4,6 +4,8 @@ include <constants.scad>
// functions need to be explicitly included, unlike special variables, which
// 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
function outer_cherry_stem(slop) = [7.2 - slop * 2, 5.5 - slop * 2];
@@ -40,3 +42,27 @@ function vertical_inclination_due_to_top_tilt() = sin($top_tilt) * (top_total_ke
// of the keycap a flat plane. 1 = front, -1 = back
// I derived this through a bunch of trig reductions I don't really understand.
function extra_keytop_length_for_flat_sides() = ($width_difference * vertical_inclination_due_to_top_tilt()) / ($total_depth);
// 3d surface functions (still in beta)
// monotonically increasing function that distributes the points of the surface mesh
// only for polar_3d_surface right now
// if it's linear it's a grid. sin(dim) * size concentrates detail around the edges
function surface_distribution_function(dim, size) = sin(dim) * size;
// the function that actually determines what the surface is.
// feel free to override, the last one wins
// debug
function surface_function(x,y) = 1;
// cylindrical
function surface_function(x,y) = (sin(acos(x/$3d_surface_size)));
// spherical
function surface_function(x,y) = (sin(acos(x/$3d_surface_size))) * sin(acos(y/$3d_surface_size));
// (statically) random!
// ripples
/* function surface_function(x,y) = cos(pow(pow(x,2)+pow(y,2),0.5)*10)/4+0.75; */
// Rosenbrock's banana
/* function surface_function(x,y) = (pow(1-(x/100), 2) + 100 * pow((y/100)-pow((x/100),2),2))/200 + 0.1; */
// y=x revolved around the y axis
/* function surface_function(x,y) = 1/(pow(pow(x,2)+pow(y,2),0.5)/100 + .01); */

19
src/hulls.scad Normal file
View File

@@ -0,0 +1,19 @@
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);
}
}
}

33
src/hulls/hull.scad Normal file
View File

@@ -0,0 +1,33 @@
module hull_shape_hull(thickness_difference, depth_difference, extra_slices = 0) {
for (index = [0:$height_slices - 1 + extra_slices]) {
hull() {
shape_slice(index / $height_slices, thickness_difference, depth_difference);
shape_slice((index + 1) / $height_slices, thickness_difference, depth_difference);
}
}
}
module shape_slice(progress, thickness_difference, depth_difference) {
skew_this_slice = $top_skew * progress;
x_skew_this_slice = $top_skew_x * progress;
depth_this_slice = ($total_depth - depth_difference) * progress;
tilt_this_slice = -$top_tilt / $key_height * progress;
y_tilt_this_slice = $double_sculpted ? (-$top_tilt_y / $key_length * progress) : 0;
translate([x_skew_this_slice, skew_this_slice, depth_this_slice]) {
rotate([tilt_this_slice,y_tilt_this_slice,0]){
linear_extrude(height = SMALLEST_POSSIBLE, scale = 1){
key_shape(
[
total_key_width(thickness_difference),
total_key_height(thickness_difference)
],
[$width_difference, $height_difference],
progress
);
}
}
}
}

View File

@@ -0,0 +1,18 @@
// corollary is hull_shape_hull
// extra_slices unused, only to match argument signatures
module linear_extrude_shape_hull(thickness_difference, depth_difference, extra_slices = 0){
height = $total_depth - depth_difference;
width_scale = top_total_key_width() / total_key_width();
height_scale = top_total_key_height() / total_key_height();
translate([0,$linear_extrude_height_adjustment,0]){
linear_extrude(height = height, scale = [width_scale, height_scale]) {
translate([0,-$linear_extrude_height_adjustment,0]){
key_shape(
[total_key_width(), total_key_height()],
[thickness_difference, thickness_difference]
);
}
}
}
}

34
src/hulls/skin.scad Normal file
View File

@@ -0,0 +1,34 @@
// use skin() instead of successive hulls. much more correct, and looks faster
// too, in most cases. successive hull relies on overlapping faces which are
// not good. But, skin works on vertex sets instead of shapes, which makes it
// a lot more difficult to use
module skin_extrude_shape_hull(thickness_difference, depth_difference, extra_slices = 0 ) {
skin([
for (index = [0:$height_slices + extra_slices])
let(
progress = (index / $height_slices),
skew_this_slice = $top_skew * progress,
x_skew_this_slice = $top_skew_x * progress,
depth_this_slice = ($total_depth - depth_difference) * progress,
tilt_this_slice = -$top_tilt / $key_height * progress,
y_tilt_this_slice = $double_sculpted ? (-$top_tilt_y / $key_length * progress) : 0
)
skin_shape_slice(progress, thickness_difference, skew_this_slice, x_skew_this_slice, depth_this_slice, tilt_this_slice, y_tilt_this_slice)
]);
}
function skin_shape_slice(progress, thickness_difference, skew_this_slice, x_skew_this_slice, depth_this_slice, tilt_this_slice, y_tilt_this_slice) =
transform(
translation([x_skew_this_slice,skew_this_slice,depth_this_slice]),
transform(
rotation([tilt_this_slice,y_tilt_this_slice,0]),
skin_key_shape([
total_key_width(0),
total_key_height(0),
],
[$width_difference, $height_difference],
progress,
thickness_difference
)
)
);

View File

@@ -25,13 +25,11 @@ $unit = 19.05;
// key shape including dish. used as the ouside and inside shape in hollow_key(). allows for itself to be shrunk in depth and width / height
module shape(thickness_difference, depth_difference=0){
dished(depth_difference, $inverted_dish) {
color($primary_color) shape_hull(thickness_difference, depth_difference, $inverted_dish ? 2 : 0);
color($primary_color) shape_hull(thickness_difference, depth_difference, $inverted_dish ? 200 : 0);
}
}
// this function is more correct, but takes _forever_
// the main difference is minkowski happens after dishing, meaning the dish is
// also minkowski'd
// Not currently used due to CGAL errors. Rounds the shape via minkowski
module rounded_shape() {
color($primary_color) minkowski(){
// half minkowski in the z direction
@@ -54,7 +52,6 @@ module minkowski_object() {
}
}
module envelope(depth_difference=0) {
s = 1.5;
hull(){
@@ -87,19 +84,6 @@ module _dish(inverted=$inverted_dish) {
color($secondary_color) dish(top_total_key_width() + $dish_overdraw_width, top_total_key_height() + $dish_overdraw_height, $dish_depth, inverted);
}
// puts its children at the center of the dishing on the key, including dish height
// more user-friendly than top_placement
module top_of_key(){
// if there is a dish, we need to account for how much it digs into the top
dish_depth = ($dish_type == "disable") ? 0 : $dish_depth;
// if the dish is inverted, we need to account for that too. in this case we do half, otherwise the children would be floating on top of the dish
corrected_dish_depth = ($inverted_dish) ? -dish_depth / 2 : dish_depth;
top_placement(corrected_dish_depth) {
children();
}
}
// puts its children at each keystem position provided
module keystem_positions(positions) {
for (connector_pos = positions) {
@@ -119,7 +103,7 @@ module support_for(positions, stem_type) {
module stems_for(positions, stem_type) {
keystem_positions(positions) {
color($tertiary_color) stem(stem_type, $total_depth, $stem_slop);
color($tertiary_color) stem(stem_type, stem_height(), $stem_slop);
if ($stem_support_type != "disable") {
color($quaternary_color) stem_support($stem_support_type, stem_type, $stem_support_height, $stem_slop);
}
@@ -140,6 +124,19 @@ module top_placement(depth_difference=0) {
}
}
// puts its children at the center of the dishing on the key, including dish height
// more user-friendly than top_placement
module top_of_key(){
// if there is a dish, we need to account for how much it digs into the top
dish_depth = ($dish_type == "disable") ? 0 : $dish_depth;
// if the dish is inverted, we need to account for that too. in this case we do half, otherwise the children would be floating on top of the dish
corrected_dish_depth = ($inverted_dish) ? -dish_depth / 2 : dish_depth;
top_placement(corrected_dish_depth) {
children();
}
}
module front_of_key() {
// all this math is to take top skew and tilt into account
// we need to find the new effective height and depth of the top, front lip
@@ -160,22 +157,16 @@ module front_of_key() {
}
module outer_shape() {
if ($rounded_key) {
rounded_shape();
} else {
shape(0, 0);
}
shape(0, 0);
}
module inner_shape(extra_wall_thickness = 0, extra_keytop_thickness = 0) {
translate([0,0,-SMALLEST_POSSIBLE]) {
if ($flat_keytop_bottom) {
/* $key_shape_type="square"; */
$height_slices = 1;
color($primary_color) shape_hull($wall_thickness + extra_wall_thickness, $keytop_thickness + extra_keytop_thickness, 0);
} else {
shape($wall_thickness + extra_wall_thickness, $keytop_thickness + extra_keytop_thickness);
}
if ($inner_shape_type == "flat") {
/* $key_shape_type="square"; */
$height_slices = 1;
color($primary_color) shape_hull($wall_thickness + extra_wall_thickness, $keytop_thickness + extra_keytop_thickness, 0);
} else {
shape($wall_thickness + extra_wall_thickness, $keytop_thickness + extra_keytop_thickness);
}
}
@@ -198,60 +189,63 @@ module subtractive_features(inset) {
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();
// this is a little confusing as it eats the stem too
/* if ($clearance_check) clearance_check(); */
}
module inside_features() {
// all stems and stabilizers
module stems_and_stabilizers() {
translate([0, 0, $stem_inset]) {
// both stem and support are optional
if ($stabilizer_type != "disable") stems_for($stabilizers, $stabilizer_type);
if ($stem_type != "disable") stems_for($stem_positions, $stem_type);
if ($stabilizer_type != "disable") support_for($stabilizers, $stabilizer_type);
// always render stem support even if there isn't a stem.
// rendering flat support w/no stem is much more common than a hollow keycap
// so if you want a hollow keycap you'll have to turn support off entirely
support_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
module inner_total_shape() {
difference() {
inner_shape();
inside_features();
}
}
module outer_total_shape(inset=false) {
outer_shape();
additive_features(inset) {
children();
};
}
// The final, penultimate key generation function.
// takes all the bits and glues them together. requires configuration with special variables.
module key(inset=false) {
difference(){
union() {
outer_shape();
additive_features(inset);
}
outer_total_shape(inset);
difference() {
inner_shape();
inside_features();
}
subtractive_features(inset);
}
}
module rounded_key(inset=false) {
difference() {
minkowski() {
difference() {
outer_shape();
inner_shape();
if ($inner_shape_type != "disable") {
translate([0,0,-SMALLEST_POSSIBLE]) {
inner_total_shape();
}
minkowski_object();
}
subtractive_features(inset);
subtractive_features(inset) {
children();
};
}
/* additive_features(inset); */
/* intersection() {
inner_shape($wall_thickness, $keytop_thickness);
inside_features();
} */
// if $stem_inset is less than zero, we add the
if ($stem_inset < 0) {
stems_and_stabilizers();
}
}
// actual full key with space carved out and keystem/stabilizer connectors

View File

@@ -9,6 +9,7 @@ include <key_profiles/sa.scad>
include <key_profiles/g20.scad>
include <key_profiles/hipro.scad>
include <key_profiles/grid.scad>
include <key_profiles/regular_polygon.scad>
// man, wouldn't it be so cool if functions were first order
module key_profile(key_profile_type, row, column=0) {
@@ -26,6 +27,10 @@ module key_profile(key_profile_type, row, column=0) {
hipro_row(row, column) children();
} else if (key_profile_type == "grid") {
grid_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 == "disable") {
children();
} else {

View File

@@ -11,7 +11,7 @@ module grid_row(row=3, column = 0) {
$dish_skew_x = 0;
$dish_skew_y = 0;
$linear_extrude_shape = true;
$hull_shape_type = "linear extrude";
$dish_overdraw_width = -8;

View File

@@ -0,0 +1,66 @@
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();
}
}

View File

@@ -1,10 +1,9 @@
// kind of a catch-all at this point for any directive that doesn't fit in the other files
//TODO duplicate def to not make this a special var. maybe not worth it
unit = 19.05;
include <constants.scad>
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() {

View File

@@ -46,7 +46,7 @@ module iso_enter() {
$top_tilt = 0;
$stem_support_type = "disable";
$key_shape_type = "iso_enter";
/* $linear_extrude_shape = true; */
/* $hull_shape_type = "linear extrude"; */
$linear_extrude_height_adjustment = 19.05 * 0.5;
// this equals (unit_length(1.5) - unit_length(1.25)) / 2
$dish_overdraw_width = 2.38125;

View File

@@ -1,7 +1,7 @@
include <../layout.scad>
// negative numbers are used for spacing
lets_split_mapping = [
lets_split_layout = [
[1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 1],
@@ -9,5 +9,5 @@ lets_split_mapping = [
];
module lets_split_default(profile) {
layout(lets_split_mapping, profile, row_sculpting_offset=1) children();
layout(lets_split_layout, profile, row_sculpting_offset=1) children();
}

View File

@@ -17,17 +17,19 @@ function rectangle_profile(size=[1,1],fn=32) = [
];
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]
let(max_fn = max(fn,8))
for (index = [0:max_fn-1])
let(a = index/max_fn*360)
r * [cos(a), sin(a)]
+ sign_x(index, max_fn) * [size[0]/2-r,0]
+ sign_y(index, max_fn) * [0,size[1]/2-r]
];
function double_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]
let(max_fn = max(fn,8))
for (index = [0:max_fn-1])
let(a = index/max_fn*360)
r * [cos(a), sin(a)]
+ sign_x(index, max_fn) * [size[0]/2-r,0]
+ sign_y(index, max_fn) * [0,size[1]/2-r]
];

View File

@@ -37,7 +37,7 @@ $outset_legends = false;
// Height in units of key. should remain 1 for most uses
$key_height = 1.0;
// Keytop thickness, aka how many millimeters between the inside and outside of the top surface of the key
$keytop_thickness = 2;
$keytop_thickness = 1;
// Wall thickness, aka the thickness of the sides of the keycap. note this is the total thickness, aka 3 = 1.5mm walls
$wall_thickness = 3;
// Radius of corners of keycap
@@ -74,6 +74,7 @@ $rounded_cherry_stem_d = 5.5;
// How much higher the stem is than the bottom of the keycap.
// Inset stem requires support but is more accurate in some profiles
// can be negative to make outset stems!
$stem_inset = 0;
// How many degrees to rotate the stems. useful for sideways keycaps, maybe
$stem_rotation = 0;
@@ -118,12 +119,10 @@ $font="DejaVu Sans Mono:style=Book";
// Whether or not to render fake keyswitches to check clearances
$clearance_check = false;
// Should be faster, also required for concave shapes
// Use linear_extrude instead of hull slices to make the shape of the key
$linear_extrude_shape = false;
// warns in trajectory.scad but it looks benign
// brand new, more correct, hopefully faster, lots more work
$skin_extrude_shape = false;
// what kind of extrusion we use to create the keycap. "hull" is standard, "linear extrude" is legacy, "skin" is new and not well supported.
$hull_shape_type = "hull"; // ["hull", "linear extrude", "skin"]
// This doesn't work very well, but you can try
$rounded_key = false;
//minkowski radius. radius of sphere used in minkowski sum for minkowski_key function. 1.75 for G20
@@ -184,15 +183,15 @@ $tertiary_color = [1, .6941, .2];
$quaternary_color = [.4078, .3569, .749];
$warning_color = [1,0,0, 0.15];
// 3d surface variables
// see functions.scad for the surface function
$3d_surface_size = 10;
$3d_surface_step = 1;
// normally the bottom of the keytop looks like the top - curved, at least
// underneath the support structure. This ensures there's a minimum thickness for the
// underside of the keycap, but it's a fair bit of geometry
$flat_keytop_bottom = true;
// how many facets circles will have when used in these features
$minkowski_facets = 30;
$shape_facets = 30;
$shape_facets =30;
// 3d surface settings
// unused for now
$3d_surface_size = 100;
// resolution in each axis. 10 = 10 divisions per x/y = 100 points total
$3d_surface_step = 5;
// "flat" / "dished" / "disable"
$inner_shape_type = "flat";

View File

@@ -1,11 +1,10 @@
$fs=.1;
unit = 19.05;
include <constants.scad>
include <shapes/ISO_enter.scad>
include <shapes/sculpted_square.scad>
include <shapes/rounded_square.scad>
include <shapes/square.scad>
include <shapes/oblong.scad>
include <shapes/regular_polygon.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
@@ -25,6 +24,10 @@ module key_shape(size, delta, progress = 0) {
square_shape(size, delta, progress);
} else if ($key_shape_type == "oblong") {
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 {
echo("Warning: unsupported $key_shape_type");
}

View File

@@ -2,6 +2,7 @@
// NOT 3D
function unit_length(length) = unit * (length - 1) + 18.16;
module ISO_enter_shape(size, delta, progress){
width = size[0];
height = size[1];
@@ -16,19 +17,21 @@ module ISO_enter_shape(size, delta, progress){
width_ratio = unit_length(1.25) / unit_length(1.5);
height_ratio = unit_length(1) / unit_length(2);
delta = delta / 2;
pointArray = [
[ 0, 0], // top right
[ 0, -height], // bottom right
[-width * width_ratio, -height], // bottom left
[-width * width_ratio,-height * height_ratio], // inner middle point
[ -width,-height * height_ratio], // outer middle point
[ -width, 0] // top left
[ 0-delta.x, 0-delta.y], // top right
[ 0-delta.x, -height+delta.y], // bottom right
[-width * width_ratio+delta.x, -height+delta.y], // bottom left
[-width * width_ratio + delta.x,-height * height_ratio+delta.y], // inner middle point
[ -width + delta.x,-height * height_ratio + delta.y], // outer middle point
[ -width + delta.x, 0-delta.y] // top left
];
minkowski(){
circle(r=corner_size);
circle(r=$corner_radius);
// gives us rounded inner corner
offset(r=-corner_size*2) {
offset(r=-$corner_radius*2) {
translate([(width * width_ratio)/2, height/2]) polygon(points=pointArray);
}
}

View File

@@ -0,0 +1,14 @@
// 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");

View File

@@ -9,4 +9,4 @@ module rounded_square_shape(size, delta, progress, center = true) {
// for skin
function skin_rounded_square(size, delta, progress, thickness_difference) =
rounded_rectangle_profile(size - (delta * progress) - [thickness_difference, thickness_difference]*2, fn=$shape_facets, r=$corner_radius);
rounded_rectangle_profile(size - (delta * progress) - [thickness_difference, thickness_difference], fn=$shape_facets, r=$corner_radius);

View File

@@ -67,7 +67,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
]
) double_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);
) double_rounded_rectangle_profile(square_size - [extra_corner_radius_this_slice, extra_corner_radius_this_slice]/4, fn=$shape_facets, 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) {