Added 3 examples to roundcorners.

Added doc text for list_increasing and list_decreasing.
Added str_match, str_matches, starts_width, ends_width.
Fixed substr to use tail recursion.
This commit is contained in:
Adrian Mariano 2019-06-22 13:33:49 -04:00
parent 2886cd907b
commit 60be226e85
3 changed files with 150 additions and 8 deletions

View file

@ -240,12 +240,18 @@ function list_insert(list, pos, elements) =
);
// True if the list is (non-strictly) increasing
// Function: list_increasing()
// Usage:
// list_increasing(list)
// Description: returns true if the list is (non-strictly) increasing
function list_increasing(list,ind=0) = ind < len(list)-1 && list[ind]<=list[ind+1] ? list_increasing(list,ind+1) :
(ind>=len(list)-1 ? true : false);
// True if the list is (non-strictly) decreasing
// Function: list_decreasing()
// Usage:
// list_increasing(list)
// Description: returns true if the list is (non-strictly) decreasing
function list_decreasing(list,ind=0) = ind < len(list)-1 && list[ind]>=list[ind+1] ? list_increasing(list,ind+1) :
(ind>=len(list)-1 ? true : false);

View file

@ -121,7 +121,43 @@ include <BOSL2/beziers.scad>
// translate([0,60,0])polygon(round_corners([[0,0],[50,0],[50,50],[0,50]],all=[5,.7],
// curve="smooth", type="cut"));
// }
// Example(Med2D): Rounding a path that is not closed in a three different ways.
// $fs=.25;
// $fa=1;
// zigzagx = [-10, 0, 10, 20, 29, 38, 46, 52, 59, 66, 72, 78, 83, 88, 92, 96, 99, 102, 112];
// zigzagy = concat([0], flatten(replist([-10,10],8)), [-10,0]);
// zig = zip(zigzagx,zigzagy);
// stroke(zig,width=1); // Original shape
// fwd(20) // Smooth all corners with a cut of 4 and curvature parameter 0.6
// stroke(round_corners(zig,all=[4,0.6],closed=false, curve="smooth", type="cut"),width=1);
//
// fwd(40) // Smooth all corners with circular arcs and a cut of 4
// stroke(round_corners(zig,all=[4,0.6],closed=false, curve="circle", type="cut"),width=1);
// // Smooth all corners with a circular arc and radius 1.5 (close to maximum possible)
// fwd(60) // Note how the different points are cut back by different amounts
// stroke(round_corners(zig,all=1.5,closed=false, curve="circle", type="radius"),width=1);
// Example(spin): Rounding some random 3d paths
// $fn=36;
// list1= [[2.88736, 4.03497, 6.37209], [5.68221, 9.37103, 0.783548], [7.80846, 4.39414, 1.84377],
// [0.941085, 5.30548, 4.46753], [1.86054, 9.81574, 6.49753], [6.93818, 7.21163, 5.79453]];
// list2= [[1.07907, 4.74091, 6.90039], [8.77585, 4.42248, 6.65185], [5.94714, 9.17137, 6.15642],
// [0.66266, 6.9563, 5.88423], [6.56454, 8.86334, 9.95311], [5.42015, 4.91874, 3.86696]];
// extrude_2dpath_along_3dpath(regular_ngon(n=36,or=.1),round_corners(list1,closed=false, curve="smooth", type="cut", all=.65));
// right(6)
// extrude_2dpath_along_3dpath(regular_ngon(n=36,or=.1),round_corners(list2,closed=false, curve="circle", type="cut", all=.75));
// Example(spin): Rounding a spiral with increased rounding along the length
// $fn=36;
// // Construct a square spiral path in 3d
// square = [[0,0],[1,0],[1,1],[0,1]];
// spiral = flatten(replist(concat(square,reverse(square)),5));
// z= list_range(40)*.2+[for(i=[0:9]) each [i,i,i,i]];
// // Make rounding parameters, which get larger up the spiral
// // and set the smoothing parameter to 1.
// rvect = zip([for(i=[0:9]) each [i,i,i,i]]/20,replist(1,40));
// rounding = [for(i=rvect) [i]]; // Needed because zip removes a list level
// path3d = zip([spiral,z,rounding]);
// rpath = round_corners(path3d, curve="smooth", type="joint",closed=false);
// extrude_2dpath_along_3dpath( regular_ngon(n=36, or=.1), rpath);
function round_corners(path, curve, type, all=undef, closed=true) =
let(
default_curvature = 0.5, // default curvature for "smooth" curves

View file

@ -15,12 +15,15 @@
// substr("abcdefg",2); // Returns "cdefg"
// substr("abcdefg",len=3); // Returns "abc"
// substr("abcdefg",[2,4]); // Returns "cde"
// substr("abcdefg",len=-2)); // Returns ""
function substr(str, pos=0, len=undef, substr="") =
is_list(pos) ? substr(str, pos[0], pos[1]-pos[0]+1) :
// substr("abcdefg",len=-2); // Returns ""
function substr(str, pos=0, len=undef) =
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 :
len == undef ? substr(str, pos, len(str)-pos, substr) :
substr(str, pos+1, len-1, str(substr, str[pos]));
_substr(str, pos+1, len-1, str(substr, str[pos]));
// Function suffix()
// Usage:
@ -198,3 +201,100 @@ function str_split_recurse(str,sep,i,result) =
function _remove_empty_strs(list) =
list_remove(list, search([""], list,0)[0]);
// _str_cmp(str,sindex,pattern)
// returns true if the string pattern matches the string
// starting at index position sindex in the string.
//
// This is carefully optimized for speed. Precomputing the length
// cuts run time in half when the string is long. Two other string
// comparison methods were slower.
function _str_cmp(str,sindex,pattern) =
len(str)-sindex <len(pattern)? false :
_str_cmp_recurse(str,sindex,pattern,len(pattern));
function _str_cmp_recurse(str,sindex,pattern,plen,pindex=0,) =
pindex < plen && pattern[pindex]==str[sindex] ? _str_cmp_recurse(str,sindex+1,pattern,plen,pindex+1): (pindex==plen);
// Function: str_match()
// Usage:
// str_match(str,pattern)
// Description:
// Searches input string `str` for the string `pattern` and returns the index of the first or last match in `str`.
// If `pattern` is empty then it returns 0. If `pattern` doesn't match it returns undef.
// Arguments:
// str = string to search
// pattern = string pattern to search for
// last = set to true to return the last match. Default: false
// Example:
// str_match("abc123def123abc","123"); // Returns 3
// str_match("abc123def123abc","b"); // Returns 1
// str_match("abc123def123abc","1234"); // Returns undef
// str_match("abc",""); // Returns 0
// str_match("abc123def123abc","123",last=true); // Returns 9
// str_match("abc123def123abc","b",last=true); // Returns 13
// str_match("abc123def123abc","1234",last=true); // Returns undef
// str_match("abc","",last=true); // Returns 2
function str_match(str,pattern,last=false) =
pattern=="" ? (last?len(str)-1:0) :
last ? _str_match_last(str,pattern,len(str)-len(pattern)) :
_str_match(str,pattern,len(str)-len(pattern));
function _str_match(str,pattern,max_sindex,sindex=0) =
sindex<=max_sindex && !_str_cmp(str,sindex, pattern) ? _str_match(str,pattern,max_sindex,sindex+1) :
(sindex <= max_sindex ? sindex : undef);
function _str_match_last(str,pattern,sindex) =
sindex>=0 && !_str_cmp(str,sindex, pattern) ? _str_match_last(str,pattern,sindex-1) :
(sindex >=0 ? sindex : undef);
// Function: str_matches()
// Usage:
// str_matches(str,pattern)
// Description:
// Returns the indices of all matches where the string `pattern` appears in the input string `str`.
// If `pattern` is empty then it matches every character of `str`.
// Arguments:
// str = string to search
// pattern = string pattern to search for
// Example:
// str_matches("abc123def123abc","123"); // Returns [3,9]
// str_matches("abc123def123abc","b"); // Returns [1,13]
// str_matches("abc123def123abc","1234"); // Returns []
// str_matches("abc",""); // Returns [0,1,2]
function str_matches(str,pattern) =
pattern == "" ? list_range(len(str)) :
[for(i=[0:1:len(str)-len(pattern)]) if (_str_cmp(str,i,pattern)) i];
// Function: starts_with()
// Usage:
// starts_with(str,pattern)
// Description:
// Returns true if the input string `str` starts with the specified string pattern, `pattern`.
// Otherwise returns false.
// Arguments:
// str = string to search
// pattern = string pattern to search for
// Example:
// starts_with("abcdef","abc"); // Returns true
// starts_with("abcdef","def"); // Returns false
// starts_with("abcdef",""); // Returns true
function starts_with(str,pattern) = _str_cmp(str,0,pattern);
// Function: ends_with()
// Usage:
// ends_with(str,pattern)
// Description:
// Returns true if the input string `str` ends with the specified string pattern, `pattern`.
// Otherwise returns false.
// Arguments:
// str = string to search
// pattern = string pattern to search for
// Example:
// ends_with("abcdef","def"); // Returns true
// ends_with("abcdef","de"); // Returns false
// ends_with("abcdef",""); // Returns true
function ends_with(str,pattern) = _str_cmp(str,len(str)-len(pattern),pattern);