From f3c70d3741269eca6c795cd529a37d3b78c691dd Mon Sep 17 00:00:00 2001 From: Revar Desmera Date: Sun, 30 Jul 2023 22:45:15 -0700 Subject: [PATCH 1/5] Corrected modang() example. --- math.scad | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/math.scad b/math.scad index a273999..8cc9587 100644 --- a/math.scad +++ b/math.scad @@ -602,12 +602,12 @@ function posmod(x,m) = // Description: // Takes an angle in degrees and normalizes it to an equivalent angle value between -180 and 180. // Example: -// a1 = modang(-700,360); // Returns: 20 -// a2 = modang(-270,360); // Returns: 90 -// a3 = modang(-120,360); // Returns: -120 -// a4 = modang(120,360); // Returns: 120 -// a5 = modang(270,360); // Returns: -90 -// a6 = modang(700,360); // Returns: -20 +// a1 = modang(-700); // Returns: 20 +// a2 = modang(-270); // Returns: 90 +// a3 = modang(-120); // Returns: -120 +// a4 = modang(120); // Returns: 120 +// a5 = modang(270); // Returns: -90 +// a6 = modang(700); // Returns: -20 function modang(x) = assert( is_finite(x), "Input must be a finite number.") let(xx = posmod(x,360)) xx<180? xx : xx-360; From 1ae1c3cf0f4953c510c3ae2b35f7ed5122109e7d Mon Sep 17 00:00:00 2001 From: Revar Desmera Date: Mon, 31 Jul 2023 01:40:49 -0700 Subject: [PATCH 2/5] Improvements to _gear_tooth_profile() --- gears.scad | 78 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 55 insertions(+), 23 deletions(-) diff --git a/gears.scad b/gears.scad index 47cbc50..183ad77 100644 --- a/gears.scad +++ b/gears.scad @@ -2280,19 +2280,22 @@ function _gear_tooth_profile( brad = _base_radius(circ_pitch, teeth, pressure_angle, helical=helical), rrad = _root_radius(circ_pitch, teeth, clearance, helical=helical, profile_shift=profile_shift, internal=internal), + adendum = _adendum(circ_pitch=circ_pitch, profile_shift=profile_shift), + dedendum = _dedendum(circ_pitch=circ_pitch, clearance=clearance, profile_shift=profile_shift), + clear = abs(dedendum-adendum), + srad = max(rrad,brad), - clear = default(clearance, circ_pitch/PI * 0.25), tthick = circ_pitch/PI / cos(helical) * (PI/2 + 2*profile_shift * tan(pressure_angle)) - backlash, tang = tthick / prad / 2 * 180 / PI, // Generate a lookup table for the involute curve angles, by radius involute_lup = [ - if (rrad < brad) - each xy_to_polar(arc(n=4, r=min(brad-rrad,clear), corner=[ - polar_to_xy(rrad,90+180/teeth), - polar_to_xy(rrad,90), - polar_to_xy(brad,90), - ])), + if (clear > 0 && false) + each xy_to_polar( + arc(n=16, r=clear, corner=[ + [-0.1,rrad], [0,rrad], [0,rrad+clear] + ]) + ), for (i=[0:5:arad/PI/brad*360]) let( xy = _involute(brad,i), @@ -2335,10 +2338,7 @@ function _gear_tooth_profile( undercut_lup = [for (i=idx(undercut)) if (i>=uc_min) undercut[i]], // The u values to use when generating the tooth. - us = [ - for (i=[0.0:0.02:0.2-EPSILON]) i, - for (i=[0:1:steps-1]) 0.2 + i/(steps-1)*0.8, - ], + us = [for (i=[0:1:steps*2]) i/steps/2], // Find top of undercut. undercut_max = max([ @@ -2354,15 +2354,41 @@ function _gear_tooth_profile( // Generate the left half of the tooth. tooth_half_raw = deduplicate([ - for (u = us) let( - r = lerp(rrad, ma_rad, u), - a1 = lookup(r, involute_lup) + soff, - a2 = lookup(r, undercut_lup), - a = internal || r < undercut_lup[0].x? a1 : min(a1,a2) - ) if(a<90+180/teeth) polar_to_xy(r, a), - for (i=[0:1:cap_steps-1]) let( - a = ma_ang + soff - i * (cap_step-1) - ) polar_to_xy(ma_rad, a), + for (u = us) + let( + r = lerp(rrad, ma_rad, u), + a1 = lookup(r, involute_lup) + soff, + a2 = lookup(r, undercut_lup), + a = internal || r < undercut_lup[0].x? a1 : min(a1,a2) + ) + if( internal || r > (rrad+clear) ) + if(!internal || r < (ma_rad-clear) ) + if(a<90+180/teeth) + polar_to_xy(r, a), + if (!internal) + for (i=[0:1:cap_steps-1]) let( + a = ma_ang + soff - i * (cap_step-1) + ) polar_to_xy(ma_rad, a), + ]), + + // Round out the clearance valley + rcircum = 2 * PI * (internal? ma_rad : rrad), + rpart = (180/teeth-tang)/360, + round_r = min(clear, rcircum*rpart), + line1 = internal + ? select(tooth_half_raw,-2,-1) + : select(tooth_half_raw,0,1), + line2 = internal + ? [[0,ma_rad],[-1,ma_rad]] + : zrot(180/teeth, p=[[0,rrad],[1,rrad]]), + isect_pt = line_intersection(line1,line2), + rcorner = internal + ? [last(line1), isect_pt, line2[0]] + : [line2[0], isect_pt, line1[0]], + rounded_tooth_half = deduplicate([ + if (!internal) each arc(n=8, r=round_r, corner=rcorner), + each tooth_half_raw, + if (internal) each arc(n=8, r=round_r, corner=rcorner), ]), // Strip "jaggies" if found. @@ -2381,14 +2407,20 @@ function _gear_tooth_profile( mti = !angs? 0 : min_index(angs), out = concat([path[i]], strip_left(path, i + mti + 1)) ) out, - tooth_half = !undercut_max? tooth_half_raw : - strip_left(tooth_half_raw, 0), + tooth_half = !undercut_max? rounded_tooth_half : + strip_left(rounded_tooth_half, 0), // Mirror the tooth to complete it. - tooth = deduplicate([ + full_tooth = deduplicate([ each tooth_half, each reverse(xflip(tooth_half)), ]), + + // Reduce number of vertices. + tooth = path_merge_collinear( + resample_path(full_tooth, n=ceil(2*steps), closed=false), + ), + out = center? fwd(prad, p=tooth) : tooth ) out; From 9233197a6c7b91f0acc11b2db5c7827cd031b7b5 Mon Sep 17 00:00:00 2001 From: Revar Desmera Date: Mon, 31 Jul 2023 02:08:30 -0700 Subject: [PATCH 3/5] Gear tooth profile clearance value bugfix. --- gears.scad | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/gears.scad b/gears.scad index 183ad77..11fc00d 100644 --- a/gears.scad +++ b/gears.scad @@ -2282,7 +2282,8 @@ function _gear_tooth_profile( adendum = _adendum(circ_pitch=circ_pitch, profile_shift=profile_shift), dedendum = _dedendum(circ_pitch=circ_pitch, clearance=clearance, profile_shift=profile_shift), - clear = abs(dedendum-adendum), + mod = module_value(circ_pitch=circ_pitch), + clear = default(clearance, 0.25 * mod), srad = max(rrad,brad), tthick = circ_pitch/PI / cos(helical) * (PI/2 + 2*profile_shift * tan(pressure_angle)) - backlash, @@ -2290,12 +2291,6 @@ function _gear_tooth_profile( // Generate a lookup table for the involute curve angles, by radius involute_lup = [ - if (clear > 0 && false) - each xy_to_polar( - arc(n=16, r=clear, corner=[ - [-0.1,rrad], [0,rrad], [0,rrad+clear] - ]) - ), for (i=[0:5:arad/PI/brad*360]) let( xy = _involute(brad,i), @@ -2361,9 +2356,9 @@ function _gear_tooth_profile( a2 = lookup(r, undercut_lup), a = internal || r < undercut_lup[0].x? a1 : min(a1,a2) ) - if( internal || r > (rrad+clear) ) - if(!internal || r < (ma_rad-clear) ) - if(a<90+180/teeth) + if ( internal || r > (rrad+clear) ) + if (!internal || r < (ma_rad-clear) ) + if (a < 90+180/teeth) polar_to_xy(r, a), if (!internal) for (i=[0:1:cap_steps-1]) let( From fdb5355b306db8cbcdadd6b392c52f680c717829 Mon Sep 17 00:00:00 2001 From: Revar Desmera Date: Mon, 31 Jul 2023 02:37:53 -0700 Subject: [PATCH 4/5] Removed an evil extra comma. --- gears.scad | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gears.scad b/gears.scad index 11fc00d..01a1671 100644 --- a/gears.scad +++ b/gears.scad @@ -2413,7 +2413,7 @@ function _gear_tooth_profile( // Reduce number of vertices. tooth = path_merge_collinear( - resample_path(full_tooth, n=ceil(2*steps), closed=false), + resample_path(full_tooth, n=ceil(2*steps), closed=false) ), out = center? fwd(prad, p=tooth) : tooth From 8c8912ae29f0a2a1036b8c68604ed628fe204d4b Mon Sep 17 00:00:00 2001 From: Revar Desmera Date: Mon, 31 Jul 2023 03:10:41 -0700 Subject: [PATCH 5/5] Minor code cleanup in gears.scad --- gears.scad | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/gears.scad b/gears.scad index 01a1671..99403a6 100644 --- a/gears.scad +++ b/gears.scad @@ -2273,6 +2273,8 @@ function _gear_tooth_profile( steps = 16, circ_pitch = circular_pitch(pitch=pitch, circ_pitch=circ_pitch, diam_pitch=diam_pitch, mod=mod), + mod = module_value(circ_pitch=circ_pitch), + clear = default(clearance, 0.25 * mod), // Calculate the important circle radii arad = outer_radius(circ_pitch, teeth, helical=helical, profile_shift=profile_shift, internal=internal), @@ -2280,11 +2282,6 @@ function _gear_tooth_profile( brad = _base_radius(circ_pitch, teeth, pressure_angle, helical=helical), rrad = _root_radius(circ_pitch, teeth, clearance, helical=helical, profile_shift=profile_shift, internal=internal), - adendum = _adendum(circ_pitch=circ_pitch, profile_shift=profile_shift), - dedendum = _dedendum(circ_pitch=circ_pitch, clearance=clearance, profile_shift=profile_shift), - mod = module_value(circ_pitch=circ_pitch), - clear = default(clearance, 0.25 * mod), - srad = max(rrad,brad), tthick = circ_pitch/PI / cos(helical) * (PI/2 + 2*profile_shift * tan(pressure_angle)) - backlash, tang = tthick / prad / 2 * 180 / PI,