mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2025-12-13 19:52:19 +00:00
Merge pull request #1644 from adrianVmariano/master
tex_aspect and pixel_aspect to rotate_sweep + strings doc fixes
This commit is contained in:
commit
2a412be227
2 changed files with 156 additions and 71 deletions
91
skin.scad
91
skin.scad
|
|
@ -726,6 +726,8 @@ function skin(profiles, slices, refine=1, method="direct", sampling, caps, close
|
||||||
// tex_size=[5,5], convexity=12);
|
// tex_size=[5,5], convexity=12);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
module linear_sweep(
|
module linear_sweep(
|
||||||
region, height, center,
|
region, height, center,
|
||||||
twist=0, scale=1, shift=[0,0],
|
twist=0, scale=1, shift=[0,0],
|
||||||
|
|
@ -898,6 +900,12 @@ function linear_sweep(
|
||||||
// a horizontal segment at each end, resulting in flat faces at the top and bottom. These flat faces do not receive any applied texture. No segment of of the
|
// a horizontal segment at each end, resulting in flat faces at the top and bottom. These flat faces do not receive any applied texture. No segment of of the
|
||||||
// region---including the closing segments added to polygons---can lie on the Y axis. When `closed=false` you can terminate one or both ends of the path
|
// region---including the closing segments added to polygons---can lie on the Y axis. When `closed=false` you can terminate one or both ends of the path
|
||||||
// on the Y axis if you want texturing to continue all the way to the center.
|
// on the Y axis if you want texturing to continue all the way to the center.
|
||||||
|
// .
|
||||||
|
// If you want to place just one or a few copies of a texture onto an object rather than texturing the entire object you can do that by using
|
||||||
|
// and angle smaller than 360. However, if you want to control the aspect ratio of the resulting texture you will have to carefully calculate the proper
|
||||||
|
// angle to use. To simplify this process you can use `pixel_aspect` or `tex_aspect`. You can set `tex_aspect` for any type of tile and it specifies
|
||||||
|
// the desired aspect ratio (width/height) for the tiles. You must specify `tex_reps` in order to use this feature. For heightfields you can instead provide
|
||||||
|
// a pixel aspect ratio, which is suited to the case where your texture is a non-square image that you want to place on a curved object.
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// shape = The polygon or [region](regions.scad) to sweep around the Z axis.
|
// shape = The polygon or [region](regions.scad) to sweep around the Z axis.
|
||||||
// angle = If given, specifies the number of degrees to sweep the region around the Z axis, counterclockwise from the X+ axis. Default: 360 (full rotation)
|
// angle = If given, specifies the number of degrees to sweep the region around the Z axis, counterclockwise from the X+ axis. Default: 360 (full rotation)
|
||||||
|
|
@ -911,6 +919,8 @@ function linear_sweep(
|
||||||
// tex_depth = Specify texture depth; if negative, invert the texture. Default: 1.
|
// tex_depth = Specify texture depth; if negative, invert the texture. Default: 1.
|
||||||
// tex_samples = Minimum number of "bend points" to have in VNF texture tiles. Default: 8
|
// tex_samples = Minimum number of "bend points" to have in VNF texture tiles. Default: 8
|
||||||
// tex_taper = If given as a number, tapers the texture height to zero over the first and last given percentage of the path. If given as a lookup table with indices between 0 and 100, uses the percentage lookup table to ramp the texture heights. Default: `undef` (no taper)
|
// tex_taper = If given as a number, tapers the texture height to zero over the first and last given percentage of the path. If given as a lookup table with indices between 0 and 100, uses the percentage lookup table to ramp the texture heights. Default: `undef` (no taper)
|
||||||
|
// tex_aspect = Choose the angle of the revolution to maintain this aspect ratio for the tiles. You must specify tex_reps. Overrides any angle specified.
|
||||||
|
// pixel_aspect = Choose the angle of the revolution to maintain this apsect ratio for pixels in a heightfield texture. You must specify tex_reps. Overrides any angle specified.
|
||||||
// style = {{vnf_vertex_array()}} style. Default: "min_edge"
|
// style = {{vnf_vertex_array()}} style. Default: "min_edge"
|
||||||
// closed = If false, and `shape` is a path, then the revolved path is connected to the axis of rotation with untextured caps. Ignored if `shape` is not a path. Default: `true`
|
// closed = If false, and `shape` is a path, then the revolved path is connected to the axis of rotation with untextured caps. Ignored if `shape` is not a path. Default: `true`
|
||||||
// convexity = (Module only) Convexity setting for use with polyhedron. Default: 10
|
// convexity = (Module only) Convexity setting for use with polyhedron. Default: 10
|
||||||
|
|
@ -1097,7 +1107,7 @@ function linear_sweep(
|
||||||
// h = 20;
|
// h = 20;
|
||||||
// r = 15;
|
// r = 15;
|
||||||
// ang = len(img[0])/len(img)*h/(2*PI*r)*360;
|
// ang = len(img[0])/len(img)*h/(2*PI*r)*360;
|
||||||
// rotate_sweep([[15,-10],[15,10]], texture=img,
|
// rotate_sweep([[r,-h/2],[r,h/2]], texture=img,
|
||||||
// tex_reps=1,angle=ang, closed=false);
|
// tex_reps=1,angle=ang, closed=false);
|
||||||
//
|
//
|
||||||
// Example(3D,VPR=[80.20,0.00,138.40],VPD=82.67,VPT=[6.88,7.29,1.77],NoAxes): Here we have combined the above model with a suitable cylinder. Note that with a coarse texture like this you need to either match the `$fn` of the cylinder to the texture, or choose a sufficiently fine cylinder to avoid conflicting facets.
|
// Example(3D,VPR=[80.20,0.00,138.40],VPD=82.67,VPT=[6.88,7.29,1.77],NoAxes): Here we have combined the above model with a suitable cylinder. Note that with a coarse texture like this you need to either match the `$fn` of the cylinder to the texture, or choose a sufficiently fine cylinder to avoid conflicting facets.
|
||||||
|
|
@ -1118,16 +1128,54 @@ function linear_sweep(
|
||||||
// h = 20;
|
// h = 20;
|
||||||
// r = 15;
|
// r = 15;
|
||||||
// ang = len(img[0])/len(img)*h/(2*PI*r)*360;
|
// ang = len(img[0])/len(img)*h/(2*PI*r)*360;
|
||||||
// rotate_sweep([[15,-10],[15,10]], texture=img,
|
// rotate_sweep([[r,-h/2],[r,h/2]], texture=img,
|
||||||
// tex_reps=1,angle=ang, closed=false);
|
// tex_reps=1,angle=ang, closed=false);
|
||||||
// cyl(r=r,h=27,$fn=128);
|
// cyl(r=r,h=27,$fn=128);
|
||||||
|
// Example(3D,VPR=[68.30,0.00,148.90],VPD=91.85,VPT=[-0.56,5.78,-0.90],NoAxes): Above we explicitly calculated the required angle to produce the correct aspect ratio. Here we use `pixel_aspect` which produces an output whose average width has the desired aspect ratio.
|
||||||
|
// img = [
|
||||||
|
// [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
// [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
|
||||||
|
// [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
|
||||||
|
// [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
|
||||||
|
// [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
|
||||||
|
// [0, 1, 0, 0, 0,.5,.5, 0, 0, 0, 1, 0],
|
||||||
|
// [0, 1, 0, 0, 0,.5,.5, 0, 0, 0, 1, 0],
|
||||||
|
// [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
|
||||||
|
// [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
|
||||||
|
// [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
|
||||||
|
// [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
|
||||||
|
// [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
// ];
|
||||||
|
// rotate_sweep([[15,-10],[5,10]], texture=img,
|
||||||
|
// tex_reps=[1,1], closed=false, pixel_aspect=1);
|
||||||
|
// cyl(r1=16,r2=4,h=24,$fn=128);
|
||||||
|
// Example(3D,VPR=[96.30,0.00,133.50],VPD=54.24,VPT=[1.94,2.85,-0.47]): Here we apply the texture to a sphere using the automatic `pixel_aspect` to determine the angle. Note that using {{spheroid()}} with the circum option eliminates artifacts arising due to mimatched faceting.
|
||||||
|
// img = [
|
||||||
|
// [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
// [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
|
||||||
|
// [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
|
||||||
|
// [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
|
||||||
|
// [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
|
||||||
|
// [0, 1, 0, 0, 0,.5,.5, 0, 0, 0, 1, 0],
|
||||||
|
// [0, 1, 0, 0, 0,.5,.5, 0, 0, 0, 1, 0],
|
||||||
|
// [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
|
||||||
|
// [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
|
||||||
|
// [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
|
||||||
|
// [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
|
||||||
|
// [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
// ];
|
||||||
|
// arc = arc(r=10, angle=[-44,44],n=100);
|
||||||
|
// rotate_sweep(arc, texture=img, tex_reps=[1,1],
|
||||||
|
// closed=false, pixel_aspect=1);
|
||||||
|
// spheroid(10,$fn=64,circum=true);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function rotate_sweep(
|
function rotate_sweep(
|
||||||
shape, angle=360,
|
shape, angle=360,
|
||||||
texture, tex_size=[5,5], tex_counts, tex_reps,
|
texture, tex_size=[5,5], tex_counts, tex_reps,
|
||||||
tex_inset=false, tex_rot=0,
|
tex_inset=false, tex_rot=0,
|
||||||
tex_scale, tex_depth, tex_samples,
|
tex_scale, tex_depth, tex_samples, tex_aspect, pixel_aspect,
|
||||||
tex_taper, shift=[0,0], closed=true,
|
tex_taper, shift=[0,0], closed=true,
|
||||||
style="min_edge", cp="centroid",
|
style="min_edge", cp="centroid",
|
||||||
atype="hull", anchor="origin",
|
atype="hull", anchor="origin",
|
||||||
|
|
@ -1163,7 +1211,7 @@ function rotate_sweep(
|
||||||
rot=tex_rot,
|
rot=tex_rot,
|
||||||
samples=tex_samples,
|
samples=tex_samples,
|
||||||
inhibit_y_slicing=_tex_inhibit_y_slicing,
|
inhibit_y_slicing=_tex_inhibit_y_slicing,
|
||||||
taper=tex_taper,
|
taper=tex_taper, tex_aspect=tex_aspect, pixel_aspect=pixel_aspect,
|
||||||
shift=shift,
|
shift=shift,
|
||||||
closed=closed,
|
closed=closed,
|
||||||
angle=angle,
|
angle=angle,
|
||||||
|
|
@ -1197,7 +1245,7 @@ module rotate_sweep(
|
||||||
tex_scale, tex_depth, tex_samples,
|
tex_scale, tex_depth, tex_samples,
|
||||||
tex_taper, shift=[0,0],
|
tex_taper, shift=[0,0],
|
||||||
style="min_edge",
|
style="min_edge",
|
||||||
closed=true, tex_extra,
|
closed=true, tex_extra, tex_aspect, pixel_aspect,
|
||||||
cp="centroid",
|
cp="centroid",
|
||||||
convexity=10,
|
convexity=10,
|
||||||
atype="hull",
|
atype="hull",
|
||||||
|
|
@ -1234,7 +1282,7 @@ module rotate_sweep(
|
||||||
rot=tex_rot,
|
rot=tex_rot,
|
||||||
samples=tex_samples,
|
samples=tex_samples,
|
||||||
taper=tex_taper,
|
taper=tex_taper,
|
||||||
shift=shift,tex_extra=tex_extra,
|
shift=shift,tex_extra=tex_extra,tex_aspect=tex_aspect, pixel_aspect=pixel_aspect,
|
||||||
closed=closed,
|
closed=closed,
|
||||||
inhibit_y_slicing=_tex_inhibit_y_slicing,
|
inhibit_y_slicing=_tex_inhibit_y_slicing,
|
||||||
angle=angle,
|
angle=angle,
|
||||||
|
|
@ -4472,7 +4520,7 @@ function _textured_revolution(
|
||||||
shape, texture, tex_size, tex_scale=1,
|
shape, texture, tex_size, tex_scale=1,
|
||||||
inset=false, rot=false, shift=[0,0],
|
inset=false, rot=false, shift=[0,0],
|
||||||
taper, closed=true, angle=360,
|
taper, closed=true, angle=360,
|
||||||
inhibit_y_slicing=false,
|
inhibit_y_slicing=false,tex_aspect, pixel_aspect,
|
||||||
counts, samples, start=0,tex_extra,
|
counts, samples, start=0,tex_extra,
|
||||||
style="min_edge", atype="intersect",
|
style="min_edge", atype="intersect",
|
||||||
anchor=CENTER, spin=0, orient=UP
|
anchor=CENTER, spin=0, orient=UP
|
||||||
|
|
@ -4488,6 +4536,8 @@ function _textured_revolution(
|
||||||
assert(taper_is_ok, "Bad taper= value.")
|
assert(taper_is_ok, "Bad taper= value.")
|
||||||
assert(in_list(atype, _ANCHOR_TYPES), "Anchor type must be \"hull\" or \"intersect\"")
|
assert(in_list(atype, _ANCHOR_TYPES), "Anchor type must be \"hull\" or \"intersect\"")
|
||||||
assert(is_undef(tex_extra) || is_finite(tex_extra) || is_vector(tex_extra,2), "tex_extra must be a number of 2-vector")
|
assert(is_undef(tex_extra) || is_finite(tex_extra) || is_vector(tex_extra,2), "tex_extra must be a number of 2-vector")
|
||||||
|
assert(num_defined([tex_aspect, pixel_aspect])<=1, "Cannot give both tex_aspect and pixel_aspect")
|
||||||
|
//assert(num_defined([tex_aspect, pixel_aspect])==0 || is_undef(angle), "Cannot give tex_aspect or pixel_aspect if you give angle")
|
||||||
let(
|
let(
|
||||||
regions = !is_path(shape,2)? region_parts(shape)
|
regions = !is_path(shape,2)? region_parts(shape)
|
||||||
: closed? region_parts([shape])
|
: closed? region_parts([shape])
|
||||||
|
|
@ -4512,10 +4562,13 @@ function _textured_revolution(
|
||||||
: is_def(tex_extra) ? force_list(tex_extra,2)
|
: is_def(tex_extra) ? force_list(tex_extra,2)
|
||||||
: counts==[1,1] ? [0,0]
|
: counts==[1,1] ? [0,0]
|
||||||
: [1,1],
|
: [1,1],
|
||||||
dummy = assert(is_undef(samples) || is_vnf(texture), "You gave the tex_samples argument with a heightfield texture, which is not permitted. Use the n= argument to texture() instead"),
|
dummy = assert(is_def(counts) || num_defined([pixel_aspect,tex_aspect])==0, "Must specify tex_counts (not tex_size) when using pixel_aspect or tex_aspect")
|
||||||
|
assert(is_undef(pixel_aspect) || !is_vnf(texture), "Cannot give pixel aspect with a VNF texture")
|
||||||
|
assert(is_undef(samples) || is_vnf(texture), "You gave the tex_samples argument with a heightfield texture, which is not permitted. Use the n= argument to texture() instead"),
|
||||||
inset = is_num(inset)? inset : inset? 1 : 0,
|
inset = is_num(inset)? inset : inset? 1 : 0,
|
||||||
samples = !is_vnf(texture)? len(texture) :
|
samples = !is_vnf(texture)? len(texture)
|
||||||
is_num(samples)? samples : 8,
|
: is_num(samples)? samples
|
||||||
|
: 8,
|
||||||
bounds = pointlist_bounds(flatten(flatten(regions))),
|
bounds = pointlist_bounds(flatten(flatten(regions))),
|
||||||
maxx = bounds[1].x,
|
maxx = bounds[1].x,
|
||||||
miny = bounds[0].y,
|
miny = bounds[0].y,
|
||||||
|
|
@ -4523,6 +4576,20 @@ function _textured_revolution(
|
||||||
h = maxy - miny,
|
h = maxy - miny,
|
||||||
circumf = 2 * PI * maxx,
|
circumf = 2 * PI * maxx,
|
||||||
texcnt = is_vnf(texture) ? undef : [len(texture[0]), len(texture)],
|
texcnt = is_vnf(texture) ? undef : [len(texture[0]), len(texture)],
|
||||||
|
angle = num_defined([tex_aspect,pixel_aspect])==0 ? angle
|
||||||
|
: let(
|
||||||
|
paths = flatten(regions),
|
||||||
|
lengths = [for(path=paths) path_length(path,closed=closed)],
|
||||||
|
ind = max_index(lengths),
|
||||||
|
rpath = resample_path(paths[ind], n=counts.y * samples + (closed?0:tex_extra.y), closed=closed),
|
||||||
|
h = path_length(rpath),
|
||||||
|
r = mean(column(rpath,0)),
|
||||||
|
width = counts.x/counts.y * (is_def(pixel_aspect) ? (texcnt.x+tex_extra.x-1)/(texcnt.y+tex_extra.y-1) : tex_aspect) * h + (is_def(pixel_aspect)?1:0),
|
||||||
|
ang = 360 * width / (2*PI*r)
|
||||||
|
)
|
||||||
|
assert(ang<=360, str("Angle required for requested tile counts and aspect is ",ang, " which exceeds 360 degrees."))
|
||||||
|
360 * width / (2*PI*r),
|
||||||
|
|
||||||
tile = !is_vnf(texture) || samples==1 ? texture
|
tile = !is_vnf(texture) || samples==1 ? texture
|
||||||
:
|
:
|
||||||
let(
|
let(
|
||||||
|
|
@ -4764,7 +4831,7 @@ module _textured_revolution(
|
||||||
shape, texture, tex_size, tex_scale=1,
|
shape, texture, tex_size, tex_scale=1,
|
||||||
inset=false, rot=false, shift=[0,0],
|
inset=false, rot=false, shift=[0,0],
|
||||||
taper, closed=true, angle=360,
|
taper, closed=true, angle=360,
|
||||||
style="min_edge", atype="intersect",
|
style="min_edge", atype="intersect",tex_aspect, pixel_aspect,
|
||||||
inhibit_y_slicing=false,tex_extra,
|
inhibit_y_slicing=false,tex_extra,
|
||||||
convexity=10, counts, samples, start=0,
|
convexity=10, counts, samples, start=0,
|
||||||
anchor=CENTER, spin=0, orient=UP
|
anchor=CENTER, spin=0, orient=UP
|
||||||
|
|
@ -4773,7 +4840,7 @@ module _textured_revolution(
|
||||||
vnf = _textured_revolution(
|
vnf = _textured_revolution(
|
||||||
shape, texture, tex_size=tex_size,
|
shape, texture, tex_size=tex_size,
|
||||||
tex_scale=tex_scale, inset=inset, rot=rot,
|
tex_scale=tex_scale, inset=inset, rot=rot,
|
||||||
taper=taper, closed=closed, style=style,
|
taper=taper, closed=closed, style=style,tex_aspect=tex_aspect, pixel_aspect=pixel_aspect,
|
||||||
shift=shift, angle=angle,tex_extra=tex_extra,
|
shift=shift, angle=angle,tex_extra=tex_extra,
|
||||||
samples=samples, counts=counts, start=start,
|
samples=samples, counts=counts, start=start,
|
||||||
inhibit_y_slicing=inhibit_y_slicing
|
inhibit_y_slicing=inhibit_y_slicing
|
||||||
|
|
|
||||||
130
strings.scad
130
strings.scad
|
|
@ -28,11 +28,11 @@ function _is_liststr(s) = is_list(s) || is_str(s);
|
||||||
// pos = starting index of substring, or vector of first and last position. Default: 0
|
// pos = starting index of substring, or vector of first and last position. Default: 0
|
||||||
// len = length of substring, or omit it to get the rest of the string. If len is zero or less then the emptry string is returned.
|
// len = length of substring, or omit it to get the rest of the string. If len is zero or less then the emptry string is returned.
|
||||||
// Example:
|
// Example:
|
||||||
// substr("abcdefg",3,3); // Returns "def"
|
// s1=substr("abcdefg",3,3); // Returns "def"
|
||||||
// substr("abcdefg",2); // Returns "cdefg"
|
// s2=substr("abcdefg",2); // Returns "cdefg"
|
||||||
// substr("abcdefg",len=3); // Returns "abc"
|
// s3=substr("abcdefg",len=3); // Returns "abc"
|
||||||
// substr("abcdefg",[2,4]); // Returns "cde"
|
// s4=substr("abcdefg",[2,4]); // Returns "cde"
|
||||||
// substr("abcdefg",len=-2); // Returns ""
|
// s5=substr("abcdefg",len=-2); // Returns ""
|
||||||
function substr(str, pos=0, len=undef) =
|
function substr(str, pos=0, len=undef) =
|
||||||
assert(is_string(str))
|
assert(is_string(str))
|
||||||
is_list(pos) ? _substr(str, pos[0], pos[1]-pos[0]+1) :
|
is_list(pos) ? _substr(str, pos[0], pos[1]-pos[0]+1) :
|
||||||
|
|
@ -84,20 +84,20 @@ function suffix(str,len) =
|
||||||
// all = set to true to return all matches as a list. Overrides last. Default: false
|
// all = set to true to return all matches as a list. Overrides last. Default: false
|
||||||
// start = index where the search starts
|
// start = index where the search starts
|
||||||
// Example:
|
// Example:
|
||||||
// str_find("abc123def123abc","123"); // Returns 3
|
// a=str_find("abc123def123abc","123"); // Returns 3
|
||||||
// str_find("abc123def123abc","b"); // Returns 1
|
// b=str_find("abc123def123abc","b"); // Returns 1
|
||||||
// str_find("abc123def123abc","1234"); // Returns undef
|
// c=str_find("abc123def123abc","1234"); // Returns undef
|
||||||
// str_find("abc",""); // Returns 0
|
// d=str_find("abc",""); // Returns 0
|
||||||
// str_find("abc123def123", "123", start=4); // Returns 9
|
// e=str_find("abc123def123", "123", start=4); // Returns 9
|
||||||
// str_find("abc123def123abc","123",last=true); // Returns 9
|
// f=str_find("abc123def123abc","123",last=true); // Returns 9
|
||||||
// str_find("abc123def123abc","b",last=true); // Returns 13
|
// g=str_find("abc123def123abc","b",last=true); // Returns 13
|
||||||
// str_find("abc123def123abc","1234",last=true); // Returns undef
|
// h=str_find("abc123def123abc","1234",last=true); // Returns undef
|
||||||
// str_find("abc","",last=true); // Returns 3
|
// i=str_find("abc","",last=true); // Returns 3
|
||||||
// str_find("abc123def123", "123", start=8, last=true)); // Returns 3
|
// j=str_find("abc123def123", "123", start=8, last=true)); // Returns 3
|
||||||
// str_find("abc123def123abc","123",all=true); // Returns [3,9]
|
// k=str_find("abc123def123abc","123",all=true); // Returns [3,9]
|
||||||
// str_find("abc123def123abc","b",all=true); // Returns [1,13]
|
// l=str_find("abc123def123abc","b",all=true); // Returns [1,13]
|
||||||
// str_find("abc123def123abc","1234",all=true); // Returns []
|
// m=str_find("abc123def123abc","1234",all=true); // Returns []
|
||||||
// str_find("abc","",all=true); // Returns [0,1,2]
|
// n=str_find("abc","",all=true); // Returns [0,1,2]
|
||||||
function str_find(str,pattern,start=undef,last=false,all=false) =
|
function str_find(str,pattern,start=undef,last=false,all=false) =
|
||||||
assert(_is_liststr(str), "str must be a string or list")
|
assert(_is_liststr(str), "str must be a string or list")
|
||||||
assert(_is_liststr(pattern), "pattern must be a string or list")
|
assert(_is_liststr(pattern), "pattern must be a string or list")
|
||||||
|
|
@ -136,13 +136,13 @@ function _str_find_all(str,pattern) =
|
||||||
// str = String to search
|
// str = String to search
|
||||||
// start = Starting index for search in str
|
// start = Starting index for search in str
|
||||||
// pattern = String pattern to search for
|
// pattern = String pattern to search for
|
||||||
// Examples:
|
// Example:
|
||||||
// substr_match("abcde",2,"cd"); // Returns true
|
// a=substr_match("abcde",2,"cd"); // Returns true
|
||||||
// substr_match("abcde",2,"cx"); // Returns false
|
// b=substr_match("abcde",2,"cx"); // Returns false
|
||||||
// substr_match("abcde",2,"cdef"); // Returns false
|
// c=substr_match("abcde",2,"cdef"); // Returns false
|
||||||
// substr_match("abcde",-2,"cd"); // Returns false
|
// d=substr_match("abcde",-2,"cd"); // Returns false
|
||||||
// substr_match("abcde",19,"cd"); // Returns false
|
// e=substr_match("abcde",19,"cd"); // Returns false
|
||||||
// substr_match("abc",1,""); // Returns true
|
// f=substr_match("abc",1,""); // Returns true
|
||||||
|
|
||||||
//
|
//
|
||||||
// This is carefully optimized for speed. Precomputing the length
|
// This is carefully optimized for speed. Precomputing the length
|
||||||
|
|
@ -173,9 +173,9 @@ function _substr_match_recurse(str,sindex,pattern,plen,pindex=0,) =
|
||||||
// str = String to search.
|
// str = String to search.
|
||||||
// pattern = String pattern to search for.
|
// pattern = String pattern to search for.
|
||||||
// Example:
|
// Example:
|
||||||
// starts_with("abcdef","abc"); // Returns true
|
// b1=starts_with("abcdef","abc"); // Returns true
|
||||||
// starts_with("abcdef","def"); // Returns false
|
// b2=starts_with("abcdef","def"); // Returns false
|
||||||
// starts_with("abcdef",""); // Returns true
|
// b3=starts_with("abcdef",""); // Returns true
|
||||||
function starts_with(str,pattern) = _is_liststr(str) && substr_match(str,0,pattern);
|
function starts_with(str,pattern) = _is_liststr(str) && substr_match(str,0,pattern);
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -192,9 +192,9 @@ function starts_with(str,pattern) = _is_liststr(str) && substr_match(str,0,patte
|
||||||
// str = String to search.
|
// str = String to search.
|
||||||
// pattern = String pattern to search for.
|
// pattern = String pattern to search for.
|
||||||
// Example:
|
// Example:
|
||||||
// ends_with("abcdef","def"); // Returns true
|
// b1=ends_with("abcdef","def"); // Returns true
|
||||||
// ends_with("abcdef","de"); // Returns false
|
// b2=ends_with("abcdef","de"); // Returns false
|
||||||
// ends_with("abcdef",""); // Returns true
|
// b3=ends_with("abcdef",""); // Returns true
|
||||||
function ends_with(str,pattern) = _is_liststr(str) && substr_match(str,len(str)-len(pattern),pattern);
|
function ends_with(str,pattern) = _is_liststr(str) && substr_match(str,len(str)-len(pattern),pattern);
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -220,12 +220,12 @@ function ends_with(str,pattern) = _is_liststr(str) && substr_match(str,len(str)-
|
||||||
// sep = a string or list of strings to use for the separator
|
// sep = a string or list of strings to use for the separator
|
||||||
// keep_nulls = boolean value indicating whether to keep null strings in the output list. Default: true
|
// keep_nulls = boolean value indicating whether to keep null strings in the output list. Default: true
|
||||||
// Example:
|
// Example:
|
||||||
// str_split("abc+def-qrs*iop","*-+"); // Returns ["abc", "def", "qrs", "iop"]
|
// s1=str_split("abc+def-qrs*iop","*-+"); // Returns ["abc", "def", "qrs", "iop"]
|
||||||
// str_split("abc+*def---qrs**iop+","*-+");// Returns ["abc", "", "def", "", "", "qrs", "", "iop", ""]
|
// s2=str_split("abc+*def---qrs**iop+","*-+");// Returns ["abc", "", "def", "", "", "qrs", "", "iop", ""]
|
||||||
// str_split("abc def"," "); // Returns ["abc", "", "", "", "", "", "def"]
|
// s3=str_split("abc def"," "); // Returns ["abc", "", "", "", "", "", "def"]
|
||||||
// str_split("abc def"," ",keep_nulls=false); // Returns ["abc", "def"]
|
// s4=str_split("abc def"," ",keep_nulls=false); // Returns ["abc", "def"]
|
||||||
// str_split("abc+def-qrs*iop",["+","-","*"]); // Returns ["abc", "def", "qrs", "iop"]
|
// s5=str_split("abc+def-qrs*iop",["+","-","*"]); // Returns ["abc", "def", "qrs", "iop"]
|
||||||
// str_split("abc+def-qrs*iop",["-","+","*"]); // Returns ["abc+def", "qrs*iop", "", ""]
|
// s6=str_split("abc+def-qrs*iop",["-","+","*"]); // Returns ["abc+def", "qrs*iop", "", ""]
|
||||||
function str_split(str,sep,keep_nulls=true) =
|
function str_split(str,sep,keep_nulls=true) =
|
||||||
!keep_nulls ? _remove_empty_strs(str_split(str,sep,keep_nulls=true)) :
|
!keep_nulls ? _remove_empty_strs(str_split(str,sep,keep_nulls=true)) :
|
||||||
is_list(sep) ? _str_split_recurse(str,sep,i=0,result=[]) :
|
is_list(sep) ? _str_split_recurse(str,sep,i=0,result=[]) :
|
||||||
|
|
@ -265,8 +265,8 @@ function _remove_empty_strs(list) =
|
||||||
// list = list of strings to concatenate
|
// list = list of strings to concatenate
|
||||||
// sep = separator string to insert. Default: ""
|
// sep = separator string to insert. Default: ""
|
||||||
// Example:
|
// Example:
|
||||||
// str_join(["abc","def","ghi"]); // Returns "abcdefghi"
|
// s1=str_join(["abc","def","ghi"]); // Returns "abcdefghi"
|
||||||
// str_join(["abc","def","ghi"], " + "); // Returns "abc + def + ghi"
|
// s2=str_join(["abc","def","ghi"], " + "); // Returns "abc + def + ghi"
|
||||||
function str_join(list,sep="",_i=0, _result="") =
|
function str_join(list,sep="",_i=0, _result="") =
|
||||||
assert(is_list(list))
|
assert(is_list(list))
|
||||||
_i >= len(list)-1 ? (_i==len(list) ? _result : str(_result,list[_i])) :
|
_i >= len(list)-1 ? (_i==len(list) ? _result : str(_result,list[_i])) :
|
||||||
|
|
@ -285,22 +285,22 @@ function str_join(list,sep="",_i=0, _result="") =
|
||||||
// Takes a string `s` and strips off all leading and/or trailing characters that exist in string `c`.
|
// 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
|
// By default strips both leading and trailing characters. If you set start or end to true then
|
||||||
// it will strip only the leading or trailing characters respectively. If you set start
|
// it will strip only the leading or trailing characters respectively. If you set start
|
||||||
// or end to false then it will strip only lthe trailing or leading characters.
|
// or end to false then it will strip only the trailing or leading characters.
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// s = The string to strip leading or trailing characters from.
|
// s = The string to strip leading or trailing characters from.
|
||||||
// c = The string of characters to strip.
|
// c = The string of characters to strip.
|
||||||
// start = if true then strip leading characters
|
// start = if true then strip leading characters
|
||||||
// end = if true then strip trailing characters
|
// end = if true then strip trailing characters
|
||||||
// Example:
|
// Example:
|
||||||
// str_strip("--##--123--##--","#-"); // Returns: "123"
|
// s1=str_strip("--##--123--##--","#-"); // Returns: "123"
|
||||||
// str_strip("--##--123--##--","-"); // Returns: "##--123--##"
|
// s2=str_strip("--##--123--##--","-"); // Returns: "##--123--##"
|
||||||
// str_strip("--##--123--##--","#"); // Returns: "--##--123--##--"
|
// s3=str_strip("--##--123--##--","#"); // Returns: "--##--123--##--"
|
||||||
// str_strip("--##--123--##--","#-",end=true); // Returns: "--##--123"
|
// s4=str_strip("--##--123--##--","#-",end=true); // Returns: "--##--123"
|
||||||
// str_strip("--##--123--##--","-",end=true); // Returns: "--##--123--##"
|
// s5=str_strip("--##--123--##--","-",end=true); // Returns: "--##--123--##"
|
||||||
// str_strip("--##--123--##--","#",end=true); // Returns: "--##--123--##--"
|
// s6=str_strip("--##--123--##--","#",end=true); // Returns: "--##--123--##--"
|
||||||
// str_strip("--##--123--##--","#-",start=true); // Returns: "123--##--"
|
// s7=str_strip("--##--123--##--","#-",start=true); // Returns: "123--##--"
|
||||||
// str_strip("--##--123--##--","-",start=true); // Returns: "##--123--##--"
|
// s8=str_strip("--##--123--##--","-",start=true); // Returns: "##--123--##--"
|
||||||
// str_strip("--##--123--##--","#",start=true); // Returns: "--##--123--##--"
|
// s9=str_strip("--##--123--##--","#",start=true); // Returns: "--##--123--##--"
|
||||||
|
|
||||||
function _str_count_leading(s,c,_i=0) =
|
function _str_count_leading(s,c,_i=0) =
|
||||||
(_i>=len(s)||!in_list(s[_i],[each c]))? _i :
|
(_i>=len(s)||!in_list(s[_i],[each c]))? _i :
|
||||||
|
|
@ -337,6 +337,10 @@ function str_strip(s,c,start,end) =
|
||||||
// length = length to pad to
|
// length = length to pad to
|
||||||
// char = character to pad with. Default: " " (space)
|
// char = character to pad with. Default: " " (space)
|
||||||
// left = if true, pad on the left side. Default: false
|
// left = if true, pad on the left side. Default: false
|
||||||
|
// Example:
|
||||||
|
// s1=str_pad("hello", 10, "*"); // Returns: "hello*****"
|
||||||
|
// s2=str_pad("hello", 10, "*", left=true); // Returns: "*****hello"
|
||||||
|
|
||||||
function str_pad(str,length,char=" ",left=false) =
|
function str_pad(str,length,char=" ",left=false) =
|
||||||
assert(is_str(str))
|
assert(is_str(str))
|
||||||
assert(is_str(char) && len(char)==1, "char must be a single character string")
|
assert(is_str(char) && len(char)==1, "char must be a single character string")
|
||||||
|
|
@ -349,14 +353,22 @@ function str_pad(str,length,char=" ",left=false) =
|
||||||
|
|
||||||
|
|
||||||
// Function: str_replace_char()
|
// Function: str_replace_char()
|
||||||
// Synopsis: Replace given chars in a string with another substring.
|
// Synopsis: Replace specified character in a string with a string.
|
||||||
// Topics: Strings
|
// Topics: Strings
|
||||||
// See Also: suffix(), str_find(), substr_match(), starts_with(), ends_with(), str_split(), str_join(), str_strip()
|
// See Also: suffix(), str_find(), substr_match(), starts_with(), ends_with(), str_split(), str_join(), str_strip()
|
||||||
// Usage:
|
// Usage:
|
||||||
// newstr = str_replace_char(str, char, replace);
|
// newstr = str_replace_char(str, char, replace);
|
||||||
// Description:
|
// Description:
|
||||||
// Replace every occurence of `char` in the input string with the string `replace` which
|
// Replace every occurence of `char` (a single character string) in the input string
|
||||||
// can be any string.
|
// with the string `replace` which can be any string.
|
||||||
|
// Arguments:
|
||||||
|
// str = string to process
|
||||||
|
// char = single character string to search for
|
||||||
|
// replace = string that replaces all copies of `char`
|
||||||
|
// Example:
|
||||||
|
// s1 = str_replace_char("abcdcba","c","_123_"); // Returns: "ab123d123ba"
|
||||||
|
// s2 = str_replace_char(" s t r i n g ", " ", ""); // Returns: "string"
|
||||||
|
|
||||||
function str_replace_char(str,char,replace) =
|
function str_replace_char(str,char,replace) =
|
||||||
assert(is_str(str))
|
assert(is_str(str))
|
||||||
assert(is_str(char) && len(char)==1, "Search pattern 'char' must be a single character string")
|
assert(is_str(char) && len(char)==1, "Search pattern 'char' must be a single character string")
|
||||||
|
|
@ -376,7 +388,7 @@ function str_replace_char(str,char,replace) =
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// str = String to convert.
|
// str = String to convert.
|
||||||
// Example:
|
// Example:
|
||||||
// downcase("ABCdef"); // Returns "abcdef"
|
// s=downcase("ABCdef"); // Returns "abcdef"
|
||||||
function downcase(str) =
|
function downcase(str) =
|
||||||
assert(is_string(str))
|
assert(is_string(str))
|
||||||
str_join([for(char=str) let(code=ord(char)) code>=65 && code<=90 ? chr(code+32) : char]);
|
str_join([for(char=str) let(code=ord(char)) code>=65 && code<=90 ? chr(code+32) : char]);
|
||||||
|
|
@ -394,7 +406,7 @@ function downcase(str) =
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// str = String to convert.
|
// str = String to convert.
|
||||||
// Example:
|
// Example:
|
||||||
// upcase("ABCdef"); // Returns "ABCDEF"
|
// s=upcase("ABCdef"); // Returns "ABCDEF"
|
||||||
function upcase(str) =
|
function upcase(str) =
|
||||||
assert(is_string(str))
|
assert(is_string(str))
|
||||||
str_join([for(char=str) let(code=ord(char)) code>=97 && code<=122 ? chr(code-32) : char]);
|
str_join([for(char=str) let(code=ord(char)) code>=97 && code<=122 ? chr(code-32) : char]);
|
||||||
|
|
@ -412,8 +424,12 @@ function upcase(str) =
|
||||||
// Produce a random string of length `n`. If you give a string `charset` then the
|
// Produce a random string of length `n`. If you give a string `charset` then the
|
||||||
// characters of the random string are drawn from that list, weighted by the number
|
// characters of the random string are drawn from that list, weighted by the number
|
||||||
// of times each character appears in the list. If you do not give a character set
|
// of times each character appears in the list. If you do not give a character set
|
||||||
// then the string is generated with characters ranging from 0 to z (based on
|
// then the string is generated with characters ranging from "0" to "z" (based on
|
||||||
// character code).
|
// character code).
|
||||||
|
// Arguments:
|
||||||
|
// n = number of characters to produce
|
||||||
|
// charset = string to draw the characters from. Default: characters from "0" to "z".
|
||||||
|
// seed = random number seed
|
||||||
function rand_str(n, charset, seed) =
|
function rand_str(n, charset, seed) =
|
||||||
is_undef(charset)? str_join([for(c=rand_int(48,122,n,seed)) chr(c)])
|
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]]);
|
: str_join([for(i=rand_int(0,len(charset)-1,n,seed)) charset[i]]);
|
||||||
|
|
@ -560,6 +576,8 @@ function parse_frac(str,mixed=true,improper=true,signed=true) =
|
||||||
// Description:
|
// Description:
|
||||||
// Converts a string to a number. The string can be either a fraction (two integers separated by a "/") or a floating point number.
|
// 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.
|
// Returns NaN if the conversion fails.
|
||||||
|
// Arguments:
|
||||||
|
// str = string to process
|
||||||
// Example:
|
// Example:
|
||||||
// parse_num("3/4"); // Returns 0.75
|
// parse_num("3/4"); // Returns 0.75
|
||||||
// parse_num("3.4e-2"); // Returns 0.034
|
// parse_num("3.4e-2"); // Returns 0.034
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue