From f328ca87a5d09ad67ba7fcec3ae578ac00098642 Mon Sep 17 00:00:00 2001 From: Garth Minette Date: Thu, 7 Jan 2021 19:17:10 -0800 Subject: [PATCH] Clean up Usage docs lines for arrays.scad. Typo fix in joiners.scad. --- arrays.scad | 390 ++++++++++++++++++++++++++++++--------------------- joiners.scad | 2 +- version.scad | 2 +- 3 files changed, 230 insertions(+), 164 deletions(-) diff --git a/arrays.scad b/arrays.scad index cbc7e05..42b2c05 100644 --- a/arrays.scad +++ b/arrays.scad @@ -19,7 +19,7 @@ // Function: is_homogeneous() // Usage: -// is_homogeneous(list,depth) +// bool = is_homogeneous(list,depth); // Description: // Returns true when the list have elements of same type up to the depth `depth`. // Booleans and numbers are not distinguinshed as of distinct types. @@ -27,11 +27,11 @@ // list = the list to check // depth = the lowest level the check is done // Example: -// is_homogeneous( [[1,["a"]], [2,["b"]]] ) // Returns true -// is_homogeneous( [[1,["a"]], [2,[true]]] ) // Returns false -// is_homogeneous( [[1,["a"]], [2,[true]]], 1 ) // Returns true -// is_homogeneous( [[1,["a"]], [2,[true]]], 2 ) // Returns false -// is_homogeneous( [[1,["a"]], [true,["b"]]] ) // Returns true +// a = is_homogeneous([[1,["a"]], [2,["b"]]]); // Returns true +// b = is_homogeneous([[1,["a"]], [2,[true]]]); // Returns false +// c = is_homogeneous([[1,["a"]], [2,[true]]], 1); // Returns true +// d = is_homogeneous([[1,["a"]], [2,[true]]], 2); // Returns false +// e = is_homogeneous([[1,["a"]], [true,["b"]]]); // Returns true function is_homogeneous(l, depth=10) = !is_list(l) || l==[] ? false : let( l0=l[0] ) @@ -54,23 +54,23 @@ function _same_type(a,b, depth) = // The last item is -1. If only the `start` index is given, returns just the value // at that position. // Usage: -// select(list,start) -// select(list,start,end) +// item = select(list,start); +// list = select(list,start,end); // Arguments: // list = The list to get the portion of. // start = The index of the first item. // end = The index of the last item. // Example: // l = [3,4,5,6,7,8,9]; -// select(l, 5, 6); // Returns [8,9] -// select(l, 5, 8); // Returns [8,9,3,4] -// select(l, 5, 2); // Returns [8,9,3,4,5] -// select(l, -3, -1); // Returns [7,8,9] -// select(l, 3, 3); // Returns [6] -// select(l, 4); // Returns 7 -// select(l, -2); // Returns 8 -// select(l, [1:3]); // Returns [4,5,6] -// select(l, [1,3]); // Returns [4,6] +// a = select(l, 5, 6); // Returns [8,9] +// b = select(l, 5, 8); // Returns [8,9,3,4] +// c = select(l, 5, 2); // Returns [8,9,3,4,5] +// d = select(l, -3, -1); // Returns [7,8,9] +// e = select(l, 3, 3); // Returns [6] +// f = select(l, 4); // Returns 7 +// g = select(l, -2); // Returns 8 +// h = select(l, [1:3]); // Returns [4,5,6] +// i = select(l, [1,3]); // Returns [4,6] function select(list, start, end=undef) = assert( is_list(list) || is_string(list), "Invalid list.") let(l=len(list)) @@ -88,18 +88,20 @@ function select(list, start, end=undef) = // Function: last() +// Usage: +// item = last(list); // Description: // Returns the last element of a list, or undef if empty. -// Usage: -// last(list) // Arguments: // list = The list to get the last element of. // Example: // l = [3,4,5,6,7,8,9]; -// last(l); // Returns 9. +// x = last(l); // Returns 9. function last(list) = list[len(list)-1]; // Function: delete_last() +// Usage: +// list = delete_last(list); // Description: // Returns a list of all but the last entry. If input is empty, returns empty list. // Usage: @@ -109,6 +111,8 @@ function delete_last(list) = list==[] ? [] : slice(list,0,-2); // Function: slice() +// Usage: +// list = slice(list,start,end); // Description: // Returns a slice of a list. The first item is index 0. // Negative indexes are counted back from the end. The last item is -1. @@ -117,11 +121,11 @@ function delete_last(list) = // start = The index of the first item to return. // end = The index after the last item to return, unless negative, in which case the last item to return. // Example: -// slice([3,4,5,6,7,8,9], 3, 5); // Returns [6,7] -// slice([3,4,5,6,7,8,9], 2, -1); // Returns [5,6,7,8,9] -// slice([3,4,5,6,7,8,9], 1, 1); // Returns [] -// slice([3,4,5,6,7,8,9], 6, -1); // Returns [9] -// slice([3,4,5,6,7,8,9], 2, -2); // Returns [5,6,7,8] +// a = slice([3,4,5,6,7,8,9], 3, 5); // Returns [6,7] +// b = slice([3,4,5,6,7,8,9], 2, -1); // Returns [5,6,7,8,9] +// c = slice([3,4,5,6,7,8,9], 1, 1); // Returns [] +// d = slice([3,4,5,6,7,8,9], 6, -1); // Returns [9] +// e = slice([3,4,5,6,7,8,9], 2, -2); // Returns [5,6,7,8] function slice(list,start,end) = assert( is_list(list), "Invalid list" ) assert( is_finite(start) && is_finite(end), "Invalid number(s)" ) @@ -134,15 +138,18 @@ function slice(list,start,end) = // Function: in_list() -// Description: Returns true if value `val` is in list `list`. When `val==NAN` the answer will be false for any list. +// Usage: +// bool = in_list(val,list, ); +// Description: +// Returns true if value `val` is in list `list`. When `val==NAN` the answer will be false for any list. // Arguments: // val = The simple value to search for. // list = The list to search. // idx = If given, searches the given subindex for matches for `val`. // Example: -// in_list("bar", ["foo", "bar", "baz"]); // Returns true. -// in_list("bee", ["foo", "bar", "baz"]); // Returns false. -// in_list("bar", [[2,"foo"], [4,"bar"], [3,"baz"]], idx=1); // Returns true. +// a = in_list("bar", ["foo", "bar", "baz"]); // Returns true. +// b = in_list("bee", ["foo", "bar", "baz"]); // Returns false. +// c = in_list("bar", [[2,"foo"], [4,"bar"], [3,"baz"]], idx=1); // Returns true. function in_list(val,list,idx=undef) = assert( is_list(list) && (is_undef(idx) || is_finite(idx)), "Invalid input." ) @@ -154,7 +161,8 @@ function in_list(val,list,idx=undef) = // Function: min_index() // Usage: -// min_index(vals,[all]); +// idx = min_index(vals); +// idxlist = min_index(vals,all=true); // Description: // Returns the index of the first occurrence of the minimum value in the given list. // If `all` is true then returns a list of all indices where the minimum value occurs. @@ -162,8 +170,8 @@ function in_list(val,list,idx=undef) = // vals = vector of values // all = set to true to return indices of all occurences of the minimum. Default: false // Example: -// min_index([5,3,9,6,2,7,8,2,1]); // Returns: 8 -// min_index([5,3,9,6,2,7,8,2,7],all=true); // Returns: [4,7] +// a = min_index([5,3,9,6,2,7,8,2,1]); // Returns: 8 +// b = min_index([5,3,9,6,2,7,8,2,7],all=true); // Returns: [4,7] function min_index(vals, all=false) = assert( is_vector(vals) && len(vals)>0 , "Invalid or empty list of numbers.") all ? search(min(vals),vals,0) : search(min(vals), vals)[0]; @@ -171,7 +179,8 @@ function min_index(vals, all=false) = // Function: max_index() // Usage: -// max_index(vals,[all]); +// idx = max_index(vals); +// idxlist = max_index(vals,all=true); // Description: // Returns the index of the first occurrence of the maximum value in the given list. // If `all` is true then returns a list of all indices where the maximum value occurs. @@ -188,13 +197,13 @@ function max_index(vals, all=false) = // Function: list_increasing() // Usage: -// list_increasing(list) +// bool = list_increasing(list); // Description: // Returns true if the list is (non-strictly) increasing // Example: -// list_increasing([1,2,3,4]); // Returns: true -// list_increasing([1,3,2,4]); // Returns: false -// list_increasing([4,3,2,1]); // Returns: false +// a = list_increasing([1,2,3,4]); // Returns: true +// b = list_increasing([1,3,2,4]); // Returns: false +// c = list_increasing([4,3,2,1]); // Returns: false function list_increasing(list) = assert(is_list(list)||is_string(list)) len([for (p=pair(list)) if(p.x>p.y) true])==0; @@ -202,13 +211,13 @@ function list_increasing(list) = // Function: list_decreasing() // Usage: -// list_decreasing(list) +// bool = list_decreasing(list); // Description: // Returns true if the list is (non-strictly) decreasing // Example: -// list_decreasing([1,2,3,4]); // Returns: false -// list_decreasing([4,2,3,1]); // Returns: false -// list_decreasing([4,3,2,1]); // Returns: true +// a = list_decreasing([1,2,3,4]); // Returns: false +// b = list_decreasing([4,2,3,1]); // Returns: false +// c = list_decreasing([4,3,2,1]); // Returns: true function list_decreasing(list) = assert(is_list(list)||is_string(list)) len([for (p=pair(list)) if(p.x, ); +// list = list_range(n, , ); +// list = list_range(e, ); +// list = list_range(s, e, ); // Description: // Returns a list, counting up from starting value `s`, by `step` increments, // until either `n` values are in the list, or it reaches the end value `e`. @@ -256,16 +265,16 @@ function repeat(val, n, i=0) = // e = Ending value to stop at, if given. // step = Amount to increment each value. Default: 1 // Example: -// list_range(4); // Returns [0,1,2,3] -// list_range(n=4, step=2); // Returns [0,2,4,6] -// list_range(n=4, s=3, step=3); // Returns [3,6,9,12] -// list_range(n=5, s=0, e=10); // Returns [0, 2.5, 5, 7.5, 10] -// list_range(e=3); // Returns [0,1,2,3] -// list_range(e=7, step=2); // Returns [0,2,4,6] -// list_range(s=3, e=5); // Returns [3,4,5] -// list_range(s=3, e=8, step=2); // Returns [3,5,7] -// list_range(s=4, e=8.3, step=2); // Returns [4,6,8] -// list_range(n=4, s=[3,4], step=[2,3]); // Returns [[3,4], [5,7], [7,10], [9,13]] +// a = list_range(4); // Returns [0,1,2,3] +// b = list_range(n=4, step=2); // Returns [0,2,4,6] +// c = list_range(n=4, s=3, step=3); // Returns [3,6,9,12] +// d = list_range(n=5, s=0, e=10); // Returns [0, 2.5, 5, 7.5, 10] +// e = list_range(e=3); // Returns [0,1,2,3] +// f = list_range(e=7, step=2); // Returns [0,2,4,6] +// g = list_range(s=3, e=5); // Returns [3,4,5] +// h = list_range(s=3, e=8, step=2); // Returns [3,5,7] +// i = list_range(s=4, e=8.3, step=2); // Returns [4,6,8] +// j = list_range(n=4, s=[3,4], step=[2,3]); // Returns [[3,4], [5,7], [7,10], [9,13]] function list_range(n=undef, s=0, e=undef, step=undef) = assert( is_undef(n) || is_finite(n), "Parameter `n` must be a number.") assert( is_undef(n) || is_undef(e) || is_undef(step), "At most 2 of n, e, and step can be given.") @@ -281,7 +290,10 @@ function list_range(n=undef, s=0, e=undef, step=undef) = // Section: List Manipulation // Function: reverse() -// Description: Reverses a list/array or string. +// Usage: +// rlist = reverse(list); +// Description: +// Reverses a list/array or string. // Arguments: // x = The list or string to reverse. // Example: @@ -294,7 +306,7 @@ function reverse(x) = // Function: list_rotate() // Usage: -// rlist = list_rotate(list,n); +// rlist = list_rotate(list,); // Description: // Rotates the contents of a list by `n` positions left. // If `n` is negative, then the rotation is `abs(n)` positions to the right. @@ -321,7 +333,7 @@ function list_rotate(list,n=1) = // Function: deduplicate() // Usage: -// deduplicate(list,[close],[eps]); +// list = deduplicate(list,,); // Description: // Removes consecutive duplicate items in a list. // When `eps` is zero, the comparison between consecutive items is exact. @@ -332,11 +344,11 @@ function list_rotate(list,n=1) = // closed = If true, drops trailing items if they match the first list item. // eps = The maximum tolerance between items. // Examples: -// deduplicate([8,3,4,4,4,8,2,3,3,8,8]); // Returns: [8,3,4,8,2,3,8] -// deduplicate(closed=true, [8,3,4,4,4,8,2,3,3,8,8]); // Returns: [8,3,4,8,2,3] -// deduplicate("Hello"); // Returns: "Helo" -// deduplicate([[3,4],[7,2],[7,1.99],[1,4]],eps=0.1); // Returns: [[3,4],[7,2],[1,4]] -// deduplicate([[7,undef],[7,undef],[1,4],[1,4+1e-12]],eps=0); // Returns: [[7,undef],[1,4],[1,4+1e-12]] +// a = deduplicate([8,3,4,4,4,8,2,3,3,8,8]); // Returns: [8,3,4,8,2,3,8] +// b = deduplicate(closed=true, [8,3,4,4,4,8,2,3,3,8,8]); // Returns: [8,3,4,8,2,3] +// c = deduplicate("Hello"); // Returns: "Helo" +// d = deduplicate([[3,4],[7,2],[7,1.99],[1,4]],eps=0.1); // Returns: [[3,4],[7,2],[1,4]] +// e = deduplicate([[7,undef],[7,undef],[1,4],[1,4+1e-12]],eps=0); // Returns: [[7,undef],[1,4],[1,4+1e-12]] function deduplicate(list, closed=false, eps=EPSILON) = assert(is_list(list)||is_string(list)) let( @@ -350,7 +362,7 @@ function deduplicate(list, closed=false, eps=EPSILON) = // Function: deduplicate_indexed() // Usage: -// new_idxs = deduplicate_indexed(list, indices, [closed], [eps]); +// new_idxs = deduplicate_indexed(list, indices, , ); // Description: // Given a list, and indices into it, removes consecutive indices that // index to the same values in the list. @@ -360,9 +372,9 @@ function deduplicate(list, closed=false, eps=EPSILON) = // closed = If true, drops trailing indices if what they index matches what the first index indexes. // eps = The maximum difference to allow between numbers or vectors. // Examples: -// deduplicate_indexed([8,6,4,6,3], [1,4,3,1,2,2,0,1]); // Returns: [1,4,3,2,0,1] -// deduplicate_indexed([8,6,4,6,3], [1,4,3,1,2,2,0,1], closed=true); // Returns: [1,4,3,2,0] -// deduplicate_indexed([[7,undef],[7,undef],[1,4],[1,4],[1,4+1e-12]],eps=0); // Returns: [0,2,4] +// a = deduplicate_indexed([8,6,4,6,3], [1,4,3,1,2,2,0,1]); // Returns: [1,4,3,2,0,1] +// b = deduplicate_indexed([8,6,4,6,3], [1,4,3,1,2,2,0,1], closed=true); // Returns: [1,4,3,2,0] +// c = deduplicate_indexed([[7,undef],[7,undef],[1,4],[1,4],[1,4+1e-12]],eps=0); // Returns: [0,2,4] function deduplicate_indexed(list, indices, closed=false, eps=EPSILON) = assert(is_list(list)||is_string(list), "Improper list or string.") indices==[]? [] : @@ -384,7 +396,7 @@ function deduplicate_indexed(list, indices, closed=false, eps=EPSILON) = // Function: repeat_entries() // Usage: -// newlist = repeat_entries(list, N) +// newlist = repeat_entries(list, N, ); // Description: // Takes a list as input and duplicates some of its entries to produce a list // with length `N`. If the requested `N` is not a multiple of the list length then @@ -404,10 +416,10 @@ function deduplicate_indexed(list, indices, closed=false, eps=EPSILON) = // exact = if true return exactly the requested number of points, possibly sacrificing uniformity. If false, return uniform points that may not match the number of points requested. Default: True // Examples: // list = [0,1,2,3]; -// echo(repeat_entries(list, 6)); // Outputs [0,0,1,2,2,3] -// echo(repeat_entries(list, 6, exact=false)); // Outputs [0,0,1,1,2,2,3,3] -// echo(repeat_entries(list, [1,1,2,1], exact=false)); // Outputs [0,1,2,2,3] -function repeat_entries(list, N, exact = true) = +// a = repeat_entries(list, 6); // Returns: [0,0,1,2,2,3] +// b = repeat_entries(list, 6, exact=false); // Returns: [0,0,1,1,2,2,3,3] +// c = repeat_entries(list, [1,1,2,1], exact=false); // Returns: [0,1,2,2,3] +function repeat_entries(list, N, exact=true) = assert(is_list(list) && len(list)>0, "The list cannot be void.") assert((is_finite(N) && N>0) || is_vector(N,len(list)), "Parameter N must be a number greater than zero or vector with the same length of `list`") @@ -423,7 +435,7 @@ function repeat_entries(list, N, exact = true) = // Function: list_set() // Usage: -// list_set(list, indices, values, [dflt], [minlen]) +// list = list_set(list, indices, values, , ); // Description: // Takes the input list and returns a new list such that `list[indices[i]] = values[i]` for all of // the (index,value) pairs supplied and unchanged for other indices. If you supply `indices` that are @@ -438,8 +450,8 @@ function repeat_entries(list, N, exact = true) = // dflt = Default value to store in sparse skipped indices. // minlen = Minimum length to expand list to. // Examples: -// list_set([2,3,4,5], 2, 21); // Returns: [2,3,21,5] -// list_set([2,3,4,5], [1,3], [81,47]); // Returns: [2,81,4,47] +// a = list_set([2,3,4,5], 2, 21); // Returns: [2,3,21,5] +// b = list_set([2,3,4,5], [1,3], [81,47]); // Returns: [2,81,4,47] function list_set(list=[],indices,values,dflt=0,minlen=0) = assert(is_list(list)) !is_list(indices)? ( @@ -464,12 +476,12 @@ function list_set(list=[],indices,values,dflt=0,minlen=0) = // Function: list_insert() // Usage: -// list_insert(list, indices, values); +// list = list_insert(list, indices, values); // Description: // Insert `values` into `list` before position `indices`. // Example: -// list_insert([3,6,9,12],1,5); // Returns [3,5,6,9,12] -// list_insert([3,6,9,12],[1,3],[5,11]); // Returns [3,5,6,9,11,12] +// a = list_insert([3,6,9,12],1,5); // Returns [3,5,6,9,12] +// b = list_insert([3,6,9,12],[1,3],[5,11]); // Returns [3,5,6,9,11,12] function list_insert(list, indices, values) = assert(is_list(list)) !is_list(indices)? @@ -499,15 +511,15 @@ function list_insert(list, indices, values) = // Function: list_remove() // Usage: -// list_remove(list, indices) +// list = list_remove(list, indices); // Description: // Remove all items from `list` whose indexes are in `indices`. // Arguments: // list = The list to remove items from. // indices = The list of indexes of items to remove. // Example: -// list_insert([3,6,9,12],1); // Returns: [3,9,12] -// list_insert([3,6,9,12],[1,3]); // Returns: [3,9] +// a = list_insert([3,6,9,12],1); // Returns: [3,9,12] +// b = list_insert([3,6,9,12],[1,3]); // Returns: [3,9] function list_remove(list, indices) = assert(is_list(list)) is_finite(indices) ? @@ -526,7 +538,8 @@ function list_remove(list, indices) = // Function: list_remove_values() // Usage: -// list_remove_values(list,values,all=false) = +// list = list_remove_values(list,values); +// list = list_remove_values(list,values,all=true); // Description: // Removes the first, or all instances of the given `values` from the `list`. // Returns the modified list. @@ -552,14 +565,14 @@ function list_remove_values(list,values=[],all=false) = // Function: bselect() // Usage: -// bselect(array,index); +// array = bselect(array,index); // Description: // Returns the items in `array` whose matching element in `index` is true. // Arguments: // array = Initial list to extract items from. // index = List of booleans. // Example: -// bselect([3,4,5,6,7], [false,true,true,false,true]); // Returns: [4,5,7] +// a = bselect([3,4,5,6,7], [false,true,true,false,true]); // Returns: [4,5,7] function bselect(array,index) = assert(is_list(array)||is_string(array), "Improper array." ) assert(is_list(index) && len(index)>=len(array) , "Improper index list." ) @@ -569,7 +582,7 @@ function bselect(array,index) = // Function: list_bset() // Usage: -// list_bset(indexset, valuelist,[dflt]) +// arr = list_bset(indexset, valuelist, ); // Description: // Opposite of `bselect()`. Returns a list the same length as `indexlist`, where each item will // either be 0 if the corresponding item in `indexset` is false, or the next sequential value @@ -580,8 +593,8 @@ function bselect(array,index) = // valuelist = The list of values to set into the returned list. // dflt = Default value to store when the indexset item is false. // Example: -// list_bset([false,true,false,true,false], [3,4]); // Returns: [0,3,0,4,0] -// list_bset([false,true,false,true,false], [3,4],dflt=1); // Returns: [1,3,1,4,1] +// a = list_bset([false,true,false,true,false], [3,4]); // Returns: [0,3,0,4,0] +// b = list_bset([false,true,false,true,false], [3,4], dflt=1); // Returns: [1,3,1,4,1] function list_bset(indexset, valuelist, dflt=0) = assert(is_list(indexset), "The index set is not a list." ) assert(is_list(valuelist), "The `valuelist` is not a list." ) @@ -597,6 +610,8 @@ function list_bset(indexset, valuelist, dflt=0) = // Section: List Length Manipulation // Function: list_shortest() +// Usage: +// llen = list_shortest(array); // Description: // Returns the length of the shortest sublist in a list of lists. // Arguments: @@ -607,6 +622,8 @@ function list_shortest(array) = // Function: list_longest() +// Usage: +// llen = list_longest(array); // Description: // Returns the length of the longest sublist in a list of lists. // Arguments: @@ -617,6 +634,8 @@ function list_longest(array) = // Function: list_pad() +// Usage: +// arr = list_pad(array, minlen, ); // Description: // If the list `array` is shorter than `minlen` length, pad it to length with the value given in `fill`. // Arguments: @@ -629,6 +648,8 @@ function list_pad(array, minlen, fill=undef) = // Function: list_trim() +// Usage: +// arr = list_trim(array, maxlen); // Description: // If the list `array` is longer than `maxlen` length, truncates it to be `maxlen` items long. // Arguments: @@ -640,6 +661,8 @@ function list_trim(array, maxlen) = // Function: list_fit() +// Usage: +// arr = list_fit(array, length, fill); // Description: // If the list `array` is longer than `length` items long, truncates it to be exactly `length` items long. // If the list `array` is shorter than `length` items long, pad it to length with the value given in `fill`. @@ -676,12 +699,15 @@ function _valid_idx(idx,imin,imax) = // Function: shuffle() // Usage: -// shuffled = shuffle(list,[seed]) +// shuffled = shuffle(list,) // Description: // Shuffles the input list into random order. // If given a string, shuffles the characters within the string. // If you give a numeric seed value then the permutation // will be repeatable. +// Arguments: +// list = The list to shuffle. +// seed = Optional random number seed for the shuffling. function shuffle(list,seed) = assert(is_list(list)||is_string(list), "Invalid input." ) is_string(list)? str_join(shuffle([for (x = list) x],seed=seed)) : @@ -780,7 +806,7 @@ function _indexed_sort(arrind) = // Function: sort() // Usage: -// sort(list, [idx]) +// slist = sort(list, ); // Description: // Sorts the given list in lexicographic order. If the input is a homogeneous simple list or a homogeneous // list of vectors (see function is_homogeneous), the sorting method uses the native comparison operator and is faster. @@ -818,12 +844,17 @@ function sort(list, idx=undef) = // Function: sortidx() +// Usage: +// idxlist = sort_idx(list, ); // Description: // Given a list, sort it as function `sort()`, and returns // a list of indexes into the original list in that sorted order. // If you iterate the returned list in order, and use the list items // to index into the original list, you will be iterating the original // values in sorted order. +// Arguments: +// list = The list to sort. +// idx = If given, do the comparison based just on the specified index, range or list of indices. // Example: // lst = ["d","b","e","c"]; // idxs = sortidx(lst); // Returns: [1,3,0,2] @@ -864,7 +895,7 @@ function sortidx(list, idx=undef) = // Function: unique() // Usage: -// l = unique(list); +// ulist = unique(list); // Description: // Returns a sorted list with all repeated items removed. // Arguments: @@ -900,8 +931,8 @@ function unique_count(list) = // Function: idx() // Usage: -// i = idx(list); -// for(i=idx(list)) ... +// rng = idx(list, , , ); +// for(i=idx(list, , , )) ... // Description: // Returns the range of indexes for the given list. // Arguments: @@ -918,6 +949,9 @@ function idx(list, step=1, end=-1,start=0) = // Function: enumerate() +// Usage: +// arr = enumerate(l, ); +// for (x = enumerate(l, )) ... // x[0] is the index number, x[1] is the item. // Description: // Returns a list, with each item of the given list `l` numbered in a sublist. // Something like: `[[0,l[0]], [1,l[1]], [2,l[2]], ...]` @@ -941,7 +975,7 @@ function enumerate(l,idx=undef) = // Function: force_list() // Usage: -// list = force_list(value, [n], [fill]) +// list = force_list(value, , ) // Description: // Coerces non-list values into a list. Makes it easy to treat a scalar input // consistently as a singleton list, as well as list inputs. @@ -964,7 +998,8 @@ function force_list(value, n=1, fill) = // Function: pair() // Usage: -// pair(v) +// p = pair(v); +// for (p = pair(v)) ... // p contains a list of two adjacent items. // Description: // Takes a list, and returns a list of adjacent pairs from it. // Example(2D): Note that the last point and first point do NOT get paired together. @@ -982,7 +1017,8 @@ function pair(v) = // Function: pair_wrap() // Usage: -// pair_wrap(v) +// p = pair_wrap(v); +// for (p = pair_wrap(v)) ... // Description: // Takes a list, and returns a list of adjacent pairs from it, wrapping around from the end to the start of the list. // Example(2D): @@ -1000,7 +1036,8 @@ function pair_wrap(v) = // Function: triplet() // Usage: -// triplet(v) +// list = triplet(v); +// for (t = triplet(v)) ... // Description: // Takes a list, and returns a list of adjacent triplets from it. // Example: @@ -1013,7 +1050,8 @@ function triplet(v) = // Function: triplet_wrap() // Usage: -// triplet_wrap(v) +// list = triplet_wrap(v); +// for (t = triplet_wrap(v)) ... // Description: // Takes a list, and returns a list of adjacent triplets from it, wrapping around from the end to the start of the list. // Example: @@ -1026,7 +1064,8 @@ function triplet_wrap(v) = // Function: permute() // Usage: -// list = permute(l, [n]); +// list = permute(l, ); +// for (p = permute(l, )) ... // Description: // Returns an ordered list of every unique permutation of `n` items out of the given list `l`. // For the list `[1,2,3,4]`, with `n=2`, this will return `[[1,2], [1,3], [1,4], [2,3], [2,4], [3,4]]`. @@ -1043,8 +1082,8 @@ function permute(l,n=2,_s=0) = assert(is_list(l), "Invalid list." ) assert( is_finite(n) && n>=1 && n<=len(l), "Invalid number `n`." ) n==1 - ? [for (i=[_s:1:len(l)-1]) [l[i]]] - : [for (i=[_s:1:len(l)-n], p=permute(l,n=n-1,_s=i+1)) concat([l[i]], p)]; + ? [for (i=[_s:1:len(l)-1]) [l[i]]] + : [for (i=[_s:1:len(l)-n], p=permute(l,n=n-1,_s=i+1)) concat([l[i]], p)]; @@ -1052,7 +1091,7 @@ function permute(l,n=2,_s=0) = // Function: set_union() // Usage: -// s = set_union(a, b, [get_indices]); +// s = set_union(a, b, ); // Description: // Given two sets (lists with unique items), returns the set of unique items that are in either `a` or `b`. // If `get_indices` is true, a list of indices into the new union set are returned for each item in `b`, @@ -1133,23 +1172,23 @@ function set_intersection(a, b) = // Function: add_scalar() // Usage: -// add_scalar(v,s); +// v = add_scalar(v,s); // Description: -// Given an array and a scalar, returns the array with the scalar added to each item in it. +// Given a list and a scalar, returns the list with the scalar added to each item in it. // If given a list of arrays, recursively adds the scalar to the each array. // Arguments: // v = The initial array. // s = A scalar value to add to every item in the array. // Example: -// add_scalar([1,2,3],3); // Returns: [4,5,6] -// add_scalar([[1,2,3],[3,4,5]],3); // Returns: [[4,5,6],[6,7,8]] +// a = add_scalar([1,2,3],3); // Returns: [4,5,6] +// b = add_scalar([[1,2,3],[3,4,5]],3); // Returns: [[4,5,6],[6,7,8]] function add_scalar(v,s) = is_finite(s) ? [for (x=v) is_list(x)? add_scalar(x,s) : is_finite(x) ? x+s: x] : v; // Function: subindex() // Usage: -// subindex(M, idx) +// list = subindex(M, idx); // Description: // Extracts the entries listed in idx from each entry in M. For a matrix this means // selecting a specified set of columns. If idx is a number the return is a vector, @@ -1160,12 +1199,12 @@ function add_scalar(v,s) = // idx = The index, list of indices, or range of indices to fetch. // Example: // M = [[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]]; -// subindex(M,2); // Returns [3, 7, 11, 15] -// subindex(M,[2]); // Returns [[3], [7], [11], [15]] -// subindex(M,[2,1]); // Returns [[3, 2], [7, 6], [11, 10], [15, 14]] -// subindex(M,[1:3]); // Returns [[2, 3, 4], [6, 7, 8], [10, 11, 12], [14, 15, 16]] +// a = subindex(M,2); // Returns [3, 7, 11, 15] +// b = subindex(M,[2]); // Returns [[3], [7], [11], [15]] +// c = subindex(M,[2,1]); // Returns [[3, 2], [7, 6], [11, 10], [15, 14]] +// d = subindex(M,[1:3]); // Returns [[2, 3, 4], [6, 7, 8], [10, 11, 12], [14, 15, 16]] // N = [ [1,2], [3], [4,5], [6,7,8] ]; -// subindex(N,[0,1]); // Returns [ [1,2], [3,undef], [4,5], [6,7] ] +// e = subindex(N,[0,1]); // Returns [ [1,2], [3,undef], [4,5], [6,7] ] function subindex(M, idx) = assert( is_list(M), "The input is not a list." ) assert( !is_undef(idx) && _valid_idx(idx,0,1/0), "Invalid index input." ) @@ -1176,7 +1215,7 @@ function subindex(M, idx) = // Function: submatrix() // Usage: -// mat = submatrix(M, idx1, idx2) +// mat = submatrix(M, idx1, idx2); // Description: // The input must be a list of lists (a matrix or 2d array). Returns a submatrix by selecting the rows listed in idx1 and columns listed in idx2. // Arguments: @@ -1205,49 +1244,59 @@ function submatrix(M,idx1,idx2) = // Function: zip() -// Usage: -// zip(v1, v2, v3, [fit], [fill]); -// zip(vecs, [fit], [fill]); +// 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*>)) ... // 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. `[[A1, B1, C1], [A2, B2, C2], ...]` +// 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], ...]` // Arguments: -// vecs = A list of two or more lists to zipper together. +// 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 // Example: // v1 = [1,2,3,4]; // v2 = [5,6,7]; // v3 = [8,9,10,11]; -// zip(v1,v3); // returns [[1,8], [2,9], [3,10], [4,11]] -// zip([v1,v3]); // returns [[1,8], [2,9], [3,10], [4,11]] -// zip([v1,v2], fit="short"); // returns [[1,5], [2,6], [3,7]] -// zip([v1,v2], fit="long"); // returns [[1,5], [2,6], [3,7], [4,undef]] -// zip([v1,v2], fit="long, fill=0); // returns [[1,5], [2,6], [3,7], [4,0]] -// zip([v1,v2,v3], fit="long"); // returns [[1,5,8], [2,6,9], [3,7,10], [4,undef,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(vecs, v2, v3, fit=false, fill=undef) = - (v3!=undef)? zip([vecs,v2,v3], fit=fit, fill=fill) : - (v2!=undef)? zip([vecs,v2], fit=fit, fill=fill) : +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=vecs) is_list(v)]), "One of the inputs to zip is not a list") + assert(all([for(v=v1) is_list(v)]), "One of the inputs to zip is not a list") let( - minlen = list_shortest(vecs), - maxlen = list_longest(vecs) + minlen = list_shortest(v1), + maxlen = list_longest(v1) ) assert(fit!=false || minlen==maxlen, "Input vectors to zip must have the same length") - (fit == "long") - ? [for(i=[0:1:maxlen-1]) [for(v=vecs) for(x=(i); // Description: // Creates a square matrix with the items in the list `diag` on // its diagonal. The off diagonal entries are set to offdiag, // which is zero by default. -function diagonal_matrix(diag,offdiag=0) = +// Arguments: +// diag = A list of items to put in the diagnal cells of the matrix. +// offdiag = Value to put in non-diagonal matrix cells. +function diagonal_matrix(diag, offdiag=0) = assert(is_list(diag) && len(diag)>0) [for(i=[0:1:len(diag)-1]) [for(j=[0:len(diag)-1]) i==j?diag[i] : offdiag]]; // Function: submatrix_set() // Usage: -// mat = submatrix_set(M,A,[m],[n]) +// mat = submatrix_set(M,A,,); // Description: -// Sets a submatrix of M equal to the matrix A. By default the top left corner of M is set to A, but -// you can specify offset coordinates m and n. If A (as adjusted by m and n) extends beyond the bounds -// of M then the extra entries are ignored. You can pass in A=[[]], a null matrix, and M will be -// returned unchanged. Note that the input M need not be rectangular in shape. +// Sets a submatrix of M equal to the matrix A. By default the top left corner of M is set to A, but +// you can specify offset coordinates m and n. If A (as adjusted by m and n) extends beyond the bounds +// of M then the extra entries are ignored. You can pass in A=[[]], a null matrix, and M will be +// returned unchanged. Note that the input M need not be rectangular in shape. +// Arguments: +// M = Original matrix. +// A = Sub-matrix of parts to set. +// m = Row number of upper-left corner to place A at. +// n = Column number of upper-left corner to place A at. function submatrix_set(M,A,m=0,n=0) = assert(is_list(M)) assert(is_list(A)) @@ -1296,38 +1354,46 @@ function submatrix_set(M,A,m=0,n=0) = // Function: array_group() +// Usage: +// groups = array_group(v, , ); // Description: // Takes a flat array of values, and groups items in sets of `cnt` length. // The opposite of this is `flatten()`. // Arguments: // v = The list of items to group. -// cnt = The number of items to put in each grouping. -// dflt = The default value to fill in with is the list is not a multiple of `cnt` items long. +// cnt = The number of items to put in each grouping. Default:2 +// dflt = The default value to fill in with is the list is not a multiple of `cnt` items long. Default: 0 // Example: // v = [1,2,3,4,5,6]; -// array_group(v,2) returns [[1,2], [3,4], [5,6]] -// array_group(v,3) returns [[1,2,3], [4,5,6]] -// array_group(v,4,0) returns [[1,2,3,4], [5,6,0,0]] -function array_group(v, cnt=2, dflt=0) = [for (i = [0:cnt:len(v)-1]) [for (j = [0:1:cnt-1]) default(v[i+j], dflt)]]; +// a = array_group(v,2) returns [[1,2], [3,4], [5,6]] +// b = array_group(v,3) returns [[1,2,3], [4,5,6]] +// c = array_group(v,4,0) returns [[1,2,3,4], [5,6,0,0]] +function array_group(v, cnt=2, dflt=0) = + [for (i = [0:cnt:len(v)-1]) [for (j = [0:1:cnt-1]) default(v[i+j], dflt)]]; // Function: flatten() -// Description: Takes a list of lists and flattens it by one level. +// Usage: +// list = flatten(l); +// Description: +// Takes a list of lists and flattens it by one level. // Arguments: // l = List to flatten. // Example: -// flatten([[1,2,3], [4,5,[6,7,8]]]) returns [1,2,3,4,5,[6,7,8]] +// l = flatten([[1,2,3], [4,5,[6,7,8]]]); // returns [1,2,3,4,5,[6,7,8]] function flatten(l) = [for (a = l) each a]; // Function: full_flatten() +// Usage: +// list = full_flatten(l); // Description: // Collects in a list all elements recursively found in any level of the given list. // The output list is ordered in depth first order. // Arguments: // l = List to flatten. // Example: -// full_flatten([[1,2,3], [4,5,[6,7,8]]]) returns [1,2,3,4,5,6,7,8] +// l = full_flatten([[1,2,3], [4,5,[6,7,8]]]); // returns [1,2,3,4,5,6,7,8] function full_flatten(l) = [for(a=l) if(is_list(a)) (each full_flatten(a)) else a ]; @@ -1353,7 +1419,7 @@ function _array_dim_recurse(v) = // Function: array_dim() // Usage: -// array_dim(v, [depth]) +// dims = array_dim(v, ); // Description: // Returns the size of a multi-dimensional array. Returns a list of // dimension lengths. The length of `v` is the dimension `0`. The @@ -1367,10 +1433,10 @@ function _array_dim_recurse(v) = // v = Array to get dimensions of. // depth = Dimension to get size of. If not given, returns a list of dimension lengths. // Examples: -// array_dim([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]]); // Returns [2,2,3] -// array_dim([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]], 0); // Returns 2 -// array_dim([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]], 2); // Returns 3 -// array_dim([[[1,2,3],[4,5,6]],[[7,8,9]]]); // Returns [2,undef,3] +// a = array_dim([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]]); // Returns [2,2,3] +// b = array_dim([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]], 0); // Returns 2 +// c = array_dim([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]], 2); // Returns 3 +// d = array_dim([[[1,2,3],[4,5,6]],[[7,8,9]]]); // Returns [2,undef,3] function array_dim(v, depth=undef) = assert( is_undef(depth) || ( is_finite(depth) && depth>=0 ), "Invalid depth.") ! is_list(v) ? 0 : @@ -1386,7 +1452,7 @@ function array_dim(v, depth=undef) = // Function: transpose() // Usage: -// transpose(arr, [reverse]) +// arr = transpose(arr, ); // Description: // Returns the transpose of the given input array. The input should be a list of lists that are // all the same length. If you give a vector then transpose returns it unchanged. diff --git a/joiners.scad b/joiners.scad index a3cc636..44a2212 100644 --- a/joiners.scad +++ b/joiners.scad @@ -487,7 +487,7 @@ module joiner_quad(spacing1=undef, spacing2=undef, xspacing=undef, yspacing=unde // diff("remove") // cuboid([50,30,10]) // attach(TOP) dovetail("female", length=50, width=18, height=4, back_width=15, spin=90,$tags="remove"); -// Example: A series of dovtails +// Example: A series of dovetails // cuboid([50,30,10]) // attach(BACK) xcopies(10,5) dovetail("male", length=10, width=7, height=4); // Example: Mating pin board for a right angle joint. Note that the anchor method and use of `spin` ensures that the joint works even with a taper. diff --git a/version.scad b/version.scad index fb04b74..9ff2c98 100644 --- a/version.scad +++ b/version.scad @@ -6,7 +6,7 @@ ////////////////////////////////////////////////////////////////////// -BOSL_VERSION = [2,0,517]; +BOSL_VERSION = [2,0,518]; // Section: BOSL Library Version Functions