mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2025-01-04 03:09:45 +00:00
Merge branch 'master' of github.com:revarbat/BOSL2
This commit is contained in:
commit
2b829f185a
3 changed files with 88 additions and 0 deletions
40
arrays.scad
40
arrays.scad
|
@ -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])
|
||||
|
|
45
math.scad
45
math.scad
|
@ -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
|
||||
|
|
|
@ -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),
|
||||
|
|
Loading…
Reference in a new issue