diff --git a/keys.scad b/keys.scad index 8439cea..5af7206 100644 --- a/keys.scad +++ b/keys.scad @@ -38,4 +38,19 @@ for (p = [0:len(key_profiles)-1]) { } /* translate_u(0, 0) one_row_profile("oem"); */ -legend("C", [-1,-1], 3) cherry() key(true); +/* dsa_row(3) u(1) uh(1) cherry() key(); */ + +translate_u(0) sa_row(3) cherry() { + key(); +} + +translate_u(1) sa_row(2) cherry() { + key(); +} + +translate_u(2) sa_row(1) cherry() { + key(); +} + +/* sculpted_square_shape([19,19], [0,0], 0.3); +translate([26,0,0]) rounded_square_shape([19,19], [0,0], 0.3); */ diff --git a/src/key_profiles/dsa.scad b/src/key_profiles/dsa.scad index 3ec217b..af33b20 100644 --- a/src/key_profiles/dsa.scad +++ b/src/key_profiles/dsa.scad @@ -1,5 +1,6 @@ module dsa_row(n=3) { - depth_raisers = [0, 3.5, 1, 0, 1, 3]; + $key_shape_type = "sculpted_square"; + depth_raisers = [0, 3.5, 1, 0, 1, 3]; $bottom_key_width = 18.24; // 18.4; $bottom_key_height = 18.24; // 18.4; $width_difference = 6; // 5.7; @@ -8,11 +9,10 @@ module dsa_row(n=3) { $top_tilt = n == 5 ? -21 : (n-3) * 7; $top_skew = 0; $dish_type = "spherical"; - $dish_depth = 1.2; + $dish_depth = 1; $dish_skew_x = 0; $dish_skew_y = 0; $height_slices = 10; - $enable_side_sculpting = true; // might wanna change this if you don't minkowski // do you even minkowski bro $corner_radius = 0.25; diff --git a/src/key_profiles/sa.scad b/src/key_profiles/sa.scad index 3333959..be0583d 100644 --- a/src/key_profiles/sa.scad +++ b/src/key_profiles/sa.scad @@ -1,4 +1,5 @@ module sa_row(n=1) { + $key_shape_type = "sculpted_square"; $bottom_key_width = 18.4; $bottom_key_height = 18.4; $width_difference = 5.7; @@ -9,7 +10,6 @@ module sa_row(n=1) { $dish_skew_y = 0; $top_skew = 0; $height_slices = 10; - $enable_side_sculpting = true; // might wanna change this if you don't minkowski // do you even minkowski bro $corner_radius = 0.25; diff --git a/src/libraries/scad-utils/se3.scad b/src/libraries/scad-utils/se3.scad index 48b59e6..4a80922 100644 --- a/src/libraries/scad-utils/se3.scad +++ b/src/libraries/scad-utils/se3.scad @@ -5,26 +5,26 @@ function combine_se3_exp(w, ABt) = construct_Rt(rodrigues_so3_exp(w, ABt[0], ABt // [A,B,t] function se3_exp_1(t,w) = concat( - so3_exp_1(w*w), - [t + 0.5 * cross(w,t)] + so3_exp_1(w*w), + [t + 0.5 * cross(w,t)] ); function se3_exp_2(t,w) = se3_exp_2_0(t,w,w*w); -function se3_exp_2_0(t,w,theta_sq) = +function se3_exp_2_0(t,w,theta_sq) = se3_exp_23( - so3_exp_2(theta_sq), - C = (1.0 - theta_sq/20) / 6, - t=t,w=w); + so3_exp_2(theta_sq), + C = (1.0 - theta_sq/20) / 6, + t=t,w=w); function se3_exp_3(t,w) = se3_exp_3_0(t,w,sqrt(w*w)*180/PI,1/sqrt(w*w)); -function se3_exp_3_0(t,w,theta_deg,inv_theta) = +function se3_exp_3_0(t,w,theta_deg,inv_theta) = se3_exp_23( - so3_exp_3_0(theta_deg = theta_deg, inv_theta = inv_theta), - C = (1 - sin(theta_deg) * inv_theta) * (inv_theta * inv_theta), - t=t,w=w); + so3_exp_3_0(theta_deg = theta_deg, inv_theta = inv_theta), + C = (1 - sin(theta_deg) * inv_theta) * (inv_theta * inv_theta), + t=t,w=w); -function se3_exp_23(AB,C,t,w) = +function se3_exp_23(AB,C,t,w) = [AB[0], AB[1], t + AB[1] * cross(w,t) + C * cross(w,cross(w,t)) ]; function se3_exp(mu) = se3_exp_0(t=take3(mu),w=tail3(mu)/180*PI); @@ -32,29 +32,29 @@ function se3_exp(mu) = se3_exp_0(t=take3(mu),w=tail3(mu)/180*PI); function se3_exp_0(t,w) = combine_se3_exp(w, // Evaluate by Taylor expansion when near 0 - w*w < 1e-8 - ? se3_exp_1(t,w) - : w*w < 1e-6 - ? se3_exp_2(t,w) - : se3_exp_3(t,w) + w*w < 1e-8 + ? se3_exp_1(t,w) + : w*w < 1e-6 + ? se3_exp_2(t,w) + : se3_exp_3(t,w) ); function se3_ln(m) = se3_ln_to_deg(se3_ln_rad(m)); function se3_ln_to_deg(v) = concat(take3(v),tail3(v)*180/PI); -function se3_ln_rad(m) = se3_ln_0(m, - rot = so3_ln_rad(rotation_part(m))); +function se3_ln_rad(m) = se3_ln_0(m, + rot = so3_ln_rad(rotation_part(m))); function se3_ln_0(m,rot) = se3_ln_1(m,rot, - theta = sqrt(rot*rot)); + theta = sqrt(rot*rot)); function se3_ln_1(m,rot,theta) = se3_ln_2(m,rot,theta, - shtot = theta > 0.00001 ? sin(theta/2*180/PI)/theta : 0.5, - halfrotator = so3_exp_rad(rot * -.5)); + shtot = theta > 0.00001 ? sin(theta/2*180/PI)/theta : 0.5, + halfrotator = so3_exp_rad(rot * -.5)); function se3_ln_2(m,rot,theta,shtot,halfrotator) = -concat( (halfrotator * translation_part(m) - - (theta > 0.001 - ? rot * ((translation_part(m) * rot) * (1-2*shtot) / (rot*rot)) - : rot * ((translation_part(m) * rot)/24) - )) / (2 * shtot), rot); +concat( (halfrotator * translation_part(m) - + (theta > 0.001 + ? rot * ((translation_part(m) * rot) * (1-2*shtot) / (rot*rot)) + : rot * ((translation_part(m) * rot)/24) + )) / (2 * shtot), rot); __se3_test = [20,-40,60,-80,100,-120]; echo(UNITTEST_se3=norm(__se3_test-se3_ln(se3_exp(__se3_test))) < 1e-8); diff --git a/src/settings.scad b/src/settings.scad index 9c7f194..d6b2fd0 100644 --- a/src/settings.scad +++ b/src/settings.scad @@ -75,16 +75,6 @@ $dish_overdraw_height = 0; // how many slices will be made, to approximate curves on corners. Leave at 1 if you are not curving corners // if you're doing fancy bowed keycap sides, this controls how many slices you take $height_slices = 1; -// this enables some fancy and currently hardcoded logic to bow the sides and corners of SA keycaps -$enable_side_sculpting = false; -// this enables even more fancy and hardcoded logic for corner bowing of SA keycaps. (Also needs enable_side_sculpting to be true) -$enable_more_side_sculpting = false; -// When sculpting sides, how much in should the tops come -$side_sculpting_factor = 2.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; //minkowski radius. radius of sphere used in minkowski sum for minkowski_key function. 1.75 for G20 $minkowski_radius = .33; diff --git a/src/shapes.scad b/src/shapes.scad index 5a496d0..63d0b93 100644 --- a/src/shapes.scad +++ b/src/shapes.scad @@ -2,6 +2,7 @@ $fs=.1; unit = 19.05; include +include include include include @@ -9,6 +10,8 @@ include module key_shape(size, delta, progress = 0) { if ($key_shape_type == "iso_enter") { ISO_enter_shape(size, delta, progress); + } else if ($key_shape_type == "sculpted_square") { + sculpted_square_shape(size, delta, progress); } else if ($key_shape_type == "rounded_square") { rounded_square_shape(size, delta, progress); } else if ($key_shape_type == "square") { diff --git a/src/shapes/rounded_square.scad b/src/shapes/rounded_square.scad index bc51f78..4f0b318 100644 --- a/src/shapes/rounded_square.scad +++ b/src/shapes/rounded_square.scad @@ -1,79 +1,22 @@ -// side sculpting functions -// bows the sides out on stuff like SA and DSA keycaps -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; - module rounded_square_shape(size, delta, progress, center = true) { - width = size[0]; - height = size[1]; + width = size[0]; + height = size[1]; - width_difference = delta[0]; - height_difference = delta[1]; - // makes the sides bow - extra_side_size = $enable_side_sculpting ? side_sculpting(progress) : 0; - // makes the rounded corners of the keycap grow larger as they move upwards - extra_corner_size = $enable_side_sculpting ? corner_sculpting(progress) : 0; + width_difference = delta[0]; + height_difference = delta[1]; - // 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); + // computed values for this slice + extra_width_this_slice = (width_difference) * progress; + extra_height_this_slice = (height_difference) * progress; + extra_corner_radius_this_slice = ($corner_radius); - square_size = [width - extra_width_this_slice, height - extra_height_this_slice]; - offset(r = extra_corner_radius_this_slice) offset(r = -extra_corner_radius_this_slice) { - if ($enable_more_side_sculpting != false && progress > 0) { - side_rounded_square(square_size, r = $more_side_sculpting_factor * progress); - } else { - square(square_size, center=center); - } - } -} - -// Brings in a square at each corner by r, applied over the length of each side. -module side_rounded_square(size, r) { - if ($enable_more_side_sculpting == "slow") { - side_rounded_square_slow(size, r); - } else { - side_rounded_square_fast(size, r); - } -} -module side_rounded_square_fast(size, r) { - iw = size.x - 2 * r; - ih = size.y - 2 * r; - resolution = 100; - sr = r / resolution * 2; - sh = ih / resolution; - sw = iw / resolution; - union() { - translate([-iw/2, 0]) scale([sr, sh]) circle(d = resolution); - translate([iw/2, 0]) scale([sr, sh]) circle(d = resolution); - translate([0, -ih/2]) scale([sw, sr]) circle(d = resolution); - translate([0, ih/2]) scale([sw, sr]) circle(d = resolution); - square([iw, ih], center=true); - } -} -module side_rounded_square_slow(size, r) { - // These two from: https://openscadsnippetpad.blogspot.co.nz/2017/05/circle-defined-by-three-points.html - function len3(v) = sqrt(pow(v.x, 2) + pow(v.y, 2)); - function circle_by_three_points(A, B, C) = let ( - yD_b = C.y - B.y, xD_b = C.x - B.x, yD_a = B.y - A.y, - xD_a = B.x - A.x, aS = yD_a / xD_a, bS = yD_b / xD_b, - cex = (aS * bS * (A.y - C.y) + bS * (A.x + B.x) - aS * (B.x + C.x)) / (2 * (bS - aS)), - cey = -1 * (cex - (A.x + B.x) / 2) / aS + (A.y + B.y) / 2 - ) - [cex, cey]; - - w = size.x - r * 2; - h = size.y - r * 2; - cw = circle_by_three_points([-w / 2, 0], [0, r], [w / 2, 0]); - rw = len3([w / 2, 0] - cw); - ch = circle_by_three_points([0, -h / 2], [r, 0], [0, h / 2]); - rh = len3([0, h / 2] - ch); - intersection() { - translate(cw + [0, h / 2]) circle(r = rw, $fa=1); - translate(cw * -1 + [0, -h / 2]) circle(r = rw, $fa=1); - translate(ch + [w / 2, 0]) circle(r = rh, $fa=1); - translate(ch * -1 + [-w / 2, 0]) circle(r = rh, $fa=1); + offset(r=extra_corner_radius_this_slice){ + square( + [ + width - extra_width_this_slice - extra_corner_radius_this_slice * 2, + height - extra_height_this_slice - extra_corner_radius_this_slice * 2 + ], + center=center + ); } } diff --git a/src/shapes/sculpted_square.scad b/src/shapes/sculpted_square.scad new file mode 100644 index 0000000..c79c6e2 --- /dev/null +++ b/src/shapes/sculpted_square.scad @@ -0,0 +1,59 @@ +// 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; +// makes the rounded corners of the keycap grow larger as they move upwards +function corner_sculpting(progress) = pow(progress, 2) * $corner_sculpting_factor; + +module sculpted_square_shape(size, delta, progress) { + 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 + ]; + + 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) { + iw = size.x - 2 * r; + ih = size.y - 2 * r; + resolution = 100; + sr = r / resolution * 2; + sh = ih / resolution; + sw = iw / resolution; + union() { + translate([-iw/2, 0]) scale([sr, sh]) circle(d = resolution); + translate([iw/2, 0]) scale([sr, sh]) circle(d = resolution); + translate([0, -ih/2]) scale([sw, sr]) circle(d = resolution); + translate([0, ih/2]) scale([sw, sr]) circle(d = resolution); + square([iw, ih], center=true); + } +}