Renamed spread() to line_of(). Renamed [xyz]spread() to [xyz]copies()

This commit is contained in:
Revar Desmera 2020-03-24 19:11:05 -07:00
parent 971c1e795f
commit b0b436eb63
13 changed files with 93 additions and 89 deletions

View file

@ -3,7 +3,11 @@ module xmove(x) right(x) children();
module ymove(y) back(y) children();
module zmove(z) up(z) children();
module line_of(p1=[0,0,0], p2=[10,0,0], n=2) spread(p1=p1, p2=p2, n=n) children();
module xspread(spacing, n, l, sp) xcopies(spacing=spacing, n=n, l=l, sp=sp) children();
module yspread(spacing, n, l, sp) ycopies(spacing=spacing, n=n, l=l, sp=sp) children();
module zspread(spacing, n, l, sp) zcopies(spacing=spacing, n=n, l=l, sp=sp) children();
module spread(p1=[0,0,0], p2=[10,0,0], spacing, l, n=2) line_of(p1=p1, p2=p2, spacing=spacing, l=l, n=n) children();
module grid_of(xa=[0],ya=[0],za=[0],count,spacing) grid3d(xa=xa, ya=ya, za=za, n=count, spacing=spacing) children();
module xring(n=2,r=0,sa=0,cp=[0,0,0],rot=true) xrot_copies(n=n,r=r,sa=sa,cp=cp,subrot=rot) children();

View file

@ -151,8 +151,8 @@ module cubetruss_clip(extents=1, size=undef, strut=undef, clipthick=undef, ancho
yscale(1.5) chamfer_mask_z(l=size+1, chamfer=clipsize+clipthick/3);
}
}
zspread(clipheight-strut) cube([clipthick*3, cliplen*2, strut], center=true);
zspread(clipheight-2*strut) right(clipthick) chamfer_mask_y(l=cliplen*2, chamfer=clipthick);
zcopies(clipheight-strut) cube([clipthick*3, cliplen*2, strut], center=true);
zcopies(clipheight-2*strut) right(clipthick) chamfer_mask_y(l=cliplen*2, chamfer=clipthick);
}
}
children();
@ -192,7 +192,7 @@ module cubetruss_foot(w=1, size=undef, strut=undef, clipthick=undef, anchor=CENT
}
// Walls
xspread(w*(size-strut)+strut+clipthick) {
xcopies(w*(size-strut)+strut+clipthick) {
up(clipthick-0.01) {
prismoid([clipthick, (size-4*strut)], [clipthick, size/3.5], h=wall_h, anchor=BOT);
}
@ -200,7 +200,7 @@ module cubetruss_foot(w=1, size=undef, strut=undef, clipthick=undef, anchor=CENT
// Horiz Wall Clips
up(clipthick+strut+$slop*2) {
xspread(w*(size-strut)+strut) {
xcopies(w*(size-strut)+strut) {
prismoid([clipsize*2, size/3.5], [0.1, size/3.5], h=clipsize*3, anchor=BOT);
}
}
@ -216,7 +216,7 @@ module cubetruss_foot(w=1, size=undef, strut=undef, clipthick=undef, anchor=CENT
// Bevel to fit.
up(clipthick+strut) {
yspread(size-2*strut-4*$slop) {
ycopies(size-2*strut-4*$slop) {
chamfer_mask_x(l=size-strut, chamfer=strut*2/3);
}
}
@ -263,18 +263,18 @@ module cubetruss_joiner(w=1, vert=true, size=undef, strut=undef, clipthick=undef
// Base
cube([w*(size-strut)+strut+2*clipthick, size, clipthick], anchor=BOT);
xspread(w*(size-strut)+strut+clipthick) {
xcopies(w*(size-strut)+strut+clipthick) {
cube([clipthick, size, clipthick+strut*3/4], anchor=BOT);
}
// Use feet
yspread(size) {
ycopies(size) {
cubetruss_foot(w=w, size=size, strut=strut, clipthick=clipthick, anchor=BOT);
}
if (vert) {
// Vert Walls
xspread(w*(size-strut)+strut+clipthick) {
xcopies(w*(size-strut)+strut+clipthick) {
up(clipthick-0.01) {
prismoid([clipthick, size], [clipthick, 2*strut+2*clipthick], h=size*0.6, anchor=BOT);
}

View file

@ -406,7 +406,7 @@ module ruler(length=100, width=undef, thickness=1, depth=3, labels=false, pipsca
count = ceil(length/scales[i]);
fontsize = 0.5*min(widths[i], scales[i]/ceil(log(count*scales[i]/unit)));
back(offsets[i]) {
xspread(scales[i], n=count, sp=[0,0,0]) union() {
xcopies(scales[i], n=count, sp=[0,0,0]) union() {
actlen = ($idx<count-1) || approx(length%scales[i],0) ? scales[i] : length % scales[i];
color(colors[$idx%2], alpha=alpha) {
w = i>0 ? quantup(widths[i],1/1024) : widths[i]; // What is the i>0 test supposed to do here?

View file

@ -42,18 +42,18 @@ module move_copies(a=[[0,0,0]])
}
// Module: spread()
// Module: line_of()
//
// Description:
// Evenly distributes `n` copies of all children along a line.
// Copies every child at each position.
//
// Usage:
// spread(l, [n], [p1]) ...
// spread(l, spacing, [p1]) ...
// spread(spacing, [n], [p1]) ...
// spread(p1, p2, [n]) ...
// spread(p1, p2, spacing) ...
// line_of(l, [n], [p1]) ...
// line_of(l, spacing, [p1]) ...
// line_of(spacing, [n], [p1]) ...
// line_of(p1, p2, [n]) ...
// line_of(p1, p2, spacing) ...
//
// Arguments:
// p1 = Starting point of line.
@ -67,18 +67,18 @@ module move_copies(a=[[0,0,0]])
// `$idx` is set to the index number of each child being copied.
//
// Example(FlatSpin):
// spread([0,0,0], [5,5,20], n=6) cube(size=[3,2,1],center=true);
// line_of([0,0,0], [5,5,20], n=6) cube(size=[3,2,1],center=true);
// Examples:
// spread(l=40, n=6) cube(size=[3,2,1],center=true);
// spread(l=[15,30], n=6) cube(size=[3,2,1],center=true);
// spread(l=40, spacing=10) cube(size=[3,2,1],center=true);
// spread(spacing=[5,5,0], n=5) cube(size=[3,2,1],center=true);
// line_of(l=40, n=6) cube(size=[3,2,1],center=true);
// line_of(l=[15,30], n=6) cube(size=[3,2,1],center=true);
// line_of(l=40, spacing=10) cube(size=[3,2,1],center=true);
// line_of(spacing=[5,5,0], n=5) cube(size=[3,2,1],center=true);
// Example:
// spread(l=20, n=3) {
// line_of(l=20, n=3) {
// cube(size=[1,3,1],center=true);
// cube(size=[3,1,1],center=true);
// }
module spread(p1=undef, p2=undef, spacing=undef, l=undef, n=undef)
module line_of(p1, p2, spacing, l, n)
{
ll = (
!is_undef(l)? scalar_vec3(l, 0) :
@ -96,7 +96,7 @@ module spread(p1=undef, p2=undef, spacing=undef, l=undef, n=undef)
is_num(spacing) && !is_undef(ll)? (ll/(cnt-1)) :
scalar_vec3(spacing, 0)
);
assert(!is_undef(cnt), "Need two of `spacing`, 'l', 'n', or `p1`/`p2` arguments in `spread()`.");
assert(!is_undef(cnt), "Need two of `spacing`, 'l', 'n', or `p1`/`p2` arguments in `line_of()`.");
spos = !is_undef(p1)? point3d(p1) : -(cnt-1)/2 * spc;
for (i=[0:1:cnt-1]) {
pos = i * spc + spos;
@ -107,14 +107,14 @@ module spread(p1=undef, p2=undef, spacing=undef, l=undef, n=undef)
}
// Module: xspread()
// Module: xcopies()
//
// Description:
// Spreads out `n` copies of the children along a line on the X axis.
//
// Usage:
// xspread(spacing, [n], [sp]) ...
// xspread(l, [n], [sp]) ...
// xcopies(spacing, [n], [sp]) ...
// xcopies(l, [n], [sp]) ...
//
// Arguments:
// spacing = spacing between copies. (Default: 1.0)
@ -127,29 +127,29 @@ module spread(p1=undef, p2=undef, spacing=undef, l=undef, n=undef)
// `$idx` is set to the index number of each child being copied.
//
// Examples:
// xspread(20) sphere(3);
// xspread(20, n=3) sphere(3);
// xspread(spacing=15, l=50) sphere(3);
// xspread(n=4, l=30, sp=[0,10,0]) sphere(3);
// xcopies(20) sphere(3);
// xcopies(20, n=3) sphere(3);
// xcopies(spacing=15, l=50) sphere(3);
// xcopies(n=4, l=30, sp=[0,10,0]) sphere(3);
// Example:
// xspread(10, n=3) {
// xcopies(10, n=3) {
// cube(size=[1,3,1],center=true);
// cube(size=[3,1,1],center=true);
// }
module xspread(spacing=undef, n=undef, l=undef, sp=undef)
module xcopies(spacing, n, l, sp)
{
spread(l=l*RIGHT, spacing=spacing*RIGHT, n=n, p1=sp) children();
line_of(l=l*RIGHT, spacing=spacing*RIGHT, n=n, p1=sp) children();
}
// Module: yspread()
// Module: ycopies()
//
// Description:
// Spreads out `n` copies of the children along a line on the Y axis.
//
// Usage:
// yspread(spacing, [n], [sp]) ...
// yspread(l, [n], [sp]) ...
// ycopies(spacing, [n], [sp]) ...
// ycopies(l, [n], [sp]) ...
//
// Arguments:
// spacing = spacing between copies. (Default: 1.0)
@ -162,29 +162,29 @@ module xspread(spacing=undef, n=undef, l=undef, sp=undef)
// `$idx` is set to the index number of each child being copied.
//
// Examples:
// yspread(20) sphere(3);
// yspread(20, n=3) sphere(3);
// yspread(spacing=15, l=50) sphere(3);
// yspread(n=4, l=30, sp=[10,0,0]) sphere(3);
// ycopies(20) sphere(3);
// ycopies(20, n=3) sphere(3);
// ycopies(spacing=15, l=50) sphere(3);
// ycopies(n=4, l=30, sp=[10,0,0]) sphere(3);
// Example:
// yspread(10, n=3) {
// ycopies(10, n=3) {
// cube(size=[1,3,1],center=true);
// cube(size=[3,1,1],center=true);
// }
module yspread(spacing=undef, n=undef, l=undef, sp=undef)
module ycopies(spacing, n, l, sp)
{
spread(l=l*BACK, spacing=spacing*BACK, n=n, p1=sp) children();
line_of(l=l*BACK, spacing=spacing*BACK, n=n, p1=sp) children();
}
// Module: zspread()
// Module: zcopies()
//
// Description:
// Spreads out `n` copies of the children along a line on the Z axis.
//
// Usage:
// zspread(spacing, [n], [sp]) ...
// zspread(l, [n], [sp]) ...
// zcopies(spacing, [n], [sp]) ...
// zcopies(l, [n], [sp]) ...
//
// Arguments:
// spacing = spacing between copies. (Default: 1.0)
@ -197,18 +197,18 @@ module yspread(spacing=undef, n=undef, l=undef, sp=undef)
// `$idx` is set to the index number of each child being copied.
//
// Examples:
// zspread(20) sphere(3);
// zspread(20, n=3) sphere(3);
// zspread(spacing=15, l=50) sphere(3);
// zspread(n=4, l=30, sp=[10,0,0]) sphere(3);
// zcopies(20) sphere(3);
// zcopies(20, n=3) sphere(3);
// zcopies(spacing=15, l=50) sphere(3);
// zcopies(n=4, l=30, sp=[10,0,0]) sphere(3);
// Example:
// zspread(10, n=3) {
// zcopies(10, n=3) {
// cube(size=[1,3,1],center=true);
// cube(size=[3,1,1],center=true);
// }
module zspread(spacing=undef, n=undef, l=undef, sp=undef)
module zcopies(spacing, n, l, sp)
{
spread(l=l*UP, spacing=spacing*UP, n=n, p1=sp) children();
line_of(l=l*UP, spacing=spacing*UP, n=n, p1=sp) children();
}

View file

@ -65,7 +65,7 @@ module snap_lock(thick, snaplen=5, snapdiam=5, layerheight=0.2, foldangle=90, hi
back(snap_x) {
cube([snaplen, snapdiam, snapdiam/2+thick], anchor=BOT) {
attach(TOP) xcyl(l=snaplen, d=snapdiam, $fn=16);
attach(TOP) xspread(snaplen-snapdiam/4/3) xscale(0.333) sphere(d=snapdiam*0.8, $fn=12);
attach(TOP) xcopies(snaplen-snapdiam/4/3) xscale(0.333) sphere(d=snapdiam*0.8, $fn=12);
}
}
children();

View file

@ -41,14 +41,14 @@ module half_joiner_clear(h=20, w=10, a=30, clearance=0, overlap=0.01, anchor=CEN
attachable(anchor,spin,orient, size=[w, guide_width, h]) {
union() {
yspread(overlap, n=overlap>0? 2 : 1) {
ycopies(overlap, n=overlap>0? 2 : 1) {
difference() {
// Diamonds.
scale([w+clearance, dmnd_width/2, dmnd_height/2]) {
xrot(45) cube(size=[1,sqrt(2),sqrt(2)], center=true);
}
// Blunt point of tab.
yspread(guide_width+4) {
ycopies(guide_width+4) {
cube(size=[(w+clearance)*1.05, 4, h*0.99], center=true);
}
}
@ -96,7 +96,7 @@ module half_joiner(h=20, w=10, l=10, a=30, screwsize=undef, guides=true, anchor=
fwd(l/2) cube(size=[w, l, h], center=true);
// Clear diamond for tab
xspread(2*w*2/3) {
xcopies(2*w*2/3) {
half_joiner_clear(h=h+0.01, w=w, clearance=$slop*2, a=a);
}
}
@ -114,7 +114,7 @@ module half_joiner(h=20, w=10, l=10, a=30, screwsize=undef, guides=true, anchor=
// Guide ridges.
if (guides == true) {
xspread(w/3-$slop*2) {
xcopies(w/3-$slop*2) {
// Guide ridge.
fwd(0.05/2) {
scale([0.75, 1, 2]) yrot(45)
@ -285,7 +285,7 @@ module joiner_pair_clear(spacing=100, h=40, w=10, a=30, n=2, clearance=0, overla
guide_width = 2*(dmnd_height/2-guide_size)*tan(a);
attachable(anchor,spin,orient, size=[spacing+w, guide_width, h]) {
xspread(spacing, n=n) {
xcopies(spacing, n=n) {
joiner_clear(h=h, w=w, a=a, clearance=clearance, overlap=overlap);
}
children();
@ -490,11 +490,11 @@ module joiner_quad(spacing1=undef, spacing2=undef, xspacing=undef, yspacing=unde
// attach(TOP) dovetail("female", length=50, width=18, height=4, back_width=15, spin=90,$tags="remove");
// Example: A series of dovtails
// cuboid([50,30,10])
// attach(BACK) xspread(10,5) dovetail("male", length=10, width=7, height=4);
// attach(BACK) xcopies(10,5) dovetail("male", length=10, width=7, height=4);
// Example: Mating pin board for a right angle joint. Note that the anchor method and use of `spin` ensures that the joint works even with a taper.
// diff("remove")
// cuboid([50,30,10])
// position(TOP+BACK) xspread(10,5) dovetail("female", length=10, width=7, taper=4, height=4, $tags="remove",anchor=BOTTOM+FRONT,spin=180);
// position(TOP+BACK) xcopies(10,5) dovetail("female", length=10, width=7, taper=4, height=4, $tags="remove",anchor=BOTTOM+FRONT,spin=180);
module dovetail(gender, length, l, width, w, height, h, angle, slope, taper, back_width, chamfer, extra=0.01, r, radius, round=false, anchor=BOTTOM, spin=0, orient)
{
radius = get_radius(r1=radius,r2=r);
@ -679,7 +679,7 @@ function _pin_size(size) =
// Example: Pin in native orientation
// snap_pin("standard", anchor=CENTER, orient=UP, thickness = 1, $fn=40);
// Example: Pins oriented for printing
// xspread(spacing=10, n=4) snap_pin("standard", $fn=40);
// xcopies(spacing=10, n=4) snap_pin("standard", $fn=40);
module snap_pin(size,r,radius,d,diameter, l,length, nub_depth, snap, thickness, clearance=0.2, preload, pointed=true, anchor=FRONT, spin=0, orient=FRONT, center) {
preload_default = 0.2;
sizedat = _pin_size(size);

View file

@ -416,7 +416,7 @@ module rounding_mask(l=undef, r=undef, r1=undef, r2=undef, anchor=CENTER, spin=0
linear_extrude(height=l, convexity=4, center=true, scale=r1/r2) {
difference() {
square(2*r2, center=true);
xspread(2*r2) yspread(2*r2) circle(r=r2, $fn=sides);
xcopies(2*r2) ycopies(2*r2) circle(r=r2, $fn=sides);
}
}
}
@ -424,7 +424,7 @@ module rounding_mask(l=undef, r=undef, r1=undef, r2=undef, anchor=CENTER, spin=0
linear_extrude(height=l, convexity=4, center=true, scale=r2/r1) {
difference() {
square(2*r1, center=true);
xspread(2*r1) yspread(2*r1) circle(r=r1, $fn=sides);
xcopies(2*r1) ycopies(2*r1) circle(r=r1, $fn=sides);
}
}
}

View file

@ -140,8 +140,8 @@ module nema11_stepper(h=24, shaft=5, shaft_len=20, anchor=TOP, spin=0, orient=UP
color([0.4, 0.4, 0.4])
cuboid(size=[motor_width, motor_width, h], chamfer=2, edges=edges("Z"), anchor=TOP);
color("silver")
xspread(screw_spacing)
yspread(screw_spacing)
xcopies(screw_spacing)
ycopies(screw_spacing)
cyl(r=screw_size/2, h=screw_depth*2, $fn=max(12,segs(screw_size/2)));
}
color([0.6, 0.6, 0.6]) {
@ -205,8 +205,8 @@ module nema14_stepper(h=24, shaft=5, shaft_len=24, anchor=TOP, spin=0, orient=UP
color([0.4, 0.4, 0.4])
cuboid(size=[motor_width, motor_width, h], chamfer=2, edges=edges("Z"), anchor=TOP);
color("silver")
xspread(screw_spacing)
yspread(screw_spacing)
xcopies(screw_spacing)
ycopies(screw_spacing)
cyl(d=screw_size, h=screw_depth*2, $fn=max(12,segs(screw_size/2)));
}
color([0.6, 0.6, 0.6]) {
@ -270,8 +270,8 @@ module nema17_stepper(h=34, shaft=5, shaft_len=20, anchor=TOP, spin=0, orient=UP
color([0.4, 0.4, 0.4])
cuboid([motor_width, motor_width, h], chamfer=2, edges=edges("Z"), anchor=TOP);
color("silver")
xspread(screw_spacing)
yspread(screw_spacing)
xcopies(screw_spacing)
ycopies(screw_spacing)
cyl(d=screw_size, h=screw_depth*2, $fn=max(12,segs(screw_size/2)));
}
color([0.6, 0.6, 0.6]) {
@ -360,8 +360,8 @@ module nema23_stepper(h=50, shaft=6.35, shaft_len=25, anchor=TOP, spin=0, orient
cylinder(h=shaft_len, d=shaft, $fn=max(12,segs(shaft/2)));
}
color([0.4, 0.4, 0.4]) {
xspread(screw_spacing) {
yspread(screw_spacing) {
xcopies(screw_spacing) {
ycopies(screw_spacing) {
cyl(d=screw_size, h=screw_depth*3, $fn=max(12,segs(screw_size/2)));
down(screw_depth) cuboid([screw_inset, screw_inset, h], anchor=TOP);
}
@ -427,8 +427,8 @@ module nema34_stepper(h=75, shaft=12.7, shaft_len=32, anchor=TOP, spin=0, orient
cylinder(h=shaft_len, d=shaft, $fn=max(24,segs(shaft/2)));
}
color([0.4, 0.4, 0.4]) {
xspread(screw_spacing) {
yspread(screw_spacing) {
xcopies(screw_spacing) {
ycopies(screw_spacing) {
cylinder(d=screw_size, h=screw_depth*3, center=true, $fn=max(12,segs(screw_size/2)));
down(screw_depth) cube([screw_inset, screw_inset, h], anchor=TOP);
}
@ -484,11 +484,11 @@ module nema_mount_holes(size=17, depth=5, l=5, anchor=CENTER, spin=0, orient=UP)
s = [screw_spacing+screw_size, screw_spacing+screw_size+l, depth];
attachable(anchor,spin,orient, size=s, anchors=anchors) {
union() {
xspread(screw_spacing) {
yspread(screw_spacing) {
xcopies(screw_spacing) {
ycopies(screw_spacing) {
if (l>0) {
union() {
yspread(l) cyl(h=depth, d=screw_size, $fn=screwfn);
ycopies(l) cyl(h=depth, d=screw_size, $fn=screwfn);
cube([screw_size, l, depth], center=true);
}
} else {
@ -498,7 +498,7 @@ module nema_mount_holes(size=17, depth=5, l=5, anchor=CENTER, spin=0, orient=UP)
}
if (l>0) {
union () {
yspread(l) cyl(h=depth, d=plinth_diam, $fn=plinthfn);
ycopies(l) cyl(h=depth, d=plinth_diam, $fn=plinthfn);
cube([plinth_diam, l, depth], center=true);
}
} else {

View file

@ -728,7 +728,7 @@ module modulated_circle(r=40, sines=[10])
// slices = Number of slices along the extrusion to break the extrusion into. Useful for refining `twist` extrusions.
// Example(FlatSpin):
// extrude_from_to([0,0,0], [10,20,30], convexity=4, twist=360, scale=3.0, slices=40) {
// xspread(3) circle(3, $fn=32);
// xcopies(3) circle(3, $fn=32);
// }
module extrude_from_to(pt1, pt2, convexity=undef, twist=undef, scale=undef, slices=undef) {
rtp = xyz_to_spherical(pt2-pt1);

View file

@ -195,8 +195,8 @@ module cuboid(
difference() {
down(-rounding/2) cube([size.x-2*rounding, size.y-2*rounding, -rounding], center=true);
down(-rounding) {
yspread(size.y-2*rounding) xcyl(l=size.x-3*rounding, r=-rounding);
xspread(size.x-2*rounding) ycyl(l=size.y-3*rounding, r=-rounding);
ycopies(size.y-2*rounding) xcyl(l=size.x-3*rounding, r=-rounding);
xcopies(size.x-2*rounding) ycyl(l=size.y-3*rounding, r=-rounding);
}
}
}
@ -1278,7 +1278,7 @@ module slot(
r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=5);
sides = quantup(segs(max(r1, r2)), 4);
// TODO: implement orient and anchors.
hull() spread(p1=p1, p2=p2, l=l, n=2) cyl(l=h, r1=r1, r2=r2, center=true, $fn=sides);
hull() line_of(p1=p1, p2=p2, l=l, n=2) cyl(l=h, r1=r1, r2=r2, center=true, $fn=sides);
}

View file

@ -278,7 +278,7 @@ module trapezoidal_threaded_rod(
attachable(anchor,spin,orient, d=d, l=l) {
difference() {
polyhedron(points=poly_points, faces=poly_faces, convexity=threads*starts*2);
zspread(l+4*pitch*starts) cube([d+1, d+1, 4*pitch*starts], center=true);
zcopies(l+4*pitch*starts) cube([d+1, d+1, 4*pitch*starts], center=true);
if (bevel) cylinder_mask(d=d, l=l+0.01, chamfer=depth);
}
children();

View file

@ -8,7 +8,7 @@
//////////////////////////////////////////////////////////////////////
BOSL_VERSION = [2,0,223];
BOSL_VERSION = [2,0,224];
// Section: BOSL Library Version Functions

View file

@ -352,8 +352,8 @@ module sparse_strut(h=50, l=100, thick=4, maxang=30, strut=5, max_bridge=20, anc
square([h, l], center=true);
square([h-2*strut, l-2*strut], center=true);
}
yspread(ystep, n=yreps) {
xspread(zstep, n=zreps) {
ycopies(ystep, n=yreps) {
xcopies(zstep, n=zreps) {
skew(syx=tan(-ang)) square([(h-strut)/zreps, strut], center=true);
skew(syx=tan( ang)) square([(h-strut)/zreps, strut], center=true);
}
@ -420,8 +420,8 @@ module sparse_strut3d(h=50, l=100, w=50, thick=3, maxang=40, strut=3, max_bridge
intersection() {
union() {
ybridge = (l - (yreps+1) * strut) / yreps;
xspread(xoff) sparse_strut(h=h, l=l, thick=thick, maxang=maxang, strut=strut, max_bridge=ybridge/ceil(ybridge/max_bridge));
yspread(yoff) zrot(90) sparse_strut(h=h, l=w, thick=thick, maxang=maxang, strut=strut, max_bridge=max_bridge);
xcopies(xoff) sparse_strut(h=h, l=l, thick=thick, maxang=maxang, strut=strut, max_bridge=ybridge/ceil(ybridge/max_bridge));
ycopies(yoff) zrot(90) sparse_strut(h=h, l=w, thick=thick, maxang=maxang, strut=strut, max_bridge=max_bridge);
for(zs = [0:1:zreps-1]) {
for(xs = [0:1:xreps-1]) {
for(ys = [0:1:yreps-1]) {