Merge branch 'master' of github.com:revarbat/BOSL2

This commit is contained in:
Revar Desmera 2019-12-06 19:14:31 -08:00
commit 2b829f185a
3 changed files with 88 additions and 0 deletions

View file

@ -208,6 +208,46 @@ function deduplicate(list, closed=false, eps=EPSILON) =
[for (i=[0:1:l-1]) if (i==end || list[i] != list[(i+1)%l]) list[i]];
// Function: repeat_entries()
// Usage:
// newlist = repeat_entries(list, N)
// Description:
// Takes a list as input and duplicates some of its entries to produce a list
// with length `N`. If the requested `N` is not a multiple of the list length then
// the entries will be duplicated as uniformly as possible. You can also set `N` to a vector,
// in which case len(N) must equal len(list) and the output repeats the ith entry N[i] times.
// In either case, the result will be a list of length `N`. The `exact` option requires
// that the final length is exactly as requested. If you set it to `false` then the
// algorithm will favor uniformity and the output list may have a different number of
// entries due to rounding.
//
// When applied to a path the output path is the same geometrical shape but has some vertices
// repeated. This can be useful when you need to align paths with a different number of points.
// (See also subdivide_path for a different way to do that.)
// Arguments:
// list = list whose entries will be repeated
// N = scalar total number of points desired or vector requesting N[i] copies of vertex i.
// exact = if true return exactly the requested number of points, possibly sacrificing uniformity. If false, return uniform points that may not match the number of points requested. Default: True
// Examples:
// list = [0,1,2,3]/
// echo(repeat_entries(list, 6)); // Ouputs [0,0,1,2,2,3]
// echo(repeat_entries(list, 6, exact=false)); // Ouputs [0,0,1,1,2,2,3,3]
// echo(repeat_entries(list, [1,1,2,1], exact=false)); // Ouputs [0,1,2,2,3]
function repeat_entries(list, N, exact = true) =
assert(is_list(list))
assert((is_num(N) && N>0) || is_vector(N),"Parameter N to repeat_entries must be postive number or vector")
let(
length = len(list),
reps_guess = is_list(N) ?
assert(len(N)==len(list), "Vector parameter N to repeat_entries has the wrong length")
N
: replist(N/length,length),
reps = exact ? _sum_preserving_round(reps_guess)
: [for (val=reps_guess) round(val)]
)
[for(i=[0:length-1]) each replist(list[i],reps[i])];
// Function: list_set()
// Usage:
// list_set(list, indices, values, [dflt], [minlen])

View file

@ -648,5 +648,50 @@ function count_true(l, nmax=undef, i=0, cnt=0) =
)
);
// If argument is a list return it. Otherwise return a singleton list containing the argument.
function _force_list(x) = is_list(x) ? x : [x];
// Function: gcd()
// Usage:
// gcd(a,b)
// Description:
// Computes the greatest common divisor of `a` and `b`.
function gcd(a,b) =
assert(is_integer(a) && is_integer(b),"Arguments to gcd must be integers")
b==0 ? abs(a) : gcd(b,a % b);
// Computes lcm for two scalars
function _lcm(a,b) =
let(
parmok = is_integer(a) && is_integer(b),
dummy=assert(parmok,"Invalid non-integer parameters to lcm")
assert(a!=0 && b!=0, "Arguments to lcm must be nonzero")
)
abs(a*b) / gcd(a,b);
// Computes lcm for a list of values
function _lcmlist(a) =
len(a)==1 ? a[0] : _lcmlist(concat(slice(a,0,len(a)-2),[lcm(a[len(a)-2],a[len(a)-1])]));
// Function: lcm()
// Usage:
// lcm(a,b)
// lcm(list)
// Description: Computes the least common multiple of the two arguments or a list of arguments. Inputs should be
// nonzero integers. The output is always a positive integer. It is an error to pass zero as an argument.
function lcm(a,b=[]) =
!is_list(a) && !is_list(b) ? _lcm(a,b) :
let(
arglist = concat(_force_list(a),_force_list(b))
)
assert(len(arglist)>0,"invalid call to lcm with empty list(s)")
_lcmlist(arglist);
// Function: is_integer()
// Usage:
// is_integer(n)
// Description: returns true if the given value is an integer (it is a number and it rounds to itself).
function is_integer(n) = is_num(n) && n == round(n);
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap

View file

@ -645,6 +645,9 @@ function _superformula(theta,m1,m2,n1,n2=1,n3=1,a=1,b=1) =
// for(i=[-1.5:3:1.5]) right(i*1.5) supershape(m1=2,m2=10,n1=i,n2=1);
// for(i=[1:3],j=[-1,1]) translate([3.5*i,1.5*j])supershape(m1=4,m2=6,n1=i*j,n2=1);
// for(i=[1:3]) right(2.5*i)supershape(step=.5,m1=88, m2=64, n1=-i*i,n2=1,r=1);
// Examples:
// linear_extrude(height=0.3, scale=0) supershape(step=1, m1=6, n1=0.4, n2=0, n3=6);
// linear_extrude(height=5, scale=0) supershape(step=1, b=3, m1=6, n1=3.8, n2=16, n3=10);
function supershape(step=0.5,m1=4,m2=undef,n1=1,n2=undef,n3=undef,a=1,b=undef,r=undef,d=undef,anchor=CENTER, spin=0) =
let(
r = get_radius(r=r, d=d, dflt=undef),