mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2025-01-15 08:59:40 +00:00
Compare commits
No commits in common. "11b801ec4691a4bcf3d46a1be7bf66bc1305fead" and "f564a0f060e7dd802f2ca874d5bee3030e9ee51a" have entirely different histories.
11b801ec46
...
f564a0f060
3 changed files with 67 additions and 76 deletions
53
beziers.scad
53
beziers.scad
|
@ -634,7 +634,7 @@ function path_to_bezpath(path, closed, tangents, uniform=false, size, relsize) =
|
|||
second + L*tangent2
|
||||
],
|
||||
select(path,lastpt)
|
||||
];
|
||||
];
|
||||
|
||||
|
||||
|
||||
|
@ -666,31 +666,30 @@ 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_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], i<pathlen-2?0.5*(p3[1]+p3[2]):p3[2]],
|
||||
sizevect[i], relative),
|
||||
[path[pathlen-1]]
|
||||
]
|
||||
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)
|
||||
)
|
||||
flatten(roundpath);
|
||||
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], i<pathlen-2?0.5*(p3[1]+p3[2]):p3[2]],
|
||||
sizevect[i], relative),
|
||||
[path[pathlen-1]]
|
||||
]
|
||||
) flatten(roundpath);
|
||||
|
||||
|
||||
/// Internal function: _bez_path_corner()
|
||||
|
@ -744,7 +743,9 @@ let(
|
|||
// bz6 is p3
|
||||
bz3 = p2 + middir * bzdist, // center control point
|
||||
bz2 = bz3 + midto12unit*(d1<d3 ? cornerlegmin : cornerlegmax),
|
||||
bz1 = p1 - (d1<=d3 ? leglenmin : leglenmax)*p21unit,
|
||||
bz1 = p1 - (d1<=d3 ? leglenmin :
|
||||
leglenmax)*p21unit,
|
||||
//norm(0.333*(bz2-p1)))*p21unit,
|
||||
bz4 = bz3 - midto12unit*(d3<d1 ? cornerlegmin : cornerlegmax),
|
||||
bz5 = p3 - (d3<=d1 ? leglenmin : leglenmax)*p23unit
|
||||
) [p1, bz1, bz2, bz3, bz4, bz5]; // do not include last control point
|
||||
|
|
|
@ -629,7 +629,7 @@ function _rounding_offsets(edgespec,z_dir=1) =
|
|||
// relative to the segment length (e.g. 0.05 means 5% of the segment length). For the "corners" method,
|
||||
// `relsize` determines where the curve intersects the corner bisector, relative to the maximum deviation
|
||||
// possible (which corresponds to a circle rounding from the shortest leg of the corner). For example,
|
||||
// `relsize=1` is the maximum deviation from the corner (a circle arc from the shortest leg), and `relsize=0.5`
|
||||
// `relsize=1` is the maximum deviation from the corner (a circle arc from the shortest leg), and `relsize=0.5`
|
||||
// causes the curve to intersect the corner bisector halfway between the maximum and the tip of the corner.
|
||||
// .
|
||||
// At a given segment or corner (depending on the method) there is a maximum size: a size value that is too
|
||||
|
@ -735,20 +735,18 @@ function _rounding_offsets(edgespec,z_dir=1) =
|
|||
// pts = [[-3.3, 1.7], [-3.7, -2.2], [3.8, -4.8], [-0.9, -2.4]];
|
||||
// stroke(smooth_path(pts, uniform=false, relsize=0.1),width=.1);
|
||||
// color("red")move_copies(pts)circle(r=.15,$fn=12);
|
||||
module smooth_path(path, tangents, size, relsize, method="edges", splinesteps=10, uniform, closed=false) {no_module();}
|
||||
function smooth_path(path, tangents, size, relsize, method="edges", splinesteps=10, uniform, closed) =
|
||||
is_1region(path)
|
||||
? smooth_path(path[0], tangents, size, relsize, method, splinesteps, uniform, default(closed,true))
|
||||
: assert(method=="edges" || method=="corners", "method must be \"edges\" or \"corners\".")
|
||||
assert(method=="edges" || (is_undef(tangents) && is_undef(uniform)), "The tangents and uniform parameters are incompatible with method=\"corners\".")
|
||||
let (
|
||||
uniform = default(uniform,false),
|
||||
bez = method=="edges"
|
||||
? path_to_bezpath(path, tangents=tangents, size=size, relsize=relsize, uniform=uniform, closed=default(closed,false))
|
||||
module smooth_path(path, tangents, size, relsize, method="edges", splinesteps=10, uniform=false, closed=false) {no_module();}
|
||||
function smooth_path(path, tangents, size, relsize, method="edges", splinesteps=10, uniform=false, closed) =
|
||||
is_1region(path) ? smooth_path(path[0], tangents, size, relsize, method, splinesteps, uniform, default(closed,true)) :
|
||||
assert(method=="edges" || method=="corners", "method must be \"edges\" or \"corners\".")
|
||||
assert(method=="edges" || is_undef(tangent), "The tangents parameter is incompatible with method=\"corners\".")
|
||||
let (
|
||||
bez = method=="edges" ?
|
||||
path_to_bezpath(path, tangents=tangents, size=size, relsize=relsize, uniform=uniform, closed=default(closed,false))
|
||||
: path_to_bezcornerpath(path, size=size, relsize=relsize, closed=default(closed,false)),
|
||||
smoothed = bezpath_curve(bez,splinesteps=splinesteps)
|
||||
)
|
||||
closed ? list_unwrap(smoothed) : smoothed;
|
||||
smoothed = bezpath_curve(bez,splinesteps=splinesteps)
|
||||
)
|
||||
closed ? list_unwrap(smoothed) : smoothed;
|
||||
|
||||
|
||||
|
||||
|
@ -3404,11 +3402,11 @@ Access to the derivative smoothing parameter?
|
|||
// aux="sphere",aux_r=-30,fillet=8, overlap=17);
|
||||
// }
|
||||
// Example(3D,VPT=[0.59633,-3.01826,-3.89606],VPR=[129.2,0,26.4],VPD=192.044,NoScales): Here we have rotated the auxiliary sphere which results in a hole that is off-center through the sphere. Because we rotate the auxiliary object, both ends of the prism have moved. Note that setting k to a large value better matches the bezier curve to the curvature of the sphere, resulting in a better result.
|
||||
// difference(){
|
||||
// spheroid(r=30,circum=true);
|
||||
// join_prism(circle(r=15),base="sphere",base_r=-30, n=15,
|
||||
// aux="sphere",aux_T=xrot(30), aux_r=-30,fillet=8, overlap=17, k=0.9);
|
||||
// }
|
||||
// difference(){
|
||||
// spheroid(r=30,circum=true);
|
||||
// join_prism(circle(r=15),base="sphere",base_r=-30, n=15,
|
||||
// aux="sphere",aux_T=xrot(30), aux_r=-30,fillet=8, overlap=17, k=0.9);
|
||||
// }
|
||||
// Example(3D,VPT=[-12.5956,-5.1125,-0.322237],VPR=[82.3,0,116.7],VPD=213.382,NoScales): Here we adjust just the auxiliary end, which note is at the bottom. We rotate it by 45 deg, but this rotation would normally be relative to the other prism end, so we add a centerpoint based on the radius so that the rotation is relative to the sphere center instead.
|
||||
// difference(){
|
||||
// spheroid(r=30,circum=true);
|
||||
|
@ -3416,14 +3414,14 @@ Access to the derivative smoothing parameter?
|
|||
// aux="sphere",prism_end_T=xrot(45,cp=[0,0,-30]), aux_r=-30,fillet=8, overlap=17, k=0.9);
|
||||
// }
|
||||
// Example(3D,NoScales,VPT=[12.3373,11.6037,-1.87883],VPR=[40.3,0,323.4],VPD=292.705): A diagonal hole through a cylinder with rounded ends, created by shifting the auxiliary prism end along the prism length.
|
||||
// back_half(200)
|
||||
// back_half(200)
|
||||
// difference(){
|
||||
// right(15)xcyl(r=30,l=100,circum=true);
|
||||
// join_prism(circle(r=15),base="cyl",base_r=-30, n=15,
|
||||
// aux="cyl",prism_end_T=right(35),aux_r=-30,fillet=7, overlap=17);
|
||||
// }
|
||||
// Example(3D,NoScales,VPT=[-7.63774,-0.808304,13.8874],VPR=[46.6,0,71.2],VPD=237.091): A hole created by shifting along prism width.
|
||||
// left_half()
|
||||
// left_half()
|
||||
// difference(){
|
||||
// xcyl(r=30,l=100,circum=true);
|
||||
// join_prism(circle(r=15),base="cyl",base_r=-30, n=15,
|
||||
|
|
|
@ -1793,7 +1793,7 @@ module glued_circles(r, spread=10, tangent=30, d, anchor=CENTER, spin=0) {
|
|||
// Examples(2D):
|
||||
// squircle(size=50, squareness=0.4);
|
||||
// squircle([80,60], 0.7, $fn=64);
|
||||
// Example(3D,VPD=48,VPR=[40,0,40],NoAxes): Corner differences between the three squircle styles for squareness=0.5. Style "superellipse" is pink, "fg" is gold, "bezier" is blue.
|
||||
// Example(2D,VPD=48,VPR=[40,0,40],NoAxes): Corner differences between the three squircle styles for squareness=0.5. Style "superellipse" is pink, "fg" is gold, "bezier" is blue.
|
||||
// color("pink") squircle(size=50, style="superellipse", squareness=0.5, $fn=256);
|
||||
// color("yellow") up(1) squircle(size=50, style="fg", squareness=0.5, $fn=256);
|
||||
// color("lightblue") up(2) squircle(size=50, style="bezier", squareness=0.5, $fn=256);
|
||||
|
@ -1854,17 +1854,15 @@ function _squircle_fg(size, squareness) = [
|
|||
) p*[cos(theta), aspect*sin(theta)]
|
||||
];
|
||||
|
||||
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 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 */
|
||||
|
@ -1886,33 +1884,27 @@ 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);
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue