Merge pull request #1006 from adrianVmariano/master

spiral_sweep fixes
This commit is contained in:
Revar Desmera 2022-12-14 21:04:43 -08:00 committed by GitHub
commit 1257b9b936
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 98 additions and 78 deletions

View file

@ -117,7 +117,7 @@ module pco1810_neck(wall=2, anchor="support-ring", spin=0, orient=UP)
thread_depth=thread_h+0.1, thread_depth=thread_h+0.1,
flank_angle=flank_angle, flank_angle=flank_angle,
turns=810/360, turns=810/360,
higbee=thread_h*2, taper=-thread_h*2,
anchor=TOP anchor=TOP
); );
zrot_copies(rots=[90,270]) { zrot_copies(rots=[90,270]) {
@ -190,7 +190,7 @@ module pco1810_cap(wall=2, texture="none", anchor=BOTTOM, spin=0, orient=UP)
} }
up(wall) cyl(d=cap_id, h=tamper_ring_h+wall, anchor=BOTTOM); up(wall) cyl(d=cap_id, h=tamper_ring_h+wall, anchor=BOTTOM);
} }
up(wall+2) thread_helix(d=thread_od-thread_depth*2, pitch=thread_pitch, thread_depth=thread_depth, flank_angle=flank_angle, turns=810/360, higbee=thread_depth, internal=true, anchor=BOTTOM); up(wall+2) thread_helix(d=thread_od-thread_depth*2, pitch=thread_pitch, thread_depth=thread_depth, flank_angle=flank_angle, turns=810/360, taper=-thread_depth, internal=true, anchor=BOTTOM);
} }
children(); children();
} }
@ -306,7 +306,7 @@ module pco1881_neck(wall=2, anchor="support-ring", spin=0, orient=UP)
thread_depth=thread_h+0.1, thread_depth=thread_h+0.1,
flank_angle=flank_angle, flank_angle=flank_angle,
turns=650/360, turns=650/360,
higbee=thread_h*2, taper=-thread_h*2,
anchor=TOP anchor=TOP
); );
zrot_copies(rots=[90,270]) { zrot_copies(rots=[90,270]) {
@ -371,7 +371,7 @@ module pco1881_cap(wall=2, texture="none", anchor=BOTTOM, spin=0, orient=UP)
} }
up(wall) cyl(d=28.58, h=11.2+wall, anchor=BOTTOM); up(wall) cyl(d=28.58, h=11.2+wall, anchor=BOTTOM);
} }
up(wall+2) thread_helix(d=25.5, pitch=2.7, thread_depth=1.6, flank_angle=15, turns=650/360, higbee=1.6, internal=true, anchor=BOTTOM); up(wall+2) thread_helix(d=25.5, pitch=2.7, thread_depth=1.6, flank_angle=15, turns=650/360, taper=-1.6, internal=true, anchor=BOTTOM);
} }
children(); children();
} }
@ -475,7 +475,7 @@ module generic_bottle_neck(
thread_depth = thread_h + 0.1 * diamMagMult, thread_depth = thread_h + 0.1 * diamMagMult,
flank_angle = flank_angle, flank_angle = flank_angle,
turns = (height - pitch - lip_roundover_r) * .6167 / pitch, turns = (height - pitch - lip_roundover_r) * .6167 / pitch,
higbee = thread_h * 2, taper = -thread_h * 2,
anchor = TOP anchor = TOP
); );
zrot_copies(rots = [90, 270]) { zrot_copies(rots = [90, 270]) {
@ -578,7 +578,8 @@ module generic_bottle_cap(
} }
difference(){ difference(){
up(wall + pitch / 2) { up(wall + pitch / 2) {
thread_helix(d = neckOuterDTol, pitch = pitch, thread_depth = threadDepth, flank_angle = flank_angle, turns = ((height - pitch) / pitch), higbee = threadDepth, internal = true, anchor = BOTTOM); thread_helix(d = neckOuterDTol, pitch = pitch, thread_depth = threadDepth, flank_angle = flank_angle,
turns = ((height - pitch) / pitch), taper = -threadDepth, internal = true, anchor = BOTTOM);
} }
} }
} }
@ -1100,8 +1101,7 @@ module sp_neck(diam,type,wall,id,style="L",bead=false, anchor, spin, orient)
profile = _sp_thread_profile(tpi,a,S,style); profile = _sp_thread_profile(tpi,a,S,style);
depth = a/2; depth = a/2;
higlen = 2*a; taperlen = 2*a;
higang = higlen / ((T-2*depth)*PI) * 360;
beadmax = type==400 ? (T/2-depth)+depth*1.25 beadmax = type==400 ? (T/2-depth)+depth*1.25
: diam <=15 ? (T-.15)/2 : (T-.05)/2; : diam <=15 ? (T-.15)/2 : (T-.05)/2;
@ -1126,7 +1126,7 @@ module sp_neck(diam,type,wall,id,style="L",bead=false, anchor, spin, orient)
up((H+extra_bot)/2){ up((H+extra_bot)/2){
difference(){ difference(){
union(){ union(){
thread_helix(d=T-.01, profile=profile, pitch = INCH/tpi, turns=(twist+2*higang)/360, higbee=higlen, anchor=TOP); thread_helix(d=T-.01, profile=profile, pitch = INCH/tpi, turns=twist/360, taper=taperlen, anchor=TOP);
cylinder(d=T-depth*2,l=H,anchor=TOP); cylinder(d=T-depth*2,l=H,anchor=TOP);
if (bead) if (bead)
down(bead_shift) down(bead_shift)
@ -1144,7 +1144,7 @@ module sp_neck(diam,type,wall,id,style="L",bead=false, anchor, spin, orient)
// Module: sp_cap() // Module: sp_cap()
// Usage: // Usage:
// sp_cap(diam, type, wall, [style=], [top_adj=], [bot_adj=], [$slop]) [ATTACHMENTS]; // sp_cap(diam, type, wall, [style=], [top_adj=], [bot_adj=], [texture=], [$slop]) [ATTACHMENTS];
// Description: // Description:
// Make a SPI (Society of Plastics Industry) threaded bottle neck. You must // Make a SPI (Society of Plastics Industry) threaded bottle neck. You must
// supply the nominal outer diameter of the threads and the thread type, one of // supply the nominal outer diameter of the threads and the thread type, one of
@ -1175,6 +1175,7 @@ module sp_neck(diam,type,wall,id,style="L",bead=false, anchor, spin, orient)
// style = Either "L" or "M" to specify the thread style. Default: "L" // style = Either "L" or "M" to specify the thread style. Default: "L"
// top_adj = Amount to reduce top space in the cap, which means it doesn't screw down as far. Default: 0 // top_adj = Amount to reduce top space in the cap, which means it doesn't screw down as far. Default: 0
// bot_adj = Amount to reduce extension of cap at the bottom, which also means it doesn't screw down as far. Default: 0 // bot_adj = Amount to reduce extension of cap at the bottom, which also means it doesn't screw down as far. Default: 0
// texture = texture for outside of cap, one of "knurled", "ribbed" or "none. Default: "none"
// $slop = Increase inner diameter by `2 * $slop`. // $slop = Increase inner diameter by `2 * $slop`.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER` // anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0` // spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
@ -1183,7 +1184,7 @@ module sp_neck(diam,type,wall,id,style="L",bead=false, anchor, spin, orient)
// sp_cap(48,400,2); // sp_cap(48,400,2);
// sp_cap(22,410,2); // sp_cap(22,410,2);
// sp_cap(28,415,1.5,style="M"); // sp_cap(28,415,1.5,style="M");
module sp_cap(diam,type,wall,style="L",top_adj=0, bot_adj=0, anchor, spin, orient) module sp_cap(diam,type,wall,style="L",top_adj=0, bot_adj=0, texture="none", anchor, spin, orient)
{ {
table = struct_val(_sp_specs,type); table = struct_val(_sp_specs,type);
dum1=assert(is_def(table),"Unknown SP closure type. Type must be one of 400, 410, or 415"); dum1=assert(is_def(table),"Unknown SP closure type. Type must be one of 400, 410, or 415");
@ -1206,20 +1207,24 @@ module sp_cap(diam,type,wall,style="L",top_adj=0, bot_adj=0, anchor, spin, orien
profile = fwd(-bounds[0].y,yflip(oprofile)); profile = fwd(-bounds[0].y,yflip(oprofile));
depth = a/2; depth = a/2;
higlen = 2*a; taperlen = 2*a;
higang = higlen / ((T-2*depth)*PI) * 360; assert(in_list(texture, ["none","knurled","ribbed"]));
echo(a=a,depth=depth,halfdepth=depth/2, tpi*pointlist_bounds(profile));
space=2*depth/10+2*get_slop(); space=2*depth/10+2*get_slop();
attachable(anchor,spin,orient,r= (T+space)/2+wall, l=H-bot_adj+wall){ attachable(anchor,spin,orient,r= (T+space)/2+wall, l=H-bot_adj+wall){
xrot(180) xrot(180)
up((H-bot_adj)/2-wall/2){ up((H-bot_adj)/2-wall/2){
difference(){ difference(){
up(wall)cyl(d=T+space+2*wall,l=H+wall-bot_adj,anchor=TOP,chamfer2=.8); up(wall){
if (texture=="knurled")
cyl(d=T+space+2*wall,l=H+wall-bot_adj,anchor=TOP,texture="trunc_pyramids", tex_size=[3,3], tex_style="convex");
else if (texture == "ribbed")
cyl(d=T+space+2*wall,l=H+wall-bot_adj,anchor=TOP,chamfer2=.8,tex_taper=0,texture="trunc_ribs", tex_size=[3,3], tex_style="min_edge");
else
cyl(d=T+space+2*wall,l=H+wall-bot_adj,anchor=TOP,chamfer2=.8);
}
cyl(d=T+space, l=H-bot_adj+1, anchor=TOP); cyl(d=T+space, l=H-bot_adj+1, anchor=TOP);
} }
thread_helix(d=T+space-.01, profile=profile, pitch = INCH/tpi, turns=(twist+2*higang)/360, higbee=higlen, anchor=TOP, internal=true); thread_helix(d=T+space-.01, profile=profile, pitch = INCH/tpi, turns=twist/360, taper=taperlen, anchor=TOP, internal=true);
} }
children(); children();
} }

101
skin.scad
View file

@ -991,8 +991,8 @@ module rotate_sweep(
// Function&Module: spiral_sweep() // Function&Module: spiral_sweep()
// Usage: As Module // Usage: As Module
// spiral_sweep(poly, h, r|d=, turns, [higbee=], [center=], [higbee1=], [higbee2=], [internal=], ...)[ATTACHMENTS]; // spiral_sweep(poly, h, r|d=, turns, [taper=], [center=], [taper1=], [taper2=], [internal=], ...)[ATTACHMENTS];
// spiral_sweep(poly, h, r1=|d1=, r2=|d2=, turns, [higbee=], [center=], [higbee1=], [higbee2=], [internal=], ...)[ATTACHMENTS]; // spiral_sweep(poly, h, r1=|d1=, r2=|d2=, turns, [taper=], [center=], [taper1=], [taper2=], [internal=], ...)[ATTACHMENTS];
// Usage: As Function // Usage: As Function
// vnf = spiral_sweep(poly, h, r|d=, turns, ...); // vnf = spiral_sweep(poly, h, r|d=, turns, ...);
// vnf = spiral_sweep(poly, h, r1=|d1=, r1=|d2=, turns, ...); // vnf = spiral_sweep(poly, h, r1=|d1=, r1=|d2=, turns, ...);
@ -1002,19 +1002,22 @@ module rotate_sweep(
// of a given radius, height and degrees of rotation. The origin in the profile traces out the helix of the specified radius. // of a given radius, height and degrees of rotation. The origin in the profile traces out the helix of the specified radius.
// If turns is positive the path will be right-handed; if turns is negative the path will be left-handed. // If turns is positive the path will be right-handed; if turns is negative the path will be left-handed.
// . // .
// Higbee specifies tapering applied to the ends of the extrusion and is given as the linear distance // The taper options specify tapering at of the ends of the extrusion, and are given as the linear distance
// over which to taper. // over which to taper. If taper is positive the extrusion lengthened by the specified distance; if taper
// is negative, the taper is included in the extrusion length specified by `turns`.
// Arguments: // Arguments:
// poly = Array of points of a polygon path, to be extruded. // poly = Array of points of a polygon path, to be extruded.
// h = height of the spiral to extrude along. // h = height of the spiral to extrude along.
// r = Radius of the spiral to extrude along. Default: 50 // r = Radius of the spiral to extrude along.
// turns = number of revolutions to spiral up along the height. // turns = number of revolutions to spiral up along the height.
// --- // ---
// d = Diameter of the spiral to extrude along. // d = Diameter of the spiral to extrude along.
// higbee = Length to taper thread ends over. // d1|r1 = Bottom inside diameter or radius of spiral to extrude along.
// higbee1 = Taper length at start // d2|r2 = Top inside diameter or radius of spiral to extrude along.
// higbee2 = Taper length at end // taper = Length of tapers for thread ends. Positive to add taper to threads, negative to taper within specified length. Default: 0
// internal = direction to taper the threads with higbee. If true threads taper outward; if false they taper inward. Default: false // taper1 = Length of taper for bottom thread end
// taper2 = Length of taper for top thread end
// internal = if true make internal threads. The only effect this has is to change how the extrusion tapers if tapering is selected. When true, the extrusion tapers towards the outside; when false, it tapers towards the inside. Default: false
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER` // anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0` // spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP` // orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
@ -1026,66 +1029,75 @@ module rotate_sweep(
function _taperfunc(x) = function _taperfunc(x) =
let(higofs = pow(0.05,2)) // Smallest hig scale is the square root of this value let(higofs = pow(0.05,2)) // Smallest hig scale is the square root of this value
sqrt((1-higofs)*x+higofs); sqrt((1-higofs)*x+higofs);
function _taperfunc(x) = function _taperfunc_ellipse(x) =
sqrt(1-(1-x)^2); sqrt(1-(1-x)^2);
function _ss_polygon_r(N,theta) = function _ss_polygon_r(N,theta) =
let( alpha = 360/N ) let( alpha = 360/N )
cos(alpha/2)/(cos(posmod(theta,alpha)-alpha/2)); cos(alpha/2)/(cos(posmod(theta,alpha)-alpha/2));
function spiral_sweep(poly, h, r, turns=1, higbee, center, r1, r2, d, d1, d2, higbee1, higbee2, internal=false, anchor=CENTER, spin=0, orient=UP) = function spiral_sweep(poly, h, r, turns=1, taper, center, r1, r2, d, d1, d2, taper1, taper2, internal=false, anchor=CENTER, spin=0, orient=UP) =
assert(is_num(turns) && turns != 0) assert(is_num(turns) && turns != 0)
let( let(
twist = 360*turns, tapersample = 10, // Oversample factor for higbee tapering
higsample = 10, // Oversample factor for higbee tapering dir = sign(turns),
r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=50),
r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=50),
bounds = pointlist_bounds(poly), bounds = pointlist_bounds(poly),
yctr = (bounds[0].y+bounds[1].y)/2, yctr = (bounds[0].y+bounds[1].y)/2,
xmin = bounds[0].x, xmin = bounds[0].x,
xmax = bounds[1].x, xmax = bounds[1].x,
poly = path3d(clockwise_polygon(poly)), poly = path3d(clockwise_polygon(poly)),
anchor = get_anchor(anchor,center,BOT,BOT), anchor = get_anchor(anchor,center,BOT,BOT),
r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=50),
r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=50),
sides = segs(max(r1,r2)), sides = segs(max(r1,r2)),
dir = sign(twist), ang_step = 360/sides,
ang_step = 360/sides*dir, turns = abs(turns),
orig_anglist = [for(ang = [0:ang_step:twist-EPSILON]) ang, taper1 = first_defined([taper1, taper, 0]),
twist], taper2 = first_defined([taper2, taper, 0]),
higbee1 = first_defined([higbee1, higbee, 0]), taperang1 = 360 * abs(taper1) / (2 * r1 * PI),
higbee2 = first_defined([higbee2, higbee, 0]), taperang2 = 360 * abs(taper2) / (2 * r2 * PI),
higang1 = 360 * higbee1 / (2 * r1 * PI), minang = taper1<=0 ? 0 : -taperang1,
higang2 = 360 * higbee2 / (2 * r2 * PI) tapercut1 = taper1<=0 ? taperang1 : 0,
maxang = taper2<=0 ? 360*turns : 360*turns+taperang2,
tapercut2 = taper2<=0 ? 360*turns-taperang2 : 360*turns
) )
assert(higbee1>=0 && higbee2>=0) assert( tapercut1<tapercut2 && tapercut1<maxang, "Tapers are too long to fit")
assert(higang1 < dir*twist/2,"Higbee1 is more than half the threads") assert( all_positive([r1,r2]), "Diameter/radius must be positive")
assert(higang2 < dir*twist/2,"Higbee2 is more than half the threads")
let( let(
// This complicated sampling scheme is designed to ensure that there is always a facet boundary // This complicated sampling scheme is designed to ensure that faceting always starts at angle zero
// at the $fn specified location, regardless of what kind of subsampling occurs for tapers." // for alignment with cylinders, and there is always a facet boundary at the $fn specified locations,
// regardless of what kind of subsampling occurs for tapers.
orig_anglist = [
if (minang<0) minang,
each reverse([for(ang = [-ang_step:-ang_step:minang+EPSILON]) ang]),
for(ang = [0:ang_step:maxang-EPSILON]) ang,
maxang
],
anglist = [ anglist = [
for(a=orig_anglist) if (a*dir<higang1-EPSILON) a, for(a=orig_anglist) if (a<tapercut1-EPSILON) a,
dir*higang1, tapercut1,
for(a=orig_anglist) if (a*dir>higang1+EPSILON && (twist-a)*dir>higang2+EPSILON) a, for(a=orig_anglist) if (a>tapercut1+EPSILON && a<tapercut2-EPSILON) a,
twist-dir*higang2, tapercut2,
for(a=orig_anglist) if ((twist-a)*dir<higang2-EPSILON) a for(a=orig_anglist) if (a>tapercut2+EPSILON) a
], ],
interp_ang = [ interp_ang = [
for(i=idx(anglist,e=-2)) for(i=idx(anglist,e=-2))
each lerpn(anglist[i],anglist[i+1], each lerpn(anglist[i],anglist[i+1],
(higang1>0 && dir*anglist[i+1]<=higang1) || (higang2>0 && dir*(twist-anglist[i])<=higang2) (taper1!=0 && anglist[i+1]<=tapercut1) || (taper2!=0 && anglist[i]>=tapercut2)
? ceil((anglist[i+1]-anglist[i])/ang_step*higsample) ? ceil((anglist[i+1]-anglist[i])/ang_step*tapersample)
: 1, : 1,
endpoint=false), endpoint=false),
last(anglist) last(anglist)
], ],
e=echo(lenlist=len(interp_ang)),
skewmat = affine3d_skew_xz(xa=atan2(r2-r1,h)), skewmat = affine3d_skew_xz(xa=atan2(r2-r1,h)),
points = [ points = [
for (a = interp_ang) let ( for (a = interp_ang) let (
hsc = dir*a<higang1 ? _taperfunc(dir*a/higang1) hsc = a<tapercut1 ? _taperfunc((a-minang)/taperang1)
: dir*(twist-a)<higang2 ? _taperfunc(dir*(twist-a)/higang2) : a>tapercut2 ? _taperfunc((maxang-a)/taperang2)
: 1, : 1,
u = a/twist, u = a/(360*turns),
r = lerp(r1,r2,u), r = lerp(r1,r2,u),
mat = affine3d_zrot(a) mat = affine3d_zrot(dir*a)
* affine3d_translate([_ss_polygon_r(sides,a)*r, 0, h * (u-0.5)]) * affine3d_translate([_ss_polygon_r(sides,dir*a)*r, 0, dir*h * (u-0.5)])
* affine3d_xrot(90) * affine3d_xrot(90)
* skewmat * skewmat
* scale([hsc,lerp(hsc,1,0.25),1], cp=[internal ? xmax : xmin, yctr, 0]), * scale([hsc,lerp(hsc,1,0.25),1], cp=[internal ? xmax : xmin, yctr, 0]),
@ -1102,12 +1114,15 @@ function spiral_sweep(poly, h, r, turns=1, higbee, center, r1, r2, d, d1, d2, hi
module spiral_sweep(poly, h, r, turns=1, higbee, center, r1, r2, d, d1, d2, higbee1, higbee2, internal=false, anchor=CENTER, spin=0, orient=UP) { module spiral_sweep(poly, h, r, turns=1, taper, center, r1, r2, d, d1, d2, taper1, taper2, internal=false, anchor=CENTER, spin=0, orient=UP) {
vnf = spiral_sweep(poly, h, r, turns, higbee, center, r1, r2, d, d1, d2, higbee1, higbee2, internal); vnf = spiral_sweep(poly, h, r, turns, taper, center, r1, r2, d, d1, d2, taper1, taper2, internal);
r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=50); r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=50);
r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=50); r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=50);
taper1 = first_defined([taper1,taper,0]);
taper2 = first_defined([taper2,taper,0]);
extra = PI/2*(max(0,taper1/r1)+max(0,taper2/r2));
attachable(anchor,spin,orient, r1=r1, r2=r2, l=h) { attachable(anchor,spin,orient, r1=r1, r2=r2, l=h) {
vnf_polyhedron(vnf, convexity=ceil(abs(2*turns))); vnf_polyhedron(vnf, convexity=ceil(2*(abs(turns)+extra)));
children(); children();
} }
} }

View file

@ -1436,9 +1436,8 @@ module _nutshape(nutwidth, h, shape, bevel1, bevel2)
// Module: thread_helix() // Module: thread_helix()
// Usage: // Usage:
// thread_helix(d, pitch, [thread_depth], [flank_angle], [twist], [profile=], [left_handed=], [higbee=], [internal=]); // thread_helix(d, pitch, [thread_depth], [flank_angle], [turns], [profile=], [left_handed=], [higbee=], [internal=]);
// Description: // Description:
// Creates a right-handed helical thread with optional end tapering. Unlike // Creates a right-handed helical thread with optional end tapering. Unlike
// {{generic_threaded_rod()}, this module just generates the thread, and you specify the total // {{generic_threaded_rod()}, this module just generates the thread, and you specify the total
// angle of threading that you want, which makes it easy to put complete threads onto a longer // angle of threading that you want, which makes it easy to put complete threads onto a longer
@ -1462,24 +1461,25 @@ module _nutshape(nutwidth, h, shape, bevel1, bevel2)
// unlike the threaded_rod modules, thread_helix does not adjust the diameter for faceting, nor does it // unlike the threaded_rod modules, thread_helix does not adjust the diameter for faceting, nor does it
// subtract any $slop for clearance. // subtract any $slop for clearance.
// . // .
// The taper options specify Higbee specifies tapering applied to the ends of the threads and is given as the linear distance // The taper options specify tapering at of the threads at each end, and is given as the linear distance
// over which to taper. Tapering works on both internal and external threads. // over which to taper. If taper is positive the threads are lengthened by the specified distance; if taper
// is negative, the taper is included in the thread length specified by `turns`. Tapering works on both internal and external threads.
// Arguments: // Arguments:
// d = Inside base diameter of threads. Default: 10 // d = Inside base diameter of threads. Default: 10
// pitch = Distance between threads. Default: 2mm/thread // pitch = Distance between threads. Default: 2
// thread_depth = Depth of threads from top to bottom. // thread_depth = Depth of threads from top to bottom.
// flank_angle = Angle of thread faces to plane perpendicular to screw. Default: 15 degrees. // flank_angle = Angle of thread faces to plane perpendicular to screw. Default: 15 degrees.
// turns = Number of revolutions to rotate thread around. Default: 2. // turns = Number of revolutions to rotate thread around.
// --- // ---
// profile = If an asymmetrical thread profile is needed, it can be specified here. // profile = If an asymmetrical thread profile is needed, it can be specified here.
// starts = The number of thread starts. Default: 1 // starts = The number of thread starts. Default: 1
// left_handed = If true, thread has a left-handed winding. // left_handed = If true, thread has a left-handed winding.
// internal = If true, apply tapers for internal threading, and invert the default profile. Default: false // internal = if true make internal threads. The only effect this has is to change how the threads taper if tapering is selected. When true, threads taper towards the outside; when false, they taper towards the inside. Default: false
// d1 = Bottom inside base diameter of threads. // d1 = Bottom inside base diameter of threads.
// d2 = Top inside base diameter of threads. // d2 = Top inside base diameter of threads.
// higbee = Length to taper thread ends over. Default: 0 // taper = Length of tapers for thread ends. Positive to add taper to threads, negative to taper within specified length. Default: 0
// higbee1 = Length to taper bottom thread end over. // taper1 = Length of taper for bottom thread end
// higbee2 = Length to taper top thread end over. // taper2 = Length of taper for top thread end
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER` // anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0` // spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP` // orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
@ -1519,19 +1519,19 @@ module _nutshape(nutwidth, h, shape, bevel1, bevel2)
// } // }
// Examples: // Examples:
// thread_helix(d=10, pitch=2, thread_depth=0.75, flank_angle=15, turns=2.5, $fn=72); // thread_helix(d=10, pitch=2, thread_depth=0.75, flank_angle=15, turns=2.5, $fn=72);
// thread_helix(d=10, pitch=2, thread_depth=0.75, flank_angle=15, turns=2.5, higbee=1, $fn=72); // thread_helix(d=10, pitch=2, thread_depth=0.75, flank_angle=15, turns=2.5, taper=1, $fn=72);
// thread_helix(d=10, pitch=2, thread_depth=0.75, flank_angle=15, turns=2, higbee=2, internal=true, $fn=72); // thread_helix(d=10, pitch=2, thread_depth=0.75, flank_angle=15, turns=2, taper=2, internal=true, $fn=72);
// thread_helix(d=10, pitch=2, thread_depth=0.75, flank_angle=15, turns=1, left_handed=true, higbee=1, $fn=36); // thread_helix(d=10, pitch=2, thread_depth=0.75, flank_angle=15, turns=1, left_handed=true, taper=1, $fn=36);
function thread_helix( function thread_helix(
d, pitch, thread_depth, flank_angle, turns=2, d, pitch, thread_depth, flank_angle, turns,
profile, starts=1, left_handed=false, internal=false, profile, starts=1, left_handed=false, internal=false,
d1, d2, higbee, higbee1, higbee2, d1, d2, taper, taper1, taper2,
anchor, spin, orient anchor, spin, orient
) = no_function("thread_helix"); ) = no_function("thread_helix");
module thread_helix( module thread_helix(
d, pitch, thread_depth, flank_angle, turns=2, d, pitch, thread_depth, flank_angle, turns=2,
profile, starts=1, left_handed=false, internal=false, profile, starts=1, left_handed=false, internal=false,
d1, d2, higbee, higbee1, higbee2, d1, d2, taper, taper1, taper2,
anchor, spin, orient anchor, spin, orient
) { ) {
dummy1=assert(is_undef(profile) || !any_defined([thread_depth, flank_angle]),"Cannot give thread_depth or flank_angle with a profile"); dummy1=assert(is_undef(profile) || !any_defined([thread_depth, flank_angle]),"Cannot give thread_depth or flank_angle with a profile");
@ -1562,7 +1562,7 @@ module thread_helix(
dir = left_handed? -1 : 1; dir = left_handed? -1 : 1;
attachable(anchor,spin,orient, r1=r1, r2=r2, l=h) { attachable(anchor,spin,orient, r1=r1, r2=r2, l=h) {
zrot_copies(n=starts) { zrot_copies(n=starts) {
spiral_sweep(pline, h=h, r1=r1, r2=r2, turns=turns*dir, higbee=higbee, higbee1=higbee1, higbee2=higbee2, internal=internal, anchor=CENTER); spiral_sweep(pline, h=h, r1=r1, r2=r2, turns=turns*dir, taper=taper, taper1=taper1, taper2=taper2, internal=internal, anchor=CENTER);
} }
children(); children();
} }