mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2024-12-29 00:09:41 +00:00
Docs cleanup for common.scad
This commit is contained in:
parent
1ce59caa57
commit
a13a09db8d
5 changed files with 257 additions and 134 deletions
|
@ -131,6 +131,9 @@ module pco1810_neck(wall=2, anchor="support-ring", spin=0, orient=UP)
|
|||
}
|
||||
}
|
||||
|
||||
function pco1810_neck(wall=2, anchor="support-ring", spin=0, orient=UP) =
|
||||
no_function("pco1810_neck");
|
||||
|
||||
|
||||
// Module: pco1810_cap()
|
||||
// Usage:
|
||||
|
@ -195,6 +198,10 @@ module pco1810_cap(wall=2, texture="none", anchor=BOTTOM, spin=0, orient=UP)
|
|||
}
|
||||
}
|
||||
|
||||
function pco1810_cap(wall=2, texture="none", anchor=BOTTOM, spin=0, orient=UP) =
|
||||
no_function("pco1810_cap");
|
||||
|
||||
|
||||
|
||||
// Section: PCO-1881 Bottle Threading
|
||||
|
||||
|
@ -316,6 +323,9 @@ module pco1881_neck(wall=2, anchor="support-ring", spin=0, orient=UP)
|
|||
}
|
||||
}
|
||||
|
||||
function pco1881_neck(wall=2, anchor="support-ring", spin=0, orient=UP) =
|
||||
no_function("pco1881_neck");
|
||||
|
||||
|
||||
// Module: pco1881_cap()
|
||||
// Usage:
|
||||
|
@ -372,6 +382,9 @@ module pco1881_cap(wall=2, texture="none", anchor=BOTTOM, spin=0, orient=UP)
|
|||
}
|
||||
}
|
||||
|
||||
function pco1881_cap(wall=2, texture="none", anchor=BOTTOM, spin=0, orient=UP) =
|
||||
no_function("pco1881_cap");
|
||||
|
||||
|
||||
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
|
347
common.scad
347
common.scad
|
@ -13,8 +13,17 @@
|
|||
// Usage:
|
||||
// typ = typeof(x);
|
||||
// Description:
|
||||
// Returns a string representing the type of the value. One of "undef", "boolean", "number", "nan", "string", "list", "range" or "invalid".
|
||||
// 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".
|
||||
// Examples:
|
||||
// typ = typeof(undef); // Returns: "undef"
|
||||
// typ = typeof(true); // Returns: "boolean"
|
||||
// typ = typeof(42); // Returns: "number"
|
||||
// typ = typeof(NAN); // Returns: "nan"
|
||||
// typ = typeof("foo"); // Returns: "string"
|
||||
// typ = typeof([3,4,5]); // Returns: "list"
|
||||
// typ = typeof([3:1:8]); // Returns: "range"
|
||||
// typ = typeof(function (x,y) x+y); // Returns: "function"
|
||||
function typeof(x) =
|
||||
is_undef(x)? "undef" :
|
||||
is_bool(x)? "boolean" :
|
||||
|
@ -23,16 +32,17 @@ function typeof(x) =
|
|||
is_string(x)? "string" :
|
||||
is_list(x)? "list" :
|
||||
is_range(x) ? "range" :
|
||||
version_num()>20210000 && is_function(x) ? "function" :
|
||||
"invalid";
|
||||
|
||||
|
||||
|
||||
// Function: is_type()
|
||||
// Usage:
|
||||
// b = is_type(x, types);
|
||||
// bool = is_type(x, types);
|
||||
// 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", or "range"
|
||||
// Valid types are "undef", "boolean", "number", "nan", "string", "list", "range", or "function".
|
||||
// Arguments:
|
||||
// x = The value to check the type of.
|
||||
// types = A list of types to check
|
||||
|
@ -52,54 +62,103 @@ function is_type(x,types) =
|
|||
|
||||
// Function: is_def()
|
||||
// Usage:
|
||||
// is_def(x)
|
||||
// bool = is_def(x);
|
||||
// Description:
|
||||
// Returns true if `x` is not `undef`. False if `x==undef`.
|
||||
// Example:
|
||||
// bool = is_def(undef); // Returns: false
|
||||
// bool = is_def(false); // Returns: true
|
||||
// bool = is_def(42); // Returns: true
|
||||
// bool = is_def("foo"); // Returns: true
|
||||
function is_def(x) = !is_undef(x);
|
||||
|
||||
|
||||
// Function: is_str()
|
||||
// Usage:
|
||||
// is_str(x)
|
||||
// bool = is_str(x);
|
||||
// Description:
|
||||
// Returns true if `x` is a string. A shortcut for `is_string()`.
|
||||
// Example:
|
||||
// bool = is_str(undef); // Returns: false
|
||||
// bool = is_str(false); // Returns: false
|
||||
// bool = is_str(42); // Returns: false
|
||||
// bool = is_str("foo"); // Returns: true
|
||||
function is_str(x) = is_string(x);
|
||||
|
||||
|
||||
// Function: is_int()
|
||||
// Usage:
|
||||
// is_int(n)
|
||||
// bool = is_int(n);
|
||||
// bool = is_integer(n);
|
||||
// Description:
|
||||
// Returns true if the given value is an integer (it is a number and it rounds to itself).
|
||||
// Example:
|
||||
// bool = is_int(undef); // Returns: false
|
||||
// bool = is_int(false); // Returns: false
|
||||
// bool = is_int(42); // Returns: true
|
||||
// bool = is_int("foo"); // Returns: false
|
||||
function is_int(n) = is_finite(n) && n == round(n);
|
||||
function is_integer(n) = is_finite(n) && n == round(n);
|
||||
|
||||
|
||||
// Function: is_nan()
|
||||
// Usage:
|
||||
// is_nan(x);
|
||||
// bool = is_nan(x);
|
||||
// Description:
|
||||
// Returns true if a given value `x` is nan, a floating point value representing "not a number".
|
||||
// Example:
|
||||
// bool = is_nan(undef); // Returns: false
|
||||
// bool = is_nan(false); // Returns: false
|
||||
// bool = is_nan(42); // Returns: false
|
||||
// bool = is_nan("foo"); // Returns: false
|
||||
// bool = is_nan(NAN); // Returns: true
|
||||
function is_nan(x) = (x!=x);
|
||||
|
||||
|
||||
// Function: is_finite()
|
||||
// Usage:
|
||||
// is_finite(x);
|
||||
// bool = is_finite(x);
|
||||
// Description:
|
||||
// Returns true if a given value `x` is a finite number.
|
||||
// Example:
|
||||
// bool = is_finite(undef); // Returns: false
|
||||
// bool = is_finite(false); // Returns: false
|
||||
// bool = is_finite(42); // Returns: true
|
||||
// bool = is_finite("foo"); // Returns: false
|
||||
// bool = is_finite(NAN); // Returns: false
|
||||
// bool = is_finite(INF); // Returns: false
|
||||
// bool = is_finite(-INF); // Returns: false
|
||||
function is_finite(x) = is_num(x) && !is_nan(0*x);
|
||||
|
||||
|
||||
// Function: is_range()
|
||||
// Usage:
|
||||
// bool = is_range(x);
|
||||
// Description:
|
||||
// Returns true if its argument is a range
|
||||
// Example:
|
||||
// bool = is_range(undef); // Returns: false
|
||||
// bool = is_range(false); // Returns: false
|
||||
// bool = is_range(42); // Returns: false
|
||||
// bool = is_range([3,4,5]); // Returns: false
|
||||
// bool = is_range("foo"); // Returns: false
|
||||
// bool = is_range([3:5]); // Returns: true
|
||||
function is_range(x) = !is_list(x) && is_finite(x[0]) && is_finite(x[1]) && is_finite(x[2]) ;
|
||||
|
||||
|
||||
// Function: valid_range()
|
||||
// Usage:
|
||||
// bool = valid_range(x);
|
||||
// Description:
|
||||
// Returns true if its argument is a valid range (deprecated ranges excluded).
|
||||
// Example:
|
||||
// bool = is_range(undef); // Returns: false
|
||||
// bool = is_range(false); // Returns: false
|
||||
// bool = is_range(42); // Returns: false
|
||||
// bool = is_range([3,4,5]); // Returns: false
|
||||
// bool = is_range("foo"); // Returns: false
|
||||
// bool = is_range([3:5]); // Returns: true
|
||||
// bool = is_range([3:1]); // Returns: false
|
||||
function valid_range(x) =
|
||||
is_range(x)
|
||||
&& ( x[1]>0
|
||||
|
@ -109,7 +168,7 @@ function valid_range(x) =
|
|||
|
||||
// Function: is_list_of()
|
||||
// Usage:
|
||||
// is_list_of(list, pattern)
|
||||
// bool = is_list_of(list, pattern);
|
||||
// Description:
|
||||
// Tests whether the input is a list whose entries are all numeric lists that have the same
|
||||
// list shape as the pattern.
|
||||
|
@ -130,7 +189,7 @@ function is_list_of(list,pattern) =
|
|||
|
||||
// Function: is_consistent()
|
||||
// Usage:
|
||||
// is_consistent(list)
|
||||
// bool = is_consistent(list);
|
||||
// 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.
|
||||
|
@ -154,7 +213,7 @@ function _list_pattern(list) =
|
|||
|
||||
// Function: same_shape()
|
||||
// Usage:
|
||||
// same_shape(a,b)
|
||||
// bool = same_shape(a,b);
|
||||
// Description:
|
||||
// Tests whether the inputs `a` and `b` are both numeric and are the same shaped list.
|
||||
// Example:
|
||||
|
@ -167,9 +226,10 @@ function same_shape(a,b) = _list_pattern(a) == b*0;
|
|||
|
||||
|
||||
// Function: default()
|
||||
// Usage:
|
||||
// val = default(val, dflt);
|
||||
// Description:
|
||||
// Returns the value given as `v` if it is not `undef`.
|
||||
// Otherwise, returns the value of `dflt`.
|
||||
// Returns the value given as `v` if it is not `undef`. Otherwise, returns the value of `dflt`.
|
||||
// Arguments:
|
||||
// v = Value to pass through if not `undef`.
|
||||
// dflt = Value to return if `v` *is* `undef`.
|
||||
|
@ -177,6 +237,8 @@ function default(v,dflt=undef) = is_undef(v)? dflt : v;
|
|||
|
||||
|
||||
// Function: first_defined()
|
||||
// Usage:
|
||||
// val = first_defined(v, <recursive>);
|
||||
// Description:
|
||||
// Returns the first item in the list that is not `undef`.
|
||||
// If all items are `undef`, or list is empty, returns `undef`.
|
||||
|
@ -195,42 +257,86 @@ function first_defined(v,recursive=false,_i=0) =
|
|||
|
||||
// Function: one_defined()
|
||||
// Usage:
|
||||
// one_defined(vars, names, <required>)
|
||||
// val = one_defined(vals, names, <dflt>)
|
||||
// Description:
|
||||
// Examines the input list `vars` and returns the entry which is not `undef`. If more
|
||||
// than one entry is `undef` then issues an assertion specifying "Must define exactly one of" followed
|
||||
// by the defined items from the `names` parameter. If `required` is set to false then it is OK if all of the
|
||||
// entries of `vars` are undefined, and in this case, `undef` is returned.
|
||||
// Example:
|
||||
// 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
|
||||
// "Must define exactly one of" followed by the names in the `names` parameter.
|
||||
// If `dflt` is given, and all `vals` are `undef`, then the value in `dflt` is returned.
|
||||
// If `dflt` is *not* given, and all `vals` are `undef`, then an error is asserted.
|
||||
// Arguments:
|
||||
// vals = The values to return the first one which is not `undef`.
|
||||
// names = A string with comma-separated names for the arguments whose values are passed in `vals`.
|
||||
// dflt = If given, the value returned if all `vals` are `undef`.
|
||||
// Examples:
|
||||
// length = one_defined([length,L,l], ["length","L","l"]);
|
||||
function one_defined(vars, names, required=true) =
|
||||
assert(len(vars)==len(names))
|
||||
let (
|
||||
ok = num_defined(vars)==1 || (!required && num_defined(vars)==0)
|
||||
)
|
||||
assert(ok,str("Must define ",required?"exactly":"at most"," one of ",num_defined(vars)==0?names:[for(i=[0:len(vars)]) if (is_def(vars[i])) names[i]]))
|
||||
first_defined(vars);
|
||||
// length = one_defined([length,L,l], "length,L,l", dflt=1);
|
||||
function one_defined(vals, names, dflt=_undef) =
|
||||
let(
|
||||
checkargs = is_list(names)? assert(len(vals) == len(names)) :
|
||||
is_string(names)? let(
|
||||
name_cnt = len([for (c=names) if (c==",") 1]) + 1
|
||||
) assert(len(vals) == name_cnt) :
|
||||
assert(is_list(names) || is_string(names)) 0,
|
||||
ok = num_defined(vals)==1 || (dflt!=_undef && num_defined(vals)==0)
|
||||
) ok? default(first_defined(vals), dflt) :
|
||||
let(
|
||||
names = is_string(names) ? str_split(names,",") : names,
|
||||
defd = [for (i=idx(vals)) if (is_def(vals[i])) names[i]],
|
||||
msg = str(
|
||||
"Must define ",
|
||||
dflt==_undef? "exactly" : "at most",
|
||||
" one of ",
|
||||
num_defined(vals) == 0 ? names : defd
|
||||
)
|
||||
) assert(ok,msg);
|
||||
|
||||
|
||||
// Function: num_defined()
|
||||
// Description: Counts how many items in list `v` are not `undef`.
|
||||
function num_defined(v) = len([for(vi=v) if(!is_undef(vi)) 1]);
|
||||
// Usage:
|
||||
// cnt = num_defined(v);
|
||||
// Description:
|
||||
// Counts how many items in list `v` are not `undef`.
|
||||
// Example:
|
||||
// cnt = num_defined([3,7,undef,2,undef,undef,1]); // Returns: 4
|
||||
function num_defined(v) =
|
||||
len([for(vi=v) if(!is_undef(vi)) 1]);
|
||||
|
||||
|
||||
// Function: any_defined()
|
||||
// Usage:
|
||||
// bool = any_defined(v, <recursive>);
|
||||
// Description:
|
||||
// Returns true if any item in the given array is not `undef`.
|
||||
// Arguments:
|
||||
// v = The list whose items are being checked.
|
||||
// recursive = If true, any sublists are evaluated recursively.
|
||||
function any_defined(v,recursive=false) = first_defined(v,recursive=recursive) != undef;
|
||||
// Example:
|
||||
// bool = any_defined([undef,undef,undef]); // Returns: false
|
||||
// bool = any_defined([undef,42,undef]); // Returns: true
|
||||
// bool = any_defined([34,42,87]); // Returns: true
|
||||
// bool = any_defined([undef,undef,[undef]]); // Returns: true
|
||||
// bool = any_defined([undef,undef,[undef]],recursive=true); // Returns: false
|
||||
// bool = any_defined([undef,undef,[42]],recursive=true); // Returns: true
|
||||
function any_defined(v,recursive=false) =
|
||||
first_defined(v,recursive=recursive) != undef;
|
||||
|
||||
|
||||
// Function: all_defined()
|
||||
// Usage:
|
||||
// bool = all_defined(v, <recursive>);
|
||||
// Description:
|
||||
// Returns true if all items in the given array are not `undef`.
|
||||
// Arguments:
|
||||
// v = The list whose items are being checked.
|
||||
// recursive = If true, any sublists are evaluated recursively.
|
||||
// Example:
|
||||
// bool = all_defined([undef,undef,undef]); // Returns: false
|
||||
// bool = all_defined([undef,42,undef]); // Returns: false
|
||||
// bool = all_defined([34,42,87]); // Returns: true
|
||||
// bool = all_defined([23,34,[undef]]); // Returns: true
|
||||
// bool = all_defined([23,34,[undef]],recursive=true); // Returns: false
|
||||
// bool = all_defined([23,34,[42]],recursive=true); // Returns: true
|
||||
function all_defined(v,recursive=false) =
|
||||
[]==[for (x=v) if(is_undef(x)||(recursive && is_list(x) && !all_defined(x,recursive))) 0 ];
|
||||
|
||||
|
@ -241,7 +347,7 @@ function all_defined(v,recursive=false) =
|
|||
|
||||
// Function: get_anchor()
|
||||
// Usage:
|
||||
// get_anchor(anchor,center,<uncentered>,<dflt>);
|
||||
// anchr = get_anchor(anchor,center,<uncentered>,<dflt>);
|
||||
// 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.
|
||||
|
@ -254,6 +360,13 @@ function all_defined(v,recursive=false) =
|
|||
// center = If not `undef`, this overrides the value of `anchor`.
|
||||
// uncentered = The value to return if `center` is not `undef` and evaluates as false. Default: ALLNEG
|
||||
// dflt = The default value to return if both `anchor` and `center` are `undef`. Default: `CENTER`
|
||||
// Examples:
|
||||
// anchr = get_anchor(undef, undef, BOTTOM, TOP); // Returns: [0, 0, 1] (TOP)
|
||||
// anchr = get_anchor(RIGHT, undef, BOTTOM, TOP); // Returns: [1, 0, 0] (RIGHT)
|
||||
// anchr = get_anchor(undef, false, BOTTOM, TOP); // Returns: [0, 0,-1] (BOTTOM)
|
||||
// anchr = get_anchor(RIGHT, false, BOTTOM, TOP); // Returns: [0, 0,-1] (BOTTOM)
|
||||
// anchr = get_anchor(undef, true, BOTTOM, TOP); // Returns: [0, 0, 0] (CENTER)
|
||||
// anchr = get_anchor(RIGHT, true, BOTTOM, TOP); // Returns: [0, 0, 0] (CENTER)
|
||||
function get_anchor(anchor,center,uncentered=BOT,dflt=CENTER) =
|
||||
!is_undef(center)? (center? CENTER : uncentered) :
|
||||
!is_undef(anchor)? anchor :
|
||||
|
@ -262,24 +375,35 @@ function get_anchor(anchor,center,uncentered=BOT,dflt=CENTER) =
|
|||
|
||||
// Function: get_radius()
|
||||
// Usage:
|
||||
// get_radius(<r1>, <r2>, <r>, <d1>, <d2>, <d>, <dflt>);
|
||||
// r = get_radius(<r1=>, <r2=>, <r=>, <d1=>, <d2=>, <d=>, <dflt=>);
|
||||
// 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, returns the value of dflt.
|
||||
// Value specificity order is r1, r2, d1, d2, r, d, then dflt
|
||||
// Only one of `r1`, `r2`, `d1`, or `d2` can be defined at once, or else it
|
||||
// errors out, complaining about conflicting radius/diameter values.
|
||||
// Only one of `r` or `d` can be defined at once, or else it errors out,
|
||||
// complaining about conflicting radius/diameter values.
|
||||
// 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,
|
||||
// returns the value of `dflt`. Value specificity order is `r1`, `r2`, `d1`, `d2`, `r`, `d`,
|
||||
// then `dflt`. Only one of `r1`, `r2`, `d1`, or `d2` can be defined at once, or else it errors
|
||||
// out, complaining about conflicting radius/diameter values. Only one of `r` or `d` can be
|
||||
// defined at once, or else it errors out, complaining about conflicting radius/diameter values.
|
||||
// Arguments:
|
||||
// ---
|
||||
// r1 = Most specific radius.
|
||||
// d1 = Most specific diameter.
|
||||
// r2 = Second most specific radius.
|
||||
// d2 = Second most specific diameter.
|
||||
// r = Most general radius.
|
||||
// d1 = Most specific diameter.
|
||||
// d2 = Second most specific diameter.
|
||||
// d = Most general diameter.
|
||||
// dflt = Value to return if all other values given are `undef`.
|
||||
// Examples:
|
||||
// r = get_radius(r1=undef, r=undef, dflt=undef); // Returns: undef
|
||||
// r = get_radius(r1=undef, r=undef, dflt=1); // Returns: 1
|
||||
// r = get_radius(r1=undef, r=6, dflt=1); // Returns: 6
|
||||
// r = get_radius(r1=7, r=6, dflt=1); // Returns: 7
|
||||
// r = get_radius(r1=undef, r2=8, r=6, dflt=1); // Returns: 8
|
||||
// r = get_radius(r1=undef, r2=8, d=6, dflt=1); // Returns: 8
|
||||
// r = get_radius(r1=undef, d=6, dflt=1); // Returns: 3
|
||||
// r = get_radius(d1=7, d=6, dflt=1); // Returns: 3.5
|
||||
// r = get_radius(d1=7, d2=8, d=6, dflt=1); // Returns: 3.5
|
||||
// r = get_radius(d1=undef, d2=8, d=6, dflt=1); // Returns: 4
|
||||
// r = get_radius(r1=8, d=6, dflt=1); // Returns: 8
|
||||
function get_radius(r1, r2, r, d1, d2, d, dflt) =
|
||||
assert(num_defined([r1,d1,r2,d2])<2, "Conflicting or redundant radius/diameter arguments given.")
|
||||
!is_undef(r1) ? assert(is_finite(r1), "Invalid radius r1." ) r1
|
||||
|
@ -294,61 +418,37 @@ function get_radius(r1, r2, r, d1, d2, d, dflt) =
|
|||
: dflt;
|
||||
|
||||
|
||||
// Function: get_height()
|
||||
// Usage:
|
||||
// get_height(<h>,<l>,<height>,<dflt>)
|
||||
// Description:
|
||||
// Given several different parameters for height check that height is not multiply defined
|
||||
// and return a single value. If the three values `l`, `h`, and `height` are all undefined
|
||||
// then return the value `dflt`, if given, or undef otherwise.
|
||||
// Arguments:
|
||||
// l = l.
|
||||
// h = h.
|
||||
// height = height.
|
||||
// dflt = Value to return if other values are `undef`.
|
||||
function get_height(h,l,height,dflt) =
|
||||
assert(num_defined([h,l,height])<=1,"You must specify only one of `l`, `h`, and `height`")
|
||||
first_defined([h,l,height,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], ...)
|
||||
// Description:
|
||||
// Given the values of some positional and named arguments,
|
||||
// returns a list of the values assigned to named parameters.
|
||||
// in the following steps:
|
||||
// - First, all named parameters which were explicitly assigned in the
|
||||
// function call take their provided value.
|
||||
// Given the values of some positional and named arguments, returns a list of the values assigned to
|
||||
// named parameters. in the following steps:
|
||||
// - First, all named parameters which were explicitly assigned in the function call take their
|
||||
// provided value.
|
||||
// - Then, any positional arguments are assigned to remaining unassigned
|
||||
// parameters; this is governed both by the `priority` entries
|
||||
// (if there are `N` positional arguments, then the `N` parameters with
|
||||
// lowest `priority` value will be assigned) and by the order of the
|
||||
// positional arguments (matching that of the assigned named parameters).
|
||||
// If no priority is given, then these two ordering coincide:
|
||||
// parameters are assigned in order, starting from the first one.
|
||||
// - Finally, any remaining named parameters can take default values.
|
||||
// If no default values are given, then `undef` is used.
|
||||
// parameters; this is governed both by the `priority` entries (if there are `N` positional
|
||||
// arguments, then the `N` parameters with lowest `priority` value will be assigned) and by the
|
||||
// order of the positional arguments (matching that of the assigned named parameters). If no
|
||||
// priority is given, then these two ordering coincide: parameters are assigned in order, starting
|
||||
// from the first one.
|
||||
// - Finally, any remaining named parameters can take default values. If no default values are
|
||||
// given, then `undef` is used.
|
||||
// .
|
||||
// This allows an author to declare a function prototype with named or
|
||||
// optional parameters, so that the user may then call this function
|
||||
// using either positional or named parameters. In practice the author
|
||||
// will declare the function as using *both* positional and named
|
||||
// parameters, and let `get_named_args()` do the parsing from the whole
|
||||
// set of arguments.
|
||||
// See the example below.
|
||||
// This allows an author to declare a function prototype with named or optional parameters, so that
|
||||
// the user may then call this function using either positional or named parameters. In practice the
|
||||
// author will declare the function as using *both* positional and named parameters, and let
|
||||
// `get_named_args()` do the parsing from the whole set of arguments. See the example below.
|
||||
// .
|
||||
// This supports the user explicitly passing `undef` as a function argument.
|
||||
// To distinguish between an intentional `undef` and
|
||||
// the absence of an argument, we use a custom `_undef` value
|
||||
// as a guard marking the absence of any arguments
|
||||
// (in practice, `_undef` is a random-generated string,
|
||||
// which will never coincide with any useful user value).
|
||||
// This forces the author to declare all the function parameters
|
||||
// as having `_undef` as their default value.
|
||||
// This supports the user explicitly passing `undef` as a function argument. To distinguish between
|
||||
// an intentional `undef` and the absence of an argument, we use a custom `_undef` value as a guard
|
||||
// marking the absence of any arguments (in practice, `_undef` is a random-generated string, which
|
||||
// will never coincide with any useful user value). This forces the author to declare all the
|
||||
// function parameters as having `_undef` as their default value.
|
||||
// Arguments:
|
||||
// positional = the list of values of positional arguments.
|
||||
// named = the list of named arguments; each entry of the list has the form `[passed-value, <default-value>, <priority>]`, where `passed-value` is the value that was passed at function call; `default-value` is the value that will be used if nothing is read from either named or positional arguments; `priority` is the priority assigned to this argument (lower means more priority, default value is `+inf`). Since stable sorting is used, if no priority at all is given, all arguments will be read in order.
|
||||
// _undef = the default value used by the calling function for all arguments. The default value, `_undef`, is a random string. This value **must** be the default value of all parameters in the outer function call (see example below).
|
||||
// positional = The list of values of positional arguments.
|
||||
// named = The list of named arguments; each entry of the list has the form `[passed-value, <default-value>, <priority>]`, where `passed-value` is the value that was passed at function call; `default-value` is the value that will be used if nothing is read from either named or positional arguments; `priority` is the priority assigned to this argument (lower means more priority, default value is `+inf`). Since stable sorting is used, if no priority at all is given, all arguments will be read in order.
|
||||
// _undef = The default value used by the calling function for all arguments. The default value, `_undef`, is a random string. This value **must** be the default value of all parameters in the outer function call (see example below).
|
||||
//
|
||||
// Example: a function with prototype `f(named1,< <named2>, named3 >)`
|
||||
// function f(_p1=_undef, _p2=_undef, _p3=_undef,
|
||||
|
@ -404,7 +504,7 @@ function get_named_args(positional, named,_undef=_undef) =
|
|||
|
||||
// Function: scalar_vec3()
|
||||
// Usage:
|
||||
// scalar_vec3(v, <dflt>);
|
||||
// vec = scalar_vec3(v, <dflt>);
|
||||
// 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]`.
|
||||
|
@ -413,7 +513,12 @@ function get_named_args(positional, named,_undef=_undef) =
|
|||
// Arguments:
|
||||
// v = Value to return vector from.
|
||||
// dflt = Default value to set empty vector parts from.
|
||||
function scalar_vec3(v, dflt=undef) =
|
||||
// Examples:
|
||||
// vec = scalar_vec3(undef); // Returns: undef
|
||||
// vec = scalar_vec3(10); // Returns: [10,10,10]
|
||||
// vec = scalar_vec3(10,1); // Returns: [10,1,1]
|
||||
// vec = scalar_vec3([10,10],1); // Returns: [10,10,1]
|
||||
function scalar_vec3(v, dflt) =
|
||||
is_undef(v)? undef :
|
||||
is_list(v)? [for (i=[0:2]) default(v[i], default(dflt, 0))] :
|
||||
!is_undef(dflt)? [v,dflt,dflt] : [v,v,v];
|
||||
|
@ -426,11 +531,13 @@ function scalar_vec3(v, dflt=undef) =
|
|||
// Calculate the standard number of sides OpenSCAD would give a circle based on `$fn`, `$fa`, and `$fs`.
|
||||
// Arguments:
|
||||
// r = Radius of circle to get the number of segments for.
|
||||
// Examples:
|
||||
// $fn=12; sides=segs(10); // Returns: 12
|
||||
// $fa=2; $fs=3, sides=segs(10); // Returns: 21
|
||||
function segs(r) =
|
||||
$fn>0? ($fn>3? $fn : 3) :
|
||||
let( r = is_finite(r)? r: 0 )
|
||||
ceil(max(5, min(360/$fa, abs(r)*2*PI/$fs))) ;
|
||||
|
||||
let( r = is_finite(r)? r : 0 )
|
||||
ceil(max(5, min(360/$fa, abs(r)*2*PI/$fs)));
|
||||
|
||||
|
||||
// Module: no_children()
|
||||
|
@ -441,18 +548,22 @@ function segs(r) =
|
|||
// as indicated by its argument.
|
||||
// Arguments:
|
||||
// $children = number of children the module has.
|
||||
// Example:
|
||||
// no_children($children);
|
||||
module no_children(count) {
|
||||
assert($children==0, "Module no_children() does not support child modules");
|
||||
assert(count==0, str("Module ",parent_module(1),"() does not support child modules"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Function: no_function()
|
||||
// Usage:
|
||||
// dummy = no_function(name)
|
||||
// Description:
|
||||
// Asserts that the function, "name", only exists as a module.
|
||||
// Example:
|
||||
//
|
||||
// x = no_function("foo");
|
||||
function no_function(name) =
|
||||
assert(false,str("You called ",name,"() as a function, but it is available only as a module"));
|
||||
|
||||
|
@ -462,6 +573,8 @@ function no_function(name) =
|
|||
// no_module();
|
||||
// Description:
|
||||
// Asserts that the called module exists only as a function.
|
||||
// Example:
|
||||
// no_module();
|
||||
module no_module() {
|
||||
assert(false, str("You called ",parent_module(1),"() as a module but it is available only as a function"));
|
||||
}
|
||||
|
@ -486,6 +599,8 @@ function _valstr(x) =
|
|||
// got = The value actually received.
|
||||
// expected = The value that was expected.
|
||||
// info = Extra info to print out to make the error clearer.
|
||||
// Example:
|
||||
// assert_approx(1/3, 0.333333333333333, str("numer=",1,", demon=",3));
|
||||
module assert_approx(got, expected, info) {
|
||||
no_children($children);
|
||||
if (!approx(got, expected)) {
|
||||
|
@ -507,13 +622,14 @@ module assert_approx(got, expected, info) {
|
|||
// Usage:
|
||||
// assert_equal(got, expected, <info>);
|
||||
// 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.
|
||||
// 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.
|
||||
// Arguments:
|
||||
// got = The value actually received.
|
||||
// expected = The value that was expected.
|
||||
// info = Extra info to print out to make the error clearer.
|
||||
// Example:
|
||||
// assert_approx(3*9, 27, str("a=",3,", b=",9));
|
||||
module assert_equal(got, expected, info) {
|
||||
no_children($children);
|
||||
if (got != expected || (is_nan(got) && is_nan(expected))) {
|
||||
|
@ -536,9 +652,15 @@ module assert_equal(got, expected, info) {
|
|||
// shape_compare(<eps>) {test_shape(); expected_shape();}
|
||||
// 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 nearly the same shape and size.
|
||||
// Returns the differential geometry if they are not quite the same shape and size.
|
||||
// Arguments:
|
||||
// eps = The surface of the two shapes must be within this size of each other. Default: 1/1024
|
||||
// Example:
|
||||
// $fn=36;
|
||||
// shape_compare() {
|
||||
// sphere(d=100);
|
||||
// rotate_extrude() right_half(planar=true) circle(d=100);
|
||||
// }
|
||||
module shape_compare(eps=1/1024) {
|
||||
union() {
|
||||
difference() {
|
||||
|
@ -548,7 +670,7 @@ module shape_compare(eps=1/1024) {
|
|||
} else {
|
||||
minkowski() {
|
||||
children(1);
|
||||
cube(eps, center=true);
|
||||
spheroid(r=eps, style="octa");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -559,7 +681,7 @@ module shape_compare(eps=1/1024) {
|
|||
} else {
|
||||
minkowski() {
|
||||
children(0);
|
||||
cube(eps, center=true);
|
||||
spheroid(r=eps, style="octa");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -582,6 +704,7 @@ module shape_compare(eps=1/1024) {
|
|||
// to run the loop one extra time to return the final value. This tends to make the loop code
|
||||
// look rather ugly. The `looping()`, `loop_while()` and `loop_done()` functions
|
||||
// can make this somewhat more legible.
|
||||
// .
|
||||
// ```openscad
|
||||
// function flat_sum(l) = [
|
||||
// for (
|
||||
|
@ -604,11 +727,11 @@ module shape_compare(eps=1/1024) {
|
|||
|
||||
// Function: looping()
|
||||
// Usage:
|
||||
// looping(state)
|
||||
// bool = looping(state);
|
||||
// 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.
|
||||
// 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.
|
||||
// Arguments:
|
||||
// state = The loop state value.
|
||||
function looping(state) = state < 2;
|
||||
|
@ -616,12 +739,12 @@ function looping(state) = state < 2;
|
|||
|
||||
// Function: loop_while()
|
||||
// Usage:
|
||||
// state = loop_while(state, continue)
|
||||
// state = loop_while(state, continue);
|
||||
// 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.
|
||||
// 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.
|
||||
// Arguments:
|
||||
// state = The loop state value.
|
||||
// continue = A boolean value indicating whether the current loop should progress.
|
||||
|
@ -632,11 +755,11 @@ function loop_while(state, continue) =
|
|||
|
||||
// Function: loop_done()
|
||||
// Usage:
|
||||
// loop_done(state)
|
||||
// bool = loop_done(state);
|
||||
// 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()`. See [Looping Helpers](#5-looping-helpers) for an example.
|
||||
// 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()`.
|
||||
// See [Looping Helpers](#5-looping-helpers) for an example.
|
||||
// Arguments:
|
||||
// state = The loop state value.
|
||||
function loop_done(state) = state > 0;
|
||||
|
|
|
@ -223,7 +223,7 @@ function round_corners(path, method="circle", radius, cut, joint, k, closed=true
|
|||
assert(in_list(method,["circle", "smooth", "chamfer"]), "method must be one of \"circle\", \"smooth\" or \"chamfer\"")
|
||||
let(
|
||||
default_k = 0.5,
|
||||
size=one_defined([radius, cut, joint], ["radius", "cut", "joint"]),
|
||||
size=one_defined([radius, cut, joint], "radius,cut,joint"),
|
||||
path = is_region(path)?
|
||||
assert(len(path)==1, "Region supplied as path does not have exactly one component")
|
||||
path[0] : path,
|
||||
|
@ -972,7 +972,7 @@ function offset_sweep(
|
|||
bottom_height = len(offsets_bot)==0 ? 0 : abs(select(offsets_bot,-1)[1]) - struct_val(bottom,"extra"),
|
||||
top_height = len(offsets_top)==0 ? 0 : abs(select(offsets_top,-1)[1]) - struct_val(top,"extra"),
|
||||
|
||||
height = get_height(l=l,h=h,height=height,dflt=bottom_height+top_height),
|
||||
height = one_defined([l,h,height], "l,h,height", dflt=u_add(bottom_height,top_height)),
|
||||
middle = height-bottom_height-top_height
|
||||
)
|
||||
echo(height=height)
|
||||
|
@ -1241,7 +1241,7 @@ module convex_offset_extrude(
|
|||
bottom_height = len(offsets_bot)==0 ? 0 : abs(select(offsets_bot,-1)[1]) - struct_val(bottom,"extra");
|
||||
top_height = len(offsets_top)==0 ? 0 : abs(select(offsets_top,-1)[1]) - struct_val(top,"extra");
|
||||
|
||||
height = get_height(l=l,h=h,height=height,dflt=bottom_height+top_height);
|
||||
height = one_defined([l,h,height], "l,h,height", dflt=u_add(bottom_height,top_height));
|
||||
assert(height>=0, "Height must be nonnegative");
|
||||
|
||||
middle = height-bottom_height-top_height;
|
||||
|
@ -1809,7 +1809,7 @@ function rounded_prism(bottom, top, joint_bot=0, joint_top=0, joint_sides=0, k_b
|
|||
k_top = default(k_top, k),
|
||||
k_bot = default(k_bot, k),
|
||||
k_sides = default(k_sides, k),
|
||||
height = one_defined([h,l,height,length],["height","length","l","h"], required=false),
|
||||
height = one_defined([h,l,height,length],"height,length,l,h", dflt=undef),
|
||||
shapedimok = (len(bottom[0])==3 && is_path(top,3)) || (len(bottom[0])==2 && (is_undef(top) || is_path(top,2)))
|
||||
)
|
||||
assert(is_num(k_top) && k_top>=0 && k_top<=1, "Curvature parameter k_top must be in interval [0,1]")
|
||||
|
|
|
@ -276,10 +276,10 @@ test_first_defined();
|
|||
|
||||
|
||||
module test_one_defined() {
|
||||
assert_equal(one_defined([27,undef,undef], ["length","L","l"]) ,27);
|
||||
assert_equal(one_defined([undef,28,undef], ["length","L","l"]) ,28);
|
||||
assert_equal(one_defined([undef,undef,29], ["length","L","l"]) ,29);
|
||||
assert_equal(one_defined([undef,undef,undef], ["length","L","l"], required=false), undef);
|
||||
assert_equal(one_defined([27,undef,undef], "length,L,l"]) ,27);
|
||||
assert_equal(one_defined([undef,28,undef], "length,L,l"]) ,28);
|
||||
assert_equal(one_defined([undef,undef,29], "length,L,l"]) ,29);
|
||||
assert_equal(one_defined([undef,undef,undef], "length,L,l"], dflt=undef), undef);
|
||||
}
|
||||
test_one_defined();
|
||||
|
||||
|
@ -361,19 +361,6 @@ module test_get_radius() {
|
|||
test_get_radius();
|
||||
|
||||
|
||||
module test_get_height() {
|
||||
assert(get_height(h=undef, l=undef, height=undef, dflt=undef) == undef);
|
||||
assert(get_height(h=undef, l=undef, height=undef, dflt=23) == 23);
|
||||
assert(get_height(h=undef, l=undef, height=50, dflt=23) == 50);
|
||||
assert(get_height(h=undef, l=50, height=undef, dflt=23) == 50);
|
||||
assert(get_height(h=50, l=undef, height=undef, dflt=23) == 50);
|
||||
assert(get_height(h=undef, l=undef, height=75, dflt=23) == 75);
|
||||
assert(get_height(h=undef, l=75, height=undef, dflt=23) == 75);
|
||||
assert(get_height(h=75, l=undef, height=undef, dflt=23) == 75);
|
||||
}
|
||||
test_get_height();
|
||||
|
||||
|
||||
module test_scalar_vec3() {
|
||||
assert(scalar_vec3(undef) == undef);
|
||||
assert(scalar_vec3(3) == [3,3,3]);
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
BOSL_VERSION = [2,0,544];
|
||||
BOSL_VERSION = [2,0,545];
|
||||
|
||||
|
||||
// Section: BOSL Library Version Functions
|
||||
|
|
Loading…
Reference in a new issue