Added Topics/SeeAlso to affine, arrays, attachments, beziers, common, constants, gears

This commit is contained in:
Garth Minette 2021-03-01 22:44:00 -08:00
parent 1a4f9ad0a4
commit a346a0cbf0
8 changed files with 417 additions and 103 deletions

View file

@ -45,4 +45,5 @@ PrioritizeFiles:
structs.scad
DefineHeader(BulletList): Side Effects
DefineHeader(Table:Anchor Name|Position): Extra Anchors
DefineHeader(Table:Name|Definition): Terminology

View file

@ -43,7 +43,7 @@ function ident(n) = [
// Function: is_affine()
// Usage:
// bool = is_affine(x,<dim>);
// Topics: Affine, Matrices, Transforms
// Topics: Affine, Matrices, Transforms, Type Checking
// See Also: is_matrix()
// Description:
// Tests if the given value is an affine matrix, possibly also checking it's dimenstion.
@ -67,7 +67,7 @@ function is_affine(x,dim=[2,3]) =
// Function: is_2d_transform()
// Usage:
// x = is_2d_transform(t);
// Topics: Affine, Matrices, Transforms
// Topics: Affine, Matrices, Transforms, Type Checking
// See Also: is_affine(), is_matrix()
// Description:
// Checks if the input is a 3D transform that does not act on the z coordinate, except possibly

View file

@ -6,12 +6,12 @@
//////////////////////////////////////////////////////////////////////
// Section: Terminology
// - **List**: An ordered collection of zero or more items. ie: `["a", "b", "c"]`
// - **Vector**: A list of numbers. ie: `[4, 5, 6]`
// - **Array**: A nested list of lists, or list of lists of lists, or deeper. ie: `[[2,3], [4,5], [6,7]]`
// - **Dimension**: The depth of nesting of lists in an array. A List is 1D. A list of lists is 2D. etc.
// - **Set**: A list of unique items.
// Terminology:
// **List** = An ordered collection of zero or more items. ie: `["a", "b", "c"]`
// **Vector** = A list of numbers. ie: `[4, 5, 6]`
// **Array** = A nested list of lists, or list of lists of lists, or deeper. ie: `[[2,3], [4,5], [6,7]]`
// **Dimension** = The depth of nesting of lists in an array. A List is 1D. A list of lists is 2D. etc.
// **Set** = A list of unique items.
// Section: List Query Operations
@ -20,8 +20,10 @@
// Function: is_homogeneous()
// Usage:
// bool = is_homogeneous(list,depth);
// Topics: List Handling, Type Checking
// See Also: is_vector(), is_matrix()
// Description:
// Returns true when the list have elements of same type up to the depth `depth`.
// Returns true when the list has elements of same type up to the depth `depth`.
// Booleans and numbers are not distinguinshed as of distinct types.
// Arguments:
// l = the list to check
@ -53,6 +55,8 @@ function _same_type(a,b, depth) =
// The first item is index 0. Negative indexes are counted back from the end.
// The last item is -1. If only the `start` index is given, returns just the value
// at that position.
// Topics: List Handling
// See Also: slice(), subindex(), last()
// Usage:
// item = select(list,start);
// list = select(list,start,end);
@ -89,35 +93,11 @@ function select(list, start, end) =
: concat([for (i = [s:1:l-1]) list[i]], [for (i = [0:1:e]) list[i]]) ;
// Function: last()
// Usage:
// item = last(list);
// Description:
// Returns the last element of a list, or undef if empty.
// Arguments:
// list = The list to get the last element of.
// Example:
// l = [3,4,5,6,7,8,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 with all but the last entry from the input list. If input is empty, returns empty list.
// Example:
// nlist = delete_last(["foo", "bar", "baz"]); // Returns: ["foo", "bar"]
function delete_last(list) =
assert(is_list(list))
list==[] ? [] : slice(list,0,-2);
// Function: slice()
// Usage:
// list = slice(list,start,end);
// Topics: List Handling
// See Also: select(), subindex(), last()
// 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.
@ -143,9 +123,82 @@ function slice(list,start,end) =
) [for (i=[s:1:e-1]) if (e>s) list[i]];
// Function: last()
// Usage:
// item = last(list);
// Topics: List Handling
// See Also: select(), slice(), subindex()
// Description:
// Returns the last element of a list, or undef if empty.
// Arguments:
// list = The list to get the last element of.
// Example:
// l = [3,4,5,6,7,8,9];
// x = last(l); // Returns 9.
function last(list) =
list[len(list)-1];
// Function: delete_last()
// Usage:
// list = delete_last(list);
// Topics: List Handling
// See Also: select(), slice(), subindex(), last()
// Description:
// Returns a list with all but the last entry from the input list. If input is empty, returns empty list.
// Example:
// nlist = delete_last(["foo", "bar", "baz"]); // Returns: ["foo", "bar"]
function delete_last(list) =
assert(is_list(list))
list==[] ? [] : slice(list,0,-2);
// Function: force_list()
// Usage:
// list = force_list(value, <n>, <fill>);
// Topics: List Handling
// See Also: scalar_vec3()
// 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.
// - If `value` is a list, then that list is returned verbatim.
// - If `value` is not a list, and `fill` is not given, then a list of `n` copies of `value` will be returned.
// - If `value` is not a list, and `fill` is given, then a list `n` items long will be returned where `value` will be the first item, and the rest will contain the value of `fill`.
// Arguments:
// value = The value or list to coerce into a list.
// n = The number of items in the coerced list. Default: 1
// fill = The value to pad the coerced list with, after the firt value. Default: undef (pad with copies of `value`)
// Examples:
// x = force_list([3,4,5]); // Returns: [3,4,5]
// y = force_list(5); // Returns: [5]
// z = force_list(7, n=3); // Returns: [7,7,7]
// w = force_list(4, n=3, fill=1); // Returns: [4,1,1]
function force_list(value, n=1, fill) =
is_list(value) ? value :
is_undef(fill)? [for (i=[1:1:n]) value] : [value, for (i=[2:1:n]) fill];
// Function: add_scalar()
// Usage:
// v = add_scalar(v,s);
// Topics: List Handling
// Description:
// 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:
// 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: in_list()
// Usage:
// bool = in_list(val,list, <idx>);
// Topics: List Handling
// Description:
// Returns true if value `val` is in list `list`. When `val==NAN` the answer will be false for any list.
// Arguments:
@ -169,6 +222,8 @@ function in_list(val,list,idx) =
// Usage:
// idx = min_index(vals);
// idxlist = min_index(vals,all=true);
// Topics: List Handling
// See Also: max_index(), list_increasing(), list_decreasing()
// 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.
@ -187,6 +242,8 @@ function min_index(vals, all=false) =
// Usage:
// idx = max_index(vals);
// idxlist = max_index(vals,all=true);
// Topics: List Handling
// See Also: min_index(), list_increasing(), list_decreasing()
// 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.
@ -204,6 +261,8 @@ function max_index(vals, all=false) =
// Function: list_increasing()
// Usage:
// bool = list_increasing(list);
// Topics: List Handling
// See Also: max_index(), min_index(), list_decreasing()
// Description:
// Returns true if the list is (non-strictly) increasing
// Example:
@ -218,6 +277,8 @@ function list_increasing(list) =
// Function: list_decreasing()
// Usage:
// bool = list_decreasing(list);
// Topics: List Handling
// See Also: max_index(), min_index(), list_increasing()
// Description:
// Returns true if the list is (non-strictly) decreasing
// Example:
@ -236,6 +297,8 @@ function list_decreasing(list) =
// Function: repeat()
// Usage:
// list = repeat(val, n);
// Topics: List Handling
// See Also: list_range()
// Description:
// Generates a list or array of `n` copies of the given value `val`.
// If the count `n` is given as a list of counts, then this creates a
@ -261,6 +324,8 @@ function repeat(val, n, i=0) =
// list = list_range(n=, <s=>, <step=>);
// list = list_range(e=, <step=>);
// list = list_range(s=, e=, <step=>);
// Topics: List Handling
// See Also: repeat()
// 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`.
@ -300,6 +365,8 @@ function list_range(n, s=0, e, step) =
// Function: reverse()
// Usage:
// rlist = reverse(list);
// Topics: List Handling
// See Also: select(), list_rotate()
// Description:
// Reverses a list/array or string.
// Arguments:
@ -315,6 +382,8 @@ function reverse(x) =
// Function: list_rotate()
// Usage:
// rlist = list_rotate(list,<n>);
// Topics: List Handling
// See Also: select(), reverse()
// 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.
@ -342,6 +411,8 @@ function list_rotate(list,n=1) =
// Function: deduplicate()
// Usage:
// list = deduplicate(list,<close>,<eps>);
// Topics: List Handling
// See Also: deduplicate_indexed()
// Description:
// Removes consecutive duplicate items in a list.
// When `eps` is zero, the comparison between consecutive items is exact.
@ -371,6 +442,8 @@ function deduplicate(list, closed=false, eps=EPSILON) =
// Function: deduplicate_indexed()
// Usage:
// new_idxs = deduplicate_indexed(list, indices, <closed>, <eps>);
// Topics: List Handling
// See Also: deduplicate()
// Description:
// Given a list, and indices into it, removes consecutive indices that
// index to the same values in the list.
@ -406,6 +479,8 @@ function deduplicate_indexed(list, indices, closed=false, eps=EPSILON) =
// Function: repeat_entries()
// Usage:
// newlist = repeat_entries(list, N, <exact>);
// Topics: List Handling
// See Also: repeat()
// 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
@ -445,6 +520,8 @@ function repeat_entries(list, N, exact=true) =
// Function: list_set()
// Usage:
// list = list_set(list, indices, values, <dflt>, <minlen>);
// Topics: List Handling
// See Also: list_insert(), list_remove(), list_remove_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
@ -489,6 +566,8 @@ function list_set(list=[],indices,values,dflt=0,minlen=0) =
// Function: list_insert()
// Usage:
// list = list_insert(list, indices, values);
// Topics: List Handling
// See Also: list_set(), list_remove(), list_remove_values()
// Description:
// Insert `values` into `list` before position `indices`.
// Example:
@ -526,6 +605,8 @@ function list_insert(list, indices, values) =
// Function: list_remove()
// Usage:
// list = list_remove(list, indices);
// Topics: List Handling
// See Also: list_set(), list_insert(), list_remove_values()
// Description:
// Remove all items from `list` whose indexes are in `indices`.
// Arguments:
@ -554,6 +635,8 @@ function list_remove(list, indices) =
// Usage:
// list = list_remove_values(list,values);
// list = list_remove_values(list,values,all=true);
// Topics: List Handling
// See Also: list_set(), list_insert(), list_remove()
// Description:
// Removes the first, or all instances of the given `values` from the `list`.
// Returns the modified list.
@ -580,6 +663,8 @@ function list_remove_values(list,values=[],all=false) =
// Function: bselect()
// Usage:
// array = bselect(array,index);
// Topics: List Handling
// See Also: list_bset()
// Description:
// Returns the items in `array` whose matching element in `index` is true.
// Arguments:
@ -597,6 +682,8 @@ function bselect(array,index) =
// Function: list_bset()
// Usage:
// arr = list_bset(indexset, valuelist, <dflt>);
// Topics: List Handling
// See Also: bselect()
// 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
@ -626,6 +713,8 @@ function list_bset(indexset, valuelist, dflt=0) =
// Function: list_shortest()
// Usage:
// llen = list_shortest(array);
// Topics: List Handling
// See Also: list_longest()
// Description:
// Returns the length of the shortest sublist in a list of lists.
// Arguments:
@ -640,6 +729,8 @@ function list_shortest(array) =
// Function: list_longest()
// Usage:
// llen = list_longest(array);
// Topics: List Handling
// See Also: list_shortest()
// Description:
// Returns the length of the longest sublist in a list of lists.
// Arguments:
@ -654,6 +745,8 @@ function list_longest(array) =
// Function: list_pad()
// Usage:
// arr = list_pad(array, minlen, <fill>);
// Topics: List Handling
// See Also: list_trim(), list_fit()
// Description:
// If the list `array` is shorter than `minlen` length, pad it to length with the value given in `fill`.
// Arguments:
@ -671,6 +764,8 @@ function list_pad(array, minlen, fill) =
// Function: list_trim()
// Usage:
// arr = list_trim(array, maxlen);
// Topics: List Handling
// See Also: list_pad(), list_fit()
// Description:
// If the list `array` is longer than `maxlen` length, truncates it to be `maxlen` items long.
// Arguments:
@ -687,6 +782,8 @@ function list_trim(array, maxlen) =
// Function: list_fit()
// Usage:
// arr = list_fit(array, length, fill);
// Topics: List Handling
// See Also: list_pad(), list_trim()
// 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`.
@ -730,6 +827,8 @@ function _valid_idx(idx,imin,imax) =
// Function: shuffle()
// Usage:
// shuffled = shuffle(list,<seed>);
// Topics: List Handling
// See Also: sort(), sortidx(), unique(), unique_count()
// Description:
// Shuffles the input list into random order.
// If given a string, shuffles the characters within the string.
@ -843,6 +942,8 @@ function _indexed_sort(arrind) =
// Function: sort()
// Usage:
// slist = sort(list, <idx>);
// Topics: List Handling
// See Also: shuffle(), sortidx(), unique(), unique_count()
// 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.
@ -881,7 +982,9 @@ function sort(list, idx=undef) =
// Function: sortidx()
// Usage:
// idxlist = sort_idx(list, <idx>);
// idxlist = sortidx(list, <idx>);
// Topics: List Handling
// See Also: shuffle(), sort(), unique(), unique_count()
// Description:
// Given a list, sort it as function `sort()`, and returns
// a list of indexes into the original list in that sorted order.
@ -932,6 +1035,8 @@ function sortidx(list, idx=undef) =
// Function: unique()
// Usage:
// ulist = unique(list);
// Topics: List Handling
// See Also: shuffle(), sort(), sortidx(), unique_count()
// Description:
// Returns a sorted list with all repeated items removed.
// Arguments:
@ -952,6 +1057,8 @@ function unique(list) =
// Function: unique_count()
// Usage:
// counts = unique_count(list);
// Topics: List Handling
// See Also: shuffle(), sort(), sortidx(), unique()
// Description:
// Returns `[sorted,counts]` where `sorted` is a sorted list of the unique items in `list` and `counts` is a list such
// that `count[i]` gives the number of times that `sorted[i]` appears in `list`.
@ -973,6 +1080,8 @@ function unique_count(list) =
// Usage:
// rng = idx(list, <s=>, <e=>, <step=>);
// for(i=idx(list, <s=>, <e=>, <step=>)) ...
// Topics: List Handling, Iteration
// See Also: enumerate(), pair(), triplet(), permute()
// Description:
// Returns the range of indexes for the given list.
// Arguments:
@ -997,6 +1106,8 @@ function idx(list, s=0, e=-1, step=1) =
// Usage:
// arr = enumerate(l, <idx>);
// for (x = enumerate(l, <idx>)) ... // x[0] is the index number, x[1] is the item.
// Topics: List Handling, Iteration
// See Also: idx(), pair(), triplet(), permute()
// 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]], ...]`
@ -1018,33 +1129,12 @@ function enumerate(l,idx=undef) =
: [for (i=[0:1:len(l)-1]) [ i, for (j=idx) l[i][j]] ];
// Function: force_list()
// Usage:
// list = force_list(value, <n>, <fill>);
// 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.
// - If `value` is a list, then that list is returned verbatim.
// - If `value` is not a list, and `fill` is not given, then a list of `n` copies of `value` will be returned.
// - If `value` is not a list, and `fill` is given, then a list `n` items long will be returned where `value` will be the first item, and the rest will contain the value of `fill`.
// Arguments:
// value = The value or list to coerce into a list.
// n = The number of items in the coerced list. Default: 1
// fill = The value to pad the coerced list with, after the firt value. Default: undef (pad with copies of `value`)
// Examples:
// x = force_list([3,4,5]); // Returns: [3,4,5]
// y = force_list(5); // Returns: [5]
// z = force_list(7, n=3); // Returns: [7,7,7]
// w = force_list(4, n=3, fill=1); // Returns: [4,1,1]
function force_list(value, n=1, fill) =
is_list(value) ? value :
is_undef(fill)? [for (i=[1:1:n]) value] : [value, for (i=[2:1:n]) fill];
// Function: pair()
// Usage:
// p = pair(list, <wrap>);
// for (p = pair(list, <wrap>)) ... // On each iteration, p contains a list of two adjacent items.
// Topics: List Handling, Iteration
// See Also: idx(), enumerate(), triplet(), permute()
// Description:
// Takes a list, and returns a list of adjacent pairs from it, optionally wrapping back to the front.
// Arguments:
@ -1073,6 +1163,8 @@ function pair(list, wrap=false) =
// Usage:
// list = triplet(list, <wrap>);
// for (t = triplet(list, <wrap>)) ...
// Topics: List Handling, Iteration
// See Also: idx(), enumerate(), pair(), permute()
// Description:
// Takes a list, and returns a list of adjacent triplets from it, optionally wrapping back to the front.
// Example:
@ -1100,6 +1192,8 @@ function triplet(list, wrap=false) =
// Usage:
// list = permute(l, <n>);
// for (p = permute(l, <n>)) ...
// Topics: List Handling, Iteration
// See Also: idx(), enumerate(), pair(), triplet()
// 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]]`.
@ -1126,6 +1220,8 @@ function permute(l,n=2,_s=0) =
// Function: set_union()
// Usage:
// s = set_union(a, b, <get_indices>);
// Topics: Set Handling, List Handling
// See Also: set_difference(), set_intersection()
// 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`,
@ -1166,6 +1262,8 @@ function set_union(a, b, get_indices=false) =
// Function: set_difference()
// Usage:
// s = set_difference(a, b);
// Topics: Set Handling, List Handling
// See Also: set_union(), set_intersection()
// Description:
// Given two sets (lists with unique items), returns the set of items that are in `a`, but not `b`.
// Arguments:
@ -1185,6 +1283,8 @@ function set_difference(a, b) =
// Function: set_intersection()
// Usage:
// s = set_intersection(a, b);
// Topics: Set Handling, List Handling
// See Also: set_union(), set_difference()
// Description:
// Given two sets (lists with unique items), returns the set of items that are in both sets.
// Arguments:
@ -1204,25 +1304,11 @@ function set_intersection(a, b) =
// Section: Array Manipulation
// Function: add_scalar()
// Usage:
// v = add_scalar(v,s);
// Description:
// 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:
// 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:
// list = subindex(M, idx);
// Topics: Array Handling, List Handling
// See Also: select(), slice()
// 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,
@ -1250,6 +1336,8 @@ function subindex(M, idx) =
// Function: submatrix()
// Usage:
// mat = submatrix(M, idx1, idx2);
// Topics: Matrices, Array Handling
// See Also: subindex(), block_matrix(), submatrix_set()
// 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:
@ -1282,6 +1370,8 @@ function submatrix(M,idx1,idx2) =
// A = hstack(M1, M2)
// A = hstack(M1, M2, M3)
// A = hstack([M1, M2, M3, ...])
// Topics: Matrices, Array Handling
// See Also: subindex(), submatrix(), block_matrix()
// Description:
// 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
@ -1332,12 +1422,14 @@ function hstack(M1, M2, M3) =
// Function: block_matrix()
// Usage:
// bmat = block_matrix([[M11, M12,...],[M21, M22,...], ... ]);
// Topics: Matrices, Array Handling
// See Also: subindex(), submatrix()
// Description:
// 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. Strings will stay strings.
// Examples:
// Example:
// A = [[1,2],
// [3,4]];
// B = ident(2);
@ -1358,7 +1450,7 @@ function hstack(M1, M2, M3) =
// // [0, 0, 1, 0],
// // [0, 0, 0, 1]]);
// E = [["one", "two"], [3,4]];
// F = block_matrix([[A,A]]);
// F = block_matrix([[E,E]]);
// // Returns:
// // [["one", "two", "one", "two"],
// // [ 3, 4, 3, 4]]
@ -1375,6 +1467,8 @@ function block_matrix(M) =
// Function: diagonal_matrix()
// Usage:
// mat = diagonal_matrix(diag, <offdiag>);
// Topics: Matrices, Array Handling
// See Also: subindex(), submatrix()
// Description:
// Creates a square matrix with the items in the list `diag` on
// its diagonal. The off diagonal entries are set to offdiag,
@ -1390,6 +1484,8 @@ function diagonal_matrix(diag, offdiag=0) =
// Function: submatrix_set()
// Usage:
// mat = submatrix_set(M,A,<m>,<n>);
// Topics: Matrices, Array Handling
// See Also: subindex(), submatrix()
// 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
@ -1419,6 +1515,8 @@ function submatrix_set(M,A,m=0,n=0) =
// Description:
// Takes a flat array of values, and groups items in sets of `cnt` length.
// The opposite of this is `flatten()`.
// Topics: Matrices, Array Handling
// See Also: subindex(), submatrix(), hstack(), flatten(), full_flatten()
// Arguments:
// v = The list of items to group.
// cnt = The number of items to put in each grouping. Default:2
@ -1435,6 +1533,8 @@ function array_group(v, cnt=2, dflt=0) =
// Function: flatten()
// Usage:
// list = flatten(l);
// Topics: Matrices, Array Handling
// See Also: subindex(), submatrix(), hstack(), full_flatten()
// Description:
// Takes a list of lists and flattens it by one level.
// Arguments:
@ -1449,6 +1549,8 @@ function flatten(l) =
// Function: full_flatten()
// Usage:
// list = full_flatten(l);
// Topics: Matrices, Array Handling
// See Also: subindex(), submatrix(), hstack(), flatten()
// 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.
@ -1484,6 +1586,7 @@ function _array_dim_recurse(v) =
// Function: array_dim()
// Usage:
// dims = array_dim(v, <depth>);
// Topics: Matrices, Array Handling
// Description:
// Returns the size of a multi-dimensional array. Returns a list of dimension lengths. The length
// of `v` is the dimension `0`. The length of the items in `v` is dimension `1`. The length of the
@ -1515,6 +1618,8 @@ function array_dim(v, depth=undef) =
// Function: transpose()
// Usage:
// arr = transpose(arr, <reverse>);
// Topics: Matrices, Array Handling
// See Also: submatrix(), block_matrix(), hstack(), flatten()
// 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.

View file

@ -86,6 +86,8 @@ $tags_hidden = [];
// Function: anchorpt()
// Usage:
// a = anchorpt(name, pos, <orient>, <spin>);
// Topics: Attachments
// See Also: attach_geom(), reorient(), attachable()
// Description:
// Creates a anchor data structure.
// Arguments:
@ -115,6 +117,9 @@ function anchorpt(name, pos=[0,0,0], orient=UP, spin=0) = [name, pos, orient, sp
// Usage: VNF Geometry
// geom = attach_geom(vnf=, <extent=>, ...);
//
// Topics: Attachments
// See Also: reorient(), attachable()
//
// Description:
// Given arguments that describe the geometry of an attachable object, returns the internal geometry description.
//
@ -276,6 +281,8 @@ function attach_geom(
// Function: attach_geom_2d()
// Usage:
// bool = attach_geom_2d(geom);
// Topics: Attachments
// See Also: reorient(), attachable()
// Description:
// Returns true if the given attachment geometry description is for a 2D shape.
function attach_geom_2d(geom) =
@ -287,6 +294,8 @@ function attach_geom_2d(geom) =
// Function: attach_geom_size()
// Usage:
// bounds = attach_geom_size(geom);
// Topics: Attachments
// See Also: reorient(), attachable()
// Description:
// Returns the `[X,Y,Z]` bounding size for the given attachment geometry description.
function attach_geom_size(geom) =
@ -343,6 +352,8 @@ function attach_geom_size(geom) =
// mat = attach_transform(anchor, spin, orient, geom);
// Usage: To Transform Points, Paths, Patches, or VNFs
// new_p = attach_transform(anchor, spin, orient, geom, p);
// Topics: Attachments
// See Also: reorient(), attachable()
// Description:
// Returns the affine3d transformation matrix needed to `anchor`, `spin`, and `orient`
// the given geometry `geom` shape into position.
@ -417,6 +428,8 @@ function attach_transform(anchor, spin, orient, geom, p) =
// Function: find_anchor()
// Usage:
// anchorinfo = find_anchor(anchor, geom);
// Topics: Attachments
// See Also: reorient(), attachable()
// Description:
// Calculates the anchor data for the given `anchor` vector or name, in the given attachment
// geometry. Returns `[ANCHOR, POS, VEC, ANG]` where `ANCHOR` is the requested anchorname
@ -611,6 +624,8 @@ function find_anchor(anchor, geom) =
// Function: attachment_is_shown()
// Usage:
// bool = attachment_is_shown(tags);
// Topics: Attachments
// See Also: reorient(), attachable()
// Description:
// Returns true if the given space-delimited string of tag names should currently be shown.
function attachment_is_shown(tags) =
@ -650,6 +665,9 @@ function attachment_is_shown(tags) =
// mat = reorient(anchor, spin, <orient>, vnf, <extent>, ...);
// pts = reorient(anchor, spin, <orient>, vnf, <extent>, p=, ...);
//
// Topics: Attachments
// See Also: reorient(), attachable()
//
// Description:
// Given anchor, spin, orient, and general geometry info for a managed volume, this calculates
// the transformation matrix needed to be applied to the contents of that volume. A managed 3D
@ -752,6 +770,9 @@ function reorient(
// Usage: VNF Geometry
// attachable(anchor, spin, <orient>, vnf=, <extent=>, ...) {...}
//
// Topics: Attachments
// See Also: reorient()
//
// Description:
// Manages the anchoring, spin, orientation, and attachments for a 3D volume or 2D area.
// A managed 3D volume is assumed to be vertically (Z-axis) oriented, and centered.
@ -959,6 +980,10 @@ module attachable(
// Module: position()
// Usage:
// position(from) {...}
//
// Topics: Attachments
// See Also: attachable()
//
// Description:
// Attaches children to a parent object at an anchor point.
// Arguments:
@ -987,6 +1012,8 @@ module position(from)
// Usage:
// attach(from, <overlap=>, <norot=>) {...}
// attach(from, to, <overlap=>, <norot=>) {...}
// Topics: Attachments
// See Also: attachable(), position(), face_profile(), edge_profile(), corner_profile()
// Description:
// Attaches children to a parent object at an anchor point and orientation.
// Attached objects will be overlapped into the parent object by a little bit,
@ -1030,6 +1057,8 @@ module attach(from, to, overlap, norot=false)
// Module: face_profile()
// Usage:
// face_profile(faces, r|d=, <convexity=>) {...}
// Topics: Attachments
// See Also: attachable(), position(), attach(), edge_profile(), corner_profile()
// Description:
// Given a 2D edge profile, extrudes it into a mask for all edges and corners bounding each given face.
// Arguments:
@ -1058,6 +1087,8 @@ module face_profile(faces=[], r, d, convexity=10) {
// Module: edge_profile()
// Usage:
// edge_profile(<edges>, <except>, <convexity>) {...}
// Topics: Attachments
// See Also: attachable(), position(), attach(), face_profile(), corner_profile()
// Description:
// Takes a 2D mask shape and attaches it to the selected edges, with the appropriate orientation
// and extruded length to be `diff()`ed away, to give the edge a matching profile.
@ -1108,6 +1139,8 @@ module edge_profile(edges=EDGES_ALL, except=[], convexity=10) {
// Module: corner_profile()
// Usage:
// corner_profile(<corners>, <except>, <r=|d=>, <convexity=>) {...}
// Topics: Attachments
// See Also: attachable(), position(), attach(), face_profile(), edge_profile()
// Description:
// Takes a 2D mask shape, rotationally extrudes and converts it into a corner mask, and attaches it
// to the selected corners with the appropriate orientation. Tags it as a "mask" to allow it to be
@ -1171,6 +1204,8 @@ module corner_profile(corners=CORNERS_ALL, except=[], r, d, convexity=10) {
// Module: edge_mask()
// Usage:
// edge_mask(<edges>, <except>) {...}
// Topics: Attachments
// See Also: attachable(), position(), attach(), face_profile(), edge_profile(), corner_mask()
// Description:
// Takes a 3D mask shape, and attaches it to the given edges, with the
// appropriate orientation to be `diff()`ed away.
@ -1213,6 +1248,8 @@ module edge_mask(edges=EDGES_ALL, except=[]) {
// Module: corner_mask()
// Usage:
// corner_mask(<corners>, <except>) {...}
// Topics: Attachments
// See Also: attachable(), position(), attach(), face_profile(), edge_profile(), edge_mask()
// Description:
// Takes a 3D mask shape, and attaches it to the given corners, with the appropriate
// orientation to be `diff()`ed away. The 3D corner mask shape should be designed to
@ -1253,6 +1290,8 @@ module corner_mask(corners=CORNERS_ALL, except=[]) {
// Module: tags()
// Usage:
// tags(tags) {...}
// Topics: Attachments
// See Also: recolor(), hide(), show(), diff(), intersect()
// Description:
// Marks all children with the given tags, so that they will `hide()`/`show()`/`diff()` correctly.
// This is especially useful for working with children that are not attachment enhanced, such as:
@ -1280,6 +1319,8 @@ module tags(tags)
// Module: recolor()
// Usage:
// recolor(c) {...}
// Topics: Attachments
// See Also: tags(), hide(), show(), diff(), intersect()
// Description:
// Sets the color for children that can use the $color special variable.
// Arguments:
@ -1296,6 +1337,8 @@ module recolor(c)
// Module: hide()
// Usage:
// hide(tags) {...}
// Topics: Attachments
// See Also: tags(), recolor(), show(), diff(), intersect()
// Description:
// Hides all children with the given tags. Overrides any previous `hide()` or `show()` calls.
// Example:
@ -1314,6 +1357,8 @@ module hide(tags="")
// Module: show()
// Usage:
// show(tags) {...}
// Topics: Attachments
// See Also: tags(), recolor(), hide(), diff(), intersect()
// Description:
// Shows only children with the given tags. Overrides any previous `hide()` or `show()` calls.
// Example:
@ -1333,6 +1378,8 @@ module show(tags="")
// Usage:
// diff(neg, <keep>) {...}
// diff(neg, pos, <keep>) {...}
// Topics: Attachments
// See Also: tags(), recolor(), show(), hide(), intersect()
// Description:
// If `neg` is given, takes the union of all children with tags that are in `neg`, and differences
// them from the union of all children with tags in `pos`. If `pos` is not given, then all items in
@ -1391,6 +1438,8 @@ module diff(neg, pos, keep)
// Usage:
// intersect(a, <keep=>) {...}
// intersect(a, b, <keep=>) {...}
// Topics: Attachments
// See Also: tags(), recolor(), show(), hide(), diff()
// Description:
// If `a` is given, takes the union of all children with tags that are in `a`, and `intersection()`s
// them with the union of all children with tags in `b`. If `b` is not given, then the union of all
@ -1438,6 +1487,8 @@ module intersect(a, b=undef, keep=undef)
// Module: hulling()
// Usage:
// hulling(a) {...}
// Topics: Attachments
// See Also: tags(), recolor(), show(), hide(), diff(), intersect()
// Description:
// If `a` is not given, then all children are `hull()`ed together.
// If `a` is given as a string, then all children with `$tags` that are in `a` are

View file

@ -6,29 +6,17 @@
// include <BOSL2/beziers.scad>
//////////////////////////////////////////////////////////////////////
// Section: Terminology
// **Path**: A series of points joined by straight line segements.
// .
// **Bezier Curve**: A mathematical curve that joins two endpoints, following a curve determined by one or more control points.
// .
// **Endpoint**: A point that is on the end of a bezier segment. This point lies on the bezier curve.
// .
// **Control Point**: A point that influences the shape of the curve that connects two endpoints. This is often *NOT* on the bezier curve.
// .
// **Degree**: The number of control points, plus one endpoint, needed to specify a bezier segment. Most beziers are cubic (degree 3).
// .
// **Bezier Segment**: A list consisting of an endpoint, one or more control points, and a final endpoint. The number of control points is one less than the degree of the bezier. A cubic (degree 3) bezier segment looks something like:
// `[endpt1, cp1, cp2, endpt2]`
// .
// **Bezier Path**: A list of bezier segments flattened out into a list of points, where each segment shares the endpoint of the previous segment as a start point. A cubic Bezier Path looks something like:
// `[endpt1, cp1, cp2, endpt2, cp3, cp4, endpt3]`
// **NOTE**: A "bezier path" is *NOT* a standard path. It is only the points and controls used to define the curve.
// .
// **Bezier Patch**: A surface defining grid of (N+1) by (N+1) bezier points. If a Bezier Segment defines a curved line, a Bezier Patch defines a curved surface.
// .
// **Bezier Surface**: A surface defined by a list of one or more bezier patches.
// .
// **Spline Steps**: The number of straight-line segments to split a bezier segment into, to approximate the bezier curve. The more spline steps, the closer the approximation will be to the curve, but the slower it will be to generate. Usually defaults to 16.
// Terminology:
// Path = A series of points joined by straight line segements.
// Bezier Curve = A mathematical curve that joins two endpoints, following a curve determined by one or more control points.
// Endpoint = A point that is on the end of a bezier segment. This point lies on the bezier curve.
// Control Point = A point that influences the shape of the curve that connects two endpoints. This is often *NOT* on the bezier curve.
// Degree = The number of control points, plus one endpoint, needed to specify a bezier segment. Most beziers are cubic (degree 3).
// Bezier Segment = A list consisting of an endpoint, one or more control points, and a final endpoint. The number of control points is one less than the degree of the bezier. A cubic (degree 3) bezier segment looks something like: `[endpt1, cp1, cp2, endpt2]`
// Bezier Path = A list of bezier segments flattened out into a list of points, where each segment shares the endpoint of the previous segment as a start point. A cubic Bezier Path looks something like: `[endpt1, cp1, cp2, endpt2, cp3, cp4, endpt3]` **NOTE:** A "bezier path" is *NOT* a standard path. It is only the points and controls used to define the curve.
// Bezier Patch = A surface defining grid of (N+1) by (N+1) bezier points. If a Bezier Segment defines a curved line, a Bezier Patch defines a curved surface.
// Bezier Surface = A surface defined by a list of one or more bezier patches.
// Spline Steps = The number of straight-line segments to split a bezier segment into, to approximate the bezier curve. The more spline steps, the closer the approximation will be to the curve, but the slower it will be to generate. Usually defaults to 16.
// Section: Segment Functions
@ -38,6 +26,7 @@
// pt = bezier_points(curve, u);
// ptlist = bezier_points(curve, RANGE);
// ptlist = bezier_points(curve, LIST);
// Topics: Bezier Segments
// Description:
// Computes bezier points for bezier with control points specified by `curve` at parameter values
// specified by `u`, which can be a scalar or a list. This function uses an optimized method which
@ -184,6 +173,8 @@ function _bezier_matrix(N) =
// deriv = bezier_derivative(curve, u, <order>);
// derivs = bezier_derivative(curve, LIST, <order>);
// derivs = bezier_derivative(curve, RANGE, <order>);
// Topics: Bezier Segments
// See Also: bezier_curvature(), bezier_tangent(), bezier_points()
// Description:
// Finds the `order`th derivative of the bezier segment at the given position `u`.
// The degree of the bezier segment is one less than the number of points in `curve`.
@ -206,6 +197,8 @@ function bezier_derivative(curve, u, order=1) =
// tanvec = bezier_tangent(curve, u);
// tanvecs = bezier_tangent(curve, LIST);
// tanvecs = bezier_tangent(curve, RANGE);
// Topics: Bezier Segments
// See Also: bezier_curvature(), bezier_derivative(), bezier_points()
// Description:
// Returns the unit vector of the tangent at the given position `u` on the bezier segment `curve`.
// Arguments:
@ -224,6 +217,8 @@ function bezier_tangent(curve, u) =
// crv = bezier_curvature(curve, u);
// crvlist = bezier_curvature(curve, LIST);
// crvlist = bezier_curvature(curve, RANGE);
// Topics: Bezier Segments
// See Also: bezier_tangent(), bezier_derivative(), bezier_points()
// Description:
// Returns the curvature value for the given position `u` on the bezier segment `curve`.
// The curvature is the inverse of the radius of the tangent circle at the given point.
@ -249,6 +244,8 @@ function bezier_curvature(curve, u) =
// Function: bezier_curve()
// Usage:
// path = bezier_curve(curve, n, <endpoint>);
// Topics: Bezier Segments
// See Also: bezier_curvature(), bezier_tangent(), bezier_derivative(), bezier_points()
// Description:
// Takes a list of bezier curve control points and generates n points along the bezier path.
// Points start at the first control point and are sampled every `1/n`th
@ -279,6 +276,8 @@ function bezier_curve(curve,n,endpoint) = [each bezier_points(curve, [0:1/n:(n-0
// Function: bezier_segment_closest_point()
// Usage:
// u = bezier_segment_closest_point(bezier, pt, <max_err>);
// Topics: Bezier Segments
// See Also: bezier_points()
// Description:
// Finds the closest part of the given bezier segment to point `pt`.
// The degree of the curve, N, is one less than the number of points in `curve`.
@ -326,6 +325,8 @@ function bezier_segment_closest_point(curve, pt, max_err=0.01, u=0, end_u=1) =
// Function: bezier_segment_length()
// Usage:
// pathlen = bezier_segment_length(curve, <start_u>, <end_u>, <max_deflect>);
// Topics: Bezier Segments
// See Also: bezier_points()
// Description:
// Approximates the length of the bezier segment between start_u and end_u.
// Arguments:
@ -361,6 +362,8 @@ function bezier_segment_length(curve, start_u=0, end_u=1, max_deflect=0.01) =
// Function: bezier_line_intersection()
// Usage:
// u = bezier_line_intersection(curve, line);
// Topics: Bezier Segments, Geometry, Intersection
// See Also: bezier_points(), bezier_segment_length(), bezier_segment_closest_point()
// Description:
// Finds the parameter(s) of the 2d curve whose Bezier control points are `curve`
// corresponding to its intersection points with the line through
@ -384,6 +387,8 @@ function bezier_line_intersection(curve, line) =
// Usage:
// bez_path_pts = fillet3pts(p0, p1, p2, r);
// bez_path_pts = fillet3pts(p0, p1, p2, d=);
// Topics: Bezier Segments, Rounding
// See Also: bezier_points(), bezier_curve()
// Description:
// Takes three points, defining two line segments, and works out the cubic (degree 3) bezier segment
// (and surrounding control points) needed to approximate a rounding of the corner with radius `r`.
@ -433,6 +438,8 @@ function fillet3pts(p0, p1, p2, r, d, maxerr=0.1, w=0.5, dw=0.25) = let(
// pt = bezier_path_point(path, seg, u, <N>);
// ptlist = bezier_path_point(path, seg, LIST, <N>);
// path = bezier_path_point(path, seg, RANGE, <N>);
// Topics: Bezier Paths
// See Also: bezier_points(), bezier_curve()
// Description:
// Returns the coordinates of bezier path segment `seg` at position `u`.
// Arguments:
@ -448,6 +455,8 @@ function bezier_path_point(path, seg, u, N=3) =
// Function: bezier_path_closest_point()
// Usage:
// res = bezier_path_closest_point(bezier,pt);
// Topics: Bezier Paths
// See Also: bezier_points(), bezier_curve(), bezier_segment_closest_point()
// Description:
// Finds the closest part of the given bezier path to point `pt`.
// Returns [segnum, u] for the closest position on the bezier path to the given point `pt`.
@ -490,6 +499,8 @@ function bezier_path_closest_point(path, pt, N=3, max_err=0.01, seg=0, min_seg=u
// Function: bezier_path_length()
// Usage:
// plen = bezier_path_length(path, <N>, <max_deflect>);
// Topics: Bezier Paths
// See Also: bezier_points(), bezier_curve(), bezier_segment_length()
// Description:
// Approximates the length of the bezier path.
// Arguments:
@ -514,6 +525,8 @@ function bezier_path_length(path, N=3, max_deflect=0.001) =
// Function: bezier_path()
// Usage:
// path = bezier_path(bezier, <splinesteps>, <N>)
// Topics: Bezier Paths
// See Also: bezier_points(), bezier_curve()
// Description:
// Takes a bezier path and converts it into a path of points.
// Arguments:
@ -547,6 +560,8 @@ function bezier_path(bezier, splinesteps=16, N=3) =
// Function: path_to_bezier()
// Usage:
// bezpath = path_to_bezier(path, <closed>, <tangents>, <uniform>, <size=>|<relsize=>);
// Topics: Bezier Paths, Rounding
// See Also: path_tangents(), fillet_path()
// Description:
// Given a 2d or 3d input path and optional list of tangent vectors, computes a cubic (degree 3) bezier
// path that passes through every point on the input path and matches the tangent vectors. If you do
@ -627,6 +642,8 @@ function path_to_bezier(path, closed=false, tangents, uniform=false, size, relsi
// Function: fillet_path()
// Usage:
// bezpath = fillet_path(pts, fillet, <maxerr>);
// Topics: Bezier Paths, Rounding
// See Also: path_to_bezier(), bezier_path()
// Description:
// Takes a 3D path and fillets the corners, returning a 3d cubic (degree 3) bezier path.
// Arguments:
@ -654,6 +671,8 @@ function fillet_path(pts, fillet, maxerr=0.1) = concat(
// Function: bezier_close_to_axis()
// Usage:
// bezpath = bezier_close_to_axis(bezier, <axis>, <N>);
// Topics: Bezier Paths
// See Also: bezier_offset()
// Description:
// Takes a 2D bezier path and closes it to the specified axis.
// Arguments:
@ -694,6 +713,8 @@ function bezier_close_to_axis(bezier, axis="X", N=3) =
// Function: bezier_offset()
// Usage:
// bezpath = bezier_offset(offset, bezier, <N>);
// Topics: Bezier Paths
// See Also: bezier_close_to_axis()
// Description:
// Takes a 2D bezier path and closes it with a matching reversed path that is offset by the given `offset` [X,Y] distance.
// Arguments:
@ -731,6 +752,8 @@ function bezier_offset(offset, bezier, N=3) =
// Module: bezier_polygon()
// Usage:
// bezier_polygon(bezier, <splinesteps>, <N>) {
// Topics: Bezier Paths
// See Also: bezier_path()
// Description:
// Takes a closed 2D bezier path, and creates a 2D polygon from it.
// Arguments:
@ -761,6 +784,8 @@ module bezier_polygon(bezier, splinesteps=16, N=3) {
// Module: trace_bezier()
// Usage:
// trace_bezier(bez, <size>, <N=>) {
// Topics: Bezier Paths, Debugging
// See Also: bezier_path()
// Description:
// Renders 2D or 3D bezier paths and their associated control points.
// Useful for debugging bezier paths.
@ -795,6 +820,8 @@ module trace_bezier(bez, size=1, N=3) {
// pt = bezier_patch_points(patch, u, v);
// ptgrid = bezier_patch_points(patch, LIST, LIST);
// ptgrid = bezier_patch_points(patch, RANGE, RANGE);
// Topics: Bezier Patches
// See Also: bezier_points(), bezier_curve(), bezier_path(), bezier_triangle_point()
// Description:
// Given a square 2-dimensional array of (N+1) by (N+1) points size, that represents a Bezier Patch
// of degree N, returns a point on that surface, at positions `u`, and `v`. A cubic bezier patch
@ -837,6 +864,8 @@ function bezier_patch_points(patch, u, v) =
// Function: bezier_triangle_point()
// Usage:
// pt = bezier_triangle_point(tri, u, v);
// Topics: Bezier Patches
// See Also: bezier_points(), bezier_curve(), bezier_path(), bezier_patch_points()
// Description:
// Given a triangular 2-dimensional array of N+1 by (for the first row) N+1 points,
// that represents a Bezier triangular patch of degree N, returns a point on
@ -870,6 +899,8 @@ function bezier_triangle_point(tri, u, v) =
// Function: is_tripatch()
// Usage:
// bool = is_tripatch(x);
// Topics: Bezier Patches, Type Checking
// See Also: is_rectpatch(), is_patch()
// Description:
// Returns true if the given item is a triangular bezier patch.
// Arguments:
@ -881,6 +912,8 @@ function is_tripatch(x) =
// Function: is_rectpatch()
// Usage:
// bool = is_rectpatch(x);
// Topics: Bezier Patches, Type Checking
// See Also: is_tripatch(), is_patch()
// Description:
// Returns true if the given item is a rectangular bezier patch.
// Arguments:
@ -892,6 +925,8 @@ function is_rectpatch(x) =
// Function: is_patch()
// Usage:
// bool = is_patch(x);
// Topics: Bezier Patches, Type Checking
// See Also: is_tripatch(), is_rectpatch()
// Description:
// Returns true if the given item is a bezier patch.
// Arguments:
@ -903,6 +938,8 @@ function is_patch(x) =
// Function: bezier_patch()
// Usage:
// vnf = bezier_patch(patch, <splinesteps>, <vnf=>, <style=>);
// Topics: Bezier Patches
// See Also: bezier_points(), bezier_curve(), bezier_path(), bezier_patch_points(), bezier_triangle_point()
// Description:
// Calculate vertices and faces for forming a partial polyhedron from the given bezier rectangular
// or triangular patch. Returns a [VNF structure](vnf.scad): a list containing two elements. The first is the
@ -1052,6 +1089,8 @@ function _bezier_triangle(tri, splinesteps=16, vnf=EMPTY_VNF) =
// Function: bezier_patch_flat()
// Usage:
// patch = bezier_patch_flat(size, <N=>, <spin=>, <orient=>, <trans=>);
// Topics: Bezier Patches
// See Also: bezier_patch_points()
// Description:
// Returns a flat rectangular bezier patch of degree `N`, centered on the XY plane.
// Arguments:
@ -1079,6 +1118,8 @@ function bezier_patch_flat(size=[100,100], N=4, spin=0, orient=UP, trans=[0,0,0]
// Function: patch_reverse()
// Usage:
// rpatch = patch_reverse(patch);
// Topics: Bezier Patches
// See Also: bezier_patch_points(), bezier_patch_flat()
// Description:
// Reverses the patch, so that the faces generated from it are flipped back to front.
// Arguments:
@ -1093,6 +1134,8 @@ function patch_reverse(patch) =
// Function: bezier_surface()
// Usage:
// vnf = bezier_surface(patches, <splinesteps>, <vnf=>, <style=>);
// Topics: Bezier Patches
// See Also: bezier_patch_points(), bezier_patch_flat()
// Description:
// Calculate vertices and faces for forming a (possibly partial) polyhedron from the given
// rectangular and/or triangular bezier patches. Returns a [VNF structure](vnf.scad): a list
@ -1134,6 +1177,8 @@ function bezier_surface(patches=[], splinesteps=16, vnf=EMPTY_VNF, style="defaul
// Module: trace_bezier_patches()
// Usage:
// trace_bezier_patches(patches, [size], [splinesteps], [showcps], [showdots], [showpatch], [convexity], [style]);
// Topics: Bezier Patches, Debugging
// See Also: bezier_patch_points(), bezier_patch_flat(), bezier_surface()
// Description:
// Shows the surface, and optionally, control points of a list of bezier patches.
// Arguments:

View file

@ -12,6 +12,8 @@
// Function: typeof()
// Usage:
// typ = typeof(x);
// Topics: Type Checking
// See Also: is_type()
// Description:
// Returns a string representing the type of the value. One of "undef", "boolean", "number", "nan", "string", "list", "range", "function" or "invalid".
// Some malformed "ranges", like '[0:NAN:INF]' and '[0:"a":INF]', may be classified as "undef" or "invalid".
@ -40,6 +42,8 @@ function typeof(x) =
// Function: is_type()
// Usage:
// bool = is_type(x, types);
// Topics: Type Checking
// See Also: typeof()
// Description:
// Returns true if the type of the value `x` is one of those given as strings in the list `types`.
// Valid types are "undef", "boolean", "number", "nan", "string", "list", "range", or "function".
@ -63,6 +67,8 @@ function is_type(x,types) =
// Function: is_def()
// Usage:
// bool = is_def(x);
// Topics: Type Checking
// See Also: typeof(), is_type(), is_str()
// Description:
// Returns true if `x` is not `undef`. False if `x==undef`.
// Example:
@ -76,6 +82,8 @@ function is_def(x) = !is_undef(x);
// Function: is_str()
// Usage:
// bool = is_str(x);
// Topics: Type Checking
// See Also: typeof(), is_type(), is_int(), is_def()
// Description:
// Returns true if `x` is a string. A shortcut for `is_string()`.
// Example:
@ -87,9 +95,12 @@ function is_str(x) = is_string(x);
// Function: is_int()
// Alias: is_integer()
// Usage:
// bool = is_int(n);
// bool = is_integer(n);
// Topics: Type Checking
// See Also: typeof(), is_type(), is_str(), is_def()
// Description:
// Returns true if the given value is an integer (it is a number and it rounds to itself).
// Example:
@ -104,6 +115,8 @@ function is_integer(n) = is_finite(n) && n == round(n);
// Function: is_nan()
// Usage:
// bool = is_nan(x);
// Topics: Type Checking
// See Also: typeof(), is_type(), is_str(), is_def(), is_int()
// Description:
// Returns true if a given value `x` is nan, a floating point value representing "not a number".
// Example:
@ -118,6 +131,8 @@ function is_nan(x) = (x!=x);
// Function: is_finite()
// Usage:
// bool = is_finite(x);
// Topics: Type Checking
// See Also: typeof(), is_type(), is_str(), is_def(), is_int(), is_nan()
// Description:
// Returns true if a given value `x` is a finite number.
// Example:
@ -134,6 +149,8 @@ function is_finite(x) = is_num(x) && !is_nan(0*x);
// Function: is_range()
// Usage:
// bool = is_range(x);
// Topics: Type Checking
// See Also: typeof(), is_type(), is_str(), is_def(), is_int()
// Description:
// Returns true if its argument is a range
// Example:
@ -149,6 +166,8 @@ function is_range(x) = !is_list(x) && is_finite(x[0]) && is_finite(x[1]) && is_f
// Function: valid_range()
// Usage:
// bool = valid_range(x);
// Topics: Type Checking
// See Also: typeof(), is_type(), is_str(), is_def(), is_int(), is_range()
// Description:
// Returns true if its argument is a valid range (deprecated ranges excluded).
// Example:
@ -169,6 +188,8 @@ function valid_range(x) =
// Function: is_list_of()
// Usage:
// bool = is_list_of(list, pattern);
// Topics: Type Checking
// See Also: typeof(), is_type(), is_str(), is_def(), is_int(), is_range()
// Description:
// Tests whether the input is a list whose entries are all numeric lists that have the same
// list shape as the pattern.
@ -190,6 +211,8 @@ function is_list_of(list,pattern) =
// Function: is_consistent()
// Usage:
// bool = is_consistent(list);
// Topics: Type Checking
// See Also: typeof(), is_type(), is_str(), is_def(), is_int(), is_range(), is_homogenous()
// Description:
// Tests whether input is a list of entries which all have the same list structure
// and are filled with finite numerical data. It returns `true`for the empty list.
@ -214,6 +237,8 @@ function _list_pattern(list) =
// Function: same_shape()
// Usage:
// bool = same_shape(a,b);
// Topics: Type Checking
// See Also: is_homogenous(), is_consistent()
// Description:
// Tests whether the inputs `a` and `b` are both numeric and are the same shaped list.
// Example:
@ -225,6 +250,8 @@ function same_shape(a,b) = _list_pattern(a) == b*0;
// Function: is_bool_list()
// Usage:
// check = is_bool_list(list,<length>)
// Topics: Type Checking
// See Also: is_homogenous(), is_consistent()
// Description:
// Tests whether input is a list containing only booleans, and optionally checks its length.
// Arguments:
@ -240,6 +267,8 @@ function is_bool_list(list, length) =
// Function: default()
// Usage:
// val = default(val, dflt);
// Topics: Undef Handling
// See Also: first_defined(), one_defined(), num_defined()
// Description:
// Returns the value given as `v` if it is not `undef`. Otherwise, returns the value of `dflt`.
// Arguments:
@ -251,6 +280,8 @@ function default(v,dflt=undef) = is_undef(v)? dflt : v;
// Function: first_defined()
// Usage:
// val = first_defined(v, <recursive>);
// Topics: Undef Handling
// See Also: default(), one_defined(), num_defined(), any_defined(), all_defined()
// Description:
// Returns the first item in the list that is not `undef`.
// If all items are `undef`, or list is empty, returns `undef`.
@ -270,6 +301,8 @@ function first_defined(v,recursive=false,_i=0) =
// Function: one_defined()
// Usage:
// val = one_defined(vals, names, <dflt>)
// Topics: Undef Handling
// See Also: default(), first_defined(), num_defined(), any_defined(), all_defined()
// Description:
// Examines the input list `vals` and returns the entry which is not `undef`.
// If more than one entry is not `undef` then an error is asserted, specifying
@ -307,6 +340,8 @@ function one_defined(vals, names, dflt=_UNDEF) =
// Function: num_defined()
// Usage:
// cnt = num_defined(v);
// Topics: Undef Handling
// See Also: default(), first_defined(), one_defined(), any_defined(), all_defined()
// Description:
// Counts how many items in list `v` are not `undef`.
// Example:
@ -318,6 +353,8 @@ function num_defined(v) =
// Function: any_defined()
// Usage:
// bool = any_defined(v, <recursive>);
// Topics: Undef Handling
// See Also: default(), first_defined(), one_defined(), num_defined(), all_defined()
// Description:
// Returns true if any item in the given array is not `undef`.
// Arguments:
@ -360,6 +397,8 @@ function all_defined(v,recursive=false) =
// Function: get_anchor()
// Usage:
// anchr = get_anchor(anchor,center,<uncentered>,<dflt>);
// Topics: Argument Handling
// See Also: get_radius(), get_named_args()
// Description:
// Calculated the correct anchor from `anchor` and `center`. In order:
// - If `center` is not `undef` and `center` evaluates as true, then `CENTER` (`[0,0,0]`) is returned.
@ -388,6 +427,8 @@ function get_anchor(anchor,center,uncentered=BOT,dflt=CENTER) =
// Function: get_radius()
// Usage:
// r = get_radius(<r1=>, <r2=>, <r=>, <d1=>, <d2=>, <d=>, <dflt=>);
// Topics: Argument Handling
// See Also: get_anchor(), get_named_args()
// Description:
// Given various radii and diameters, returns the most specific radius. If a diameter is most
// specific, returns half its value, giving the radius. If no radii or diameters are defined,
@ -433,6 +474,8 @@ function get_radius(r1, r2, r, d1, d2, d, dflt) =
// Function: get_named_args()
// Usage:
// function f(pos1=_UNDEF, pos2=_UNDEF,...,named1=_UNDEF, named2=_UNDEF, ...) = let(args = get_named_args([pos1, pos2, ...], [[named1, default1], [named2, default2], ...]), named1=args[0], named2=args[1], ...)
// Topics: Argument Handling
// See Also: get_anchor(), get_radius()
// Description:
// Given the values of some positional and named arguments, returns a list of the values assigned to
// named parameters. in the following steps:
@ -517,6 +560,8 @@ function get_named_args(positional, named, _undef=_UNDEF) =
// Function: scalar_vec3()
// Usage:
// vec = scalar_vec3(v, <dflt>);
// Topics: Argument Handling
// See Also: get_anchor(), get_radius(), force_list()
// Description:
// If `v` is a scalar, and `dflt==undef`, returns `[v, v, v]`.
// If `v` is a scalar, and `dflt!=undef`, returns `[v, dflt, dflt]`.
@ -539,6 +584,7 @@ function scalar_vec3(v, dflt) =
// Function: segs()
// Usage:
// sides = segs(r);
// Topics: Geometry
// Description:
// Calculate the standard number of sides OpenSCAD would give a circle based on `$fn`, `$fa`, and `$fs`.
// Arguments:
@ -553,6 +599,8 @@ function segs(r) =
// Module: no_children()
// Topics: Error Checking
// See Also: no_function(), no_module()
// Usage:
// no_children($children);
// Description:
@ -575,6 +623,8 @@ module no_children(count) {
// Function: no_function()
// Usage:
// dummy = no_function(name)
// Topics: Error Checking
// See Also: no_children(), no_module()
// Description:
// Asserts that the function, "name", only exists as a module.
// Example:
@ -586,6 +636,8 @@ function no_function(name) =
// Module: no_module()
// Usage:
// no_module();
// Topics: Error Checking
// See Also: no_children(), no_function()
// Description:
// Asserts that the called module exists only as a function.
// Example:
@ -606,6 +658,8 @@ function _valstr(x) =
// Module: assert_approx()
// Usage:
// assert_approx(got, expected, <info>);
// Topics: Error Checking, Debugging
// See Also: no_children(), no_function(), no_module(), assert_equal()
// Description:
// Tests if the value gotten is what was expected. If not, then
// the expected and received values are printed to the console and
@ -636,6 +690,8 @@ module assert_approx(got, expected, info) {
// Module: assert_equal()
// Usage:
// assert_equal(got, expected, <info>);
// Topics: Error Checking, Debugging
// See Also: no_children(), no_function(), no_module(), assert_approx()
// Description:
// Tests if the value gotten is what was expected. If not, then the expected and received values
// are printed to the console and an assertion is thrown to stop execution.
@ -665,6 +721,8 @@ module assert_equal(got, expected, info) {
// Module: shape_compare()
// Usage:
// shape_compare(<eps>) {test_shape(); expected_shape();}
// Topics: Error Checking, Debugging, Testing
// See Also: assert_approx(), assert_equal()
// Description:
// Compares two child shapes, returning empty geometry if they are very nearly the same shape and size.
// Returns the differential geometry if they are not quite the same shape and size.
@ -743,10 +801,12 @@ module shape_compare(eps=1/1024) {
// Function: looping()
// Usage:
// bool = looping(state);
// Topics: Iteration
// See Also: loop_while(), loop_done()
// Description:
// Returns true if the `state` value indicates the current loop should continue. This is useful
// when using C-style for loops to iteratively calculate a value. Used with `loop_while()` and
// `loop_done()`. See [Looping Helpers](#5-looping-helpers) for an example.
// `loop_done()`. See [Looping Helpers](section-looping-helpers) for an example.
// Arguments:
// state = The loop state value.
function looping(state) = state < 2;
@ -755,11 +815,13 @@ function looping(state) = state < 2;
// Function: loop_while()
// Usage:
// state = loop_while(state, continue);
// Topics: Iteration
// See Also: looping(), loop_done()
// Description:
// Given the current `state`, and a boolean `continue` that indicates if the loop should still be
// continuing, returns the updated state value for the the next loop. This is useful when using
// C-style for loops to iteratively calculate a value. Used with `looping()` and `loop_done()`.
// See [Looping Helpers](#5-looping-helpers) for an example.
// See [Looping Helpers](section-looping-helpers) for an example.
// Arguments:
// state = The loop state value.
// continue = A boolean value indicating whether the current loop should progress.
@ -771,6 +833,8 @@ function loop_while(state, continue) =
// Function: loop_done()
// Usage:
// bool = loop_done(state);
// Topics: Iteration
// See Also: looping(), loop_while()
// Description:
// Returns true if the `state` value indicates the loop is finishing. This is useful when using
// C-style for loops to iteratively calculate a value. Used with `looping()` and `loop_while()`.

View file

@ -104,12 +104,16 @@ INCH = 25.4;
// Vectors useful for `rotate()`, `mirror()`, and `anchor` arguments for `cuboid()`, `cyl()`, etc.
// Constant: LEFT
// Topics: Constants, Vectors
// See Also: RIGHT, FRONT, BACK, UP, DOWN, CENTER, ALLPOS, ALLNEG
// Description: Vector pointing left. [-1,0,0]
// Example(3D): Usage with `anchor`
// cuboid(20, anchor=LEFT);
LEFT = [-1, 0, 0];
// Constant: RIGHT
// Topics: Constants, Vectors
// See Also: LEFT, FRONT, BACK, UP, DOWN, CENTER, ALLPOS, ALLNEG
// Description: Vector pointing right. [1,0,0]
// Example(3D): Usage with `anchor`
// cuboid(20, anchor=RIGHT);
@ -117,6 +121,8 @@ RIGHT = [ 1, 0, 0];
// Constant: FRONT
// Aliases: FWD, FORWARD
// Topics: Constants, Vectors
// See Also: LEFT, RIGHT, BACK, UP, DOWN, CENTER, ALLPOS, ALLNEG
// Description: Vector pointing forward. [0,-1,0]
// Example(3D): Usage with `anchor`
// cuboid(20, anchor=FRONT);
@ -125,6 +131,8 @@ FWD = FRONT;
FORWARD = FRONT;
// Constant: BACK
// Topics: Constants, Vectors
// See Also: LEFT, RIGHT, FRONT, UP, DOWN, CENTER, ALLPOS, ALLNEG
// Description: Vector pointing back. [0,1,0]
// Example(3D): Usage with `anchor`
// cuboid(20, anchor=BACK);
@ -132,6 +140,8 @@ BACK = [ 0, 1, 0];
// Constant: BOTTOM
// Aliases: BOT, BTM, DOWN
// Topics: Constants, Vectors
// See Also: LEFT, RIGHT, FRONT, BACK, UP, CENTER, ALLPOS, ALLNEG
// Description: Vector pointing down. [0,0,-1]
// Example(3D): Usage with `anchor`
// cuboid(20, anchor=BOTTOM);
@ -142,6 +152,8 @@ DOWN = BOTTOM;
// Constant: TOP
// Aliases: UP
// Topics: Constants, Vectors
// See Also: LEFT, RIGHT, FRONT, BACK, DOWN, CENTER, ALLPOS, ALLNEG
// Description: Vector pointing up. [0,0,1]
// Example(3D): Usage with `anchor`
// cuboid(20, anchor=TOP);
@ -149,12 +161,16 @@ TOP = [ 0, 0, 1];
UP = TOP;
// Constant: ALLPOS
// Topics: Constants, Vectors
// See Also: LEFT, RIGHT, FRONT, BACK, UP, DOWN, CENTER, ALLNEG
// Description: Vector pointing right, back, and up. [1,1,1]
// Example(3D): Usage with `anchor`
// cuboid(20, anchor=ALLPOS);
ALLPOS = [ 1, 1, 1]; // Vector pointing X+,Y+,Z+.
// Constant: ALLNEG
// Topics: Constants, Vectors
// See Also: LEFT, RIGHT, FRONT, BACK, UP, DOWN, CENTER, ALLPOS
// Description: Vector pointing left, forwards, and down. [-1,-1,-1]
// Example(3D): Usage with `anchor`
// cuboid(20, anchor=ALLNEG);
@ -162,6 +178,8 @@ ALLNEG = [-1, -1, -1]; // Vector pointing X-,Y-,Z-.
// Constant: CENTER
// Aliases: CTR
// Topics: Constants, Vectors
// See Also: LEFT, RIGHT, FRONT, BACK, UP, DOWN, ALLNEG, ALLPOS
// Description: Zero vector. Centered. [0,0,0]
// Example(3D): Usage with `anchor`
// cuboid(20, anchor=CENTER);

View file

@ -2,7 +2,7 @@
// LibFile: gears.scad
// Spur Gears, Bevel Gears, Racks, Worms and Worm Gears.
// Originally based on code by Leemon Baird, 2011, Leemon@Leemon.com
// Almost completely rewritten for BOSL2 by Revar Desmera, 2017-2019, revarbat@gmail.com
// Almost completely rewritten for BOSL2 by Revar Desmera, 2017-2021, revarbat@gmail.com
// Includes:
// include <BOSL2/std.scad>
// include <BOSL2/gears.scad>
@ -31,6 +31,7 @@
// Function: circular_pitch()
// Usage:
// circp = circular_pitch(pitch|mod);
// Topics: Gears
// Description:
// Get tooth density expressed as "circular pitch".
// Arguments:
@ -47,6 +48,7 @@ function circular_pitch(pitch=5, mod) =
// Function: diametral_pitch()
// Usage:
// dp = diametral_pitch(pitch|mod);
// Topics: Gears
// Description:
// Get tooth density expressed as "diametral pitch".
// Arguments:
@ -63,6 +65,7 @@ function diametral_pitch(pitch=5, mod) =
// Function: pitch_value()
// Usage:
// pitch = pitch_value(mod);
// Topics: Gears
// Description:
// Get circular pitch in mm from module/modulus. The circular pitch of a gear is the number of
// millimeters per tooth around the pitch radius circle.
@ -74,6 +77,7 @@ function pitch_value(mod) = mod * PI;
// Function: module_value()
// Usage:
// mod = module_value(pitch);
// Topics: Gears
// Description:
// Get tooth density expressed as "module" or "modulus" in millimeters. The module is the pitch
// diameter of the gear divided by the number of teeth on it. For example, a gear with a pitch
@ -86,6 +90,7 @@ function module_value(pitch=5) = pitch / PI;
// Function: adendum()
// Usage:
// ad = adendum(pitch|mod);
// Topics: Gears
// Description:
// The height of the top of a gear tooth above the pitch radius circle.
// Arguments:
@ -111,6 +116,7 @@ function adendum(pitch=5, mod) =
// Function: dedendum()
// Usage:
// ddn = dedendum(pitch|mod, <clearance>);
// Topics: Gears
// Description:
// The depth of the gear tooth valley, below the pitch radius.
// Arguments:
@ -138,6 +144,7 @@ function dedendum(pitch=5, clearance, mod) =
// Function: pitch_radius()
// Usage:
// pr = pitch_radius(pitch|mod, teeth);
// Topics: Gears
// Description:
// Calculates the pitch radius for the gear. Two mated gears will have their centers spaced apart
// by the sum of the two gear's pitch radii.
@ -161,6 +168,7 @@ function pitch_radius(pitch=5, teeth=11, mod) =
// Function: outer_radius()
// Usage:
// or = outer_radius(pitch|mod, teeth, <clearance>, <interior>);
// Topics: Gears
// Description:
// Calculates the outer radius for the gear. The gear fits entirely within a cylinder of this radius.
// Arguments:
@ -186,6 +194,7 @@ function outer_radius(pitch=5, teeth=11, clearance, interior=false, mod) =
// Function: root_radius()
// Usage:
// rr = root_radius(pitch|mod, teeth, <clearance>, <interior>);
// Topics: Gears
// Description:
// Calculates the root radius for the gear, at the base of the dedendum.
// Arguments:
@ -211,6 +220,7 @@ function root_radius(pitch=5, teeth=11, clearance, interior=false, mod) =
// Function: base_radius()
// Usage:
// br = base_radius(pitch|mod, teeth, <pressure_angle>);
// Topics: Gears
// Description:
// Get the base circle for involute teeth, at the base of the teeth.
// Arguments:
@ -234,6 +244,8 @@ function base_radius(pitch=5, teeth=11, pressure_angle=28, mod) =
// Function: bevel_pitch_angle()
// Usage:
// ang = bevel_pitch_angle(teeth, mate_teeth, <drive_angle>);
// Topics: Gears
// See Also: bevel_gear()
// Description:
// Returns the correct pitch angle for a bevel gear with a given number of tooth, that is
// matched to another bevel gear with a (possibly different) number of teeth.
@ -263,6 +275,8 @@ function bevel_pitch_angle(teeth, mate_teeth, drive_angle=90) =
// Function: worm_gear_thickness()
// Usage:
// thick = worm_gear_thickness(pitch|mod, teeth, worm_diam, <worm_arc>, <crowning>, <clearance>);
// Topics: Gears
// See Also: worm(), worm_gear()
// Description:
// Calculate the thickness of the worm gear.
// Arguments:
@ -316,6 +330,8 @@ function _gear_q7(f,r,b,r2,t,s) = _gear_q6(b,s,t,(1-f)*max(b,r)+f*r2); //
// gear_tooth_profile(pitch|mod, teeth, <pressure_angle>, <clearance>, <backlash>, <interior>, <valleys>);
// Usage: As Function
// path = gear_tooth_profile(pitch|mod, teeth, <pressure_angle>, <clearance>, <backlash>, <interior>, <valleys>);
// Topics: Gears
// See Also: spur_gear2d()
// Description:
// When called as a function, returns the 2D profile path for an individual gear tooth.
// When called as a module, creates the 2D profile shape for an individual gear tooth.
@ -414,6 +430,8 @@ module gear_tooth_profile(
// spur_gear2d(pitch|mod, teeth, <hide>, <pressure_angle>, <clearance>, <backlash>, <interior>);
// Usage: As Function
// poly = spur_gear2d(pitch|mod, teeth, <hide>, <pressure_angle>, <clearance>, <backlash>, <interior>);
// Topics: Gears
// See Also: spur_gear()
// Description:
// When called as a module, creates a 2D involute spur gear. When called as a function, returns a
// 2D path for the perimeter of a 2D involute spur gear. Normally, you should just specify the
@ -511,6 +529,8 @@ module spur_gear2d(
// path = rack2d(pitch|mod, teeth, height, <pressure_angle>, <backlash>);
// Usage: As a Module
// rack2d(pitch|mod, teeth, height, <pressure_angle>, <backlash>);
// Topics: Gears
// See Also: spur_gear2d()
// Description:
// This is used to create a 2D rack, which is a linear bar with teeth that a gear can roll along.
// A rack can mesh with any gear that has the same `pitch` and `pressure_angle`.
@ -632,6 +652,8 @@ module rack2d(
// Usage: As a Function
// vnf = spur_gear(pitch, teeth, thickness, <shaft_diam>, ...);
// vnf = spur_gear(mod=, teeth=, thickness=, <shaft_diam>, ...);
// Topics: Gears
// See Also: rack()
// Description:
// Creates a (potentially helical) involute spur gear. The module `spur_gear()` gives an involute
// spur gear, with reasonable defaults for all the parameters. Normally, you should just choose the
@ -795,6 +817,8 @@ module spur_gear(
// bevel_gear(pitch|mod, teeth, face_width, pitch_angle, <shaft_diam>, <hide>, <pressure_angle>, <clearance>, <backlash>, <cutter_radius>, <spiral_angle>, <slices>, <interior>);
// Usage: As a Function
// vnf = bevel_gear(pitch|mod, teeth, face_width, pitch_angle, <hide>, <pressure_angle>, <clearance>, <backlash>, <cutter_radius>, <spiral_angle>, <slices>, <interior>);
// Topics: Gears
// See Also: bevel_pitch_angle()
// Description:
// Creates a (potentially spiral) bevel gear. The module `bevel_gear()` gives a bevel gear, with
// reasonable defaults for all the parameters. Normally, you should just choose the first 4
@ -1042,6 +1066,8 @@ module bevel_gear(
// Usage: As a Function
// vnf = rack(pitch, teeth, thickness, height, <pressure_angle=>, <backlash=>);
// vnf = rack(mod=, teeth=, thickness=, height=, <pressure_angle=>, <backlash=>);
// Topics: Gears
// See Also: spur_gear()
// Description:
// This is used to create a 3D rack, which is a linear bar with teeth that a gear can roll along.
// A rack can mesh with any gear that has the same `pitch` and `pressure_angle`.
@ -1185,6 +1211,8 @@ function rack(
// worm(pitch|mod, d, l, <starts>, <left_handed>, <pressure_angle>, <backlash>, <clearance>);
// Usage: As a Function
// vnf = worm(pitch|mod, d, l, <starts>, <left_handed>, <pressure_angle>, <backlash>, <clearance>);
// Topics: Gears
// See Also: worm_gear()
// Description:
// Creates a worm shape that can be matched to a worm gear.
// Arguments:
@ -1299,6 +1327,8 @@ module worm(
// worm_gear(pitch|mod, teeth, worm_diam, <worm_starts>, <crowning>, <left_handed>, <pressure_angle>, <backlash>, <slices>, <clearance>, <shaft_diam>);
// Usage: As a Function
// vnf = worm_gear(pitch|mod, teeth, worm_diam, <worm_starts>, <crowning>, <left_handed>, <pressure_angle>, <backlash>, <slices>, <clearance>);
// Topics: Gears
// See Also: worm()
// Description:
// Creates a worm gear to match with a worm.
// Arguments: