Merge remote-tracking branch 'upstream/master'

This commit is contained in:
RonaldoCMP 2020-08-04 00:13:26 +01:00
commit c9408a66fa
19 changed files with 109 additions and 229 deletions

View file

@ -1126,25 +1126,25 @@ function add_scalar(v,s) =
// Function: subindex() // Function: subindex()
// Usage:
// subindex(M, idx)
// Description: // Description:
// For each array item, return the indexed subitem. // Extracts the entries listed in idx from each entry in M. For a matrix this means
// Returns a list of the values of each vector at the specfied // selecting a specified set of columsn. If idx is a number the return is a vector, otherwise
// index list or range. If the index list or range has // it is a list of lists (the submatrix).
// only one entry the output list is flattened.
// Arguments: // Arguments:
// v = The given list of lists. // M = The given list of lists.
// idx = The index, list of indices, or range of indices to fetch. // idx = The index, list of indices, or range of indices to fetch.
// Example: // Example:
// v = [[[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]]; // M = [[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]];
// subindex(v,2); // Returns [3, 7, 11, 15] // subindex(M,2); // Returns [3, 7, 11, 15]
// subindex(v,[2,1]); // Returns [[3, 2], [7, 6], [11, 10], [15, 14]] // subindex(M,[2]); // Returns [[3], [7], [11], [15]]
// subindex(v,[1:3]); // Returns [[2, 3, 4], [6, 7, 8], [10, 11, 12], [14, 15, 16]] // subindex(M,[2,1]); // Returns [[3, 2], [7, 6], [11, 10], [15, 14]]
function subindex(v, idx) = // subindex(M,[1:3]); // Returns [[2, 3, 4], [6, 7, 8], [10, 11, 12], [14, 15, 16]]
[ for(val=v) function subindex(M, idx) =
let( value=[for(i=idx) val[i]] ) is_num(idx)
len(value)==1 ? value[0] : value ? [for(row=M) row[idx]]
]; : [for(row=M) [for(i=idx) row[i]]];
// Function: zip() // Function: zip()
// Usage: // Usage:

View file

@ -285,7 +285,7 @@ function attach_geom_size(geom) =
) [2*maxxr,2*maxyr,l] ) [2*maxxr,2*maxyr,l]
) : type == "spheroid"? ( //r ) : type == "spheroid"? ( //r
let( r=geom[1] ) let( r=geom[1] )
is_num(r)? [2,2,2]*r : vmul([2,2,2],r) is_num(r)? [2,2,2]*r : vmul([2,2,2],point3d(r))
) : type == "vnf_extent" || type=="vnf_isect"? ( //vnf ) : type == "vnf_extent" || type=="vnf_isect"? ( //vnf
let( let(
mm = pointlist_bounds(geom[1][0]), mm = pointlist_bounds(geom[1][0]),
@ -298,7 +298,7 @@ function attach_geom_size(geom) =
) [maxx, size.y] ) [maxx, size.y]
) : type == "circle"? ( //r ) : type == "circle"? ( //r
let( r=geom[1] ) let( r=geom[1] )
is_num(r)? [2,2]*r : vmul([2,2],r) is_num(r)? [2,2]*r : vmul([2,2],point2d(r))
) : type == "path_isect" || type == "path_extent"? ( //path ) : type == "path_isect" || type == "path_extent"? ( //path
let( let(
mm = pointlist_bounds(geom[1]), mm = pointlist_bounds(geom[1]),
@ -430,8 +430,8 @@ function find_anchor(anchor, geom) =
) : type == "cyl"? ( //r1, r2, l, shift ) : type == "cyl"? ( //r1, r2, l, shift
let( let(
rr1=geom[1], rr2=geom[2], l=geom[3], shift=point2d(geom[4]), rr1=geom[1], rr2=geom[2], l=geom[3], shift=point2d(geom[4]),
r1 = is_num(rr1)? [rr1,rr1] : rr1, r1 = is_num(rr1)? [rr1,rr1] : point2d(rr1),
r2 = is_num(rr2)? [rr2,rr2] : rr2, r2 = is_num(rr2)? [rr2,rr2] : point2d(rr2),
u = (anchor.z+1)/2, u = (anchor.z+1)/2,
axy = unit(point2d(anchor),[0,0]), axy = unit(point2d(anchor),[0,0]),
bot = point3d(vmul(r1,axy), -l/2), bot = point3d(vmul(r1,axy), -l/2),
@ -447,9 +447,9 @@ function find_anchor(anchor, geom) =
) : type == "spheroid"? ( //r ) : type == "spheroid"? ( //r
let( let(
rr = geom[1], rr = geom[1],
r = is_num(rr)? [rr,rr,rr] : rr, r = is_num(rr)? [rr,rr,rr] : point3d(rr),
anchor = unit(point3d(anchor),CENTER), anchor = unit(point3d(anchor),CENTER),
pos = point3d(cp) + vmul(r,anchor) + offset, pos = point3d(cp) + vmul(r,anchor) + point3d(offset),
vec = unit(vmul(r,anchor),UP) vec = unit(vmul(r,anchor),UP)
) [anchor, pos, vec, oang] ) [anchor, pos, vec, oang]
) : type == "vnf_isect"? ( //vnf ) : type == "vnf_isect"? ( //vnf
@ -519,10 +519,10 @@ function find_anchor(anchor, geom) =
) : type == "circle"? ( //r ) : type == "circle"? ( //r
let( let(
rr = geom[1], rr = geom[1],
r = is_num(rr)? [rr,rr] : rr, r = is_num(rr)? [rr,rr] : point2d(rr),
pos = point2d(cp) + vmul(r,anchor) + offset,
anchor = unit(point2d(anchor),[0,0]), anchor = unit(point2d(anchor),[0,0]),
vec = unit(vmul([r.y,r.x],anchor),[0,1]) pos = point2d(cp) + vmul(r,anchor) + point2d(offset),
vec = unit(vmul(r,anchor),[0,1])
) [anchor, pos, vec, 0] ) [anchor, pos, vec, 0]
) : type == "path_isect"? ( //path ) : type == "path_isect"? ( //path
let( let(
@ -970,7 +970,8 @@ module edge_profile(edges=EDGES_ALL, except=[], convexity=10) {
$attach_anchor = anch; $attach_anchor = anch;
$attach_norot = true; $attach_norot = true;
$tags = "mask"; $tags = "mask";
length = sum(vmul($parent_size, [for (x=vec) x?0:1]))+0.1; psize = point3d($parent_size);
length = [for (i=[0:2]) if(!vec[i]) psize[i]][0]+0.1;
rotang = rotang =
vec.z<0? [90,0,180+vang(point2d(vec))] : vec.z<0? [90,0,180+vang(point2d(vec))] :
vec.z==0 && sign(vec.x)==sign(vec.y)? 135+vang(point2d(vec)) : vec.z==0 && sign(vec.x)==sign(vec.y)? 135+vang(point2d(vec)) :

View file

@ -148,7 +148,7 @@ function _list_pattern(list) =
// is_consistent([[3,[3,4,[5]]], [5,[2,9,[9]]]]); // Returns true // is_consistent([[3,[3,4,[5]]], [5,[2,9,[9]]]]); // Returns true
// is_consistent([[3,[3,4,[5]]], [5,[2,9,9]]]); // Returns false // is_consistent([[3,[3,4,[5]]], [5,[2,9,9]]]); // Returns false
function is_consistent(list) = function is_consistent(list) =
is_list(list) && is_list_of(list, _list_pattern(list[0])); /*is_list(list) &&*/ is_list_of(list, _list_pattern(list[0]));
//Internal function //Internal function
@ -346,6 +346,19 @@ function segs(r) =
// Module: no_children()
// Usage:
// no_children($children);
// Description:
// Assert that the calling module does not support children. Prints an error message to this effect and fails if children are present,
// as indicated by its argument.
// Arguments:
// $children = number of children the module has.
module no_children(count) {
assert(count==0, str("Module ",parent_module(1),"() does not support child modules"));
}
// Section: Testing Helpers // Section: Testing Helpers

View file

@ -949,7 +949,7 @@ module ovoid_spread(r=undef, d=undef, n=100, cone_ang=90, scale=[1,1,1], perp=tr
for ($idx = idx(theta_phis)) { for ($idx = idx(theta_phis)) {
tp = theta_phis[$idx]; tp = theta_phis[$idx];
xyz = spherical_to_xyz(r, tp[0], tp[1]); xyz = spherical_to_xyz(r, tp[0], tp[1]);
$pos = vmul(xyz,scale); $pos = vmul(xyz,point3d(scale,1));
$theta = tp[0]; $theta = tp[0];
$phi = tp[1]; $phi = tp[1];
$rad = r; $rad = r;

View file

@ -1,126 +0,0 @@
//////////////////////////////////////////////////////////////////////
// LibFile: errors.scad
// Functions and modules to facilitate error reporting.
// To use, include this line at the top of your file:
// ```
// use <BOSL2/std.scad>
// ```
//////////////////////////////////////////////////////////////////////
// Section: Warnings and Errors
// Module: no_children()
// Usage:
// no_children($children);
// Description:
// Assert that the calling module does not support children. Prints an error message to this effect and fails if children are present,
// as indicated by its argument.
// Arguments:
// $children = number of children the module has.
module no_children(count) {
assert(count==0, str("Module ",parent_module(1),"() does not support child modules"));
}
// Function&Module: echo_error()
// Usage:
// echo_error(msg, [pfx]);
// Description:
// Emulates printing of an error message. The text will be shaded red.
// You can also use this as a function call from a function.
// Arguments:
// msg = The message to print.
// pfx = The prefix to print before `msg`. Default: `ERROR`
module echo_error(msg, pfx="ERROR") {
echo(str("<p style=\"background-color: #ffb0b0\"><b>", pfx, ":</b> ", msg, "</p>"));
}
function echo_error(msg, pfx="ERROR") =
echo(str("<p style=\"background-color: #ffb0b0\"><b>", pfx, ":</b> ", msg, "</p>"));
// Function&Module: echo_warning()
// Usage:
// echo_warning(msg, [pfx]);
// Description:
// Emulates printing of a warning message. The text will be shaded yellow.
// You can also use this as a function call from a function.
// Arguments:
// msg = The message to print.
// pfx = The prefix to print before `msg`. Default: `WARNING`
module echo_warning(msg, pfx="WARNING") {
echo(str("<p style=\"background-color: #ffffb0\"><b>", pfx, ":</b> ", msg, "</p>"));
}
function echo_warning(msg, pfx="WARNING") =
echo(str("<p style=\"background-color: #ffffb0\"><b>", pfx, ":</b> ", msg, "</p>"));
// Function&Module: deprecate()
// Usage:
// deprecate(name, [suggest]);
// Description:
// Show module deprecation warnings.
// You can also use this as a function call from a function.
// Arguments:
// name = The name of the module that is deprecated.
// suggest = If given, the module to recommend using instead.
module deprecate(name, suggest=undef) {
echo_warning(pfx="DEPRECATED",
str(
"`<code>", name, "</code>` is deprecated and should not be used.",
is_undef(suggest)? "" : str(
" You should use `<code>", suggest, "</code>` instead."
)
)
);
}
function deprecate(name, suggest=undef) =
echo_warning(pfx="DEPRECATED",
str(
"`<code>", name, "</code>` is deprecated and should not be used.",
is_undef(suggest)? "" : str(
" You should use `<code>", suggest, "</code>` instead."
)
)
);
// Function&Module: deprecate_argument()
// Usage:
// deprecate(name, arg, [suggest]);
// Description:
// Show argument deprecation warnings.
// You can also use this as a function call from a function.
// Arguments:
// name = The name of the module/function the deprecated argument is used in.
// arg = The name of the deprecated argument.
// suggest = If given, the argument to recommend using instead.
module deprecate_argument(name, arg, suggest=undef) {
echo_warning(pfx="DEPRECATED ARG", str(
"In `<code>", name, "</code>`, ",
"the argument `<code>", arg, "</code>` ",
"is deprecated and should not be used.",
is_undef(suggest)? "" : str(
" You should use `<code>", suggest, "</code>` instead."
)
));
}
function deprecate_argument(name, arg, suggest=undef) =
echo_warning(pfx="DEPRECATED ARG", str(
"In `<code>", name, "</code>`, ",
"the argument `<code>", arg, "</code>` ",
"is deprecated and should not be used.",
is_undef(suggest)? "" : str(
" You should use `<code>", suggest, "</code>` instead."
)
));
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap

View file

@ -36,7 +36,7 @@ NAN = acos(2); // The value `nan`, useful for comparisons.
function sqr(x) = function sqr(x) =
is_list(x) ? [for(val=x) sqr(val)] : is_list(x) ? [for(val=x) sqr(val)] :
is_finite(x) ? x*x : is_finite(x) ? x*x :
assert(is_finite(x) || is_vector(x), "Input is not neither a number nor a list of numbers."); assert(is_finite(x) || is_vector(x), "Input is not a number nor a list of numbers.");
// Function: log2() // Function: log2()
@ -641,17 +641,6 @@ function mean(v) =
sum(v)/len(v); sum(v)/len(v);
// Function: median()
// Usage:
// x = median(v);
// Description:
// Given a list of numbers or vectors, finds the median value or midpoint.
// If passed a list of vectors, returns the vector of the median of each component.
function median(v) =
is_vector(v) ? (min(v)+max(v))/2 :
is_matrix(v) ? [for(ti=transpose(v)) (min(ti)+max(ti))/2 ]
: assert(false , "Invalid input.");
// Function: convolve() // Function: convolve()
// Usage: // Usage:
// x = convolve(p,q); // x = convolve(p,q);
@ -773,26 +762,26 @@ function _qr_factor(A,Q, column, m, n) =
// You can supply a compatible matrix b and it will produce the solution for every column of b. Note that if you want to // You can supply a compatible matrix b and it will produce the solution for every column of b. Note that if you want to
// solve Rx=b1 and Rx=b2 you must set b to transpose([b1,b2]) and then take the transpose of the result. If the matrix // solve Rx=b1 and Rx=b2 you must set b to transpose([b1,b2]) and then take the transpose of the result. If the matrix
// is singular (e.g. has a zero on the diagonal) then it returns []. // is singular (e.g. has a zero on the diagonal) then it returns [].
function back_substitute(R, b, x=[],transpose = false) = function back_substitute(R, b, transpose = false) =
assert(is_matrix(R, square=true)) assert(is_matrix(R, square=true))
let(n=len(R)) let(n=len(R))
assert(is_vector(b,n) || is_matrix(b,n),str("R and b are not compatible in back_substitute ",n, len(b))) assert(is_vector(b,n) || is_matrix(b,n),str("R and b are not compatible in back_substitute ",n, len(b)))
!is_vector(b) ? transpose([for(i=[0:len(b[0])-1]) back_substitute(R,subindex(b,i),transpose=transpose)]) : transpose
transpose? ? reverse(_back_substitute([for(i=[0:n-1]) [for(j=[0:n-1]) R[n-1-j][n-1-i]]],
reverse(back_substitute( reverse(b)))
[for(i=[0:n-1]) [for(j=[0:n-1]) R[n-1-j][n-1-i]]], : _back_substitute(R,b);
reverse(b), x, false
)) : function _back_substitute(R, b, x=[]) =
len(x) == n ? x : let(n=len(R))
let( len(x) == n ? x
ind = n - len(x) - 1 : let(ind = n - len(x) - 1)
) R[ind][ind] == 0 ? []
R[ind][ind] == 0 ? [] : : let(
let( newvalue = len(x)==0
newvalue = ? b[ind]/R[ind][ind]
len(x)==0? b[ind]/R[ind][ind] : : (b[ind]-select(R[ind],ind+1,-1) * x)/R[ind][ind]
(b[ind]-select(R[ind],ind+1,-1) * x)/R[ind][ind] )
) back_substitute(R, b, concat([newvalue],x)); _back_substitute(R, b, concat([newvalue],x));
// Function: det2() // Function: det2()
@ -1110,19 +1099,21 @@ function _deriv_nonuniform(data, h, closed) =
// closed = boolean to indicate if the data set should be wrapped around from the end to the start. // closed = boolean to indicate if the data set should be wrapped around from the end to the start.
function deriv2(data, h=1, closed=false) = function deriv2(data, h=1, closed=false) =
assert( is_consistent(data) , "Input list is not consistent or not numerical.") assert( is_consistent(data) , "Input list is not consistent or not numerical.")
assert( len(data)>=3, "Input list has less than 3 elements.")
assert( is_finite(h), "The sampling `h` must be a number." ) assert( is_finite(h), "The sampling `h` must be a number." )
let( L = len(data) ) let( L = len(data) )
closed? [ assert( L>=3, "Input list has less than 3 elements.")
closed
? [
for(i=[0:1:L-1]) for(i=[0:1:L-1])
(data[(i+1)%L]-2*data[i]+data[(L+i-1)%L])/h/h (data[(i+1)%L]-2*data[i]+data[(L+i-1)%L])/h/h
] : ]
:
let( let(
first = L<3? undef : first =
L==3? data[0] - 2*data[1] + data[2] : L==3? data[0] - 2*data[1] + data[2] :
L==4? 2*data[0] - 5*data[1] + 4*data[2] - data[3] : L==4? 2*data[0] - 5*data[1] + 4*data[2] - data[3] :
(35*data[0] - 104*data[1] + 114*data[2] - 56*data[3] + 11*data[4])/12, (35*data[0] - 104*data[1] + 114*data[2] - 56*data[3] + 11*data[4])/12,
last = L<3? undef : last =
L==3? data[L-1] - 2*data[L-2] + data[L-3] : L==3? data[L-1] - 2*data[L-2] + data[L-3] :
L==4? -2*data[L-1] + 5*data[L-2] - 4*data[L-3] + data[L-4] : L==4? -2*data[L-1] + 5*data[L-2] - 4*data[L-3] + data[L-4] :
(35*data[L-1] - 104*data[L-2] + 114*data[L-3] - 56*data[L-4] + 11*data[L-5])/12 (35*data[L-1] - 104*data[L-2] + 114*data[L-3] - 56*data[L-4] + 11*data[L-5])/12
@ -1203,12 +1194,12 @@ function C_div(z1,z2) =
// where a_n is the z^n coefficient. Polynomial coefficients are real. // where a_n is the z^n coefficient. Polynomial coefficients are real.
// The result is a number if `z` is a number and a complex number otherwise. // The result is a number if `z` is a number and a complex number otherwise.
function polynomial(p,z,k,total) = function polynomial(p,z,k,total) =
     is_undef(k) is_undef(k)
   ?    assert( is_vector(p) , "Input polynomial coefficients must be a vector." ) ? assert( is_vector(p) , "Input polynomial coefficients must be a vector." )
        assert( is_finite(z) || is_vector(z,2), "The value of `z` must be a real or a complex number." ) assert( is_finite(z) || is_vector(z,2), "The value of `z` must be a real or a complex number." )
        polynomial( _poly_trim(p), z, 0, is_num(z) ? 0 : [0,0]) polynomial( _poly_trim(p), z, 0, is_num(z) ? 0 : [0,0])
   : k==len(p) ? total : k==len(p) ? total
   : polynomial(p,z,k+1, is_num(z) ? total*z+p[k] : C_times(total,z)+[p[k],0]); : polynomial(p,z,k+1, is_num(z) ? total*z+p[k] : C_times(total,z)+[p[k],0]);
// Function: poly_mult() // Function: poly_mult()
// Usage: // Usage:
@ -1218,13 +1209,22 @@ function polynomial(p,z,k,total) =
// Given a list of polynomials represented as real coefficient lists, with the highest degree coefficient first, // Given a list of polynomials represented as real coefficient lists, with the highest degree coefficient first,
// computes the coefficient list of the product polynomial. // computes the coefficient list of the product polynomial.
function poly_mult(p,q) = function poly_mult(p,q) =
    is_undef(q) ? is_undef(q) ?
       len(p)==2 ? poly_mult(p[0],p[1]) assert( is_list(p)
                 : poly_mult(p[0], poly_mult(select(p,1,-1))) && []==[for(pi=p) if( !is_vector(pi) && pi!=[]) 0],
    : "Invalid arguments to poly_mult")
    assert( is_vector(p) && is_vector(q),"Invalid arguments to poly_mult") len(p)==2 ? poly_mult(p[0],p[1])
_poly_trim(convolve(p,q)); : poly_mult(p[0], poly_mult(select(p,1,-1)))
:
_poly_trim(
[
for(n = [len(p)+len(q)-2:-1:0])
sum( [for(i=[0:1:len(p)-1])
let(j = len(p)+len(q)- 2 - n - i)
if (j>=0 && j<len(q)) p[i]*q[j]
])
]);
// Function: poly_div() // Function: poly_div()
// Usage: // Usage:

View file

@ -31,9 +31,13 @@ _partition_cutpaths = [
function _partition_cutpath(l, h, cutsize, cutpath, gap) = function _partition_cutpath(l, h, cutsize, cutpath, gap) =
let( let(
check = assert(is_finite(l))
assert(is_finite(h))
assert(is_finite(gap))
assert(is_finite(cutsize) || is_vector(cutsize,2))
assert(is_string(cutpath) || is_path(cutpath,2)),
cutsize = is_vector(cutsize)? cutsize : [cutsize*2, cutsize], cutsize = is_vector(cutsize)? cutsize : [cutsize*2, cutsize],
cutpath = is_path(cutpath)? cutpath : ( cutpath = is_path(cutpath)? cutpath : (
assert(is_string(cutpath), "cutpath must be a 2D path or a string.")
let(idx = search([cutpath], _partition_cutpaths)) let(idx = search([cutpath], _partition_cutpaths))
idx==[[]]? assert(in_list(cutpath,_partition_cutpaths,idx=0)) : idx==[[]]? assert(in_list(cutpath,_partition_cutpaths,idx=0)) :
_partition_cutpaths[idx.x][1] _partition_cutpaths[idx.x][1]
@ -79,7 +83,7 @@ function _partition_cutpath(l, h, cutsize, cutpath, gap) =
// partition_mask(w=20, cutpath="jigsaw"); // partition_mask(w=20, cutpath="jigsaw");
module partition_mask(l=100, w=100, h=100, cutsize=10, cutpath=undef, gap=0, inverse=false, spin=0, orient=UP) module partition_mask(l=100, w=100, h=100, cutsize=10, cutpath=undef, gap=0, inverse=false, spin=0, orient=UP)
{ {
cutsize = is_vector(cutsize)? cutsize : [cutsize*2, cutsize]; cutsize = is_vector(cutsize)? point2d(cutsize) : [cutsize*2, cutsize];
path = _partition_cutpath(l, h, cutsize, cutpath, gap); path = _partition_cutpath(l, h, cutsize, cutpath, gap);
fullpath = concat(path, [[l/2,w*(inverse?-1:1)], [-l/2,w*(inverse?-1:1)]]); fullpath = concat(path, [[l/2,w*(inverse?-1:1)], [-l/2,w*(inverse?-1:1)]]);
rot(from=UP,to=orient) { rot(from=UP,to=orient) {

View file

@ -710,7 +710,7 @@ function regular_polyhedron_info(
info == "center" ? translation : info == "center" ? translation :
info == "type" ? entry[class] : info == "type" ? entry[class] :
info == "name" ? entry[pname] : info == "name" ? entry[pname] :
echo_warning(str("Unknown info type '",info,"' requested")); assert(false, str("Unknown info type '",info,"' requested"));

View file

@ -339,7 +339,7 @@ function region_faces(region, transform, reverse=false, vnf=EMPTY_VNF) =
// linear_sweep(orgn,height=20,convexity=16) show_anchors(); // linear_sweep(orgn,height=20,convexity=16) show_anchors();
module linear_sweep(region, height=1, center, twist=0, scale=1, slices, maxseg, style="default", convexity, anchor_isect=false, anchor, spin=0, orient=UP) { module linear_sweep(region, height=1, center, twist=0, scale=1, slices, maxseg, style="default", convexity, anchor_isect=false, anchor, spin=0, orient=UP) {
region = is_path(region)? [region] : region; region = is_path(region)? [region] : region;
cp = median(flatten(region)); cp = mean(pointlist_bounds(flatten(region)));
anchor = get_anchor(anchor, center, "origin", "origin"); anchor = get_anchor(anchor, center, "origin", "origin");
vnf = linear_sweep( vnf = linear_sweep(
region, height=height, region, height=height,

View file

@ -19,7 +19,7 @@ done
if [[ "$FILES" != "" ]]; then if [[ "$FILES" != "" ]]; then
PREVIEW_LIBS="$FILES" PREVIEW_LIBS="$FILES"
else else
PREVIEW_LIBS="affine arrays attachments beziers bottlecaps common constants coords cubetruss debug distributors edges errors geometry hingesnaps hull involute_gears joiners knurling linear_bearings masks math metric_screws mutators nema_steppers partitions paths phillips_drive polyhedra primitives quaternions queues regions rounding screws shapes shapes2d skin sliders stacks strings structs threading torx_drive transforms triangulation vectors version vnf walls wiring" PREVIEW_LIBS="affine arrays attachments beziers bottlecaps common constants coords cubetruss debug distributors edges geometry hingesnaps hull involute_gears joiners knurling linear_bearings masks math metric_screws mutators nema_steppers partitions paths phillips_drive polyhedra primitives quaternions queues regions rounding screws shapes shapes2d skin sliders stacks strings structs threading torx_drive transforms triangulation vectors version vnf walls wiring"
fi fi
dir="$(basename $PWD)" dir="$(basename $PWD)"

View file

@ -785,7 +785,7 @@ function rect(size=1, center, rounding=0, chamfer=0, anchor, spin=0) =
assert(is_num(rounding) || len(rounding)==4) assert(is_num(rounding) || len(rounding)==4)
let( let(
size = is_num(size)? [size,size] : point2d(size), size = is_num(size)? [size,size] : point2d(size),
anchor = get_anchor(anchor, center, FRONT+LEFT, FRONT+LEFT), anchor = point2d(get_anchor(anchor, center, FRONT+LEFT, FRONT+LEFT)),
complex = rounding!=0 || chamfer!=0 complex = rounding!=0 || chamfer!=0
) )
(rounding==0 && chamfer==0)? let( (rounding==0 && chamfer==0)? let(

View file

@ -1202,7 +1202,7 @@ function path_sweep(shape, path, method="incremental", normal, closed=false, twi
let (pathnormal = path_normals(path, tangents, closed)) let (pathnormal = path_normals(path, tangents, closed))
assert(all_defined(pathnormal),"Natural normal vanishes on your curve, select a different method") assert(all_defined(pathnormal),"Natural normal vanishes on your curve, select a different method")
let( testnormals = [for(i=[0:len(pathnormal)-1-(closed?1:2)]) pathnormal[i]*select(pathnormal,i+2)], let( testnormals = [for(i=[0:len(pathnormal)-1-(closed?1:2)]) pathnormal[i]*select(pathnormal,i+2)],
dummy = min(testnormals) < .5 ? echo_warning("abrupt change in normal direction. Consider a different method") :0 dummy = min(testnormals) < .5 ? echo("WARNING: ***** Abrupt change in normal direction. Consider a different method *****") :0
) )
[for(i=[0:L-(closed?0:1)]) let( [for(i=[0:L-(closed?0:1)]) let(
rotation = affine_frame_map(x=pathnormal[i%L], z=tangents[i%L]) rotation = affine_frame_map(x=pathnormal[i%L], z=tangents[i%L])
@ -1216,7 +1216,7 @@ function path_sweep(shape, path, method="incremental", normal, closed=false, twi
end = reindex_polygon(start, apply(transform_list[L],path3d(shape))) end = reindex_polygon(start, apply(transform_list[L],path3d(shape)))
) )
all([for(i=idx(start)) approx(start[i],end[i])]), all([for(i=idx(start)) approx(start[i],end[i])]),
dummy = ends_match ? 0 :echo_warning("The points do not match when closing the model") dummy = ends_match ? 0 : echo("WARNING: ***** The points do not match when closing the model *****")
) )
transforms ? transform_list : sweep(shape, transform_list, closed=false, caps=fullcaps); transforms ? transform_list : sweep(shape, transform_list, closed=false, caps=fullcaps);

View file

@ -14,7 +14,6 @@ include <version.scad>
include <constants.scad> include <constants.scad>
include <edges.scad> include <edges.scad>
include <common.scad> include <common.scad>
include <errors.scad>
include <arrays.scad> include <arrays.scad>
include <strings.scad> include <strings.scad>
include <vnf.scad> include <vnf.scad>

View file

@ -350,6 +350,7 @@ test_add_scalar();
module test_subindex() { module test_subindex() {
v = [[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]]; v = [[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]];
assert(subindex(v,2) == [3, 7, 11, 15]); assert(subindex(v,2) == [3, 7, 11, 15]);
assert(subindex(v,[2]) == [[3], [7], [11], [15]]);
assert(subindex(v,[2,1]) == [[3, 2], [7, 6], [11, 10], [15, 14]]); assert(subindex(v,[2,1]) == [[3, 2], [7, 6], [11, 10], [15, 14]]);
assert(subindex(v,[1:3]) == [[2, 3, 4], [6, 7, 8], [10, 11, 12], [14, 15, 16]]); assert(subindex(v,[1:3]) == [[2, 3, 4], [6, 7, 8], [10, 11, 12], [14, 15, 16]]);
} }

View file

@ -1,11 +0,0 @@
include <../std.scad>
// Can't test echo output as yet. Include these for coverage calculations.
module test_echo_error() {}
module test_echo_warning() {}
module test_deprecate() {}
module test_deprecate_argument() {}
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap

View file

@ -391,11 +391,13 @@ module test_mean() {
} }
test_mean(); test_mean();
/*
module test_median() { module test_median() {
assert_equal(median([2,3,7]), 4.5); assert_equal(median([2,3,7]), 4.5);
assert_equal(median([[1,2,3], [3,4,5], [8,9,10]]), [4.5,5.5,6.5]); assert_equal(median([[1,2,3], [3,4,5], [8,9,10]]), [4.5,5.5,6.5]);
} }
test_median(); test_median();
*/
module test_convolve() { module test_convolve() {

View file

@ -558,12 +558,12 @@ function scale(v=1, p=undef) =
len(v)==2? affine2d_scale(v) : affine3d_scale(point3d(v)) len(v)==2? affine2d_scale(v) : affine3d_scale(point3d(v))
) : ( ) : (
assert(is_list(p)) assert(is_list(p))
is_num(p.x)? vmul(p,v) : is_vector(p)? ( len(p)==2? vmul(p,point2d(v)) : vmul(p,point3d(v,1)) ) :
is_vnf(p)? let(inv=product([for (x=v) x<0? -1 : 1])) [ is_vnf(p)? let(inv=product([for (x=v) x<0? -1 : 1])) [
scale(v=v,p=p.x), scale(v=v, p=p[0]),
inv>=0? p.y : [for (l=p.y) reverse(l)] inv>=0? p[1] : [for (l=p[1]) reverse(l)]
] : ] :
[for (l=p) is_vector(l)? vmul(l,v) : scale(v=v, p=l)] [ for (pp=p) scale(v=v, p=pp) ]
); );

View file

@ -64,13 +64,10 @@ function vang(v) =
// Example: // Example:
// vmul([3,4,5], [8,7,6]); // Returns [24, 28, 30] // vmul([3,4,5], [8,7,6]); // Returns [24, 28, 30]
function vmul(v1, v2) = function vmul(v1, v2) =
// this thighter check can be done yet because it would break other codes in the library assert( is_vector(v1) && is_vector(v2,len(v1)), "Incompatible vectors")
// assert( is_vector(v1) && is_vector(v2,len(v1)), "Incompatible vectors")
assert( is_vector(v1) && is_vector(v2), "Invalid vector(s)")
[for (i = [0:1:len(v1)-1]) v1[i]*v2[i]]; [for (i = [0:1:len(v1)-1]) v1[i]*v2[i]];
// Function: vdiv() // Function: vdiv()
// Description: // Description:
// Element-wise vector division. Divides each element of vector `v1` by // Element-wise vector division. Divides each element of vector `v1` by

View file

@ -8,7 +8,7 @@
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
BOSL_VERSION = [2,0,401]; BOSL_VERSION = [2,0,402];
// Section: BOSL Library Version Functions // Section: BOSL Library Version Functions