From 2db068d7ed688e54cef4696b94d0b2b79bf6b0ac Mon Sep 17 00:00:00 2001 From: Adrian Mariano Date: Thu, 29 Jan 2026 20:42:40 -0500 Subject: [PATCH] str_join -> chr when possible, doc fixes in masks.scad --- comparisons.scad | 6 +++--- linalg.scad | 4 ++-- masks.scad | 16 +++++++++++----- partitions.scad | 1 + strings.scad | 45 +++++++++++++++++++++++---------------------- 5 files changed, 40 insertions(+), 32 deletions(-) diff --git a/comparisons.scad b/comparisons.scad index fcc0abd..9e86f0a 100644 --- a/comparisons.scad +++ b/comparisons.scad @@ -455,7 +455,7 @@ function deduplicate(list, closed=false, eps=_EPSILON) = l = len(list), end = l-(closed?0:1) ) - is_string(list) ? str_join([for (i=[0:1:l-1]) if (i==end || list[i] != list[(i+1)%l]) list[i]]) : + is_string(list) ? chr([for (i=[0:1:l-1]) if (i==end || list[i] != list[(i+1)%l]) ord(list[i]])) : eps==0 ? [for (i=[0:1:l-1]) if (i==end || list[i] != list[(i+1)%l]) list[i]] : [for (i=[0:1:l-1]) if (i==end || !approx(list[i], list[(i+1)%l], eps)) list[i]]; @@ -580,7 +580,7 @@ function list_unwrap(list, eps=_EPSILON) = // sorted = unique([true,2,"xba",[1,0],true,[0,0],3,"a",[0,0],2]); // Returns: [true,2,3,"a","xba",[0,0],[1,0]] function unique(list) = assert(is_list(list)||is_string(list), "Invalid input." ) - is_string(list)? str_join(unique([for (x = list) x])) : + is_string(list)? chr(unique([for (x = list) ord(x)])) : len(list)<=1? list : is_homogeneous(list,1) && ! is_list(list[0]) ? _unique_sort(list) @@ -840,7 +840,7 @@ function _indexed_sort(arrind) = // sorted3 = sort(l3); // Returns: [20,[3,1],[3,9],[4],[4,0],[7],[8]] function sort(list, idx=undef) = assert(is_list(list)||is_string(list), "Invalid input." ) - is_string(list)? str_join(sort([for (x = list) x],idx)) : + is_string(list)? chr(sort([for (x = list) ord(x)])) : !is_list(list) || len(list)<=1 ? list : is_homogeneous(list,1) ? let(size = list_shape(list[0])) diff --git a/linalg.scad b/linalg.scad index 91d168b..2a10c92 100644 --- a/linalg.scad +++ b/linalg.scad @@ -126,9 +126,9 @@ function is_rotation(A,dim,centered=false) = // eps = numbers smaller than this display as zero. Default: 1e-9 function echo_matrix(M,description,sig=4,sep=1,eps=1e-9) = let( - horiz_line = chr(8213), + horiz_line = 8213, matstr = _format_matrix(M,sig=sig,sep=sep,eps=eps), - separator = str_join(repeat(horiz_line,10)), + separator = chf(repeat(horiz_line,10)), dummy=echo(str(separator,is_def(description) ? str(" ",description) : "")) [for(row=matstr) echo(row)] ) diff --git a/masks.scad b/masks.scad index 541b712..e1c06f5 100644 --- a/masks.scad +++ b/masks.scad @@ -1185,7 +1185,8 @@ module face_profile(faces=[], r, d, excess=0.01, convexity=10) { // Usage: // PARENT() edge_profile([edges], [except], [convexity]) CHILDREN; // Description: -// Takes a 2D mask shape and attaches it to the selected edges, with the appropriate orientation and +// Takes a 2D mask shape and attaches it to the selected edges of a cuboid, prismoid or cone, with the +// appropriate orientation and // extruded length to be `diff()`ed away, to give the edge a matching profile. If no tag is set // then `edge_profile` sets the tag for children to "remove" so that it works with the default {{diff()}} tag. // For details on specifying the edges to mask see [Specifying Edges](attachments.scad#subsection-specifying-edges). @@ -1223,7 +1224,8 @@ module face_profile(faces=[], r, d, excess=0.01, convexity=10) { module edge_profile(edges=EDGES_ALL, except=[], excess=0.01, convexity=10) { req_children($children); - check1 = assert($parent_geom != undef, "\nNo object to attach to!"); + check1 = assert($parent_geom != undef, "\nNo object to attach to!") + assert(in_list($parent_geom[0],["conoid","prismoid"]), "Parent must be a cyl, cuboid or prismoid"); conoid = $parent_geom[0] == "conoid"; edges = !conoid? _edges(edges, except=except) : edges==EDGES_ALL? [TOP,BOT] : @@ -1552,9 +1554,14 @@ module edge_profile_asym( [for (i=[0:2]) if (abs(e1[i])==1 && e1[i]==e2[i]) -e1[i] else 0]; req_children($children); + + is_cuboid = is_def($parent_geom) && $parent_geom[0]=="prismoid" + && point2d($parent_geom[1])==$parent_geom[2] + && $parent_geom[3]==[0,0]; check1 = assert($parent_geom != undef, "\nNo object to attach to!") - assert(in_list(corner_type, ["none", "round", "chamfer", "sharp"])) - assert(is_bool(flip)); + assert(is_cuboid, "Parent must be a cuboid") + assert(in_list(corner_type, ["none", "round", "chamfer", "sharp"])) + assert(is_bool(flip)); edges = _edges(edges, except=except); vecs = [ for (i = [0:3], axis=[0:2]) @@ -2164,7 +2171,6 @@ module polygon_edge_mask(mask, length, height, l, h, scale=1, anchor="origin", a angle = vector_angle(select(mask,corner-1,corner+1)); anchor_dir = -zrot(angle/2,RIGHT); anchors = [named_anchor("corner", CTR,anchor_dir, _compute_spin(anchor_dir, UP))]; - echo(anchors=anchors); default_tag("remove") attachable(anchor=anchor, spin=spin, orient=orient, h=length, scale=scale, path=mask, extent=atype=="hull", anchors=anchors){ linear_sweep(mask,h=length,anchor="origin", scale=scale); diff --git a/partitions.scad b/partitions.scad index a02a97c..82dcd64 100644 --- a/partitions.scad +++ b/partitions.scad @@ -201,6 +201,7 @@ function left_half(p,x=0) = half_of(p, LEFT, [x,0,0]); // right_half(planar=true) circle(r=20); module right_half(s=100, x=0, planar=false) { + req_children($children); dir = RIGHT; difference() { children(); diff --git a/strings.scad b/strings.scad index 6686ffd..60744a1 100644 --- a/strings.scad +++ b/strings.scad @@ -37,14 +37,16 @@ function _is_liststr(s) = is_list(s) || is_str(s); // s5=substr("abcdefg",len=-2); // Returns "" function substr(str, pos=0, len=undef) = assert(is_string(str)) - is_list(pos) ? _substr(str, pos[0], pos[1]-pos[0]+1) : - len == undef ? _substr(str, pos, len(str)-pos) : - _substr(str,pos,len); - -function _substr(str,pos,len,substr="") = - len <= 0 || pos>=len(str) ? substr : - _substr(str, pos+1, len-1, str(substr, str[pos])); + is_list(pos) ? _substr(str, pos[0], pos[1]-pos[0]+1) + : len == undef ? _substr(str, pos, len(str)-pos) + : _substr(str,pos,len); +function _substr(str,pos,len) = + assert(pos>=0,"pos value for substr() must be nonnegative") + len <= 0 || pos>=len(str) ? "" + : + chr([for(i=[pos:pos+len-1]) ord(str[i])]); + // Function: suffix() // Synopsis: Returns the last few characters of a string. @@ -348,7 +350,7 @@ function str_pad(str,length,char=" ",left=false) = assert(is_str(char) && len(char)==1, "char must be a single character string") assert(is_bool(left)) let( - padding = str_join(repeat(char,length-len(str))) + padding = chr(repeat(ord(char),length-len(str))) ) left ? str(padding,str) : str(str,padding); @@ -393,7 +395,7 @@ function str_replace_char(str,char,replace) = // s=downcase("ABCdef"); // Returns "abcdef" function downcase(str) = assert(is_string(str)) - str_join([for(char=str) let(code=ord(char)) code>=65 && code<=90 ? chr(code+32) : char]); + chr([for(char=str) let(code=ord(char)) code>=65 && code<=90 ? code+32 : code]); // Function: upcase() @@ -411,7 +413,7 @@ function downcase(str) = // s=upcase("ABCdef"); // Returns "ABCDEF" function upcase(str) = assert(is_string(str)) - str_join([for(char=str) let(code=ord(char)) code>=97 && code<=122 ? chr(code-32) : char]); + chr([for(char=str) let(code=ord(char)) code>=97 && code<=122 ? code-32 : code]); // Section: Random strings @@ -433,8 +435,8 @@ function upcase(str) = // charset = string to draw the characters from. Default: characters from "0" to "z". // seed = random number seed function rand_str(n, charset, seed) = - is_undef(charset)? str_join([for(c=rand_int(48,122,n,seed)) chr(c)]) - : str_join([for(i=rand_int(0,len(charset)-1,n,seed)) charset[i]]); + is_undef(charset)? chr(rand_int(48,122,n,seed)) + : chr([for(i=rand_int(0,len(charset)-1,n,seed)) ord(charset[i])]); @@ -609,17 +611,16 @@ function parse_num(str) = // Example: // str(123456789012345); // Returns "1.23457e+14" // format_int(123456789012345); // Returns "123456789012345" -// format_int(-123456789012345); // Returns "-123456789012345" +// format_int(-123456789012345); // Returns "-123456789012345" +// format_int(12,3); // Returns 012 function format_int(i,mindigits=1) = i<0? str("-", format_int(-i,mindigits)) : let(i=floor(i), e=floor(log(i))) - i==0? str_join([for (j=[0:1:mindigits-1]) "0"]) : - str_join( - concat( - [for (j=[0:1:mindigits-e-2]) "0"], - [for (j=[e:-1:0]) str(floor(i/pow(10,j)%10))] - ) - ); + i==0? chr([for (j=[0:1:mindigits-1]) 48]) : + chr([ + for (j=[0:1:mindigits-e-2]) 48, + for (j=[e:-1:0]) 48+(floor(i/pow(10,j)%10)) + ]); // Function: format_fixed() @@ -715,7 +716,7 @@ function _format_matrix(M, sig=4, sep=1, eps=1e-9) = figure_dash = chr(8210), space_punc = chr(8200), space_figure = chr(8199), - sep = is_num(sep) && sep>=0 ? str_join(repeat(space_figure,sep)) + sep = is_num(sep) && sep>=0 ? chr(repeat(ord(space_figure),sep)) : is_string(sep) ? sep : assert(false,"Invalid separator: must be a string or positive integer giving number of spaces"), strarr= @@ -832,7 +833,7 @@ function format(fmt, vals) = typ=="G"? upcase(format_float(val,default(prec,6))) : assert(false,str("Unknown format type: ",typ)), padlen = max(0,wid-len(unpad)), - padfill = str_join([for (i=[0:1:padlen-1]) zero? "0" : " "]), + padfill = chr([for (i=[0:1:padlen-1]) zero? 48 : 32]), out = left? str(unpad, padfill) : str(padfill, unpad) ) out, raw