diff --git a/arrays.scad b/arrays.scad index 2c0f36b..7a4acb7 100644 --- a/arrays.scad +++ b/arrays.scad @@ -153,9 +153,9 @@ function list_decreasing(list) = // Section: Basic List Generation -// Function: replist() +// Function: repeat() // Usage: -// replist(val, n) +// repeat(val, n) // Description: // Generates a list or array of `n` copies of the given `list`. // If the count `n` is given as a list of counts, then this creates a @@ -164,14 +164,14 @@ function list_decreasing(list) = // val = The value to repeat to make the list or array. // n = The number of copies to make of `val`. // Example: -// replist(1, 4); // Returns [1,1,1,1] -// replist(8, [2,3]); // Returns [[8,8,8], [8,8,8]] -// replist(0, [2,2,3]); // Returns [[[0,0,0],[0,0,0]], [[0,0,0],[0,0,0]]] -// replist([1,2,3],3); // Returns [[1,2,3], [1,2,3], [1,2,3]] -function replist(val, n, i=0) = +// repeat(1, 4); // Returns [1,1,1,1] +// repeat(8, [2,3]); // Returns [[8,8,8], [8,8,8]] +// repeat(0, [2,2,3]); // Returns [[[0,0,0],[0,0,0]], [[0,0,0],[0,0,0]]] +// repeat([1,2,3],3); // Returns [[1,2,3], [1,2,3], [1,2,3]] +function repeat(val, n, i=0) = is_num(n)? [for(j=[1:1:n]) val] : (i>=len(n))? val : - [for (j=[1:1:n[i]]) replist(val, n, i+1)]; + [for (j=[1:1:n[i]]) repeat(val, n, i+1)]; // Function: list_range() @@ -308,11 +308,11 @@ function repeat_entries(list, N, exact = true) = length = len(list), reps_guess = is_list(N)? assert(len(N)==len(list), "Vector parameter N to repeat_entries has the wrong length") - N : replist(N/length,length), + N : repeat(N/length,length), reps = exact? _sum_preserving_round(reps_guess) : [for (val=reps_guess) round(val)] ) - [for(i=[0:length-1]) each replist(list[i],reps[i])]; + [for(i=[0:length-1]) each repeat(list[i],reps[i])]; // Function: list_set() @@ -357,7 +357,7 @@ function list_set(list=[],indices,values,dflt=0,minlen=0) = ) ], slice(list,1+lastind, len(list)), - replist(dflt, minlen-lastind-1) + repeat(dflt, minlen-lastind-1) ); @@ -487,7 +487,7 @@ function list_bset(indexset, valuelist, dflt=0) = trueind = search([true], indexset,0)[0] ) concat( list_set([],trueind, valuelist, dflt=dflt), // Fill in all of the values - replist(dflt,len(indexset)-max(trueind)-1) // Add trailing values so length matches indexset + repeat(dflt,len(indexset)-max(trueind)-1) // Add trailing values so length matches indexset ); @@ -523,7 +523,7 @@ function list_longest(vecs) = // fill = The value to pad the list with. function list_pad(v, minlen, fill=undef) = assert(is_list(v)||is_string(list)) - concat(v,replist(fill,minlen-len(v))); + concat(v,repeat(fill,minlen-len(v))); // Function: list_trim() diff --git a/beziers.scad b/beziers.scad index e8272e4..f9f31f0 100644 --- a/beziers.scad +++ b/beziers.scad @@ -330,18 +330,17 @@ function bezier_polyline(bezier, splinesteps=16, N=3) = let( // path = path of points to define the bezier // tangents = optional list of tangent vectors at every point // closed = set to true for a closed path. Default: false -function path_to_bezier(path, tangent, closed=false) = +function path_to_bezier(path, tangents, closed=false) = assert(is_path(path,dim=undef),"Input path is not a valid path") - assert(is_undef(tangent) || is_path(tangent,dim=len(path[0])),"Tangent must be a path of the same dimension as the input path") + assert(is_undef(tangents) || is_path(tangents,dim=len(path[0])),"Tangents must be a path of the same dimension as the input path") let( - tangent = is_def(tangent)? [for(t=tangent) unit(t)] : path_tangents(path, closed=closed), + tangents = is_def(tangents)? tangents : deriv(path, closed=closed), lastpt = len(path) - (closed?0:1) ) - [for(i=[0:lastpt-1]) each [path[i], path[i]+tangent[i], select(path,i+1)-select(tangent,i+1)], + [for(i=[0:lastpt-1]) each [path[i], path[i]+tangents[i]/3, select(path,i+1)-select(tangents,i+1)/3], select(path,lastpt)]; - // Function: fillet_path() // Usage: // fillet_path(pts, fillet, [maxerr]); diff --git a/coords.scad b/coords.scad index 033830f..2d3edd0 100644 --- a/coords.scad +++ b/coords.scad @@ -31,7 +31,7 @@ function point2d(p, fill=0) = [for (i=[0:1]) (p[i]==undef)? fill : p[i]]; // fill = Value to fill missing values in vectors with. function path2d(points) = assert(is_path(points,dim=undef,fast=true),"Input to path2d is not a path") - let (result = points * concat(ident(2), replist([0,0], len(points[0])-2))) + let (result = points * concat(ident(2), repeat([0,0], len(points[0])-2))) assert(is_def(result), "Invalid input to path2d") result; @@ -58,11 +58,11 @@ function path3d(points, fill=0) = let ( change = len(points[0])-3, M = change < 0? [[1,0,0],[0,1,0]] : - concat(ident(3), replist([0,0,0],change)), + concat(ident(3), repeat([0,0,0],change)), result = points*M ) assert(is_def(result), "Input to path3d is invalid") - fill == 0 || change>=0 ? result : result + replist([0,0,fill], len(result)); + fill == 0 || change>=0 ? result : result + repeat([0,0,fill], len(result)); // Function: point4d() @@ -87,17 +87,17 @@ function path4d(points, fill=0) = let ( change = len(points[0])-4, M = change < 0 ? select(ident(4), 0, len(points[0])-1) : - concat(ident(4), replist([0,0,0,0],change)), + concat(ident(4), repeat([0,0,0,0],change)), result = points*M ) assert(is_def(result), "Input to path4d is invalid") fill == 0 || change >= 0 ? result : let( addition = is_list(fill) ? concat(0*points[0],fill) : - concat(0*points[0],replist(fill,-change)) + concat(0*points[0],repeat(fill,-change)) ) assert(len(addition) == 4, "Fill is the wrong length") - result + replist(addition, len(result)); + result + repeat(addition, len(result)); // Function: translate_points() diff --git a/math.scad b/math.scad index ec4898e..74a4a8b 100644 --- a/math.scad +++ b/math.scad @@ -590,7 +590,7 @@ function _qr_factor(A,Q, column, m, n) = let( x = [for(i=[column:1:m-1]) A[i][column]], alpha = (x[0]<=0 ? 1 : -1) * norm(x), - u = x - concat([alpha],replist(0,m-1)), + u = x - concat([alpha],repeat(0,m-1)), v = u / norm(u), Qc = ident(len(x)) - 2*transpose([v])*[v], Qf = [for(i=[0:m-1]) [for(j=[0:m-1]) i1 && let( d = len(list[0]) ) (is_undef(dim) || in_list(d, force_list(dim))) && - is_list_of(list, replist(0,d)); + is_list_of(list, repeat(0,d)); // Function: is_closed_path() @@ -1126,7 +1126,7 @@ function _path_cut(path, dists, closed=false, pind=0, dtotal=0, dind=0, result=[ [lerp(lastpt,path[pind], (dists[dind]-dtotal)/dpartial),pind] : _path_cut_single(path, dists[dind]-dtotal-dpartial, closed, pind) ) is_undef(nextpoint)? - concat(result, replist(undef,len(dists)-dind)) : + concat(result, repeat(undef,len(dists)-dind)) : _path_cut(path, dists, closed, nextpoint[1], dists[dind],dind+1, concat(result, [nextpoint])); // Search for a single cut point in the path @@ -1260,7 +1260,7 @@ function subdivide_path(path, N, closed=true, exact=true, method="length") = is_list(N)? ( assert(len(N)==count,"Vector parameter N to subdivide_path has the wrong length") add_scalar(N,-1) - ) : replist((N-len(path)) / count, count) + ) : repeat((N-len(path)) / count, count) ) : // method=="length" assert(is_num(N),"Parameter N to subdivide path must be a number when method=\"length\"") let( diff --git a/regions.scad b/regions.scad index 09f7c91..b8939dc 100644 --- a/regions.scad +++ b/regions.scad @@ -499,7 +499,7 @@ function offset( d = flip_dir * (is_def(r) ? r : delta), shiftsegs = [for(i=[0:len(path)-1]) _shift_segment(select(path,i,i+1), d)], // good segments are ones where no point on the segment is less than distance d from any point on the path - good = check_valid ? _good_segments(path, abs(d), shiftsegs, closed, quality) : replist(true,len(shiftsegs)), + good = check_valid ? _good_segments(path, abs(d), shiftsegs, closed, quality) : repeat(true,len(shiftsegs)), goodsegs = bselect(shiftsegs, good), goodpath = bselect(path,good) ) @@ -569,7 +569,7 @@ function offset( ) ], pointcount = (is_def(delta) && !chamfer)? - replist(1,len(sharpcorners)) : + repeat(1,len(sharpcorners)) : [for(i=[0:len(goodsegs)-1]) len(newcorners[i])], start = [goodsegs[0][0]], end = [goodsegs[len(goodsegs)-2][1]], diff --git a/rounding.scad b/rounding.scad index bcec54b..4987f21 100644 --- a/rounding.scad +++ b/rounding.scad @@ -161,7 +161,7 @@ include // $fs=.25; // $fa=1; // zigzagx = [-10, 0, 10, 20, 29, 38, 46, 52, 59, 66, 72, 78, 83, 88, 92, 96, 99, 102, 112]; -// zigzagy = concat([0], flatten(replist([-10,10],8)), [-10,0]); +// zigzagy = concat([0], flatten(repeat([-10,10],8)), [-10,0]); // zig = zip(zigzagx,zigzagy); // stroke(zig,width=1); // Original shape // fwd(20) // Smooth size corners with a cut of 4 and curvature parameter 0.6 @@ -194,7 +194,7 @@ include // Example(FlatSpin): Rounding a spiral with increased rounding along the length // // Construct a square spiral path in 3D // square = [[0,0],[1,0],[1,1],[0,1]]; -// spiral = flatten(replist(concat(square,reverse(square)),5)); // Squares repeat 10 times, forward and backward +// spiral = flatten(repeat(concat(square,reverse(square)),5)); // Squares repeat 10 times, forward and backward // squareind = [for(i=[0:9]) each [i,i,i,i]]; // Index of the square for each point // z = list_range(40)*.2+squareind; // path3d = zip(spiral,z); // 3D spiral @@ -246,7 +246,7 @@ function round_corners(path, curve="circle", measure="cut", size=undef, k=0.5, dim = pathdim - 1 + have_size, points = have_size ? path : subindex(path, [0:dim-1]), parm = have_size && is_list(size) && len(size)>2? size : - have_size? replist(size, len(path)) : + have_size? repeat(size, len(path)) : subindex(path, dim), // dk will be a list of parameters, for the "smooth" curve the distance and curvature parameter pair, // and for the "circle" curve, distance and radius. @@ -409,12 +409,12 @@ function _rounding_offsets(edgespec,z_dir=1) = // Function: smooth_path() // Usage: -// smooth_path(path, [tangent], [splinesteps], [closed] +// smooth_path(path, [tangents], [splinesteps], [closed] // Description: // Smooths the input path using a cubic spline. Every segment of the path will be replaced by a cubic curve // with `splinesteps` points. The cubic interpolation will pass through every input point on the path // and will match the tangents at every point. If you do not specify tangents they will be computed using -// path_tangents(). See also path_to_bezier(). +// deriv(). Note that the magnitude of the tangents affects the result. See also path_to_bezier(). // Arguments: // path = path to smooth // tangents = tangent vectors of the path @@ -425,14 +425,20 @@ function _rounding_offsets(edgespec,z_dir=1) = // stroke(smooth_path(square(4)), width=0.1); // Example(2D): Closing the path changes the end tangents // polygon(smooth_path(square(4), closed=true)); -// Example(2D): You can specify your own tangent values to alter the shape of the curve -// polygon(smooth_path(square(4),tangent=[[-2,-1], [-2,1], [1,2], [2,-1]],closed=true)); +// Example(2D): A more interesting shape: +// path = [[0,0], [4,0], [7,14], [-3,12]]; +// polygon(smooth_path(path,closed=true)); +// Example(2D): Scaling the tangent data can decrease or increase the amount of smoothing: +// shape = square(4); +// polygon(smooth_path(shape, tangents=0.5*deriv(shape, closed=true),closed=true)); +// Example(2D): Or you can specify your own tangent values to alter the shape of the curve +// polygon(smooth_path(square(4),tangents=1.25*[[-2,-1], [-2,1], [1,2], [2,-1]],closed=true)); // Example(FlatSpin): Works on 3d paths as well // path = [[0,0,0],[3,3,2],[6,0,1],[9,9,0]]; // trace_polyline(smooth_path(path),size=.3); -function smooth_path(path, tangent, splinesteps=10, closed=false) = +function smooth_path(path, tangents, splinesteps=10, closed=false) = let( - bez = path_to_bezier(path, tangent=tangent, closed=closed) + bez = path_to_bezier(path, tangents=tangents, closed=closed) ) bezier_polyline(bez,splinesteps=splinesteps); @@ -526,11 +532,11 @@ function smooth_path(path, tangent, splinesteps=10, closed=false) = // // Example: Rounding a star shaped prism with postive radius values // star = star(5, r=22, ir=13); -// rounded_star = round_corners(zip(star, flatten(replist([.5,0],5))), curve="circle", measure="cut", $fn=12); +// rounded_star = round_corners(zip(star, flatten(repeat([.5,0],5))), curve="circle", measure="cut", $fn=12); // offset_sweep(rounded_star, height=20, bottom=os_circle(r=4), top=os_circle(r=1), steps=15); // Example: Rounding a star shaped prism with negative radius values // star = star(5, r=22, ir=13); -// rounded_star = round_corners(zip(star, flatten(replist([.5,0],5))), curve="circle", measure="cut", $fn=12); +// rounded_star = round_corners(zip(star, flatten(repeat([.5,0],5))), curve="circle", measure="cut", $fn=12); // offset_sweep(rounded_star, height=20, bottom=os_circle(r=-4), top=os_circle(r=-1), steps=15); // Example: Unexpected corners in the result even with `offset="round"` (the default), even with offset_maxstep set small. // triangle = [[0,0],[10,0],[5,10]]; @@ -543,7 +549,7 @@ function smooth_path(path, tangent, splinesteps=10, closed=false) = // offset_sweep(triangle, height=6, bottom = os_circle(r=-2),steps=16,offset_maxstep=0.01); // Example: Here is the star chamfered at the top with a teardrop rounding at the bottom. Check out the rounded corners on the chamfer. Note that a very small value of `offset_maxstep` is needed to keep these round. Observe how the rounded star points vanish at the bottom in the teardrop: the number of vertices does not remain constant from layer to layer. // star = star(5, r=22, ir=13); -// rounded_star = round_corners(zip(star, flatten(replist([.5,0],5))), curve="circle", measure="cut", $fn=12); +// rounded_star = round_corners(zip(star, flatten(repeat([.5,0],5))), curve="circle", measure="cut", $fn=12); // offset_sweep(rounded_star, height=20, bottom=os_teardrop(r=4), top=os_chamfer(width=4,offset_maxstep=.1)); // Example: We round a cube using the continous curvature rounding profile. But note that the corners are not smooth because the curved square collapses into a square with corners. When a collapse like this occurs, we cannot turn `check_valid` off. // square = [[0,0],[1,0],[1,1],[0,1]]; @@ -594,7 +600,7 @@ function smooth_path(path, tangent, splinesteps=10, closed=false) = // } // Example: Star shaped box // star = star(5, r=22, ir=13); -// rounded_star = round_corners(zip(star, flatten(replist([.5,0],5))), curve="circle", measure="cut", $fn=12); +// rounded_star = round_corners(zip(star, flatten(repeat([.5,0],5))), curve="circle", measure="cut", $fn=12); // thickness = 2; // ht=20; // difference(){ @@ -606,12 +612,12 @@ function smooth_path(path, tangent, splinesteps=10, closed=false) = // } // Example: A profile defined by an arbitrary sequence of points. // star = star(5, r=22, ir=13); -// rounded_star = round_corners(zip(star, flatten(replist([.5,0],5))), curve="circle", measure="cut", $fn=12); +// rounded_star = round_corners(zip(star, flatten(repeat([.5,0],5))), curve="circle", measure="cut", $fn=12); // profile = os_profile(points=[[0,0],[.3,.1],[.6,.3],[.9,.9], [1.2, 2.7],[.8,2.7],[.8,3]]); // offset_sweep(reverse(rounded_star), height=20, top=profile, bottom=profile); // Example: Parabolic rounding // star = star(5, r=22, ir=13); -// rounded_star = round_corners(zip(star, flatten(replist([.5,0],5))), curve="circle", measure="cut", $fn=12); +// rounded_star = round_corners(zip(star, flatten(repeat([.5,0],5))), curve="circle", measure="cut", $fn=12); // offset_sweep(rounded_star, height=20, top=os_profile(points=[for(r=[0:.1:2])[sqr(r),r]]), // bottom=os_profile(points=[for(r=[0:.2:5])[-sqrt(r),r]])); // Example: This example uses a sine wave offset profile. Note that because the offsets occur sequentially and the path grows incrementally the offset needs a very fine resolution to produce the proper result. Note that we give no specification for the bottom, so it is straight. @@ -671,7 +677,7 @@ module offset_sweep( offsetind+1, vertexcount+len(path), vertices=concat( vertices, - zip(vertices_faces[0],replist(offsets[offsetind][1],len(vertices_faces[0]))) + zip(vertices_faces[0],repeat(offsets[offsetind][1],len(vertices_faces[0]))) ), faces=concat(faces, vertices_faces[1]) ) @@ -740,7 +746,7 @@ module offset_sweep( ); top_start_ind = len(vertices_faces_bot[0]); - initial_vertices_top = zip(path, replist(middle,len(path))); + initial_vertices_top = zip(path, repeat(middle,len(path))); vertices_faces_top = make_polyhedron( path, translate_points(offsets_top,[0,middle]), struct_val(top,"offset"), !clockwise, diff --git a/shapes2d.scad b/shapes2d.scad index d4a1993..c913e27 100644 --- a/shapes2d.scad +++ b/shapes2d.scad @@ -406,7 +406,7 @@ function _normal_segment(p1,p2) = // path = turtle(["move","left",360/5,"addlength",1],repeat=50); // stroke(path,width=.2); // Example(2DMed): yet another spiral, without using `repeat` -// path = turtle(concat(["angle",71],flatten(replist(["move","left","addlength",1],50)))); +// path = turtle(concat(["angle",71],flatten(repeat(["move","left","addlength",1],50)))); // stroke(path,width=.2); // Example(2DMed): The previous spiral grows linearly and eventually intersects itself. This one grows geometrically and does not. // path = turtle(["move","left",71,"scale",1.05],repeat=50); diff --git a/skin.scad b/skin.scad index c4fba71..346b173 100644 --- a/skin.scad +++ b/skin.scad @@ -211,7 +211,7 @@ include // skin( shapes, slices=0); // Example: You can fix it by specifying "tangent" for the first method, but you still need "direct" for the rest. // shapes = [for(i=[0:.2:1]) path3d(regular_ngon(n=4, side=4, rounding=i, $fn=32),i*5)]; -// skin( shapes, slices=0, method=concat(["tangent"],replist("direct",len(shapes)-2))); +// skin( shapes, slices=0, method=concat(["tangent"],repeat("direct",len(shapes)-2))); // Example(FlatSpin): Connecting square to pentagon using "direct" method. // skin([regular_ngon(n=4, r=4), regular_ngon(n=5,r=5)], z=[0,4], refine=10, slices=10); // Example(FlatSpin): Connecting square to shifted pentagon using "direct" method. @@ -335,14 +335,14 @@ function skin(profiles, slices, refine=1, method="direct", sampling, caps, close closed ? false : true, capsOK = is_bool(caps) || (is_list(caps) && len(caps)==2 && is_bool(caps[0]) && is_bool(caps[1])), fullcaps = is_bool(caps) ? [caps,caps] : caps, - refine = is_list(refine) ? refine : replist(refine, len(profiles)), - slices = is_list(slices) ? slices : replist(slices, profcount), + refine = is_list(refine) ? refine : repeat(refine, len(profiles)), + slices = is_list(slices) ? slices : repeat(slices, profcount), refineOK = [for(i=idx(refine)) if (refine[i]<=0 || !is_integer(refine[i])) i], slicesOK = [for(i=idx(slices)) if (!is_integer(slices[i]) || slices[i]<0) i], maxsize = list_longest(profiles), methodok = is_list(method) || in_list(method, legal_methods), methodlistok = is_list(method) ? [for(i=idx(method)) if (!in_list(method[i], legal_methods)) i] : [], - method = is_string(method) ? replist(method, profcount) : method, + method = is_string(method) ? repeat(method, profcount) : method, // Define to be zero where a resampling method is used and 1 where a vertex duplicator is used RESAMPLING = 0, DUPLICATOR = 1, @@ -382,7 +382,7 @@ function skin(profiles, slices, refine=1, method="direct", sampling, caps, close method_type[i] * method_type[i-1])], parts = search(1,[1,for(i=[0:1:len(profile_resampled)-2]) profile_resampled[i]!=profile_resampled[i+1] ? 1 : 0],0), plen = [for(i=idx(parts)) (i== len(parts)-1? len(refined_len) : parts[i+1]) - parts[i]], - max_list = [for(i=idx(parts)) each replist(max(select(refined_len, parts[i], parts[i]+plen[i]-1)), plen[i])], + max_list = [for(i=idx(parts)) each repeat(max(select(refined_len, parts[i], parts[i]+plen[i]-1)), plen[i])], transition_profiles = [for(i=[(closed?0:1):1:profcount-1]) if (select(method_type,i-1) != method_type[i]) i], badind = [for(tranprof=transition_profiles) if (refined_len[tranprof] != max_list[tranprof]) tranprof] ) @@ -515,7 +515,7 @@ function slice_profiles(profiles,slices,closed=false) = let(listok = !is_list(slices) || len(slices)==len(profiles)-(closed?0:1)) assert(listok, "Input slices to slice_profiles is a list with the wrong length") let( - count = is_num(slices) ? replist(slices,len(profiles)-(closed?0:1)) : slices, + count = is_num(slices) ? repeat(slices,len(profiles)-(closed?0:1)) : slices, slicelist = [for (i=[0:len(profiles)-(closed?1:2)]) each [for(j = [0:count[i]]) lerp(profiles[i],select(profiles,i+1),j/(count[i]+1))] ] @@ -591,7 +591,7 @@ function _dp_distance_array(small, big, abort_thresh=1/0) = function _dp_distance_row(small, big, small_ind, tdist) = // Top left corner is zero because it gets counted at the end in bottom right corner - small_ind == 0 ? [cumsum([0,for(i=[1:len(big)]) norm(big[i%len(big)]-small[0])]), replist(_MAP_LEFT,len(big)+1)] : + small_ind == 0 ? [cumsum([0,for(i=[1:len(big)]) norm(big[i%len(big)]-small[0])]), repeat(_MAP_LEFT,len(big)+1)] : [for(big_ind=1, newrow=[ norm(big[0] - small[small_ind%len(small)]) + tdist[small_ind-1][0] ], newmap = [_MAP_UP] @@ -1151,7 +1151,7 @@ function path_sweep(shape, path, method="incremental", normal, closed=false, twi normal = is_path(normal) ? [for(n=normal) unit(n)] : is_def(normal) ? unit(normal) : method =="incremental" && abs(tangents[0].z) > 1/sqrt(2) ? BACK : UP, - normals = is_path(normal) ? normal : replist(normal,len(path)), + normals = is_path(normal) ? normal : repeat(normal,len(path)), pathfrac = twist_by_length ? path_length_fractions(path, closed) : [for(i=[0:1:len(path)]) i / (len(path)-(closed?0:1))], L = len(path), transform_list =