diff --git a/beziers.scad b/beziers.scad index 9738cab..e6e8091 100644 --- a/beziers.scad +++ b/beziers.scad @@ -634,7 +634,7 @@ function path_to_bezpath(path, closed, tangents, uniform=false, size, relsize) = second + L*tangent2 ], select(path,lastpt) -]; + ]; @@ -666,30 +666,31 @@ function path_to_bezpath(path, closed, tangents, uniform=false, size, relsize) = function path_to_bezcornerpath(path, closed, size, relsize) = is_1region(path) ? path_to_bezcornerpath(path[0], default(closed,true), tangents, size, relsize) : let(closed=default(closed,false)) - assert(is_bool(closed)) - assert(num_defined([size,relsize])<=1, "Can't define both size and relsize") - assert(is_path(path,[2,3]),"Input path is not a valid 2d or 3d path") - let( - curvesize = first_defined([size,relsize,0.5]), - relative = is_undef(size), - pathlen = len(path) + assert(is_bool(closed)) + assert(num_defined([size,relsize])<=1, "Can't define both size and relsize") + assert(is_path(path,[2,3]),"Input path is not a valid 2d or 3d path") + let( + curvesize = first_defined([size,relsize,0.5]), + relative = is_undef(size), + pathlen = len(path) + ) + assert(is_num(curvesize) || len(curvesize)==pathlen, str("Size or relsize must have length ",pathlen)) + let(sizevect = is_num(curvesize) ? repeat(curvesize, pathlen) : curvesize) + assert(min(sizevect)>0, "Size or relsize must be greater than zero") + let( + roundpath = closed ? [ + for(i=[0:pathlen-1]) let(p3=select(path,[i-1:i+1])) + _bez_path_corner([0.5*(p3[0]+p3[1]), p3[1], 0.5*(p3[1]+p3[2])], sizevect[i], relative), + [0.5*(path[0]+path[pathlen-1])] + ] + : [ for(i=[1:pathlen-2]) let(p3=select(path,[i-1:i+1])) + _bez_path_corner( + [i>1?0.5*(p3[0]+p3[1]):p3[0], p3[1], i0, "Size or relsize must be greater than zero") - let( - roundpath = closed ? [ - for(i=[0:pathlen-1]) let(p3=select(path,[i-1:i+1])) - _bez_path_corner([0.5*(p3[0]+p3[1]), p3[1], 0.5*(p3[1]+p3[2])], sizevect[i], relative), - [0.5*(path[0]+path[pathlen-1])] - ] - : [ for(i=[1:pathlen-2]) let(p3=select(path,[i-1:i+1])) - _bez_path_corner( - [i>1?0.5*(p3[0]+p3[1]):p3[0], p3[1], i0 ? r*sqrt(2)/s2a * sqrt(1 - sqrt(1 - s2a*s2a)) : r; +function squircle_radius_fg(squareness, r, angle) = + let( + s2a = abs(squareness*sin(2*angle)) + ) + s2a>0 ? r*sqrt(2)/s2a * sqrt(1 - sqrt(1 - s2a*s2a)) : r; function _linearize_squareness(s) = // from Chamberlain Fong (2016). "Squircular Calculations". arXiv. // https://arxiv.org/pdf/1604.02174v5 let(c = 2 - 2*sqrt(2), d = 1 - 0.5*c*s) - 2 * sqrt((1+c)*s*s - c*s) / (d*d); + 2 * sqrt((1+c)*s*s - c*s) / (d*d); /* Superellipse squircle functions */ @@ -1884,27 +1886,33 @@ function _squircle_se(size, squareness) = [ ) [ra*x, rb*y] / r ]; -function squircle_radius_se(n, r, angle) = let( - x = cos(angle), - y = sin(angle) -) (abs(x)^n + abs(y)^n)^(1/n) / r; +function squircle_radius_se(n, r, angle) = + let( + x = cos(angle), + y = sin(angle) + ) + (abs(x)^n + abs(y)^n)^(1/n) / r; -function _squircle_se_exponent(squareness) = let( - // limit squareness; error if >0.99889, limit is smaller for r>1 - s=min(0.998,squareness), - rho = 1 + s*(sqrt(2)-1), - x = rho / sqrt(2) -) log(0.5) / log(x); +function _squircle_se_exponent(squareness) = + let( + // limit squareness; error if >0.99889, limit is smaller for r>1 + s=min(0.998,squareness), + rho = 1 + s*(sqrt(2)-1), + x = rho / sqrt(2) + ) + log(0.5) / log(x); /* Bezier squircle function */ -function _squircle_bz(size, squareness) = let( - splinesteps = $fn>=12 ? round($fn/4) : 10, - size = is_num(size) ? [size,size] : point2d(size), - sq = square(size, center=true), - bez = path_to_bezcornerpath(sq, relsize=1-squareness, closed=true) -) bezpath_curve(bez, splinesteps=splinesteps); +function _squircle_bz(size, squareness) = + let( + splinesteps = $fn>=12 ? round($fn/4) : 10, + size = is_num(size) ? [size,size] : point2d(size), + sq = square(size, center=true), + bez = path_to_bezcornerpath(sq, relsize=1-squareness, closed=true) + ) + bezpath_curve(bez, splinesteps=splinesteps);