From 21692e6704544331a1d1dc662a423165e90dfd62 Mon Sep 17 00:00:00 2001 From: Revar Desmera Date: Mon, 3 Oct 2022 18:40:37 -0700 Subject: [PATCH] Fix chamfered cyl() orientation for odd $fn --- shapes3d.scad | 93 ++++++++++++++++++++++++++------------------------- 1 file changed, 47 insertions(+), 46 deletions(-) diff --git a/shapes3d.scad b/shapes3d.scad index 5afa3e0..45a74ac 100644 --- a/shapes3d.scad +++ b/shapes3d.scad @@ -4,7 +4,7 @@ // that produce a VNF. Also included are shortcuts cylinders in each orientation and extended versions of // the standard modules that provide roundovers and chamfers. The spheroid() module provides // several different ways to make a sphere, and the text modules let you write text on a path -// so you can place it on a curved object. A ruler lets you measure objects. +// so you can place it on a curved object. A ruler lets you measure objects. // Includes: // include // FileGroup: Basic Modeling @@ -319,7 +319,7 @@ module cuboid( teardrop = is_bool(teardrop)&&teardrop? 45 : teardrop; chamfer = approx(chamfer,0) ? undef : chamfer; rounding = approx(rounding,0) ? undef : rounding; - checks = + checks = assert(is_vector(size,3)) assert(all_positive(size)) assert(is_undef(chamfer) || is_finite(chamfer),"chamfer must be a finite value") @@ -574,7 +574,7 @@ function cuboid( // Creates a rectangular prismoid shape with optional roundovers and chamfering. // You can only round or chamfer the vertical(ish) edges. For those edges, you can // specify rounding and/or chamferring per-edge, and for top and bottom separately. -// If you want to round the bottom or top edges see {{rounded_prism()}}. +// If you want to round the bottom or top edges see {{rounded_prism()}}. // // Arguments: // size1 = [width, length] of the bottom end of the prism. @@ -657,7 +657,7 @@ module prismoid( eps = pow(2,-14); size1 = is_num(size1)? [size1,size1] : size1; size2 = is_num(size2)? [size2,size2] : size2; - checks2 = + checks2 = assert(all_nonnegative(size1)) assert(all_nonnegative(size2)) assert(size1.x + size2.x > 0) @@ -951,7 +951,7 @@ module rect_tube( isize2 = is_def(is2)? is2 : (is_def(wall) && is_def(s2))? (s2-2*[wall,wall]) : undef; - checks2 = + checks2 = assert(wall==undef || is_num(wall)) assert(size1!=undef, "Bad size/size1 argument.") assert(size2!=undef, "Bad size/size2 argument.") @@ -1522,7 +1522,8 @@ module cyl( [0,l/2] ]; - rotate_extrude(convexity=2) polygon(path); + vnf = rotate_sweep(path); + vnf_polyhedron(vnf, convexity=2); } } children(); @@ -2007,19 +2008,19 @@ function sphere(r, d, circum=false, style="orig", anchor=CENTER, spin=0, orient= // When called as a function, returns a [VNF](vnf.scad) for a spheroid. // The exact triangulation of this spheroid can be controlled via the `style=` // argument, where the value can be one of `"orig"`, `"aligned"`, `"stagger"`, -// `"octa"`, or `"icosa"`. +// `"octa"`, or `"icosa"`. // - `style="orig"` constructs a sphere the same way that the OpenSCAD `sphere()` built-in does. // - `style="aligned"` constructs a sphere where, if `$fn` is a multiple of 4, it has vertices at all axis maxima and minima. ie: its bounding box is exactly the sphere diameter in length on all three axes. This is the default. // - `style="stagger"` forms a sphere where all faces are triangular, but the top and bottom poles have thinner triangles. // - `style="octa"` forms a sphere by subdividing an octahedron. This makes more uniform faces over the entirety of the sphere, and guarantees the bounding box is the sphere diameter in size on all axes. The effective `$fn` value is quantized to a multiple of 4. This is used in constructing rounded corners for various other shapes. -// - `style="icosa"` forms a sphere by subdividing an icosahedron. This makes even more uniform faces over the whole sphere. The effective `$fn` value is quantized to a multiple of 5. This sphere has a guaranteed bounding box when `$fn` is a multiple of 10. +// - `style="icosa"` forms a sphere by subdividing an icosahedron. This makes even more uniform faces over the whole sphere. The effective `$fn` value is quantized to a multiple of 5. This sphere has a guaranteed bounding box when `$fn` is a multiple of 10. // . // By default the object spheroid() produces is a polyhedron whose vertices all lie on the requested sphere. This means // the approximating polyhedron is inscribed in the sphere. // The `circum` argument requests a circumscribing sphere, where the true sphere is // inside and tangent to all the faces of the approximating polyhedron. To produce // a circumscribing polyhedron, we use the dual polyhedron of the basic form. The dual of a polyhedron is -// a new polyhedron whose vertices are obtained from the faces of the parent polyhedron. +// a new polyhedron whose vertices are obtained from the faces of the parent polyhedron. // The "orig" and "align" forms are duals of each other. If you request a circumscribing polyhedron in // these styles then the polyhedron will look the same as the default inscribing form. But for the other // styles, the duals are completely different from their parents, and from each other. Generation of the circumscribed versions (duals) @@ -2030,7 +2031,7 @@ function sphere(r, d, circum=false, style="orig", anchor=CENTER, spin=0, orient= // but is undersized on the Z axis. With style="octa" the circumscribed sphere has faces at each axis, so // the radius on the axes is equal to the specified radius, which is the *minimum* radius of the circumscribed sphere. // The same thing is true for style="icosa" when $fn is a multiple of 10. This would enable you to create spherical -// holes with guaranteed on-axis dimensions. +// holes with guaranteed on-axis dimensions. // Arguments: // r = Radius of the spheroid. // style = The style of the spheroid's construction. One of "orig", "aligned", "stagger", "octa", or "icosa". Default: "aligned" @@ -2052,14 +2053,14 @@ function sphere(r, d, circum=false, style="orig", anchor=CENTER, spin=0, orient= // spheroid(d=100, style="stagger", $fn=10); // Example: style="stagger" with circum=true // spheroid(d=100, style="stagger", circum=true, $fn=10); -// Example: style="octa", octahedral based tesselation. In this style, $fn is quantized to a multiple of 4. +// Example: style="octa", octahedral based tesselation. In this style, $fn is quantized to a multiple of 4. // spheroid(d=100, style="octa", $fn=10); // Example: style="octa", with circum=true, produces mostly very irregular hexagonal faces // spheroid(d=100, style="octa", circum=true, $fn=16); // Example: style="icosa", icosahedral based tesselation. In this style, $fn is quantized to a multiple of 5. -// spheroid(d=100, style="icosa", $fn=10); +// spheroid(d=100, style="icosa", $fn=10); // Example: style="icosa", circum=true. This style has hexagons and 12 pentagons, similar to (but not the same as) a soccer ball. -// spheroid(d=100, style="icosa", circum=true, $fn=10); +// spheroid(d=100, style="icosa", circum=true, $fn=10); // Example: Anchoring // spheroid(d=100, anchor=FRONT); // Example: Spin @@ -2071,10 +2072,10 @@ function sphere(r, d, circum=false, style="orig", anchor=CENTER, spin=0, orient= // Example: Called as Function // vnf = spheroid(d=100, style="icosa"); // vnf_polyhedron(vnf); -// Example: With "orig" the circumscribing sphere has the same form. The green sphere is a tiny bit oversized so it pokes through the low points in the circumscribed sphere with low $fn. This demonstrates that these spheres are in fact circumscribing. +// Example: With "orig" the circumscribing sphere has the same form. The green sphere is a tiny bit oversized so it pokes through the low points in the circumscribed sphere with low $fn. This demonstrates that these spheres are in fact circumscribing. // color("green")spheroid(r=10.01, $fn=256); // spheroid(r=10, style="orig", circum=true, $fn=16); -// Example: With "aligned" the same is true: the circumscribing sphere is also aligned, if $fn is divisible by 4. +// Example: With "aligned" the same is true: the circumscribing sphere is also aligned, if $fn is divisible by 4. // color("green")spheroid(r=10.01, $fn=256); // spheroid(r=10, style="aligned", circum=true, $fn=16); // Example: For the other styles, the circumscribing sphere is different, as shown here with "stagger" @@ -2118,8 +2119,8 @@ module spheroid(r, style="aligned", d, circum=false, dual=false, anchor=CENTER, // p is a list of 3 points defining a triangle in any dimension. N is the number of extra points -// to add, so output triangle has N+2 points on each side. -function _subsample_triangle(p,N) = +// to add, so output triangle has N+2 points on each side. +function _subsample_triangle(p,N) = [for(i=[0:N+1]) [for (j=[0:N+1-i]) unit(lerp(p[0],p[1],i/(N+1)) + (p[2]-p[0])*j/(N+1))]]; @@ -2165,7 +2166,7 @@ function spheroid(r, style="aligned", d, circum=false, anchor=CENTER, spin=0, or [reorient(anchor,spin,orient, r=r, p=dualvert), faces] : style=="icosa" ? // subdivide faces of an icosahedron and project them onto a sphere - let( + let( N = icosa_steps-1, // construct an icosahedron icovert=[ for(i=[-1,1], j=[-1,1]) each [[0,i,j*PHI], [i,j*PHI,0], [j*PHI,0,i]]], @@ -2188,7 +2189,7 @@ function spheroid(r, style="aligned", d, circum=false, anchor=CENTER, spin=0, or // Expand to full face list fullfaces = [for(i=idx(tri_list)) each [for(f=faces) f+i*size]], fullvert = flatten(flatten(tri_list)) // eliminate triangle structure - ) + ) [reorient(anchor,spin,orient, r=r, p=fullvert), fullfaces] : let( @@ -2231,10 +2232,10 @@ function spheroid(r, style="aligned", d, circum=false, anchor=CENTER, spin=0, or [ for (i=idx(meridians), j=[0:1:meridians[i]-1]) spherical_to_xyz(r, j*360/meridians[i], i*180/(len(meridians)-1)) - ] + ] : assert(in_list(style,["orig","aligned","stagger","octa","icosa"])), lv = len(verts), - faces = circum && style=="stagger" ? + faces = circum && style=="stagger" ? let(ptcount=2*hsides) [ [for(i=[ptcount-2:-2:0]) i], @@ -2252,7 +2253,7 @@ function spheroid(r, style="aligned", d, circum=false, anchor=CENTER, spin=0, or ? [(j*2+3)%ptcount, j*2+1, lv-ptcount+(2+j*2)%ptcount, lv-ptcount+(3+j*2)%ptcount, lv-ptcount+(4+j*2)%ptcount] : [(j*2+3)%ptcount, j*2+1, lv-ptcount+(1+j*2)%ptcount, lv-ptcount+(j*2)%ptcount, lv-ptcount+(3+j*2)%ptcount], [for(i=[1:2:ptcount-1]) i], - ] + ] : style=="aligned" || style=="stagger" ? // includes case of aligned with circum == true [ for (i=[0:1:hsides-1]) @@ -2270,7 +2271,7 @@ function spheroid(r, style="aligned", d, circum=false, anchor=CENTER, spin=0, or ] : [ [base+j, base+(j+1)%hsides, base+hsides+(j+1)%hsides], [base+j, base+hsides+(j+1)%hsides, base+hsides+j], - ] + ] ) ] : style=="orig"? [ @@ -2280,7 +2281,7 @@ function spheroid(r, style="aligned", d, circum=false, anchor=CENTER, spin=0, or each [ [(i+1)*hsides+j, i*hsides+j, i*hsides+(j+1)%hsides], [(i+1)*hsides+j, i*hsides+(j+1)%hsides, (i+1)*hsides+(j+1)%hsides], - ] + ] ] : /*style=="octa"?*/ let( @@ -2288,7 +2289,7 @@ function spheroid(r, style="aligned", d, circum=false, anchor=CENTER, spin=0, or 0, 1, for (i = [1:1:octa_steps]) i*4, for (i = [octa_steps-1:-1:1]) i*4, - 1, + 1, ], offs = cumsum(meridians), pc = last(offs)-1, @@ -2318,7 +2319,7 @@ function spheroid(r, style="aligned", d, circum=false, anchor=CENTER, spin=0, or [p5, p7, p8], if (k0 ? quantup(widths[i],1/1024) : widths[i]; // What is the i>0 test supposed to do here? + w = i>0 ? quantup(widths[i],1/1024) : widths[i]; // What is the i>0 test supposed to do here? cube([quantup(actlen,1/1024),quantup(w,1/1024),thickness], anchor=FRONT+LEFT); } mark =