From: daniel watson Date: Sat, 1 Apr 2017 23:43:46 +0000 (-0700) Subject: use law of cosines to make smoother curve between arms X-Git-Url: http://challenge-bot.com/repos/?p=ozzloy%40gmail.com%2F3d-printables;a=commitdiff_plain;h=85cda07f23b81f574feaaa33b290b8eed3739954 use law of cosines to make smoother curve between arms --- diff --git a/spin-data.scad b/spin-data.scad index e25eed3..57e3b2d 100644 --- a/spin-data.scad +++ b/spin-data.scad @@ -121,7 +121,6 @@ module spin_slice(weight_radius, arms) { joiner_radius = (bearing_radius + weight_radius) / 2; - bearing_xy = [0, 0]; // a = side along x axis a = bearing_radius + weight_radius + wall; // b = side from center to joiner @@ -129,11 +128,11 @@ module spin_slice(weight_radius, // c = side between joiner and arm center c = joiner_radius + weight_radius + round_extra; - weight_xy = [a, 0]; - cos_C = (pow(a, 2) + pow(b, 2) - pow(c, 2)) / (2 * a * b); sin_C = sqrt(1 - pow(cos_C, 2)); + bearing_xy = [0, 0]; + weight_xy = [a, 0]; joiner_xy = [cos_C, sin_C] * b; for(arm = [0 : arms - 1]) { @@ -150,6 +149,66 @@ module spin_slice(weight_radius, translate(joiner_xy) { circle(joiner_radius); } } } } } } +module spin_cosine_slice(weight_radius, + bearing_radius, + round_extra, + wall, + arms) { + /* in order to make a smooth transition from one arm to the next, + follow the path of a circle just barely touching both arms and + the center circle. this is referred to as the joiner circle. + + the joiner circle's radius and position are calculated using + geometry. the center of the bearing, weight and joiner circle + create a triangle. + + a = side between bearing and weight centers + b = side between bearing and joiner centers + c = side between joiner and weight centers + + A = angle opposite a, inside joiner + B = angle opposite b, inside weight + C = angle opposite c, inside bearing + */ + + r0 = bearing_radius; + r1 = weight_radius; + // slightly cheated. calculated using 3 arms, C = 60. + r2 = ((pow(r0, 2) + + r0 * wall + + r0 * r1 + + pow(wall, 2) + + 2 * r1 * wall + + r0 * round_extra + - wall * round_extra + - 3 * r1 * round_extra) + / (3 * r1 + wall - r0)); + + joiner_radius = r2; + + // a = side along x axis + a = r0 + wall + r1; + // b = side from center to joiner + b = r0 + round_extra + r2; + // c = side between joiner and arm center + c = r1 + round_extra + r2; + + bearing_xy = [0, 0]; + weight_xy = [a, 0]; + joiner_xy = [cos(60), sin(60)] * b; + + translate(bearing_xy) { + circle(bearing_radius + round_extra); } + for(arm = [0 : arms - 1]) { + rotate(arm * (360 / arms)) { + translate(weight_xy) { + circle(weight_radius + round_extra); } + mirrored([0, 1]) { + difference() { + polygon([bearing_xy, weight_xy, joiner_xy]); + translate(joiner_xy) { + circle(joiner_radius); } } } } } } + module spin_slices(weight_radius, weight_thickness, bearing_radius, @@ -221,6 +280,77 @@ module spin_slices(weight_radius, r = weight_radius + 0.15, center = true); } } } } } +module spin_cosine(weight_radius, + weight_thickness, + bearing_radius, + bearing_thickness, + weight_lip_overhang = 0.3, + bearing_lip_overhang = 0.3, + wall = 3, + arms = 3, + layer_height = 0.15) { + thicker_thickness = (bearing_thickness > weight_thickness) ? + bearing_thickness : weight_thickness; + calculated_height = thicker_thickness + 2 * wall; + layers = 2 * ceil(ceil(calculated_height / layer_height) / 2); + actual_height = layers * layer_height; + round_radius = actual_height / 2; + + /* rounding the outside edge of the spinner with a semi-circle leads + to a shape that an overhang on the second layer several times the + thickness of a printed extrusion width. + + rather than using a full semi-circle, this code aims to use just the + portion in the middle, where the overhang is less severe */ + old_start = 0; + old_end = (layers / 2) - 1; + + /* add one to have some thickness all around weight holes + for first layer */ + new_start = old_end / 16 + 1; + new_end = old_end; + + old_range = old_end - old_start; + new_range = new_end - new_start; + + factor = new_range / old_range; + + /* initial adjacent is adjusted to (new start - 1) to allow some + thickness all around weight holes on first layer */ + initial_adjacent = round_radius - ((new_start - 1) * layer_height); + initial_angle = acos(initial_adjacent / round_radius); + initial_round_extra = initial_adjacent * tan(initial_angle); + + difference() { + mirrored([0, 0, 1]) { + for(layer = [0 : (layers / 2) - 1]) { + translate([0, 0, layer * layer_height - actual_height / 2]) { + linear_extrude(height = layer_height) { + new_layer = (layer - old_start) * factor + new_start; + adjacent = round_radius - (new_layer * layer_height); + angle = acos(adjacent / round_radius); + round_extra = adjacent * tan(angle) - initial_round_extra; + spin_cosine_slice(weight_radius, + bearing_radius, + round_extra, + wall, + arms); } } } } + cylinder(h = actual_height + 0.1, + r = bearing_radius - bearing_lip_overhang, + center = true); + cylinder(h = bearing_thickness + 0.05, + r = bearing_radius + 0.15, + center = true); + for(arm = [0 : arms - 1]) { + rotate(arm * (360 / arms)) { + translate([bearing_radius + wall + weight_radius, 0]) { + cylinder(h = actual_height + 0.1, + r = weight_radius - weight_lip_overhang, + center = true); + cylinder(h = weight_thickness + 0.05, + r = weight_radius + 0.15, + center = true); } } } } } + module spin_donut(weight_radius, weight_thickness, bearing_radius, diff --git a/spin.scad b/spin.scad index 37b74f0..d72e2dd 100644 --- a/spin.scad +++ b/spin.scad @@ -2,9 +2,9 @@ see bottom for more license info */ /* spin thing that erin likes */ -include +include -object = "spin_slices"; +object = "spin_cosine"; if (object == "spin_slices") { spin_slices(weight_radius, @@ -25,6 +25,15 @@ else if (object == "spin_donut") { bearing_lip_overhang, wall, arms); } +else if (object == "spin_cosine") { + spin_cosine(weight_radius, + weight_thickness, + bearing_radius, + bearing_thickness, + weight_lip_overhang, + bearing_lip_overhang, + wall, + arms); } else if (object == "cap") { cap(bearing_inner_radius, bearing_cap_footprint_radius,