Docs cleanup for common.scad

This commit is contained in:
Garth Minette 2021-01-28 16:59:46 -08:00
parent 1ce59caa57
commit a13a09db8d
5 changed files with 257 additions and 134 deletions

View file

@ -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

View file

@ -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)
// 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,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);
) 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;

View file

@ -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]")

View file

@ -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]);

View file

@ -6,7 +6,7 @@
//////////////////////////////////////////////////////////////////////
BOSL_VERSION = [2,0,544];
BOSL_VERSION = [2,0,545];
// Section: BOSL Library Version Functions