Cleanup of path_resample, add tests for round_corners, fix

bezier_curve and arc to always return n points for either endpoint
setting.
This commit is contained in:
Adrian Mariano 2021-04-02 16:59:29 -04:00
parent 36fed2c670
commit dd13967049
5 changed files with 30 additions and 22 deletions

View file

@ -435,9 +435,11 @@ function bezier_curvature(curve, u) =
// bez = [[0,0], [5,15], [40,20], [60,-15], [80,0]];
// move_copies(bezier_curve(bez, 8)) sphere(r=1.5, $fn=12);
// trace_bezier(bez, N=len(bez)-1);
function bezier_curve(curve,n,endpoint) = [each bezier_points(curve, [0:1/n:(n-0.5)/n]),
if (endpoint) curve[len(curve)-1]
];
function bezier_curve(curve,n,endpoint=true) =
[
each bezier_points(curve, rangex(endpoint?n-1:n,0,1)),
if (endpoint) last(curve)
];
// Function: bezier_segment_closest_point()
// Usage:

View file

@ -1238,15 +1238,17 @@ module path_extrude(path, convexity=10, clipsize=100) {
module path_spread(path, n, spacing, sp=undef, rotate_children=true, closed=false)
{
length = path_length(path,closed);
distances = is_def(sp)? (
is_def(n) && is_def(spacing)? range(s=sp, step=spacing, n=n) :
is_def(n)? range(s=sp, e=length, n=n) :
range(s=sp, step=spacing, e=length)
) : is_def(n) && is_undef(spacing)? (
closed?
let(range=range(s=0,e=length, n=n+1)) list_head(range) :
range(s=0, e=length, n=n)
) : (
distances =
is_def(sp)? ( // Start point given
is_def(n) && is_def(spacing)? range(s=sp, step=spacing, n=n) :
is_def(n)? range(s=sp, e=length, n=n) :
range(s=sp, step=spacing, e=length)
)
: is_def(n) && is_undef(spacing)? ( let(a=echo(n=n)) // N alone given
closed ? rangex(s=0, e=length, n=n)
: range(s=0, e=length, n=n)
)
: ( // No start point and spacing is given, N maybe given
let(
n = is_def(n)? n : floor(length/spacing)+(closed?0:1),
ptlist = range(s=0,step=spacing,n=n),
@ -1600,13 +1602,17 @@ function resample_path(path, N, spacing, closed=false) =
assert(num_defined([N,spacing])==1,"Must define exactly one of N and spacing")
assert(is_bool(closed))
let(
length = path_length(path,closed),
N = is_def(N) ? N : round(length/spacing) + (closed?0:1),
spacing = length/(closed?N:N-1), // Note: worried about round-off error, so don't include
distlist = range(closed?N:N-1,step=spacing), // last point when closed=false
cuts = path_cut_points(path, distlist, closed=closed)
length = path_length(path,closed),
// In the open path case decrease N by 1 so that we don't try to get
// path_cut to return the endpoint (which might fail due to rounding)
// Add last point later
N = is_def(N) ? N-(closed?0:1) : round(length/spacing),
distlist = rangex(N,e=length),
cuts = path_cut_points(path, distlist, closed=closed)
)
concat(subindex(cuts,0),closed?[]:[last(path)]); // Then add last point here
[ each subindex(cuts,0),
if (!closed) last(path) // Then add last point here
];

View file

@ -346,7 +346,7 @@ function _bezcorner(points, parm) =
] : _smooth_bez_fill(points,parm),
N = max(3,$fn>0 ?$fn : ceil(bezier_segment_length(P)/$fs))
)
bezier_curve(P,N,endpoint=true);
bezier_curve(P,N+1,endpoint=true);
function _chamfcorner(points, parm) =
let(

View file

@ -533,7 +533,7 @@ module dashed_stroke(path, dashpat=[3,3], width=1, closed=false) {
function arc(N, r, angle, d, cp, points, width, thickness, start, wedge=false, long=false, cw=false, ccw=false, endpoint=true) =
assert(is_bool(endpoint))
!endpoint ? assert(!wedge, "endpoint cannot be false if wedge is true")
list_head(arc(N,r,angle,d,cp,points,width,thickness,start,wedge,long,cw,ccw,true)) :
list_head(arc(N+1,r,angle,d,cp,points,width,thickness,start,wedge,long,cw,ccw,true)) :
assert(is_undef(N) || is_integer(N), "Number of points must be an integer")
// First try for 2D arc specified by width and thickness
is_def(width) && is_def(thickness)? (
@ -1875,7 +1875,7 @@ function reuleaux_polygon(N=3, r, d, anchor=CENTER, spin=0) =
sa = ca + 180 + (90/N),
ea = ca + 180 - (90/N),
cp = polar_to_xy(r, ca)
) each arc(N=ssegs, r=slen, cp=cp, angle=[sa,ea], endpoint=false)
) each arc(N=ssegs-1, r=slen, cp=cp, angle=[sa,ea], endpoint=false)
],
anchors = [
for (i = [0:1:N-1]) let(

View file

@ -40,7 +40,7 @@ test_turtle();
module test_arc() {
assert_approx(arc(N=8, d=100, angle=135, cp=[10,10]), [[60,10],[57.1941665154,26.5139530978],[49.0915741234,41.1744900929],[36.6016038258,52.3362099614],[21.1260466978,58.7463956091],[4.40177619483,59.6856104947],[-11.6941869559,55.0484433951],[-25.3553390593,45.3553390593]]);
assert_approx(arc(N=8, d=100, angle=135, cp=[10,10],endpoint=false), [[60,10],[57.1941665154,26.5139530978],[49.0915741234,41.1744900929],[36.6016038258,52.3362099614],[21.1260466978,58.7463956091],[4.40177619483,59.6856104947],[-11.6941869559,55.0484433951]]);
assert_approx(arc(N=8, d=100, angle=135, cp=[10,10],endpoint=false), [[60,10],[57.8470167866,24.5142338627],[51.5734806151,37.778511651],[41.7196642082,48.6505226681],[29.1341716183,56.1939766256],[14.9008570165,59.7592363336],[0.245483899194,59.0392640202],[-13.5698368413,54.0960632174]]);
assert_approx(arc(N=8, d=100, angle=[45,225], cp=[10,10]), [[45.3553390593,45.3553390593],[26.5139530978,57.1941665154],[4.40177619483,59.6856104947],[-16.6016038258,52.3362099614],[-32.3362099614,36.6016038258],[-39.6856104947,15.5982238052],[-37.1941665154,-6.51395309776],[-25.3553390593,-25.3553390593]]);
assert_approx(arc(N=8, d=100, start=45, angle=135, cp=[10,10]), [[45.3553390593,45.3553390593],[31.6941869559,55.0484433951],[15.5982238052,59.6856104947],[-1.12604669782,58.7463956091],[-16.6016038258,52.3362099614],[-29.0915741234,41.1744900929],[-37.1941665154,26.5139530978],[-40,10]]);
assert_approx(arc(N=8, d=100, start=45, angle=-90, cp=[10,10]), [[45.3553390593,45.3553390593],[52.3362099614,36.6016038258],[57.1941665154,26.5139530978],[59.6856104947,15.5982238052],[59.6856104947,4.40177619483],[57.1941665154,-6.51395309776],[52.3362099614,-16.6016038258],[45.3553390593,-25.3553390593]]);