From 44fea4047e1717197badfa7b436b64f2a8555c04 Mon Sep 17 00:00:00 2001 From: Adrian Mariano Date: Sun, 3 Sep 2023 22:19:29 -0400 Subject: [PATCH 1/3] offset_sweep "extra" bugfix --- rounding.scad | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/rounding.scad b/rounding.scad index a970233..a248102 100644 --- a/rounding.scad +++ b/rounding.scad @@ -591,8 +591,7 @@ function _rounding_offsets(edgespec,z_dir=1) = _bezcorner([[0,0],[0,z_dir*abs(joint)],[-joint,z_dir*abs(joint)]], k, $fn=N+2) ) ) - - quant(extra > 0? concat(offsets, [last(offsets)+[0,z_dir*extra]]) : offsets, 1/1024); + quant(extra > 0 && len(offsets)>0 ? concat(offsets, [last(offsets)+[0,z_dir*extra]]) : offsets, 1/1024); From 2b02c890f04b4753344238aeb1c81bb403c57541 Mon Sep 17 00:00:00 2001 From: Adrian Mariano Date: Sat, 16 Sep 2023 09:51:24 -0400 Subject: [PATCH 2/3] docs update --- gears.scad | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++- rounding.scad | 4 +-- skin.scad | 23 ++++++-------- 3 files changed, 98 insertions(+), 16 deletions(-) diff --git a/gears.scad b/gears.scad index 8674b45..51be064 100644 --- a/gears.scad +++ b/gears.scad @@ -78,7 +78,8 @@ function _inherit_gear_thickness(thickness) = // * [Gear undercutting](https://www.tec-science.com/mechanical-power-transmission/involute-gear/undercut/) // * [Profile shifting](https://www.tec-science.com/mechanical-power-transmission/involute-gear/profile-shift/) // * [Detailed gear calculations](https://www.tec-science.com/mechanical-power-transmission/involute-gear/calculation-of-involute-gears/) -// - SDPSI +// * [Worm drive](https://www.tec-science.com/mechanical-power-transmission/gear-types/worms-and-worm-gears/) +// - SDPSI (A long document covering a variety of gear types and gear calculations) // * [Elements of Gear Technology](https://www.sdp-si.com/resources/elements-of-metric-gear-technology/index.php) // Subsection: Involute Spur Gears // The simplest gear form is the involute spur gear, which is an extrusion of a two dimensional form. @@ -410,6 +411,90 @@ function _inherit_gear_thickness(thickness) = // color("lightblue") // fwd(d) // spur_gear(mod=mod, teeth=teeth1, profile_shift=ps1,gear_spin=-ang*360/teeth1,helical=-30,thickness=15); +// Subsection: Worm Drive +// A worm drive is a gear system for connecting skew shafts at 90 degrees. They offer higher load capacity compared to +// crossed helical gears. The assembly is driven by the "worm", which is a gear that resembles a screw. +// Like a screw, it can have one, or several starts. These starts correspond to teeth on a helical gear; +// in fact, the worm can be regarded as a type of helical gear at a very extreme angle, where the teeth wrap +// around the gear. The worm mates with the "worm gear" which is also called the "worm wheel". The worm gear +// resembles a helical gear at a very slight angle. +// Figure(3D,Med,NoAxes): Worm drive assembly, with worm on the left and worm gear (worm wheel) on the right. When the worm turns its screwing action drives the worm gear. +// starts=2; +// ps=0; +// dist_ba=0; +// gear_ba=0; +// worm( +// d=44, // mate_teeth=30, +// circ_pitch=3*PI, +// starts=starts,orient=BACK); +// right(worm_dist(d=44,mod=3,teeth=30, starts=starts,profile_shift=ps,backlash=dist_ba)) +// zrot(360/30*.5) +// worm_gear( +// circ_pitch=3*PI, +// teeth=30, +// worm_diam=44,profile_shift=ps, +// worm_starts=starts,backlash=gear_ba); +// Continues: +// A close look at the worm gear reveals that it differs significantly from a helical or spur gear. +// This gear is an "enveloping" gear, which is designed to follow the curved profile of the worm, +// resulting in much better contact between the teeth of the worm and the teeth of the worm gear. +// The worm shown above is a cylindrical worm, which is the most common type. +// It is possible to design the worm to follow the curved shape of its mated gear, resulting +// in an enveloping (also called "globoid") worm. This type of worm makes better contact with +// the worm gear, but is less often used due to manufacturing complexity and consequent expense. +// Figure(3D,Big,NoAxes,VPT=[0,0,0],VPR=[192,0,180],VPD=172.84): A cylindrical worm appears on the left in green. Note it's straight sides. The enveloping (globoid) worm gears appears on the right in green. Note that its sides curve so several teeth can mate with the worm gear, and it requires a complex tooth form +// tilt=20; +// starts=1; +// ps=0; +// pa=27; +// dist_ba=0; +// gear_ba=0; +// xdistribute(spacing=25){ +// xflip()yrot(-tilt) +// union(){ +// color("lightgreen") +// xrot(90) +// zrot(-90) +// enveloping_worm( mate_teeth=60,$fn=128, +// d=14, pressure_angle=pa, mod=3/2, +// starts=starts); +// right(worm_dist(d=14,mod=3/2,teeth=60, starts=starts,profile_shift=ps,backlash=dist_ba,pressure_angle=pa)) +// zrot(360/30*.25) +// worm_gear( +// mod=3/2,pressure_angle=pa, +// teeth=60,crowning=0, +// worm_diam=14,profile_shift=ps, +// worm_starts=starts,backlash=gear_ba); +// } +// yrot(-tilt) +// union(){ +// color("lightgreen") +// xrot(90) +// zrot(-90) +// worm(l=43, $fn=128, +// d=14, pressure_angle=pa, left_handed=true, +// mod=3/2,//circ_pitch=3*PI/2, +// starts=starts); +// right(worm_dist(d=14,mod=3/2,teeth=60, starts=starts,profile_shift=ps,backlash=dist_ba,pressure_angle=pa)) +// zrot(360/30*.25) +// worm_gear( +// mod=3/2,pressure_angle=pa, +// teeth=60,crowning=0,left_handed=true, +// worm_diam=14,profile_shift=ps, +// worm_starts=starts,backlash=gear_ba); +// } +// } +// Continues: +// Worm drives are often "self-locking", which means that torque transmission can occur only from the worm to the worm gear, +// so they must be driven by the worm. Self-locking results from the small lead angle of the worm threads, which produces +// high frictional forces at contact. A multi-start worm has a higher lead angle and as a result is less likely +// to be self-locking, so a multi-start worm can be chosen to avoid self-locking. +// Since self-locking is associated with friction, self-locking drives have lower efficiency, +// usually less than 50%. Worm drive efficiency can exceed 90% if self-locking is not required. One consideration +// with self-locking systems is that if the worm gear moves a large mass and the drive is suddenly shut off, the +// worm wheel is still trying to move due to inertia, which can create large loads that fracture the worm. +// In such cases, the worm cannot be stopped abruptly but must rotate a little further (called "over travel") +// after switching off the drive // Subsection: Backlash (Fitting Real Gears Together) // You may have noticed that the example gears shown fit together perfectly, making contact on both sides of // the teeth. Real gears need space between the teeth to prevent the gears from jamming, to provide space diff --git a/rounding.scad b/rounding.scad index a248102..5a1f32d 100644 --- a/rounding.scad +++ b/rounding.scad @@ -1268,7 +1268,7 @@ module offset_stroke(path, width=1, rounded=true, start, end, check_valid=true, // Synopsis: Make a solid from a polygon with offset that changes along its length. // SynTags: Geom, VNF // Topics: Rounding, Offsets -// See Also: offset_sweep(), convex_offset_extrude(), rounded_prism(), bent_cutout_mask(), join_prism() +// See Also: convex_offset_extrude(), rounded_prism(), bent_cutout_mask(), join_prism(), linear_sweep() // Usage: most common module arguments. See Arguments list below for more. // offset_sweep(path, [height|length|h|l|], [bottom], [top], [offset=], [convexity=],...) [ATTACHMENTS]; // Usage: most common function arguments. See Arguments list below for more. @@ -1738,7 +1738,7 @@ function os_mask(mask, out=false, extra,check_valid, quality, offset) = // Synopsis: Make a solid from geometry where offset changes along the object's length. // SynTags: Geom // Topics: Rounding, Offsets -// See Also: offset_sweep(), convex_offset_extrude(), rounded_prism(), bent_cutout_mask(), join_prism() +// See Also: offset_sweep(), rounded_prism(), bent_cutout_mask(), join_prism(), linear_sweep() // Usage: Basic usage. See below for full options // convex_offset_extrude(height, [bottom], [top], ...) 2D-CHILDREN; // Description: diff --git a/skin.scad b/skin.scad index 7797e77..d35e04e 100644 --- a/skin.scad +++ b/skin.scad @@ -21,7 +21,7 @@ // Synopsis: Connect a sequence of arbitrary polygons into a 3D object. // SynTags: VNF, Geom // Topics: Extrusion, Skin -// See Also: sweep(), linear_sweep(), rotate_sweep(), spiral_sweep(), path_sweep() +// See Also: sweep(), linear_sweep(), rotate_sweep(), spiral_sweep(), path_sweep(), offset_sweep() // Usage: As module: // skin(profiles, slices, [z=], [refine=], [method=], [sampling=], [caps=], [closed=], [style=], [convexity=], [anchor=],[cp=],[spin=],[orient=],[atype=]) [ATTACHMENTS]; // Usage: As function: @@ -513,7 +513,7 @@ function skin(profiles, slices, refine=1, method="direct", sampling, caps, close // Synopsis: Create a linear extrusion from a path, with optional texturing. // SynTags: VNF, Geom // Topics: Extrusion, Textures, Sweep -// See Also: rotate_sweep(), sweep(), spiral_sweep(), path_sweep() +// See Also: rotate_sweep(), sweep(), spiral_sweep(), path_sweep(), offset_sweep() // Usage: As Module // linear_sweep(region, [height], [center=], [slices=], [twist=], [scale=], [style=], [caps=], [convexity=]) [ATTACHMENTS]; // Usage: With Texturing @@ -839,7 +839,7 @@ function linear_sweep( // Synopsis: Create a surface of revolution from a path with optional texturing. // SynTags: VNF, Geom // Topics: Extrusion, Sweep, Revolution, Textures -// See Also: linear_sweep(), sweep(), spiral_sweep(), path_sweep() +// See Also: linear_sweep(), sweep(), spiral_sweep(), path_sweep(), offset_sweep() // Usage: As Function // vnf = rotate_sweep(shape, [angle], ...); // Usage: As Module @@ -872,7 +872,6 @@ function linear_sweep( // Anchor Types: // "hull" = Anchors to the virtual convex hull of the shape. // "intersect" = Anchors to the surface of the shape. -// See Also: linear_sweep(), sweep() // Example: // rgn = [ // for (a = [0, 120, 240]) let( @@ -1064,7 +1063,7 @@ module rotate_sweep( // Synopsis: Sweep a path along a helix. // SynTags: VNF, Geom // Topics: Extrusion, Sweep, Spiral -// See Also: linear_sweep(), rotate_sweep(), sweep(), path_sweep() +// See Also: thread_helix(), linear_sweep(), rotate_sweep(), sweep(), path_sweep(), offset_sweep() // Usage: As Module // spiral_sweep(poly, h, r|d=, turns, [taper=], [center=], [taper1=], [taper2=], [internal=], ...)[ATTACHMENTS]; // spiral_sweep(poly, h, r1=|d1=, r2=|d2=, turns, [taper=], [center=], [taper1=], [taper2=], [internal=], ...)[ATTACHMENTS]; @@ -1110,7 +1109,6 @@ module rotate_sweep( // 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` // orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP` -// See Also: sweep(), linear_sweep(), rotate_sweep(), path_sweep(), thread_helix() // Example: // poly = [[-10,0], [-3,-5], [3,-5], [10,0], [0,-30]]; // spiral_sweep(poly, h=200, r=50, turns=3, $fn=36); @@ -1294,7 +1292,7 @@ module spiral_sweep(poly, h, r, turns=1, taper, r1, r2, d, d1, d2, internal=fals // Synopsis: Sweep a 2d polygon path along a 2d or 3d path. // SynTags: VNF, Geom // Topics: Extrusion, Sweep, Paths -// See Also: linear_sweep(), rotate_sweep(), sweep(), spiral_sweep(), path_sweep2d() +// See Also: linear_sweep(), rotate_sweep(), sweep(), spiral_sweep(), path_sweep2d(), offset_sweep() // Usage: As module // path_sweep(shape, path, [method], [normal=], [closed=], [twist=], [twist_by_length=], [symmetry=], [scale=], [scale_by_length=], [last_normal=], [tangent=], [uniform=], [relaxed=], [caps=], [style=], [convexity=], [anchor=], [cp=], [spin=], [orient=], [atype=]) [ATTACHMENTS]; // Usage: As function @@ -1453,7 +1451,6 @@ module spiral_sweep(poly, h, r, turns=1, taper, r1, r2, d, d1, d2, internal=fals // Anchor Types: // "hull" = Anchors to the virtual convex hull of the shape. // "intersect" = Anchors to the surface of the shape. -// See Also: sweep(), linear_sweep(), rotate_sweep(), spiral_sweep() // Example(NoScales): A simple sweep of a square along a sine wave: // path = [for(theta=[-180:5:180]) [theta/10, 10*sin(theta)]]; // sq = square(6,center=true); @@ -1892,7 +1889,7 @@ function path_sweep(shape, path, method="incremental", normal, closed, twist=0, // Synopsis: Sweep a 2d polygon path along a 2d path allowing self-intersection. // SynTags: VNF, Geom // Topics: Extrusion, Sweep, Paths -// See Also: linear_sweep(), rotate_sweep(), sweep(), spiral_sweep(), path_sweep() +// See Also: linear_sweep(), rotate_sweep(), sweep(), spiral_sweep(), path_sweep(), offset_sweep() // Usage: as module // path_sweep2d(shape, path, [closed], [caps], [quality], [style], [convexity=], [anchor=], [spin=], [orient=], [atype=], [cp=]) [ATTACHMENTS]; // Usage: as function @@ -2023,7 +2020,7 @@ function _ofs_face_edge(face,firstlen,second=false) = // Synopsis: Construct a 3d object from arbitrary transformations of a 2d polygon path. // SynTags: VNF, Geom // Topics: Extrusion, Sweep, Paths -// See Also: linear_sweep(), rotate_sweep(), spiral_sweep(), path_sweep(), path_sweep2d() +// See Also: linear_sweep(), rotate_sweep(), spiral_sweep(), path_sweep(), path_sweep2d(), offset_sweep() // Usage: As Module // sweep(shape, transforms, [closed], [caps], [style], [convexity=], [anchor=], [spin=], [orient=], [atype=]) [ATTACHMENTS]; // Usage: As Function @@ -2628,7 +2625,7 @@ function _find_one_tangent(curve, edge, curve_offset=[0,0,0], closed=true) = // Synopsis: Create vertex association to control how {{skin()}} links vertices. // SynTags: PathList // Topics: Extrusion, Skinning, Paths -// See Also: skin(), sweep() +// See Also: skin() // Usage: // newpoly = associate_vertices(polygons, split); // Description: @@ -3424,6 +3421,7 @@ function texture(tex, n, inset, gap, roughness) = /// _textured_linear_sweep(region, texture, tex_size, h, ...) [ATTACHMENTS]; /// _textured_linear_sweep(region, texture, counts=, h=, ...) [ATTACHMENTS]; /// Topics: Sweep, Extrusion, Textures, Knurling +/// See Also: heightfield(), cylindrical_heightfield(), texture() /// Description: /// Given a [[Region|regions.scad]], creates a linear extrusion of it vertically, optionally twisted, scaled, and/or shifted, /// with a given texture tiled evenly over the side surfaces. The texture can be given in one of three ways: @@ -3456,7 +3454,6 @@ function texture(tex, n, inset, gap, roughness) = /// centroid_top = The centroid of the top of the shape, oriented UP. /// centroid = The centroid of the center of the shape, oriented UP. /// centroid_bot = The centroid of the bottom of the shape, oriented DOWN. -/// See Also: heightfield(), cylindrical_heightfield(), texture() function _get_vnf_tile_edges(texture) = let( @@ -3720,6 +3717,7 @@ function _find_vnf_tile_edge_path(vnf, val) = /// _textured_revolution(shape, texture, tex_size, [tex_scale=], ...) [ATTACHMENTS]; /// _textured_revolution(shape, texture, counts=, [tex_scale=], ...) [ATTACHMENTS]; /// Topics: Sweep, Extrusion, Textures, Knurling +/// See Also: heightfield(), cylindrical_heightfield(), texture() /// Description: /// Given a 2D region or path, fully in the X+ half-plane, revolves that shape around the Z axis (after rotating its Y+ to Z+). /// This creates a solid from that surface of revolution, possibly capped top and bottom, with the sides covered in a given tiled texture. @@ -3749,7 +3747,6 @@ function _find_vnf_tile_edge_path(vnf, val) = /// 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` /// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP` -/// See Also: heightfield(), cylindrical_heightfield(), texture() /// Anchor Types: /// "hull" = Anchors to the virtual convex hull of the shape. /// "intersect" = Anchors to the surface of the shape. From 4e9eb7d6a513ad3b1e928d213fa30062feb1b1cf Mon Sep 17 00:00:00 2001 From: Adrian Mariano Date: Wed, 20 Sep 2023 21:12:43 -0400 Subject: [PATCH 3/3] add right multiplication to cumprod --- math.scad | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/math.scad b/math.scad index 8cc9587..d59d159 100644 --- a/math.scad +++ b/math.scad @@ -763,29 +763,38 @@ function _product(v, i=0, _tot) = // Synopsis: Returns the running cumulative product of a list of values. // Topics: Math, Statistics // See Also: sum(), mean(), median(), product(), cumsum() +// Usage: +// prod_list = cumprod(list, [right]); // Description: // Returns a list where each item is the cumulative product of all items up to and including the corresponding entry in the input list. -// If passed an array of vectors, returns a list of elementwise vector products. If passed a list of square matrices returns matrix -// products multiplying on the left, so a list `[A,B,C]` will produce the output `[A,BA,CBA]`. +// If passed an array of vectors, returns a list of elementwise vector products. If passed a list of square matrices by default returns matrix +// products multiplying on the left, so a list `[A,B,C]` will produce the output `[A,BA,CBA]`. If you set `right=true` then it returns +// the product of multiplying on the right, so a list `[A,B,C]` will produce the output `[A,AB,ABC]` in that case. // Arguments: -// list = The list to get the product of. +// list = The list to get the cumulative product of. +// right = if true multiply matrices on the right // Example: // cumprod([1,3,5]); // returns [1,3,15] // cumprod([2,2,2]); // returns [2,4,8] // cumprod([[1,2,3], [3,4,5], [5,6,7]])); // returns [[1, 2, 3], [3, 8, 15], [15, 48, 105]] -function cumprod(list) = +function cumprod(list,right=false) = is_vector(list) ? _cumprod(list) : assert(is_consistent(list), "Input must be a consistent list of scalars, vectors or square matrices") - is_matrix(list[0]) ? assert(len(list[0])==len(list[0][0]), "Matrices must be square") _cumprod(list) + assert(is_bool(right)) + is_matrix(list[0]) ? assert(len(list[0])==len(list[0][0]), "Matrices must be square") _cumprod(list,right) : _cumprod_vec(list); -function _cumprod(v,_i=0,_acc=[]) = +function _cumprod(v,right,_i=0,_acc=[]) = _i==len(v) ? _acc : _cumprod( - v, _i+1, + v, right, _i+1, concat( _acc, - [_i==0 ? v[_i] : v[_i]*_acc[len(_acc)-1]] + [ + _i==0 ? v[_i] + : right? _acc[len(_acc)-1]*v[_i] + : v[_i]*_acc[len(_acc)-1] + ] ) );