From 15d87a8f9546564255ce54a2c9e8851e96599943 Mon Sep 17 00:00:00 2001 From: Bob Date: Tue, 12 May 2020 11:33:33 -0400 Subject: [PATCH] github desktop completely screwed me --- keys.scad | 83 +++- src/key.scad | 425 ++++++------------- src/libraries/rounded_rectangle_profile.scad | 34 +- src/settings.scad | 17 +- src/shapes.scad | 6 +- src/shapes/rounded_square.scad | 6 +- src/shapes/sculpted_square.scad | 18 +- src/shapes/square.scad | 16 + 8 files changed, 278 insertions(+), 327 deletions(-) diff --git a/keys.scad b/keys.scad index 768110e..1cded27 100644 --- a/keys.scad +++ b/keys.scad @@ -5,11 +5,88 @@ // 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); */ -// example key -dcs_row(5) legend("⇪", size=9) key(); + /* 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 +// +// 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 +// . // example row /* for (x = [0:1:4]) { @@ -17,4 +94,4 @@ dcs_row(5) legend("⇪", size=9) key(); } */ // example layout -/* preonic_default("dcs"); */ \ No newline at end of file +/* preonic_default("dcs"); */ diff --git a/src/key.scad b/src/key.scad index d1efedd..cc79f64 100644 --- a/src/key.scad +++ b/src/key.scad @@ -5,7 +5,8 @@ include include include include -include +include +include include @@ -15,10 +16,10 @@ use use use - /* [Hidden] */ SMALLEST_POSSIBLE = 1/128; -$fs = .1; +// basically disable $fs - though it might be useful for these CGAL problems +$fs = .01; $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 @@ -28,197 +29,31 @@ module shape(thickness_difference, depth_difference=0){ } } -// 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() { - dished(-$minkowski_radius, $inverted_dish) { - color($primary_color) minkowski(){ - // half minkowski in the z direction - color($primary_color) shape_hull($minkowski_radius * 2, $minkowski_radius/2, $inverted_dish ? 2 : 0); - /* cube($minkowski_radius); */ - sphere(r=$minkowski_radius, $fn=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() { +module rounded_shape() { color($primary_color) minkowski(){ // half minkowski in the z direction shape($minkowski_radius * 2, $minkowski_radius/2); - difference(){ - sphere(r=$minkowski_radius, $fn=20); - translate([0,0,-$minkowski_radius]){ - cube($minkowski_radius * 2, center=true); - } - } + minkowski_object(); } -} */ +} +// minkowski places this object at every vertex of the other object then mashes +// it all together +module minkowski_object() { + // alternative minkowski shape that needs the bottom of the keycap to be trimmed + /* sphere(1); */ - -// basic key shape, no dish, no inside -// which is only used for dishing to cut the dish off correctly -// $height_difference used for keytop thickness -// extra_slices is a hack to make inverted dishes still work -module shape_hull(thickness_difference, depth_difference, extra_slices = 0){ - render() { - if ($skin_extrude_shape) { - skin_extrude_shape_hull(thickness_difference, depth_difference, extra_slices); - } else if ($linear_extrude_shape) { - linear_extrude_shape_hull(thickness_difference, depth_difference, extra_slices); - } else { - hull_shape_hull(thickness_difference, depth_difference, extra_slices); + difference(){ + sphere(r=$minkowski_radius, $fa=360/$minkowski_facets); + translate([0,0,-$minkowski_radius]){ + cube($minkowski_radius * 2, center=true); } } } -// 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 - ) - ) - ); - -// corollary is hull_shape_hull -// extra_slices unused, only to match argument signatures -module linear_extrude_shape_hull(thickness_difference, depth_difference, extra_slices = 0){ - height = $total_depth - depth_difference; - width_scale = top_total_key_width() / total_key_width(); - height_scale = top_total_key_height() / total_key_height(); - - translate([0,$linear_extrude_height_adjustment,0]){ - linear_extrude(height = height, scale = [width_scale, height_scale]) { - translate([0,-$linear_extrude_height_adjustment,0]){ - key_shape( - [total_key_width(thickness_difference), total_key_height(thickness_difference)], - [$width_difference, $height_difference] - ); - } - } - } -} - -module 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){ - key_shape( - [ - total_key_width(thickness_difference), - total_key_height(thickness_difference) - ], - [$width_difference, $height_difference], - progress - ); - } - } - } -} - -// for when you want something to only exist inside the keycap. -// used for the support structure -module inside() { - intersection() { - shape($wall_thickness, $keytop_thickness); - children(); - } -} - -// for when you want something to only exist outside the keycap -module outside() { - difference() { - children(); - shape($wall_thickness, $keytop_thickness); - } -} - -// put something at the top of the key, with no adjustments for dishing -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; - - 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(); - } - } -} - -module front_placement() { - // 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 - // of the keycap to find the angle so we can rotate things correctly into place - total_depth_difference = sin(-$top_tilt) * (top_total_key_height()/2); - total_height_difference = $top_skew + (1 - cos(-$top_tilt)) * (top_total_key_height()/2); - - angle = atan2(($total_depth - total_depth_difference), ($height_difference/2 + total_height_difference)); - hypotenuse = ($total_depth -total_depth_difference) / sin(angle); - - translate([0,-total_key_height()/2,0]) { - rotate([-(90-angle), 0, 0]) { - translate([0,0,hypotenuse/2]){ - children(); - } - } - } -} - -// just to DRY up the code -module _dish() { - color($secondary_color) dish(top_total_key_width() + $dish_overdraw_width, top_total_key_height() + $dish_overdraw_height, $dish_depth, $inverted_dish); -} module envelope(depth_difference=0) { s = 1.5; @@ -230,18 +65,6 @@ module envelope(depth_difference=0) { } } -// I think this is unused -module dished_for_show() { - difference(){ - union() { - envelope(); - if ($inverted_dish) top_placement(0) _dish(); - } - if (!$inverted_dish) top_placement(0) _dish(); - } -} - - // for when you want to take the dish out of things // used for adding the dish to the key shape and making sure stems don't stick out the top // creates a bounding box 1.5 times larger in width and height than the keycap. @@ -250,15 +73,21 @@ module dished(depth_difference = 0, inverted = false) { children(); difference(){ union() { + // envelope is needed to "fill in" the rest of the keycap envelope(depth_difference); - if (inverted) top_placement(depth_difference) _dish(); + if (inverted) top_placement(depth_difference) _dish(inverted); } - if (!inverted) top_placement(depth_difference) _dish(); + if (!inverted) top_placement(depth_difference) _dish(inverted); } } } -// puts it's children at the center of the dishing on the key, including dish height +// just to DRY up the code +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 @@ -271,16 +100,7 @@ module top_of_key(){ } } -module keytext(text, position, font_size, depth) { - woffset = (top_total_key_width()/3.5) * position[0]; - hoffset = (top_total_key_height()/3.5) * -position[1]; - translate([woffset, hoffset, -depth]){ - color($tertiary_color) linear_extrude(height=$dish_depth){ - text(text=text, font=$font, size=font_size, halign="center", valign="center"); - } - } -} - +// puts its children at each keystem position provided module keystem_positions(positions) { for (connector_pos = positions) { translate(connector_pos) { @@ -306,125 +126,132 @@ module stems_for(positions, stem_type) { } } -// 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); +// put something at the top of the key, with no adjustments for dishing +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; + + 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(); } } } -//approximate (fully depressed) cherry key to check clearances -module clearance_check() { - if($stem_type == "cherry" || $stem_type == "cherry_rounded"){ - color($warning_color){ - translate([0,0,3.6 + $stem_inset - 5]) { - cherry_keyswitch(); +module 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 + // of the keycap to find the angle so we can rotate things correctly into place + total_depth_difference = sin(-$top_tilt) * (top_total_key_height()/2); + total_height_difference = $top_skew + (1 - cos(-$top_tilt)) * (top_total_key_height()/2); + + angle = atan2(($total_depth - total_depth_difference), ($height_difference/2 + total_height_difference)); + hypotenuse = ($total_depth -total_depth_difference) / sin(angle); + + translate([0,-total_key_height()/2,0]) { + rotate([-(90-angle), 0, 0]) { + translate([0,0,hypotenuse/2]){ + children(); } } } } -module legends(depth=0) { - if (len($front_legends) > 0) { - front_placement() { - if (len($front_legends) > 0) { - for (i=[0:len($front_legends)-1]) { - rotate([90,0,0]) keytext($front_legends[i][0], $front_legends[i][1], $front_legends[i][2], depth); - } - } - } - } - if (len($legends) > 0) { - top_of_key() { - // outset legend - if (len($legends) > 0) { - for (i=[0:len($legends)-1]) { - keytext($legends[i][0], $legends[i][1], $legends[i][2], depth); - } - } - } +module outer_shape() { + if ($rounded_key) { + rounded_shape(); + } else { + shape(0, 0); } } -// legends / artisan support -module artisan(depth) { - top_of_key() { - // artisan objects / outset shape legends - color($secondary_color) children(); - } -} - -// key with hollowed inside but no stem -module hollow_key() { - difference(){ - if ($rounded_key) { - rounded_shape(); +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(0, 0); - } - // translation purely for aesthetic purposes, to get rid of that awful lattice - translate([0,0,-SMALLEST_POSSIBLE]) { - shape($wall_thickness, $keytop_thickness); + shape($wall_thickness + extra_wall_thickness, $keytop_thickness + extra_keytop_thickness); } } } +// additive objects at the top of the key +module additive_features(inset) { + top_of_key() { + if($key_bump) keybump($key_bump_depth, $key_bump_edge); + if(!inset && $children > 0) color($secondary_color) children(); + } + if($outset_legends) legends(0); + // render the clearance check if it's enabled, but don't have it intersect with anything + if ($clearance_check) %clearance_check(); +} + +// subtractive objects at the top of the key +module subtractive_features(inset) { + top_of_key() { + if (inset && $children > 0) color($secondary_color) children(); + } + if(!$outset_legends) legends($inset_legend_depth); + // subtract the clearance check if it's enabled, letting the user see the + // parts of the keycap that will hit the cherry switch + if ($clearance_check) %clearance_check(); +} + +module inside_features() { + 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); + } +} // The final, penultimate key generation function. // takes all the bits and glues them together. requires configuration with special variables. -module key(inset = false) { +module key(inset=false) { + difference(){ + union() { + outer_shape(); + additive_features(inset); + } + + difference() { + inner_shape(); + inside_features(); + } + + subtractive_features(inset); + } +} + +module rounded_key(inset=false) { difference() { - union(){ - // the shape of the key, inside and out - hollow_key(); - if($key_bump) top_of_key() keybump($key_bump_depth, $key_bump_edge); - // additive objects at the top of the key - // outside() makes them stay out of the inside. it's a bad name - if(!inset && $children > 0) outside() artisan(0) children(); - if($outset_legends) legends(0); - // render the clearance check if it's enabled, but don't have it intersect with anything - if ($clearance_check) %clearance_check(); - } - - // subtractive objects at the top of the key - // no outside() - I can't think of a use for it. will save render time - if (inset && $children > 0) artisan($inset_legend_depth) children(); - if(!$outset_legends) legends($inset_legend_depth); - // subtract the clearance check if it's enabled, letting the user see the - // parts of the keycap that will hit the cherry switch - if ($clearance_check) %clearance_check(); - } - - // both stem and support are optional - if ($stem_type != "disable" || ($stabilizers != [] && $stabilizer_type != "disable")) { - dished($keytop_thickness, $inverted_dish) { - translate([0, 0, $stem_inset]) { - if ($stabilizer_type != "disable") stems_for($stabilizers, $stabilizer_type); - - if ($stem_type != "disable") stems_for($stem_positions, $stem_type); + minkowski() { + difference() { + outer_shape(); + inner_shape(); } + + minkowski_object(); } + + subtractive_features(inset); } - if ($support_type != "disable"){ - inside() { - translate([0, 0, $stem_inset]) { - if ($stabilizer_type != "disable") support_for($stabilizers, $stabilizer_type); + /* additive_features(inset); */ - // 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); - } - } - } + /* intersection() { + inner_shape($wall_thickness, $keytop_thickness); + inside_features(); + } */ } // actual full key with space carved out and keystem/stabilizer connectors diff --git a/src/libraries/rounded_rectangle_profile.scad b/src/libraries/rounded_rectangle_profile.scad index 935fcaf..b92dd55 100644 --- a/src/libraries/rounded_rectangle_profile.scad +++ b/src/libraries/rounded_rectangle_profile.scad @@ -1,3 +1,21 @@ +function sign_x(i,n) = + i < n/4 || i > n*3/4 ? 1 : + i > n/4 && i < n*3/4 ? -1 : + 0; + +function sign_y(i,n) = + i > 0 && i < n/2 ? 1 : + i > n/2 ? -1 : + 0; + + +function rectangle_profile(size=[1,1],fn=32) = [ + for (index = [0:fn-1]) + let(a = index/fn*360) + sign_x(index, fn) * [size[0]/2,0] + + sign_y(index, fn) * [0,size[1]/2] +]; + function rounded_rectangle_profile(size=[1,1],r=1,fn=32) = [ for (index = [0:fn-1]) let(a = index/fn*360) @@ -6,12 +24,10 @@ function rounded_rectangle_profile(size=[1,1],r=1,fn=32) = [ + 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; +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] +]; diff --git a/src/settings.scad b/src/settings.scad index d2cea59..1d3227a 100644 --- a/src/settings.scad +++ b/src/settings.scad @@ -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 = 1; +$keytop_thickness = 2; // 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 @@ -86,7 +86,7 @@ $extra_long_stem_support = false; // Key shape type, determines the shape of the key. default is 'rounded square' $key_shape_type = "rounded_square"; -// ISO enter needs to be linear extruded NOT from the center. this tells the program how far up 'not from the center' is +// ISO enter needs to be linear extruded NOT from the center when not using skin. this tells the program how far up 'not from the center' is $linear_extrude_height_adjustment = 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 @@ -183,3 +183,16 @@ $secondary_color = [.4412, .7, .3784]; $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; diff --git a/src/shapes.scad b/src/shapes.scad index 005b7de..206727e 100644 --- a/src/shapes.scad +++ b/src/shapes.scad @@ -32,9 +32,11 @@ module key_shape(size, delta, progress = 0) { function skin_key_shape(size, delta, progress = 0, thickness_difference) = $key_shape_type == "rounded_square" ? - skin_rounded_square(size, delta, progress) : + skin_rounded_square(size, delta, progress, thickness_difference) : $key_shape_type == "sculpted_square" ? - skin_sculpted_square_shape(size, delta, progress) : + skin_sculpted_square_shape(size, delta, progress, thickness_difference) : + $key_shape_type == "square" ? + skin_square_shape(size, delta, progress, thickness_difference) : $key_shape_type == "iso_enter" ? skin_iso_enter_shape(size, delta, progress, thickness_difference) : echo("Warning: unsupported $key_shape_type for skin shape. disable skin_extrude_shape or pick a new shape"); diff --git a/src/shapes/rounded_square.scad b/src/shapes/rounded_square.scad index 4152239..7012b21 100644 --- a/src/shapes/rounded_square.scad +++ b/src/shapes/rounded_square.scad @@ -1,12 +1,12 @@ include <../libraries/rounded_rectangle_profile.scad> module rounded_square_shape(size, delta, progress, center = true) { - offset(r=$corner_radius){ + offset(r=$corner_radius, $fa=360/$shape_facets){ square_shape([size.x - $corner_radius*2, size.y - $corner_radius*2], delta, progress); } } // for skin -function skin_rounded_square(size, delta, progress) = - rounded_rectangle_profile(size - (delta * progress), fn=36, r=$corner_radius); +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); diff --git a/src/shapes/sculpted_square.scad b/src/shapes/sculpted_square.scad index 6b82779..6eaf9dc 100644 --- a/src/shapes/sculpted_square.scad +++ b/src/shapes/sculpted_square.scad @@ -37,7 +37,7 @@ module sculpted_square_shape(size, delta, progress) { height - extra_height_this_slice ]; - offset(r = extra_corner_radius_this_slice) { + 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); } @@ -46,7 +46,7 @@ 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) = +function skin_sculpted_square_shape(size, delta, progress, thickness_difference) = let( width = size[0], height = size[1], @@ -64,10 +64,10 @@ function skin_sculpted_square_shape(size, delta, progress) = extra_corner_radius_this_slice = ($corner_radius + extra_corner_size), square_size = [ - width - extra_width_this_slice, - height - extra_height_this_slice + width - extra_width_this_slice - thickness_difference, + height - extra_height_this_slice - thickness_difference ] - ) 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=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) { @@ -85,10 +85,10 @@ module side_rounded_square(size, r) { sw = iw / resolution; union() { if (sr > 0) { - 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); + translate([-iw/2, 0]) scale([sr, sh]) circle(d = resolution, $fa=360/$shape_facets); + translate([iw/2, 0]) scale([sr, sh]) circle(d = resolution, $fa=360/$shape_facets); + translate([0, -ih/2]) scale([sw, sr]) circle(d = resolution, $fa=360/$shape_facets); + translate([0, ih/2]) scale([sw, sr]) circle(d = resolution, $fa=360/$shape_facets); } square([iw, ih], center=true); } diff --git a/src/shapes/square.scad b/src/shapes/square.scad index 7d794c9..27a5d03 100644 --- a/src/shapes/square.scad +++ b/src/shapes/square.scad @@ -1,4 +1,6 @@ use <../functions.scad> +include <../libraries/rounded_rectangle_profile.scad> + // 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. @@ -28,3 +30,17 @@ module flat_sided_square_shape(size, delta, progress) { [(-size.x + (delta.x - extra_keytop_length_for_flat_sides()) * progress)/2, (size.y - delta.y * progress)/2] ]); } + +function skin_square_shape(size, delta, progress, thickness_difference) = + let( + width = size[0], + height = size[1], + + width_difference = delta[0] * progress, + height_difference = delta[1] * progress, + + square_size = [ + width - width_difference - thickness_difference, + height - height_difference - thickness_difference + ] + ) rectangle_profile(square_size, fn=36);