mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2024-12-29 00:09:41 +00:00
Merge pull request #926 from adrianVmariano/master
string, supershape n= arg, doc fixes
This commit is contained in:
commit
80e646aed8
3 changed files with 84 additions and 49 deletions
|
@ -305,9 +305,9 @@ module circle(r, d, points, corner, anchor=CENTER, spin=0) {
|
|||
|
||||
// Function&Module: ellipse()
|
||||
// Usage: As a Module
|
||||
// ellipse(r|d=, [realign=], [circum=], ...) [ATTACHMENTS];
|
||||
// ellipse(r|d=, [realign=], [circum=], [uniform=], ...) [ATTACHMENTS];
|
||||
// Usage: As a Function
|
||||
// path = ellipse(r|d=, [realign=], [circum=], ...);
|
||||
// path = ellipse(r|d=, [realign=], [circum=], [uniform=], ...);
|
||||
// Topics: Shapes (2D), Paths (2D), Path Generators, Attachable
|
||||
// See Also: circle(), circle_2tangents(), circle_3points()
|
||||
// Description:
|
||||
|
@ -315,13 +315,16 @@ module circle(r, d, points, corner, anchor=CENTER, spin=0) {
|
|||
// When called as a function, returns a 2D list of points (path) for a polygon that approximates a circle or ellipse of the given size.
|
||||
// By default the point list or shape is the same as the one you would get by scaling the output of {{circle()}}, but with this module your
|
||||
// attachments to the ellipse will retain their dimensions, whereas scaling a circle with attachments will also scale the attachments.
|
||||
// If you set unifom to true then you will get a polygon with congruent sides whose vertices lie on the ellipse.
|
||||
// If you set `uniform` to true then you will get a polygon with congruent sides whose vertices lie on the ellipse. The `circum` option
|
||||
// requests a polygon that circumscribes the requested ellipse (so the specified ellipse will fit into the resulting polygon). Note that
|
||||
// you cannot gives `circum=true` and `uniform=true`.
|
||||
// Arguments:
|
||||
// r = Radius of the circle or pair of semiaxes of ellipse
|
||||
// ---
|
||||
// d = Diameter of the circle or a pair giving the full X and Y axis lengths.
|
||||
// realign = If false starts the approximate ellipse with a point on the X+ axis. If true the midpoint of a side is on the X+ axis and the first point of the polygon is below the X+ axis. This can result in a very different polygon when $fn is small. Default: false
|
||||
// circum = If true, the polygon that approximates the circle will be upsized slightly to circumscribe the theoretical circle. If false, it inscribes the theoretical circle. Default: false
|
||||
// uniform = If true, the polygon that approximates the circle will have segments of equal length. Only works if `circum=false`. Default: false
|
||||
// circum = If true, the polygon that approximates the circle will be upsized slightly to circumscribe the theoretical circle. If false, it inscribes the theoretical circle. If this is true then `uniform` must be false. Default: false
|
||||
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
|
||||
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
|
||||
// Example(2D): By Radius
|
||||
|
@ -1396,18 +1399,22 @@ function _superformula(theta,m1,m2,n1,n2=1,n3=1,a=1,b=1) =
|
|||
|
||||
// Function&Module: supershape()
|
||||
// Usage: As Module
|
||||
// supershape(step, [m1=], [m2=], [n1=], [n2=], [n3=], [a=], [b=], [r=/d=]) [ATTACHMENTS];
|
||||
// supershape([step],[n=], [m1=], [m2=], [n1=], [n2=], [n3=], [a=], [b=], [r=/d=]) [ATTACHMENTS];
|
||||
// Usage: As Function
|
||||
// path = supershape(step, [m1=], [m2=], [n1=], [n2=], [n3=], [a=], [b=], [r=/d=]);
|
||||
// path = supershape([step], [n=], [m1=], [m2=], [n1=], [n2=], [n3=], [a=], [b=], [r=/d=]);
|
||||
// Topics: Shapes (2D), Paths (2D), Path Generators, Attachable
|
||||
// See Also: circle(), ellipse()
|
||||
// Description:
|
||||
// When called as a function, returns a 2D path for the outline of the [Superformula](https://en.wikipedia.org/wiki/Superformula) shape.
|
||||
// When called as a module, creates a 2D [Superformula](https://en.wikipedia.org/wiki/Superformula) shape.
|
||||
// Note that the "hull" type anchoring (the default) is more intuitive for concave star-like shapes, but the anchor points do not
|
||||
// necesarily lie on the line of the anchor vector, which can be confusing, especially for simpler, ellipse-like shapes.
|
||||
// necesarily lie on the line of the anchor vector, which can be confusing, especially for simpler, ellipse-like shapes.
|
||||
// Note that the default step angle of 0.5 is very fine and can be slow, but due to the complex curves of the supershape,
|
||||
// many points are often required to give a good result.
|
||||
// Arguments:
|
||||
// step = The angle step size for sampling the superformula shape. Smaller steps are slower but more accurate.
|
||||
// step = The angle step size for sampling the superformula shape. Smaller steps are slower but more accurate. Default: 0.5
|
||||
// ---
|
||||
// n = Produce n points as output. Alternative to step. Not to be confused with shape parameters n1 and n2.
|
||||
// m1 = The m1 argument for the superformula. Default: 4.
|
||||
// m2 = The m2 argument for the superformula. Default: m1.
|
||||
// n1 = The n1 argument for the superformula. Default: 1.
|
||||
|
@ -1416,7 +1423,6 @@ function _superformula(theta,m1,m2,n1,n2=1,n3=1,a=1,b=1) =
|
|||
// a = The a argument for the superformula. Default: 1.
|
||||
// b = The b argument for the superformula. Default: a.
|
||||
// r = Radius of the shape. Scale shape to fit in a circle of radius r.
|
||||
// ---
|
||||
// d = Diameter of the shape. Scale shape to fit in a circle of diameter d.
|
||||
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
|
||||
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
|
||||
|
@ -1446,26 +1452,25 @@ function _superformula(theta,m1,m2,n1,n2=1,n3=1,a=1,b=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, n1=1, n2, n3, a=1, b, r, d,anchor=CENTER, spin=0, atype="hull") =
|
||||
function supershape(step=0.5, n, m1=4, m2, n1=1, n2, n3, a=1, b, r, d,anchor=CENTER, spin=0, atype="hull") =
|
||||
assert(in_list(atype, _ANCHOR_TYPES), "Anchor type must be \"hull\" or \"intersect\"")
|
||||
let(
|
||||
|
||||
n = first_defined([n, ceil(360/step)]),
|
||||
angs = lerpn(360,0,n,endpoint=false),
|
||||
r = get_radius(r=r, d=d, dflt=undef),
|
||||
m2 = is_def(m2) ? m2 : m1,
|
||||
n2 = is_def(n2) ? n2 : n1,
|
||||
n3 = is_def(n3) ? n3 : n2,
|
||||
b = is_def(b) ? b : a,
|
||||
steps = ceil(360/step),
|
||||
step = 360/steps,
|
||||
angs = [for (i = [0:steps]) step*i],
|
||||
rads = [for (theta = angs) _superformula(theta=theta,m1=m1,m2=m2,n1=n1,n2=n2,n3=n3,a=a,b=b)],
|
||||
scale = is_def(r) ? r/max(rads) : 1,
|
||||
path = [for (i = [steps:-1:1]) let(a=angs[i]) scale*rads[i]*[cos(a), sin(a)]]
|
||||
// superformula returns r(theta), the point in polar coordinates
|
||||
rvals = [for (theta = angs) _superformula(theta=theta,m1=m1,m2=m2,n1=n1,n2=n2,n3=n3,a=a,b=b)],
|
||||
scale = is_def(r) ? r/max(rvals) : 1,
|
||||
path = [for (i=idx(angs)) scale*rvals[i]*[cos(angs[i]), sin(angs[i])]]
|
||||
) reorient(anchor,spin, two_d=true, path=path, p=path, extent=atype=="hull");
|
||||
|
||||
module supershape(step=0.5,m1=4,m2=undef,n1,n2=undef,n3=undef,a=1,b=undef, r=undef, d=undef, anchor=CENTER, spin=0, atype="hull") {
|
||||
module supershape(step=0.5,n,m1=4,m2=undef,n1,n2=undef,n3=undef,a=1,b=undef, r=undef, d=undef, anchor=CENTER, spin=0, atype="hull") {
|
||||
check = assert(in_list(atype, _ANCHOR_TYPES), "Anchor type must be \"hull\" or \"intersect\"");
|
||||
path = supershape(step=step,m1=m1,m2=m2,n1=n1,n2=n2,n3=n3,a=a,b=b,r=r,d=d);
|
||||
path = supershape(step=step,n=n,m1=m1,m2=m2,n1=n1,n2=n2,n3=n3,a=a,b=b,r=r,d=d);
|
||||
attachable(anchor,spin,extent=atype=="hull", two_d=true, path=path) {
|
||||
polygon(path);
|
||||
children();
|
||||
|
|
79
strings.scad
79
strings.scad
|
@ -13,7 +13,7 @@
|
|||
|
||||
// Function: substr()
|
||||
// Usage:
|
||||
// substr(str, [pos], [len])
|
||||
// newstr = substr(str, [pos], [len]);
|
||||
// Description:
|
||||
// Returns a substring from a string start at position `pos` with length `len`, or
|
||||
// if `len` isn't given, the rest of the string.
|
||||
|
@ -39,7 +39,7 @@ function _substr(str,pos,len,substr="") =
|
|||
|
||||
// Function: suffix()
|
||||
// Usage:
|
||||
// suffix(str,len)
|
||||
// newstr = suffix(str,len);
|
||||
// Description:
|
||||
// Returns the last `len` characters from the input string `str`.
|
||||
// If `len` is longer than the length of `str`, then the entirety of `str` is returned.
|
||||
|
@ -56,7 +56,7 @@ function suffix(str,len) =
|
|||
|
||||
// Function: str_find()
|
||||
// Usage:
|
||||
// str_find(str,pattern,[last=],[all=],[start=])
|
||||
// ind = str_find(str,pattern,[last=],[all=],[start=]);
|
||||
// Description:
|
||||
// Searches input string `str` for the string `pattern` and returns the index or indices of the matches in `str`.
|
||||
// By default `str_find()` returns the index of the first match in `str`. If `last` is true then it returns the index of the last match.
|
||||
|
@ -94,37 +94,56 @@ function str_find(str,pattern,start=undef,last=false,all=false) =
|
|||
_str_find_first(str,pattern,len(str)-len(pattern),start);
|
||||
|
||||
function _str_find_first(str,pattern,max_sindex,sindex) =
|
||||
sindex<=max_sindex && !_str_cmp(str,sindex, pattern)?
|
||||
sindex<=max_sindex && !substr_match(str,sindex, pattern)?
|
||||
_str_find_first(str,pattern,max_sindex,sindex+1) :
|
||||
(sindex <= max_sindex ? sindex : undef);
|
||||
|
||||
function _str_find_last(str,pattern,sindex) =
|
||||
sindex>=0 && !_str_cmp(str,sindex, pattern)?
|
||||
sindex>=0 && !substr_match(str,sindex, pattern)?
|
||||
_str_find_last(str,pattern,sindex-1) :
|
||||
(sindex >=0 ? sindex : undef);
|
||||
|
||||
function _str_find_all(str,pattern) =
|
||||
pattern == "" ? count(len(str)) :
|
||||
[for(i=[0:1:len(str)-len(pattern)]) if (_str_cmp(str,i,pattern)) i];
|
||||
[for(i=[0:1:len(str)-len(pattern)]) if (substr_match(str,i,pattern)) i];
|
||||
|
||||
// Function: substr_match()
|
||||
// Usage
|
||||
// bool = substr_match(str,start,pattern);
|
||||
// Description:
|
||||
// Returns true if the string `pattern` matches the string `str` starting
|
||||
// at `str[start]`. If the string is too short for the pattern, or
|
||||
// `start` is out of bounds---either negative or beyond the end of the
|
||||
// string---then substr_match returns false.
|
||||
// Arguments:
|
||||
// str = String to search
|
||||
// start = Starting index for search in str
|
||||
// pattern = String pattern to search for
|
||||
// Examples:
|
||||
// substr_match("abcde",2,"cd"); // Returns true
|
||||
// substr_match("abcde",2,"cx"); // Returns false
|
||||
// substr_match("abcde",2,"cdef"); // Returns false
|
||||
// substr_match("abcde",-2,"cd"); // Returns false
|
||||
// substr_match("abcde",19,"cd"); // Returns false
|
||||
// substr_match("abc",1,""); // Returns true
|
||||
|
||||
// _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 substr_match(str,start,pattern) =
|
||||
len(str)-start <len(pattern)? false
|
||||
: _substr_match_recurse(str,start,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 _substr_match_recurse(str,sindex,pattern,plen,pindex=0,) =
|
||||
pindex < plen && pattern[pindex]==str[sindex]
|
||||
? _substr_match_recurse(str,sindex+1,pattern,plen,pindex+1)
|
||||
: (pindex==plen);
|
||||
|
||||
|
||||
// Function: starts_with()
|
||||
// Usage:
|
||||
// starts_with(str,pattern)
|
||||
// bool = starts_with(str,pattern);
|
||||
// Description:
|
||||
// Returns true if the input string `str` starts with the specified string pattern, `pattern`.
|
||||
// Otherwise returns false.
|
||||
|
@ -135,12 +154,12 @@ function _str_cmp_recurse(str,sindex,pattern,plen,pindex=0,) =
|
|||
// 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 starts_with(str,pattern) = substr_match(str,0,pattern);
|
||||
|
||||
|
||||
// Function: ends_with()
|
||||
// Usage:
|
||||
// ends_with(str,pattern)
|
||||
// bool = ends_with(str,pattern);
|
||||
// Description:
|
||||
// Returns true if the input string `str` ends with the specified string pattern, `pattern`.
|
||||
// Otherwise returns false.
|
||||
|
@ -151,13 +170,13 @@ function starts_with(str,pattern) = _str_cmp(str,0,pattern);
|
|||
// 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);
|
||||
function ends_with(str,pattern) = substr_match(str,len(str)-len(pattern),pattern);
|
||||
|
||||
|
||||
|
||||
// Function: str_split()
|
||||
// Usage:
|
||||
// str_split(str, sep, [keep_nulls])
|
||||
// string_list = str_split(str, sep, [keep_nulls]);
|
||||
// Description:
|
||||
// Breaks an input string into substrings using a separator or list of separators. If keep_nulls is true
|
||||
// then two sequential separator characters produce an empty string in the output list. If keep_nulls is false
|
||||
|
@ -207,7 +226,7 @@ function _remove_empty_strs(list) =
|
|||
|
||||
// Function: str_join()
|
||||
// Usage:
|
||||
// str_join(list, [sep])
|
||||
// str = str_join(list, [sep]);
|
||||
// Description:
|
||||
// Returns the concatenation of a list of strings, optionally with a
|
||||
// separator string inserted between each string on the list.
|
||||
|
@ -226,7 +245,7 @@ function str_join(list,sep="",_i=0, _result="") =
|
|||
|
||||
// Function: str_strip()
|
||||
// Usage:
|
||||
// str_strip(s,c,[start],[end]);
|
||||
// str = str_strip(s,c,[start],[end]);
|
||||
// Description:
|
||||
// Takes a string `s` and strips off all leading and/or trailing characters that exist in string `c`.
|
||||
// By default strips both leading and trailing characters. If you set start or end to true then
|
||||
|
@ -293,7 +312,7 @@ function str_pad(str,length,char=" ",left=false) =
|
|||
|
||||
// Function: str_replace_char()
|
||||
// Usage:
|
||||
// newstr = str_replace_char(str, char, replace)
|
||||
// newstr = str_replace_char(str, char, replace);
|
||||
// Description:
|
||||
// Replace every occurence of `char` in the input string with the string `replace` which
|
||||
// can be any string.
|
||||
|
@ -306,7 +325,7 @@ function str_replace_char(str,char,replace) =
|
|||
|
||||
// Function: downcase()
|
||||
// Usage:
|
||||
// downcase(str)
|
||||
// newstr = downcase(str);
|
||||
// Description:
|
||||
// Returns the string with the standard ASCII upper case letters A-Z replaced
|
||||
// by their lower case versions.
|
||||
|
@ -320,7 +339,7 @@ function downcase(str) =
|
|||
|
||||
// Function: upcase()
|
||||
// Usage:
|
||||
// upcase(str)
|
||||
// newstr = upcase(str);
|
||||
// Description:
|
||||
// Returns the string with the standard ASCII lower case letters a-z replaced
|
||||
// by their upper case versions.
|
||||
|
@ -353,7 +372,7 @@ function rand_str(n, charset, seed) =
|
|||
|
||||
// Function: parse_int()
|
||||
// Usage:
|
||||
// parse_int(str, [base])
|
||||
// num = parse_int(str, [base])
|
||||
// Description:
|
||||
// Converts a string into an integer with any base up to 16. Returns NaN if
|
||||
// conversion fails. Digits above 9 are represented using letters A-F in either
|
||||
|
@ -389,7 +408,7 @@ function _parse_int_recurse(str,base,i) =
|
|||
|
||||
// Function: parse_float()
|
||||
// Usage:
|
||||
// parse_float(str)
|
||||
// num = parse_float(str);
|
||||
// Description:
|
||||
// Converts a string to a floating point number. Returns NaN if the
|
||||
// conversion fails.
|
||||
|
@ -417,7 +436,7 @@ function parse_float(str) =
|
|||
|
||||
// Function: parse_frac()
|
||||
// Usage:
|
||||
// parse_frac(str,[mixed=],[improper=],[signed=])
|
||||
// num = parse_frac(str,[mixed=],[improper=],[signed=]);
|
||||
// Description:
|
||||
// Converts a string fraction to a floating point number. A string fraction has the form `[-][# ][#/#]` where each `#` is one or more of the
|
||||
// digits 0-9, and there is an optional sign character at the beginning.
|
||||
|
@ -471,7 +490,7 @@ function parse_frac(str,mixed=true,improper=true,signed=true) =
|
|||
|
||||
// Function: parse_num()
|
||||
// Usage:
|
||||
// parse_num(str)
|
||||
// num = parse_num(str);
|
||||
// Description:
|
||||
// Converts a string to a number. The string can be either a fraction (two integers separated by a "/") or a floating point number.
|
||||
// Returns NaN if the conversion fails.
|
||||
|
@ -491,7 +510,7 @@ function parse_num(str) =
|
|||
|
||||
// Function: format_int()
|
||||
// Usage:
|
||||
// format_int(i, [mindigits]);
|
||||
// str = format_int(i, [mindigits]);
|
||||
// Description:
|
||||
// Formats an integer number into a string. This can handle larger numbers than `str()`.
|
||||
// Arguments:
|
||||
|
@ -539,7 +558,7 @@ function format_fixed(f,digits=6) =
|
|||
|
||||
// Function: format_float()
|
||||
// Usage:
|
||||
// format_float(f,[sig]);
|
||||
// str = format_float(f,[sig]);
|
||||
// Description:
|
||||
// Formats the given floating point number `f` into a string with `sig` significant digits.
|
||||
// Strips trailing `0`s after the decimal point. Strips trailing decimal point.
|
||||
|
|
|
@ -21,6 +21,17 @@ module test_downcase() {
|
|||
}
|
||||
test_downcase();
|
||||
|
||||
module test_substr_match(){
|
||||
assert(substr_match("abcde",2,"cd"));
|
||||
assert(!substr_match("abcde",2,"cx"));
|
||||
assert(!substr_match("abcde",2,"cdef"));
|
||||
assert(!substr_match("abcde",-2,"cd"));
|
||||
assert(!substr_match("abcde",19,"cd"));
|
||||
assert(substr_match("abc",1,""));
|
||||
assert(!substr_match("",0,"a"));
|
||||
assert(substr_match("",0,""));
|
||||
}
|
||||
|
||||
|
||||
module test_starts_with() {
|
||||
assert(!starts_with("", "abc"));
|
||||
|
|
Loading…
Reference in a new issue