From 3790783cdcfbde82da23db5319a9b71b2030a72e Mon Sep 17 00:00:00 2001 From: Adrian Mariano Date: Sun, 24 Jan 2021 10:29:34 -0500 Subject: [PATCH] Rename zip to hstack and associated changes. --- arrays.scad | 105 +++++++++++++++++++++++------------------ paths.scad | 15 +++--- rounding.scad | 16 +++---- tests/test_arrays.scad | 23 +++++++-- 4 files changed, 97 insertions(+), 62 deletions(-) diff --git a/arrays.scad b/arrays.scad index 42b2c05..d41febe 100644 --- a/arrays.scad +++ b/arrays.scad @@ -1243,55 +1243,45 @@ function submatrix(M,idx1,idx2) = [for(i=idx1) [for(j=idx2) M[i][j] ] ]; -// Function: zip() -// Usage: Zipping Two Lists -// pairs = zip(v1, v2, , ); -// for (p = zip(v1, v2, , ) ... -// Usage: Zipping Three Lists -// triplets = zip(v1, v2, v3, <*fit*>, <*fill*>); -// for (t = zip(v1, v2, v3, <*fit*>, <*fill*>)) ... -// Usage: Zipping N Lists -// zips = zip(LISTS, <*fit*>, <*fill*>); -// for (z = zip(LISTS, <*fit*>, <*fill*>)) ... +// Function: hstack() +// Usage: +// A = hstack(M1, M2) +// A = hstack(M1, M2, M3) +// A = hstack([M1, M2, M3, ...]) // Description: -// Zips together corresponding items from two or more lists. Returns a list of lists, -// where each sublist contains corresponding items from each of the input lists. -// ie: For three lists, `[[A0, B0, C0], [A1, B1, C1], [A2, B2, C2], ...]` +// Constructs a matrix by horizontally "stacking" together compatible matrices or vectors. Vectors are treated as columsn in the stack. +// This command is the inverse of subindex. Note: strings are broken apart into lists of characters. // Arguments: -// v1 = The first list if given with `v1`/`v2`. A list of two or more lists to zipper, without `v1`/`v2`. -// v2 = A second list. -// v2 = A third list. -// --- -// fit = If `fit=="short"`, the zips together up to the length of the shortest list in vecs. If `fit=="long"`, then pads all lists to the length of the longest, using the value in `fill`. If `fit==false`, then requires all lists to be the same length. Default: false. -// fill = The default value to fill in with if one or more lists if short. Default: undef +// M1 = If given with other arguments, the first matrix (or vector) to stack. If given alone, a list of matrices/vectors to stack. +// M2 = Second matrix/vector to stack +// M3 = Third matrix/vector to stack. // Example: -// v1 = [1,2,3,4]; +// M = ident(3); +// v1 = [2,3,4]; // v2 = [5,6,7]; -// v3 = [8,9,10,11]; -// a = zip(v1,v3); // returns [[1,8], [2,9], [3,10], [4,11]] -// b = zip([v1,v3]); // returns [[1,8], [2,9], [3,10], [4,11]] -// c = zip([v1,v2], fit="short"); // returns [[1,5], [2,6], [3,7]] -// d = zip([v1,v2], fit="long"); // returns [[1,5], [2,6], [3,7], [4,undef]] -// e = zip([v1,v2], fit="long, fill=0); // returns [[1,5], [2,6], [3,7], [4,0]] -// f = zip(v1,v2,v3, fit="long"); // returns [[1,5,8], [2,6,9], [3,7,10], [4,undef,11]] -// g = zip([v1,v2,v3], fit="long"); // returns [[1,5,8], [2,6,9], [3,7,10], [4,undef,11]] -// Example: -// v1 = [[1,2,3], [4,5,6], [7,8,9]]; -// v2 = [[20,19,18], [17,16,15], [14,13,12]]; -// zip(v1,v2); // Returns [[1,2,3,20,19,18], [4,5,6,17,16,15], [7,8,9,14,13,12]] -function zip(v1, v2, v3, fit=false, fill=undef) = - (v3!=undef)? zip([v1,v2,v3], fit=fit, fill=fill) : - (v2!=undef)? zip([v1,v2], fit=fit, fill=fill) : - assert(in_list(fit, [false, "short", "long"]), "Invalid fit value." ) - assert(all([for(v=v1) is_list(v)]), "One of the inputs to zip is not a list") +// v3 = [8,9,10]; +// a = hstack(v1,v2); // Returns [[2, 5], [3, 6], [4, 7]] +// b = hstack(v1,v2,v3); // Returns [[2, 5, 8], +// // [3, 6, 9], +// // [4, 7, 10]] +// c = hstack([M,v1,M]); // Returns [[1, 0, 0, 2, 1, 0, 0], +// // [0, 1, 0, 3, 0, 1, 0], +// // [0, 0, 1, 4, 0, 0, 1]] +// d = hstack(subindex(M,0), subindex(M,[1 2])); // Returns M +function hstack(M1, M2, M3) = + (M3!=undef)? hstack([M1,M2,M3]) : + (M2!=undef)? hstack([M1,M2]) : + assert(all([for(v=M1) is_list(v)]), "One of the inputs to hstack is not a list") let( - minlen = list_shortest(v1), - maxlen = list_longest(v1) + minlen = list_shortest(M1), + maxlen = list_longest(M1) ) - assert(fit!=false || minlen==maxlen, "Input vectors to zip must have the same length") - fit == "long" - ? [for(i=[0:1:maxlen-1]) [for(v=v1) for(x=(i= (closed ? 3 : 2)) assert(long_enough,len(path)<2 ? "Two points needed to define a path" : "Closed path must include three points") - !is_list(dists)? path_cut(path, [dists],closed, direction)[0] : - let(cuts = _path_cut(path,dists,closed)) - !direction ? cuts : let( - dir = _path_cuts_dir(path, cuts, closed), - normals = _path_cuts_normals(path, cuts, dir, closed) - ) zip(cuts, array_group(dir,1), array_group(normals,1)); + !is_list(dists)? path_cut(path, [dists],closed, direction)[0] + : let(cuts = _path_cut(path,dists,closed)) + !direction + ? cuts + : let( + dir = _path_cuts_dir(path, cuts, closed), + normals = _path_cuts_normals(path, cuts, dir, closed) + ) + hstack(cuts, array_group(dir,1), array_group(normals,1)); // Main recursive path cut function function _path_cut(path, dists, closed=false, pind=0, dtotal=0, dind=0, result=[]) = diff --git a/rounding.scad b/rounding.scad index e48700b..83e4b28 100644 --- a/rounding.scad +++ b/rounding.scad @@ -155,7 +155,7 @@ include // $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(repeat([-10,10],8)), [-10,0]); -// zig = zip(zigzagx,zigzagy); +// zig = hstack(zigzagx,zigzagy); // stroke(zig,width=1); // Original shape // fwd(20) // Smooth size corners with a cut of 4 and curvature parameter 0.6 // stroke(round_corners(zig,cut=4, k=0.6, method="smooth", closed=false),width=1); @@ -190,9 +190,9 @@ include // $fn=36; // square = [[0,0],[1,0],[1,1],[0,1]]; // 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 +// 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 +// path3d = hstack(spiral,z); // 3D spiral // rounding = squareind/20; // // Setting k=1 means curvature won't be continuous, but curves are as round as possible // // Try changing the value to see the effect. @@ -772,9 +772,9 @@ function _path_join(paths,joint,k=0.5,i=0,result=[],relocate=true,closed=false) // rounded_star = round_corners(star, cut=flatten(repeat([.5,0],5)), $fn=24); // 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(star, cut=flatten(repeat([.5,0],5)), $fn=24); -// offset_sweep(rounded_star, height=20, bottom=os_circle(r=-4), top=os_circle(r=-1), steps=15); + star = star(5, r=22, ir=13); + rounded_star = round_corners(star, cut=flatten(repeat([.5,0],5)), $fn=24); + 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]]; // offset_sweep(triangle, height=6, bottom = os_circle(r=-2),steps=16,offset_maxstep=0.25); @@ -914,7 +914,7 @@ function _make_offset_polyhedron(path,offsets, offset_type, flip_faces, quality, offsetind+1, vertexcount+len(path), vertices=concat( vertices, - zip(vertices_faces[0],repeat(offsets[offsetind][1],len(vertices_faces[0]))) + path3d(vertices_faces[0],offsets[offsetind][1]) ), faces=concat(faces, vertices_faces[1]) ) @@ -993,7 +993,7 @@ function offset_sweep( ), top_start_ind = len(vertices_faces_bot[0]), - initial_vertices_top = zip(path, repeat(middle,len(path))), + initial_vertices_top = path3d(path, middle), vertices_faces_top = _make_offset_polyhedron( path, move(p=offsets_top,[0,middle]), struct_val(top,"offset"), !clockwise, diff --git a/tests/test_arrays.scad b/tests/test_arrays.scad index aac41d4..ea40502 100644 --- a/tests/test_arrays.scad +++ b/tests/test_arrays.scad @@ -501,15 +501,32 @@ module test_zip() { assert(zip([v1,v2],fit="long", fill=0) == [[1,5],[2,6],[3,7],[4,0]]); assert(zip([v1,v2,v3],fit="long") == [[1,5,8],[2,6,9],[3,7,10],[4,undef,11]]); } -test_zip(); +//test_zip(); + +module test_hstack() { + M = ident(3); + v1 = [2,3,4]; + v2 = [5,6,7]; + v3 = [8,9,10]; + a = hstack(v1,v2); + b = hstack(v1,v2,v3); + c = hstack([M,v1,M]); + d = hstack(subindex(M,0), subindex(M,[1, 2])); + assert_equal(a,[[2, 5], [3, 6], [4, 7]]); + assert_equal(b,[[2, 5, 8], [3, 6, 9], [4, 7, 10]]); + assert_equal(c,[[1, 0, 0, 2, 1, 0, 0], [0, 1, 0, 3, 0, 1, 0], [0, 0, 1, 4, 0, 0, 1]]); + assert_equal(d,M); +} +test_hstack(); + module test_block_matrix() { A = [[1,2],[3,4]]; B = ident(2); assert_equal(block_matrix([[A,B],[B,A],[A,B]]), [[1,2,1,0],[3,4,0,1],[1,0,1,2],[0,1,3,4],[1,2,1,0],[3,4,0,1]]); assert_equal(block_matrix([[A,B],ident(4)]), [[1,2,1,0],[3,4,0,1],[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]]); - text = [["a","b"],["c","d"]]; - assert_equal(block_matrix([[text,B]]), [["a","b",1,0],["c","d",0,1]]); + text = [["aa","bb"],["cc","dd"]]; + assert_equal(block_matrix([[text,B]]), [["aa","bb",1,0],["cc","dd",0,1]]); } test_block_matrix();