From 046266778c1d3afccc3ec840864b5470d65341a0 Mon Sep 17 00:00:00 2001 From: Adrian Mariano Date: Thu, 30 Jul 2020 20:46:19 -0400 Subject: [PATCH 01/10] improved back_substitute, cleaned up a few other functions, removed some non-breaking space characters. --- math.scad | 101 ++++++++++++++++++++++-------------------------------- 1 file changed, 41 insertions(+), 60 deletions(-) diff --git a/math.scad b/math.scad index 55e662b..d91ffec 100644 --- a/math.scad +++ b/math.scad @@ -773,26 +773,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 // 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 []. -function back_substitute(R, b, x=[],transpose = false) = +function back_substitute(R, b, transpose = false) = assert(is_matrix(R, square=true)) 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))) - !is_vector(b) ? transpose([for(i=[0:len(b[0])-1]) back_substitute(R,subindex(b,i),transpose=transpose)]) : - transpose? - reverse(back_substitute( - [for(i=[0:n-1]) [for(j=[0:n-1]) R[n-1-j][n-1-i]]], - reverse(b), x, false - )) : - len(x) == n ? x : - let( - ind = n - len(x) - 1 - ) - R[ind][ind] == 0 ? [] : - let( - newvalue = - len(x)==0? b[ind]/R[ind][ind] : - (b[ind]-select(R[ind],ind+1,-1) * x)/R[ind][ind] - ) back_substitute(R, b, concat([newvalue],x)); + transpose + ? reverse(_back_substitute([for(i=[0:n-1]) [for(j=[0:n-1]) R[n-1-j][n-1-i]]], + reverse(b))) + : _back_substitute(R,b); + +function _back_substitute(R, b, x=[]) = + let(n=len(R)) + len(x) == n ? x + : let(ind = n - len(x) - 1) + R[ind][ind] == 0 ? [] + : let( + newvalue = len(x)==0 + ? b[ind]/R[ind][ind] + : (b[ind]-select(R[ind],ind+1,-1) * x)/R[ind][ind] + ) + _back_substitute(R, b, concat([newvalue],x)); // Function: det2() @@ -1120,19 +1120,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. function deriv2(data, h=1, closed=false) = 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." ) let( L = len(data) ) - closed? [ + assert( L>=3, "Input list has less than 3 elements.") + closed + ? [ for(i=[0:1:L-1]) (data[(i+1)%L]-2*data[i]+data[(L+i-1)%L])/h/h - ] : + ] + : let( - first = L<3? undef : + first = L==3? data[0] - 2*data[1] + data[2] : 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, - last = L<3? undef : + last = 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] : (35*data[L-1] - 104*data[L-2] + 114*data[L-3] - 56*data[L-4] + 11*data[L-5])/12 @@ -1212,34 +1214,13 @@ function C_div(z1,z2) = // The polynomial is specified as p=[a_n, a_{n-1},...,a_1,a_0] // 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. - -// Note: this should probably be recoded to use division by [1,-z], which is more accurate -// and avoids overflow with large coefficients, but requires poly_div to support complex coefficients. -function polynomial(p, z, _k, _zk, _total) = - is_undef(_k) - ? assert( is_vector(p), "Input polynomial coefficients must be a vector." ) - let(p = _poly_trim(p)) - assert( is_finite(z) || is_vector(z,2), "The value of `z` must be a real or a complex number." ) - polynomial( p, - z, - len(p)-1, - is_num(z)? 1 : [1,0], - is_num(z) ? 0 : [0,0]) - : _k==0 - ? _total + +_zk*p[0] - : polynomial( p, - z, - _k-1, - is_num(z) ? _zk*z : C_times(_zk,z), - _total+_zk*p[_k]); - function polynomial(p,z,k,total) = -     is_undef(k) -   ?    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." ) -        polynomial( _poly_trim(p), z, 0, is_num(z) ? 0 : [0,0]) -   : k==len(p) ? total -   : polynomial(p,z,k+1, is_num(z) ? total*z+p[k] : C_times(total,z)+[p[k],0]); + is_undef(k) + ? 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." ) + polynomial( _poly_trim(p), z, 0, is_num(z) ? 0 : [0,0]) + : k==len(p) ? total + : polynomial(p,z,k+1, is_num(z) ? total*z+p[k] : C_times(total,z)+[p[k],0]); // Function: poly_mult() // Usage: @@ -1266,18 +1247,18 @@ function poly_mult(p,q) = ]); function poly_mult(p,q) = -    is_undef(q) ? -       len(p)==2 ? poly_mult(p[0],p[1]) -                 : poly_mult(p[0], poly_mult(select(p,1,-1))) -    : -    assert( is_vector(p) && is_vector(q),"Invalid arguments to poly_mult") + is_undef(q) ? + len(p)==2 ? poly_mult(p[0],p[1]) + : poly_mult(p[0], poly_mult(select(p,1,-1))) + : + assert( is_vector(p) && is_vector(q),"Invalid arguments to poly_mult") _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=0 && j Date: Sat, 1 Aug 2020 15:54:58 -0400 Subject: [PATCH 02/10] Moved no_children to common.scad, and changed references to echo_warning in skin.scad and polyhedra.scad. --- common.scad | 15 +++++- errors.scad | 126 ------------------------------------------------- polyhedra.scad | 2 +- skin.scad | 4 +- 4 files changed, 17 insertions(+), 130 deletions(-) delete mode 100644 errors.scad diff --git a/common.scad b/common.scad index f0be6c1..d8941ee 100644 --- a/common.scad +++ b/common.scad @@ -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 false 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 @@ -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 diff --git a/errors.scad b/errors.scad deleted file mode 100644 index 8c174d9..0000000 --- a/errors.scad +++ /dev/null @@ -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 -// ``` -////////////////////////////////////////////////////////////////////// - - - -// 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("

", pfx, ": ", msg, "

")); -} - -function echo_error(msg, pfx="ERROR") = - echo(str("

", pfx, ": ", msg, "

")); - - -// 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("

", pfx, ": ", msg, "

")); -} - -function echo_warning(msg, pfx="WARNING") = - echo(str("

", pfx, ": ", msg, "

")); - - -// 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( - "`", name, "` is deprecated and should not be used.", - is_undef(suggest)? "" : str( - " You should use `", suggest, "` instead." - ) - ) - ); -} - -function deprecate(name, suggest=undef) = - echo_warning(pfx="DEPRECATED", - str( - "`", name, "` is deprecated and should not be used.", - is_undef(suggest)? "" : str( - " You should use `", suggest, "` 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 `", name, "`, ", - "the argument `", arg, "` ", - "is deprecated and should not be used.", - is_undef(suggest)? "" : str( - " You should use `", suggest, "` instead." - ) - )); -} - -function deprecate_argument(name, arg, suggest=undef) = - echo_warning(pfx="DEPRECATED ARG", str( - "In `", name, "`, ", - "the argument `", arg, "` ", - "is deprecated and should not be used.", - is_undef(suggest)? "" : str( - " You should use `", suggest, "` instead." - ) - )); - - - -// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap diff --git a/polyhedra.scad b/polyhedra.scad index b199fe9..e845acd 100644 --- a/polyhedra.scad +++ b/polyhedra.scad @@ -710,7 +710,7 @@ function regular_polyhedron_info( info == "center" ? translation : info == "type" ? entry[class] : info == "name" ? entry[pname] : - echo_warning(str("Unknown info type '",info,"' requested")); + assert(false, str("Unknown info type '",info,"' requested")); diff --git a/skin.scad b/skin.scad index 920f4ed..30d8a17 100644 --- a/skin.scad +++ b/skin.scad @@ -1202,7 +1202,7 @@ function path_sweep(shape, path, method="incremental", normal, closed=false, twi let (pathnormal = path_normals(path, tangents, closed)) 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)], - 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( 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))) ) 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); From f1cd94e98645cc690938a6f6e897791cc6f3671b Mon Sep 17 00:00:00 2001 From: Adrian Mariano Date: Sat, 1 Aug 2020 15:56:40 -0400 Subject: [PATCH 03/10] remove error.scad include --- std.scad | 1 - 1 file changed, 1 deletion(-) diff --git a/std.scad b/std.scad index 8375fcc..1c2e45e 100644 --- a/std.scad +++ b/std.scad @@ -14,7 +14,6 @@ include include include include -include include include include From e2817ae64d94db998b134c656acb905b4665d3d0 Mon Sep 17 00:00:00 2001 From: Adrian Mariano Date: Sun, 2 Aug 2020 01:18:33 -0400 Subject: [PATCH 04/10] removed references to errors.scad --- scripts/make_all_docs.sh | 2 +- tests/test_errors.scad | 11 ----------- 2 files changed, 1 insertion(+), 12 deletions(-) delete mode 100644 tests/test_errors.scad diff --git a/scripts/make_all_docs.sh b/scripts/make_all_docs.sh index ddd9937..fa05079 100755 --- a/scripts/make_all_docs.sh +++ b/scripts/make_all_docs.sh @@ -19,7 +19,7 @@ done if [[ "$FILES" != "" ]]; then PREVIEW_LIBS="$FILES" 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 dir="$(basename $PWD)" diff --git a/tests/test_errors.scad b/tests/test_errors.scad deleted file mode 100644 index fffe9eb..0000000 --- a/tests/test_errors.scad +++ /dev/null @@ -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 From 817bdffdef0ef66eaa528cbef750d3a6d19c0cce Mon Sep 17 00:00:00 2001 From: Adrian Mariano Date: Sun, 2 Aug 2020 01:20:11 -0400 Subject: [PATCH 05/10] Removed bogus median function --- math.scad | 11 ----------- regions.scad | 2 +- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/math.scad b/math.scad index d91ffec..7bc7924 100644 --- a/math.scad +++ b/math.scad @@ -641,17 +641,6 @@ function mean(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() // Usage: // x = convolve(p,q); diff --git a/regions.scad b/regions.scad index 6169337..fa761f0 100644 --- a/regions.scad +++ b/regions.scad @@ -339,7 +339,7 @@ function region_faces(region, transform, reverse=false, vnf=EMPTY_VNF) = // 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) { region = is_path(region)? [region] : region; - cp = median(flatten(region)); + cp = mean(pointlist_bounds(flatten(region))); anchor = get_anchor(anchor, center, "origin", "origin"); vnf = linear_sweep( region, height=height, From 47d02ae7834174ea6dc5266a5a6d13b66671e9ba Mon Sep 17 00:00:00 2001 From: Adrian Mariano Date: Sun, 2 Aug 2020 01:23:15 -0400 Subject: [PATCH 06/10] removed median tests --- tests/test_math.scad | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/test_math.scad b/tests/test_math.scad index f1b36b9..e5b1a41 100644 --- a/tests/test_math.scad +++ b/tests/test_math.scad @@ -391,11 +391,13 @@ module test_mean() { } test_mean(); +/* module test_median() { 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]); } test_median(); +*/ module test_convolve() { From 37ca6efebb6fd144b72a51c39d9f13c212b58e7c Mon Sep 17 00:00:00 2001 From: Adrian Mariano Date: Sun, 2 Aug 2020 10:35:32 -0400 Subject: [PATCH 07/10] Modified subindex to be faster. Note also changed behavior for idx=singleton list. --- arrays.scad | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/arrays.scad b/arrays.scad index 36841fe..1a10b9f 100644 --- a/arrays.scad +++ b/arrays.scad @@ -1172,25 +1172,25 @@ function add_scalar(v,s) = // Function: subindex() +// Usage: +// subindex(M, idx) // Description: -// For each array item, return the indexed subitem. -// Returns a list of the values of each vector at the specfied -// index list or range. If the index list or range has -// only one entry the output list is flattened. +// Extracts the entries listed in idx from each entry in M. For a matrix this means +// selecting a specified set of columsn. If idx is a number the return is a vector, otherwise +// it is a list of lists (the submatrix). // 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. // Example: -// v = [[[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(v,[2,1]); // Returns [[3, 2], [7, 6], [11, 10], [15, 14]] -// subindex(v,[1:3]); // Returns [[2, 3, 4], [6, 7, 8], [10, 11, 12], [14, 15, 16]] -function subindex(v, idx) = - [ for(val=v) - let( value=[for(i=idx) val[i]] ) - len(value)==1 ? value[0] : value - ]; - +// M = [[[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]]; +// subindex(M,2); // Returns [3, 7, 11, 15] +// subindex(M,[2]); // Returns [[3], [7], [11], [15]] +// subindex(M,[2,1]); // Returns [[3, 2], [7, 6], [11, 10], [15, 14]] +// subindex(M,[1:3]); // Returns [[2, 3, 4], [6, 7, 8], [10, 11, 12], [14, 15, 16]] +function subindex(v, idx) = + is_num(idx) + ? [for(row=M) row[idx]] + : [for(row=M) [for(i=idx) row[i]]]; // Function: zip() // Usage: From 06b69475cb8d1bef5794e3dcff2d0e2945af3ec9 Mon Sep 17 00:00:00 2001 From: Adrian Mariano Date: Sun, 2 Aug 2020 10:38:11 -0400 Subject: [PATCH 08/10] Fix bug. Add test for subindex. --- arrays.scad | 2 +- tests/test_arrays.scad | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/arrays.scad b/arrays.scad index 1a10b9f..0b7b924 100644 --- a/arrays.scad +++ b/arrays.scad @@ -1187,7 +1187,7 @@ function add_scalar(v,s) = // subindex(M,[2]); // Returns [[3], [7], [11], [15]] // subindex(M,[2,1]); // Returns [[3, 2], [7, 6], [11, 10], [15, 14]] // subindex(M,[1:3]); // Returns [[2, 3, 4], [6, 7, 8], [10, 11, 12], [14, 15, 16]] -function subindex(v, idx) = +function subindex(M, idx) = is_num(idx) ? [for(row=M) row[idx]] : [for(row=M) [for(i=idx) row[i]]]; diff --git a/tests/test_arrays.scad b/tests/test_arrays.scad index f621cd0..4fffb7d 100644 --- a/tests/test_arrays.scad +++ b/tests/test_arrays.scad @@ -358,6 +358,7 @@ test_add_scalar(); module test_subindex() { 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,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]]); } From 8f1162e7bf0cb1a30b9ab8758161d2f0c98ede0a Mon Sep 17 00:00:00 2001 From: Adrian Mariano Date: Sun, 2 Aug 2020 10:38:33 -0400 Subject: [PATCH 09/10] doc typo fix --- arrays.scad | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arrays.scad b/arrays.scad index 0b7b924..4f1c317 100644 --- a/arrays.scad +++ b/arrays.scad @@ -1182,7 +1182,7 @@ function add_scalar(v,s) = // M = The given list of lists. // idx = The index, list of indices, or range of indices to fetch. // Example: -// M = [[[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(M,2); // Returns [3, 7, 11, 15] // subindex(M,[2]); // Returns [[3], [7], [11], [15]] // subindex(M,[2,1]); // Returns [[3, 2], [7, 6], [11, 10], [15, 14]] From e56f953c1cd8db7e7e198e6d7d49650f133ab92a Mon Sep 17 00:00:00 2001 From: Garth Minette Date: Sun, 2 Aug 2020 23:23:50 -0700 Subject: [PATCH 10/10] Fixed calls to vmul() with heteerogenous vector sizes. --- attachments.scad | 21 +++++++++++---------- distributors.scad | 2 +- math.scad | 2 +- partitions.scad | 8 ++++++-- shapes2d.scad | 2 +- transforms.scad | 8 ++++---- vectors.scad | 5 +---- version.scad | 2 +- 8 files changed, 26 insertions(+), 24 deletions(-) diff --git a/attachments.scad b/attachments.scad index 8775832..6004e29 100644 --- a/attachments.scad +++ b/attachments.scad @@ -285,7 +285,7 @@ function attach_geom_size(geom) = ) [2*maxxr,2*maxyr,l] ) : type == "spheroid"? ( //r 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 let( mm = pointlist_bounds(geom[1][0]), @@ -298,7 +298,7 @@ function attach_geom_size(geom) = ) [maxx, size.y] ) : type == "circle"? ( //r 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 let( mm = pointlist_bounds(geom[1]), @@ -430,8 +430,8 @@ function find_anchor(anchor, geom) = ) : type == "cyl"? ( //r1, r2, l, shift let( rr1=geom[1], rr2=geom[2], l=geom[3], shift=point2d(geom[4]), - r1 = is_num(rr1)? [rr1,rr1] : rr1, - r2 = is_num(rr2)? [rr2,rr2] : rr2, + r1 = is_num(rr1)? [rr1,rr1] : point2d(rr1), + r2 = is_num(rr2)? [rr2,rr2] : point2d(rr2), u = (anchor.z+1)/2, axy = unit(point2d(anchor),[0,0]), bot = point3d(vmul(r1,axy), -l/2), @@ -447,9 +447,9 @@ function find_anchor(anchor, geom) = ) : type == "spheroid"? ( //r let( 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), - pos = point3d(cp) + vmul(r,anchor) + offset, + pos = point3d(cp) + vmul(r,anchor) + point3d(offset), vec = unit(vmul(r,anchor),UP) ) [anchor, pos, vec, oang] ) : type == "vnf_isect"? ( //vnf @@ -519,10 +519,10 @@ function find_anchor(anchor, geom) = ) : type == "circle"? ( //r let( rr = geom[1], - r = is_num(rr)? [rr,rr] : rr, - pos = point2d(cp) + vmul(r,anchor) + offset, + r = is_num(rr)? [rr,rr] : point2d(rr), 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] ) : type == "path_isect"? ( //path let( @@ -970,7 +970,8 @@ module edge_profile(edges=EDGES_ALL, except=[], convexity=10) { $attach_anchor = anch; $attach_norot = true; $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 = vec.z<0? [90,0,180+vang(point2d(vec))] : vec.z==0 && sign(vec.x)==sign(vec.y)? 135+vang(point2d(vec)) : diff --git a/distributors.scad b/distributors.scad index 5738033..787693e 100644 --- a/distributors.scad +++ b/distributors.scad @@ -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)) { tp = theta_phis[$idx]; xyz = spherical_to_xyz(r, tp[0], tp[1]); - $pos = vmul(xyz,scale); + $pos = vmul(xyz,point3d(scale,1)); $theta = tp[0]; $phi = tp[1]; $rad = r; diff --git a/math.scad b/math.scad index 7bc7924..e9b8579 100644 --- a/math.scad +++ b/math.scad @@ -36,7 +36,7 @@ NAN = acos(2); // The value `nan`, useful for comparisons. function sqr(x) = is_list(x) ? [for(val=x) sqr(val)] : 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() diff --git a/partitions.scad b/partitions.scad index 534219b..c46134c 100644 --- a/partitions.scad +++ b/partitions.scad @@ -31,9 +31,13 @@ _partition_cutpaths = [ function _partition_cutpath(l, h, cutsize, cutpath, gap) = 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], cutpath = is_path(cutpath)? cutpath : ( - assert(is_string(cutpath), "cutpath must be a 2D path or a string.") let(idx = search([cutpath], _partition_cutpaths)) idx==[[]]? assert(in_list(cutpath,_partition_cutpaths,idx=0)) : _partition_cutpaths[idx.x][1] @@ -79,7 +83,7 @@ function _partition_cutpath(l, h, cutsize, cutpath, gap) = // 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) { - 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); fullpath = concat(path, [[l/2,w*(inverse?-1:1)], [-l/2,w*(inverse?-1:1)]]); rot(from=UP,to=orient) { diff --git a/shapes2d.scad b/shapes2d.scad index 4c13d91..4c11efd 100644 --- a/shapes2d.scad +++ b/shapes2d.scad @@ -785,7 +785,7 @@ function rect(size=1, center, rounding=0, chamfer=0, anchor, spin=0) = assert(is_num(rounding) || len(rounding)==4) let( 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 ) (rounding==0 && chamfer==0)? let( diff --git a/transforms.scad b/transforms.scad index be73fbc..965f5de 100644 --- a/transforms.scad +++ b/transforms.scad @@ -558,12 +558,12 @@ function scale(v=1, p=undef) = len(v)==2? affine2d_scale(v) : affine3d_scale(point3d(v)) ) : ( 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])) [ - scale(v=v,p=p.x), - inv>=0? p.y : [for (l=p.y) reverse(l)] + scale(v=v, p=p[0]), + 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) ] ); diff --git a/vectors.scad b/vectors.scad index 80909b2..1749981 100644 --- a/vectors.scad +++ b/vectors.scad @@ -64,13 +64,10 @@ function vang(v) = // Example: // vmul([3,4,5], [8,7,6]); // Returns [24, 28, 30] 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), "Invalid vector(s)") + assert( is_vector(v1) && is_vector(v2,len(v1)), "Incompatible vectors") [for (i = [0:1:len(v1)-1]) v1[i]*v2[i]]; - // Function: vdiv() // Description: // Element-wise vector division. Divides each element of vector `v1` by diff --git a/version.scad b/version.scad index 6e03aa9..e6ba60b 100644 --- a/version.scad +++ b/version.scad @@ -8,7 +8,7 @@ ////////////////////////////////////////////////////////////////////// -BOSL_VERSION = [2,0,401]; +BOSL_VERSION = [2,0,402]; // Section: BOSL Library Version Functions