mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2024-12-29 00:09:41 +00:00
Added more flexibility to get_named_args(), and all the left_half(), etc. as functions
This commit is contained in:
parent
be8b1036d8
commit
1d324128e4
4 changed files with 112 additions and 40 deletions
12
arrays.scad
12
arrays.scad
|
@ -89,6 +89,18 @@ function select(list, start, end=undef) =
|
|||
: concat([for (i = [s:1:l-1]) list[i]], [for (i = [0:1:e]) list[i]]) ;
|
||||
|
||||
|
||||
// Function: last()
|
||||
// Description:
|
||||
// Returns the last element of a list, or undef if empty.
|
||||
// Usage:
|
||||
// last(list)
|
||||
// Arguments:
|
||||
// list = The list to get the last element of.
|
||||
// Example:
|
||||
// l = [3,4,5,6,7,8,9];
|
||||
// last(l); // Returns 9.
|
||||
function last(list) = list[len(list)-1];
|
||||
|
||||
// Function: slice()
|
||||
// Description:
|
||||
// Returns a slice of a list. The first item is index 0.
|
||||
|
|
73
common.scad
73
common.scad
|
@ -312,27 +312,41 @@ function get_height(h=undef,l=undef,height=undef,dflt=undef) =
|
|||
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(anonymous, named, _undef)
|
||||
// Function: get_named_args(positional, named, _undef)
|
||||
// Usage:
|
||||
// function f(anon1=_undef, anon2=_undef,...,
|
||||
// function f(pos1=_undef, pos2=_undef,...,
|
||||
// named1=_undef, named2=_undef, ...) =
|
||||
// let(args = get_named_args([anon1, anon2, ...],
|
||||
// [[named1, default1], [named2, default2], ...]))
|
||||
// let(args = get_named_args([pos1, pos2, ...],
|
||||
// [[named1, default1], [named2, default2], ...]),
|
||||
// named1=args[0], named2=args[1], ...)
|
||||
// ...
|
||||
// Description:
|
||||
// given a set of anonymous and named arguments, returns the values of
|
||||
// named arguments, in order.
|
||||
// - All named arguments which were provided by the user take the
|
||||
// value provided.
|
||||
// Given the values of some positional and named arguments,
|
||||
// returns a list of the values assigned to named arguments,
|
||||
// in the following way:
|
||||
// - All named arguments which were explicitly assigned in the
|
||||
// function call take the value provided.
|
||||
// - All named arguments which were not provided by the user are
|
||||
// affected from anonymous arguments, in order.
|
||||
// affected from positional arguments; the priority order in which
|
||||
// these are assigned is given by the `priority` argument, while the
|
||||
// positional assignation is done in the order of the named arguments.
|
||||
// - Any remaining named arguments take the provided default values.
|
||||
// Arguments:
|
||||
// anonymous = the list of values of anonymous arguments.
|
||||
// named = the list of [passed-value, default value] of named arguments.
|
||||
// _undef = the default value used by the calling function for all
|
||||
// arguments (this is *not* undef, or any value that the user might
|
||||
// purposely want to use as an argument value).
|
||||
// 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.
|
||||
// _undef = the default value used by the calling function for all arguments (default is some random string that you will never use). (this is *not* undef, or any value that the user might purposely want to use as an argument value).
|
||||
//
|
||||
// If only k positional arguments are used, then the k named values
|
||||
// with lowest 'priority' value (among the unassigned ones) will get them.
|
||||
// The arguments will be assigned in the order of the named values.
|
||||
// By default these two orders coincide.
|
||||
//
|
||||
//
|
||||
// Examples:
|
||||
// function f(arg1=_undef, arg2=_undef, arg3=_undef,
|
||||
// named1=_undef, named2=_undef, named3=_undef) =
|
||||
|
@ -349,16 +363,29 @@ function get_height(h=undef,l=undef,height=undef,dflt=undef) =
|
|||
// result of `dd if=/dev/random bs=32 count=1 |base64` :
|
||||
_undef="LRG+HX7dy89RyHvDlAKvb9Y04OTuaikpx205CTh8BSI";
|
||||
|
||||
function get_named_args(anonymous, named,_undef=_undef) =
|
||||
/* u: set of undefined indices in named arguments */
|
||||
let(from_anon = [for(p=enumerate(named)) if(p[1][0]==_undef) p[0]],
|
||||
n = len(anonymous))
|
||||
echo("from_anon:", from_anon)
|
||||
/* Note: however tempting it might be, it is *not* possible to accept
|
||||
* named argument as a list [named1, named2, ...] (without default
|
||||
* values), because the values [named1, named2...] themselves might be
|
||||
* lists, and we will not be able to distinguish the two cases. */
|
||||
function get_named_args(positional, named,_undef=_undef) =
|
||||
let(deft = [for(p=named) p[1]], // default is undef
|
||||
// indices of the values to fetch from positional args:
|
||||
unknown = [for(x=enumerate(named)) if(x[1][0]==_undef) x[0]],
|
||||
// number of values given to positional arguments:
|
||||
n_positional = count_true([for(p=positional) p!=_undef]))
|
||||
assert(n_positional <= len(unknown),
|
||||
str("too many positional arguments (", n_positional, " given, ",
|
||||
len(unknown), " required)"))
|
||||
let(
|
||||
// those elements which have no priority assigned go last (prio=+∞):
|
||||
prio = sortidx([for(u=unknown) default(named[u][2], 1/0)]),
|
||||
// list of indices of values assigned from positional arguments:
|
||||
assigned = sort([for(i=[0:1:n_positional-1]) prio[i]]))
|
||||
[ for(e = enumerate(named))
|
||||
// if the value is defined, return it:
|
||||
e[1][0] != _undef ? e[1][0] :
|
||||
let(k = anonymous[search(e[0], from_anon)[0]])
|
||||
k != _undef ? k : e[1][1] ];
|
||||
let(idx=e[0], val=e[1][0], ass=search(idx, assigned))
|
||||
val != _undef ? val :
|
||||
ass != [] ? positional[ass[0]] :
|
||||
deft[idx] ];
|
||||
// Function: scalar_vec3()
|
||||
// Usage:
|
||||
// scalar_vec3(v, <dflt>);
|
||||
|
|
|
@ -121,16 +121,9 @@ module half_of(v=UP, cp, s=1000, planar=false)
|
|||
function half_of(_arg1=_undef, _arg2=_undef, _arg3=_undef, _arg4=_undef,
|
||||
v=_undef, cp=_undef, p=_undef, s=_undef) =
|
||||
let(args=get_named_args([_arg1, _arg2, _arg3, _arg4],
|
||||
[[v], [cp, 0], [p], [s, 1e4]]),
|
||||
[[v,undef,0], [cp,0,2], [p,undef,1], [s,1e4,3]]),
|
||||
v=args[0], cp0=args[1], p=args[2], s=args[3],
|
||||
cp = is_num(cp0) ? cp0*unit(v) : cp0)
|
||||
echo("_undef=", _undef)
|
||||
echo("v=", v)
|
||||
echo("cp=", cp)
|
||||
echo("p=", p)
|
||||
echo("vnf?", is_vnf(p))
|
||||
echo("region?", is_region(p))
|
||||
echo("s=", s)
|
||||
assert(is_vector(v,2)||is_vector(v,3),
|
||||
"must provide a half-plane or half-space")
|
||||
let(d=len(v))
|
||||
|
@ -164,11 +157,15 @@ function half_of(_arg1=_undef, _arg2=_undef, _arg3=_undef, _arg4=_undef,
|
|||
:
|
||||
assert(false, "must pass either a point, a path, a region, or a VNF");
|
||||
|
||||
// Module: left_half()
|
||||
// Function&Module: left_half()
|
||||
//
|
||||
// Usage:
|
||||
// Usage: as module
|
||||
// left_half([s], [x]) ...
|
||||
// left_half(planar=true, [s], [x]) ...
|
||||
// Usage: as function
|
||||
// left_half([s], [x], path)
|
||||
// left_half([s], [x], region)
|
||||
// left_half([s], [x], vnf)
|
||||
//
|
||||
// Description:
|
||||
// Slices an object at a vertical Y-Z cut plane, and masks away everything that is right of it.
|
||||
|
@ -197,10 +194,16 @@ module left_half(s=1000, x=0, planar=false)
|
|||
}
|
||||
}
|
||||
}
|
||||
function left_half(_arg1=_undef, _arg2=_undef, _arg3=_undef,
|
||||
x=_undef, p=_undef, s=_undef) =
|
||||
let(args=get_named_args([_arg1, _arg2, _arg3],
|
||||
[[x, 0,1], [p,undef,0], [s, 1e4,2]]),
|
||||
x=args[0], p=args[1], s=args[2])
|
||||
half_of(v=[1,0,0], cp=x, p=p);
|
||||
|
||||
|
||||
|
||||
// Module: right_half()
|
||||
// Function&Module: right_half()
|
||||
//
|
||||
// Usage:
|
||||
// right_half([s], [x]) ...
|
||||
|
@ -233,10 +236,16 @@ module right_half(s=1000, x=0, planar=false)
|
|||
}
|
||||
}
|
||||
}
|
||||
function right_half(_arg1=_undef, _arg2=_undef, _arg3=_undef,
|
||||
x=_undef, p=_undef, s=_undef) =
|
||||
let(args=get_named_args([_arg1, _arg2, _arg3],
|
||||
[[x, 0,1], [p,undef,0], [s, 1e4,2]]),
|
||||
x=args[0], p=args[1], s=args[2])
|
||||
half_of(v=[-1,0,0], cp=x, p=p);
|
||||
|
||||
|
||||
|
||||
// Module: front_half()
|
||||
// Function&Module: front_half()
|
||||
//
|
||||
// Usage:
|
||||
// front_half([s], [y]) ...
|
||||
|
@ -269,10 +278,16 @@ module front_half(s=1000, y=0, planar=false)
|
|||
}
|
||||
}
|
||||
}
|
||||
function front_half(_arg1=_undef, _arg2=_undef, _arg3=_undef,
|
||||
x=_undef, p=_undef, s=_undef) =
|
||||
let(args=get_named_args([_arg1, _arg2, _arg3],
|
||||
[[x, 0,1], [p,undef,0], [s, 1e4,2]]),
|
||||
x=args[0], p=args[1], s=args[2])
|
||||
half_of(v=[0,1,0], cp=x, p=p);
|
||||
|
||||
|
||||
|
||||
// Module: back_half()
|
||||
// Function&Module: back_half()
|
||||
//
|
||||
// Usage:
|
||||
// back_half([s], [y]) ...
|
||||
|
@ -305,10 +320,16 @@ module back_half(s=1000, y=0, planar=false)
|
|||
}
|
||||
}
|
||||
}
|
||||
function back_half(_arg1=_undef, _arg2=_undef, _arg3=_undef,
|
||||
x=_undef, p=_undef, s=_undef) =
|
||||
let(args=get_named_args([_arg1, _arg2, _arg3],
|
||||
[[x, 0,1], [p,undef,0], [s, 1e4,2]]),
|
||||
x=args[0], p=args[1], s=args[2])
|
||||
half_of(v=[0,-1,0], cp=x, p=p);
|
||||
|
||||
|
||||
|
||||
// Module: bottom_half()
|
||||
// Function&Module: bottom_half()
|
||||
//
|
||||
// Usage:
|
||||
// bottom_half([s], [z]) ...
|
||||
|
@ -333,10 +354,16 @@ module bottom_half(s=1000, z=0)
|
|||
}
|
||||
}
|
||||
}
|
||||
function right_half(_arg1=_undef, _arg2=_undef, _arg3=_undef,
|
||||
x=_undef, p=_undef, s=_undef) =
|
||||
let(args=get_named_args([_arg1, _arg2, _arg3],
|
||||
[[x, 0,1], [p,undef,0], [s, 1e4,2]]),
|
||||
x=args[0], p=args[1], s=args[2])
|
||||
half_of(v=[0,0,-1], cp=x, p=p);
|
||||
|
||||
|
||||
|
||||
// Module: top_half()
|
||||
// Function&Module: top_half()
|
||||
//
|
||||
// Usage:
|
||||
// top_half([s], [z]) ...
|
||||
|
@ -361,6 +388,12 @@ module top_half(s=1000, z=0)
|
|||
}
|
||||
}
|
||||
}
|
||||
function right_half(_arg1=_undef, _arg2=_undef, _arg3=_undef,
|
||||
x=_undef, p=_undef, s=_undef) =
|
||||
let(args=get_named_args([_arg1, _arg2, _arg3],
|
||||
[[x, 0,1], [p,undef,0], [s, 1e4,2]]),
|
||||
x=args[0], p=args[1], s=args[2])
|
||||
half_of(v=[0,0,1], cp=x, p=p);
|
||||
|
||||
|
||||
|
||||
|
|
4
vnf.scad
4
vnf.scad
|
@ -924,7 +924,7 @@ function _vnf_halfspace_paths(edges, i=0, paths=[]) =
|
|||
*/
|
||||
i >= len(edges) ? paths : // termination condition
|
||||
let(e = edges[i],
|
||||
s = [for(x=enumerate(paths)) if(x[1][len(x[1])-1] == e[0]) x[0]])
|
||||
s = [for(x=enumerate(paths)) if(last(x[1]) == e[0]) x[0]])
|
||||
_vnf_halfspace_paths(edges, i+1,
|
||||
// if cannot attach to previous path: create a new one
|
||||
s == [] ? concat(paths, [e]) :
|
||||
|
@ -947,7 +947,7 @@ function vnf_halfspace(_arg1=_undef, _arg2=_undef,
|
|||
newedges=[for(x=tmp2) each x[1]],
|
||||
// generate new faces
|
||||
paths=_vnf_halfspace_paths(newedges),
|
||||
loops=[for(p=paths) if(p[0] == p[len(p)-1]) p])
|
||||
loops=[for(p=paths) if(p[0] == last(p)) p])
|
||||
[coords, concat(newfaces, loops)];
|
||||
|
||||
//
|
||||
|
|
Loading…
Reference in a new issue