mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2024-12-29 16:29:40 +00:00
Merge pull request #396 from adrianVmariano/master
rename zip to hstack
This commit is contained in:
commit
e622af588c
4 changed files with 112 additions and 62 deletions
116
arrays.scad
116
arrays.scad
|
@ -1243,55 +1243,56 @@ function submatrix(M,idx1,idx2) =
|
|||
[for(i=idx1) [for(j=idx2) M[i][j] ] ];
|
||||
|
||||
|
||||
// Function: zip()
|
||||
// Usage: Zipping Two Lists
|
||||
// pairs = zip(v1, v2, <fit>, <fill>);
|
||||
// for (p = zip(v1, v2, <fit>, <fill>) ...
|
||||
// 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 given in vectors are broken apart into lists of characters. Strings given
|
||||
// in matrices are preserved as strings. If you need to combine vectors of strings use array_group as shown below to convert the
|
||||
// vector into a column matrix. Also note that vertical stacking can be done directly with concat.
|
||||
// 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
|
||||
// strvec = ["one","two"];
|
||||
// strmat = [["three","four"], ["five","six"]];
|
||||
// e = hstack(strvec,strvec); // Returns [["o", "n", "e", "o", "n", "e"],
|
||||
// // ["t", "w", "o", "t", "w", "o"]]
|
||||
// f = hstack(array_group(strvec,1), array_group(strvec,1));
|
||||
// // Returns [["one", "one"],
|
||||
// // ["two", "two"]]
|
||||
// g = hstack(strmat,strmat); // Returns: [["three", "four", "three", "four"],
|
||||
// // [ "five", "six", "five", "six"]]
|
||||
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<len(v)? v[i] : (fill==undef)? [fill] : fill)) x] ]
|
||||
: [for(i=[0:1:minlen-1]) [for(v=v1) for(x=v[i]) x] ];
|
||||
assert(minlen==maxlen, "Input vectors to hstack must have the same length")
|
||||
[for(row=[0:1:minlen-1])
|
||||
[for(matrix=M1)
|
||||
each matrix[row]
|
||||
]
|
||||
];
|
||||
|
||||
|
||||
// Function: block_matrix()
|
||||
|
@ -1301,10 +1302,35 @@ function zip(v1, v2, v3, fit=false, fill=undef) =
|
|||
// Create a block matrix by supplying a matrix of matrices, which will
|
||||
// be combined into one unified matrix. Every matrix in one row
|
||||
// must have the same height, and the combined width of the matrices
|
||||
// in each row must be equal.
|
||||
// in each row must be equal. Strings will stay strings.
|
||||
// Examples:
|
||||
// A = [[1,2],
|
||||
// [3,4]];
|
||||
// B = ident(2);
|
||||
// C = block_matrix([[A,B],[B,A],[A,B]]);
|
||||
// // Returns:
|
||||
// // [[1, 2, 1, 0],
|
||||
// // [3, 4, 0, 1],
|
||||
// // [1, 0, 1, 2],
|
||||
// // [0, 1, 3, 4],
|
||||
// // [1, 2, 1, 0],
|
||||
// // [3, 4, 0, 1]]);
|
||||
// D = block_matrix([[A,B], ident(4)]);
|
||||
// // Returns:
|
||||
// // [[1, 2, 1, 0],
|
||||
// // [3, 4, 0, 1],
|
||||
// // [1, 0, 0, 0],
|
||||
// // [0, 1, 0, 0],
|
||||
// // [0, 0, 1, 0],
|
||||
// // [0, 0, 0, 1]]);
|
||||
// E = [["one", "two"], [3,4]];
|
||||
// F = block_matrix([[A,A]]);
|
||||
// // Returns:
|
||||
// // [["one", "two", "one", "two"],
|
||||
// // [ 3, 4, 3, 4]]
|
||||
function block_matrix(M) =
|
||||
let(
|
||||
bigM = [for(bigrow = M) each zip(bigrow)],
|
||||
bigM = [for(bigrow = M) each hstack(bigrow)],
|
||||
len0=len(bigM[0]),
|
||||
badrows = [for(row=bigM) if (len(row)!=len0) 1]
|
||||
)
|
||||
|
|
15
paths.scad
15
paths.scad
|
@ -1227,12 +1227,15 @@ module path_spread(path, n, spacing, sp=undef, rotate_children=true, closed=fals
|
|||
function path_cut(path, dists, closed=false, direction=false) =
|
||||
let(long_enough = len(path) >= (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=[]) =
|
||||
|
|
|
@ -155,7 +155,7 @@ include <structs.scad>
|
|||
// $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 <structs.scad>
|
|||
// $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,
|
||||
|
|
|
@ -501,15 +501,36 @@ 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);
|
||||
strmat = [["three","four"], ["five","six"]];
|
||||
assert_equal(hstack(strmat,strmat), [["three", "four", "three", "four"], ["five", "six", "five", "six"]]);
|
||||
strvec = ["one","two"];
|
||||
assert_equal(hstack(strvec,strmat),[["o", "n", "e", "three", "four"], ["t", "w", "o", "five", "six"]]);
|
||||
}
|
||||
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();
|
||||
|
||||
|
|
Loading…
Reference in a new issue