mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2024-12-29 16:29:40 +00:00
distributors name normalization & bug fix
This commit is contained in:
parent
01c07dc892
commit
a7711edf0b
5 changed files with 295 additions and 249 deletions
|
@ -835,7 +835,7 @@ module tag_scope(scope){
|
|||
// right(20)
|
||||
// circle(5);
|
||||
// }
|
||||
// Example: Here is another example where two children are intersected using the native intersection operator, and then tagged with {{force_tag()}}. Note that because the children are at the save level, you don't need to use a tagged operator for their intersection.
|
||||
// Example: Here is another example where two children are intersected using the native intersection operator, and then tagged with {{force_tag()}}. Note that because the children are at the same level, you don't need to use a tagged operator for their intersection.
|
||||
// $fn=32;
|
||||
// diff()
|
||||
// cuboid(10){
|
||||
|
|
|
@ -46,113 +46,6 @@ module move_copies(a=[[0,0,0]])
|
|||
}
|
||||
|
||||
|
||||
// Function&Module: line_of()
|
||||
//
|
||||
// Usage: Place `n` copies at a given spacing along the line
|
||||
// line_of(spacing, [n], [p1=]) CHILDREN;
|
||||
// Usage: Place as many copies as will fit at a given spacing
|
||||
// line_of(spacing, [l=], [p1=]) CHILDREN;
|
||||
// Usage: Place `n` copies along the length of the line
|
||||
// line_of([n=], [l=], [p1=]) CHILDREN;
|
||||
// Usage: Place `n` copies along the line from `p1` to `p2`
|
||||
// line_of([n=], [p1=], [p2=]) CHILDREN;
|
||||
// Usage: Place copies at the given spacing, centered along the line from `p1` to `p2`
|
||||
// line_of([spacing], [p1=], [p2=]) CHILDREN;
|
||||
// Usage: As a function
|
||||
// pts = line_of([spacing], [n], [p1=]);
|
||||
// pts = line_of([spacing], [l=], [p1=]);
|
||||
// pts = line_of([n=], [l=], [p1=]);
|
||||
// pts = line_of([n=], [p1=], [p2=]);
|
||||
// pts = line_of([spacing], [p1=], [p2=]);
|
||||
// Description:
|
||||
// When called as a function, returns a list of points at evenly spaced positions along a line.
|
||||
// When called as a module, copies `children()` at one or more evenly spaced positions along a line.
|
||||
// By default, the line will be centered at the origin, unless the starting point `p1` is given.
|
||||
// The line will be pointed towards `RIGHT` (X+) unless otherwise given as a vector in `l`,
|
||||
// `spacing`, or `p1`/`p2`. The psotion of the copies is specified in one of several ways:
|
||||
// .
|
||||
// If You Know... | Then Use Something Like...
|
||||
// -------------------------------- | --------------------------------
|
||||
// Spacing distance, Count | `line_of(spacing=10, n=5) ...` or `line_of(10, n=5) ...`
|
||||
// Spacing vector, Count | `line_of(spacing=[10,5], n=5) ...` or `line_of([10,5], n=5) ...`
|
||||
// Spacing distance, Line length | `line_of(spacing=10, l=50) ...` or `line_of(10, l=50) ...`
|
||||
// Spacing distance, Line vector | `line_of(spacing=10, l=[50,30]) ...` or `line_of(10, l=[50,30]) ...`
|
||||
// Spacing vector, Line length | `line_of(spacing=[10,5], l=50) ...` or `line_of([10,5], l=50) ...`
|
||||
// Line length, Count | `line_of(l=50, n=5) ...`
|
||||
// Line vector, Count | `line_of(l=[50,40], n=5) ...`
|
||||
// Line endpoints, Count | `line_of(p1=[10,10], p2=[60,-10], n=5) ...`
|
||||
// Line endpoints, Spacing distance | `line_of(p1=[10,10], p2=[60,-10], spacing=10) ...`
|
||||
//
|
||||
// Arguments:
|
||||
// spacing = Either the scalar spacing distance along the X+ direction, or the vector giving both the direction and spacing distance between each set of copies.
|
||||
// n = Number of copies to distribute along the line. (Default: 2)
|
||||
// ---
|
||||
// l = Either the scalar length of the line, or a vector giving both the direction and length of the line.
|
||||
// p1 = If given, specifies the starting point of the line.
|
||||
// p2 = If given with `p1`, specifies the ending point of line, and indirectly calculates the line length.
|
||||
//
|
||||
// Side Effects:
|
||||
// `$pos` is set to the relative centerpoint of each child copy, and can be used to modify each child individually.
|
||||
// `$idx` is set to the index number of each child being copied.
|
||||
//
|
||||
// Examples:
|
||||
// line_of(10) sphere(d=1);
|
||||
// line_of(10, n=5) sphere(d=1);
|
||||
// line_of([10,5], n=5) sphere(d=1);
|
||||
// line_of(spacing=10, n=6) sphere(d=1);
|
||||
// line_of(spacing=[10,5], n=6) sphere(d=1);
|
||||
// line_of(spacing=10, l=50) sphere(d=1);
|
||||
// line_of(spacing=10, l=[50,30]) sphere(d=1);
|
||||
// line_of(spacing=[10,5], l=50) sphere(d=1);
|
||||
// line_of(l=50, n=4) sphere(d=1);
|
||||
// line_of(l=[50,-30], n=4) sphere(d=1);
|
||||
// Example(FlatSpin,VPD=133):
|
||||
// line_of(p1=[0,0,0], p2=[5,5,20], n=6) cube(size=[3,2,1],center=true);
|
||||
// Example(FlatSpin,VPD=133):
|
||||
// line_of(p1=[0,0,0], p2=[5,5,20], spacing=6) cube(size=[3,2,1],center=true);
|
||||
// Example: All children are copied to each position
|
||||
// line_of(l=20, n=3) {
|
||||
// cube(size=[1,3,1],center=true);
|
||||
// cube(size=[3,1,1],center=true);
|
||||
// }
|
||||
// Example(2D): The functional form of line_of() returns a list of points.
|
||||
// pts = line_of([10,5],n=5);
|
||||
// move_copies(pts) circle(d=2);
|
||||
module line_of(spacing, n, l, p1, p2)
|
||||
{
|
||||
req_children($children);
|
||||
pts = line_of(spacing=spacing, n=n, l=l, p1=p1, p2=p2);
|
||||
for (i=idx(pts)) {
|
||||
$idx = i;
|
||||
$pos = pts[i];
|
||||
translate($pos) children();
|
||||
}
|
||||
}
|
||||
|
||||
function line_of(spacing, n, l, p1, p2) =
|
||||
assert(is_undef(spacing) || is_finite(spacing) || is_vector(spacing))
|
||||
assert(is_undef(n) || is_finite(n))
|
||||
assert(is_undef(l) || is_finite(l) || is_vector(l))
|
||||
assert(is_undef(p1) || is_vector(p1))
|
||||
assert(is_undef(p2) || is_vector(p2))
|
||||
let(
|
||||
ll = !is_undef(l)? scalar_vec3(l, 0) :
|
||||
(!is_undef(spacing) && !is_undef(n))? ((n-1) * scalar_vec3(spacing, 0)) :
|
||||
(!is_undef(p1) && !is_undef(p2))? point3d(p2-p1) :
|
||||
undef,
|
||||
cnt = !is_undef(n)? n :
|
||||
(!is_undef(spacing) && !is_undef(ll))? floor(norm(ll) / norm(scalar_vec3(spacing, 0)) + 1.000001) :
|
||||
2,
|
||||
spc = cnt<=1? [0,0,0] :
|
||||
is_undef(spacing)? (ll/(cnt-1)) :
|
||||
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 `line_of()`.")
|
||||
let( spos = !is_undef(p1)? point3d(p1) : -(cnt-1)/2 * spc )
|
||||
[for (i=[0:1:cnt-1]) i * spc + spos];
|
||||
|
||||
|
||||
// Module: xcopies()
|
||||
//
|
||||
// Description:
|
||||
|
@ -192,12 +85,14 @@ module xcopies(spacing, n, l, sp)
|
|||
sp = is_finite(sp)? (sp*dir) : sp;
|
||||
if (is_vector(spacing)) {
|
||||
translate(default(sp,[0,0,0])) {
|
||||
for (x = spacing) {
|
||||
translate(x*dir) children();
|
||||
for (i = idx(spacing)) {
|
||||
$idx = i;
|
||||
$pos = spacing[i]*dir;
|
||||
translate($pos) children();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
line_of(
|
||||
line_copies(
|
||||
l=u_mul(l,dir),
|
||||
spacing=u_mul(spacing,dir),
|
||||
n=n, p1=sp
|
||||
|
@ -245,12 +140,14 @@ module ycopies(spacing, n, l, sp)
|
|||
sp = is_finite(sp)? (sp*dir) : sp;
|
||||
if (is_vector(spacing)) {
|
||||
translate(default(sp,[0,0,0])) {
|
||||
for (x = spacing) {
|
||||
translate(x*dir) children();
|
||||
for (i = idx(spacing)) {
|
||||
$idx = i;
|
||||
$pos = spacing[i]*dir;
|
||||
translate($pos) children();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
line_of(
|
||||
line_copies(
|
||||
l=u_mul(l,dir),
|
||||
spacing=u_mul(spacing,dir),
|
||||
n=n, p1=sp
|
||||
|
@ -312,12 +209,14 @@ module zcopies(spacing, n, l, sp)
|
|||
sp = is_finite(sp)? (sp*dir) : sp;
|
||||
if (is_vector(spacing)) {
|
||||
translate(default(sp,[0,0,0])) {
|
||||
for (x = spacing) {
|
||||
translate(x*dir) children();
|
||||
for (i = idx(spacing)) {
|
||||
$idx = i;
|
||||
$pos = spacing[i]*dir;
|
||||
translate($pos) children();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
line_of(
|
||||
line_copies(
|
||||
l=u_mul(l,dir),
|
||||
spacing=u_mul(spacing,dir),
|
||||
n=n, p1=sp
|
||||
|
@ -327,6 +226,121 @@ module zcopies(spacing, n, l, sp)
|
|||
|
||||
|
||||
|
||||
// Function&Module: line_copies()
|
||||
//
|
||||
// Usage: Place `n` copies at a given spacing along the line
|
||||
// line_copies(spacing, [n], [p1=]) CHILDREN;
|
||||
// Usage: Place as many copies as will fit at a given spacing
|
||||
// line_copies(spacing, [l=], [p1=]) CHILDREN;
|
||||
// Usage: Place `n` copies along the length of the line
|
||||
// line_copies([n=], [l=], [p1=]) CHILDREN;
|
||||
// Usage: Place `n` copies along the line from `p1` to `p2`
|
||||
// line_copies([n=], [p1=], [p2=]) CHILDREN;
|
||||
// Usage: Place copies at the given spacing, centered along the line from `p1` to `p2`
|
||||
// line_copies([spacing], [p1=], [p2=]) CHILDREN;
|
||||
// Usage: As a function
|
||||
// pts = line_copies([spacing], [n], [p1=]);
|
||||
// pts = line_copies([spacing], [l=], [p1=]);
|
||||
// pts = line_copies([n=], [l=], [p1=]);
|
||||
// pts = line_copies([n=], [p1=], [p2=]);
|
||||
// pts = line_copies([spacing], [p1=], [p2=]);
|
||||
// Description:
|
||||
// When called as a function, returns a list of points at evenly spaced positions along a line.
|
||||
// When called as a module, copies `children()` at one or more evenly spaced positions along a line.
|
||||
// By default, the line will be centered at the origin, unless the starting point `p1` is given.
|
||||
// The line will be pointed towards `RIGHT` (X+) unless otherwise given as a vector in `l`,
|
||||
// `spacing`, or `p1`/`p2`. The psotion of the copies is specified in one of several ways:
|
||||
// .
|
||||
// If You Know... | Then Use Something Like...
|
||||
// -------------------------------- | --------------------------------
|
||||
// Spacing distance, Count | `line_copies(spacing=10, n=5) ...` or `line_copies(10, n=5) ...`
|
||||
// Spacing vector, Count | `line_copies(spacing=[10,5], n=5) ...` or `line_copies([10,5], n=5) ...`
|
||||
// Spacing distance, Line length | `line_copies(spacing=10, l=50) ...` or `line_copies(10, l=50) ...`
|
||||
// Spacing distance, Line vector | `line_copies(spacing=10, l=[50,30]) ...` or `line_copies(10, l=[50,30]) ...`
|
||||
// Spacing vector, Line length | `line_copies(spacing=[10,5], l=50) ...` or `line_copies([10,5], l=50) ...`
|
||||
// Line length, Count | `line_copies(l=50, n=5) ...`
|
||||
// Line vector, Count | `line_copies(l=[50,40], n=5) ...`
|
||||
// Line endpoints, Count | `line_copies(p1=[10,10], p2=[60,-10], n=5) ...`
|
||||
// Line endpoints, Spacing distance | `line_copies(p1=[10,10], p2=[60,-10], spacing=10) ...`
|
||||
//
|
||||
// Arguments:
|
||||
// spacing = Either the scalar spacing distance along the X+ direction, or the vector giving both the direction and spacing distance between each set of copies.
|
||||
// n = Number of copies to distribute along the line. (Default: 2)
|
||||
// ---
|
||||
// l = Either the scalar length of the line, or a vector giving both the direction and length of the line.
|
||||
// p1 = If given, specifies the starting point of the line.
|
||||
// p2 = If given with `p1`, specifies the ending point of line, and indirectly calculates the line length.
|
||||
//
|
||||
// Side Effects:
|
||||
// `$pos` is set to the relative centerpoint of each child copy, and can be used to modify each child individually.
|
||||
// `$idx` is set to the index number of each child being copied.
|
||||
//
|
||||
// Examples:
|
||||
// line_copies(10) sphere(d=1);
|
||||
// line_copies(10, n=5) sphere(d=1);
|
||||
// line_copies([10,5], n=5) sphere(d=1);
|
||||
// line_copies(spacing=10, n=6) sphere(d=1);
|
||||
// line_copies(spacing=[10,5], n=6) sphere(d=1);
|
||||
// line_copies(spacing=10, l=50) sphere(d=1);
|
||||
// line_copies(spacing=10, l=[50,30]) sphere(d=1);
|
||||
// line_copies(spacing=[10,5], l=50) sphere(d=1);
|
||||
// line_copies(l=50, n=4) sphere(d=1);
|
||||
// line_copies(l=[50,-30], n=4) sphere(d=1);
|
||||
// Example(FlatSpin,VPD=133):
|
||||
// line_copies(p1=[0,0,0], p2=[5,5,20], n=6) cube(size=[3,2,1],center=true);
|
||||
// Example(FlatSpin,VPD=133):
|
||||
// line_copies(p1=[0,0,0], p2=[5,5,20], spacing=6) cube(size=[3,2,1],center=true);
|
||||
// Example: All children are copied to each position
|
||||
// line_copies(l=20, n=3) {
|
||||
// cube(size=[1,3,1],center=true);
|
||||
// cube(size=[3,1,1],center=true);
|
||||
// }
|
||||
// Example(2D): The functional form of line_copies() returns a list of points.
|
||||
// pts = line_copies([10,5],n=5);
|
||||
// move_copies(pts) circle(d=2);
|
||||
|
||||
module line_of(spacing, n, l, p1, p2) {
|
||||
deprecate("line_copies");
|
||||
line_copies(spacing, n, l, p1, p2);
|
||||
}
|
||||
|
||||
module line_copies(spacing, n, l, p1, p2)
|
||||
{
|
||||
req_children($children);
|
||||
pts = line_copies(spacing=spacing, n=n, l=l, p1=p1, p2=p2);
|
||||
for (i=idx(pts)) {
|
||||
$idx = i;
|
||||
$pos = pts[i];
|
||||
translate($pos) children();
|
||||
}
|
||||
}
|
||||
|
||||
function line_copies(spacing, n, l, p1, p2) =
|
||||
assert(is_undef(spacing) || is_finite(spacing) || is_vector(spacing))
|
||||
assert(is_undef(n) || is_finite(n))
|
||||
assert(is_undef(l) || is_finite(l) || is_vector(l))
|
||||
assert(is_undef(p1) || is_vector(p1))
|
||||
assert(is_undef(p2) || is_vector(p2))
|
||||
let(
|
||||
ll = !is_undef(l)? scalar_vec3(l, 0) :
|
||||
(!is_undef(spacing) && !is_undef(n))? ((n-1) * scalar_vec3(spacing, 0)) :
|
||||
(!is_undef(p1) && !is_undef(p2))? point3d(p2-p1) :
|
||||
undef,
|
||||
cnt = !is_undef(n)? n :
|
||||
(!is_undef(spacing) && !is_undef(ll))? floor(norm(ll) / norm(scalar_vec3(spacing, 0)) + 1.000001) :
|
||||
2,
|
||||
spc = cnt<=1? [0,0,0] :
|
||||
is_undef(spacing)? (ll/(cnt-1)) :
|
||||
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 `line_copies()`.")
|
||||
let( spos = !is_undef(p1)? point3d(p1) : -(cnt-1)/2 * spc )
|
||||
[for (i=[0:1:cnt-1]) i * spc + spos];
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Module: grid_copies()
|
||||
|
@ -743,14 +757,14 @@ module zrot_copies(rots=[], cp=[0,0,0], n, sa=0, r, d, subrot=true)
|
|||
}
|
||||
|
||||
|
||||
// Module: arc_of()
|
||||
// Module: arc_copies()
|
||||
//
|
||||
// Description:
|
||||
// Evenly distributes n duplicate children around an ovoid arc on the XY plane.
|
||||
//
|
||||
// Usage:
|
||||
// arc_of(n, r|d=, [sa=], [ea=], [rot=]) CHILDREN;
|
||||
// arc_of(n, rx=|dx=, ry=|dy=, [sa=], [ea=], [rot=]) CHILDREN;
|
||||
// arc_copies(n, r|d=, [sa=], [ea=], [rot=]) CHILDREN;
|
||||
// arc_copies(n, rx=|dx=, ry=|dy=, [sa=], [ea=], [rot=]) CHILDREN;
|
||||
//
|
||||
// Arguments:
|
||||
// n = number of copies to distribute around the circle. (Default: 6)
|
||||
|
@ -772,24 +786,30 @@ module zrot_copies(rots=[], cp=[0,0,0], n, sa=0, r, d, subrot=true)
|
|||
//
|
||||
// Example:
|
||||
// #cube(size=[10,3,3],center=true);
|
||||
// arc_of(d=40, n=5) cube(size=[10,3,3],center=true);
|
||||
// arc_copies(d=40, n=5) cube(size=[10,3,3],center=true);
|
||||
//
|
||||
// Example:
|
||||
// #cube(size=[10,3,3],center=true);
|
||||
// arc_of(d=40, n=5, sa=45, ea=225) cube(size=[10,3,3],center=true);
|
||||
// arc_copies(d=40, n=5, sa=45, ea=225) cube(size=[10,3,3],center=true);
|
||||
//
|
||||
// Example:
|
||||
// #cube(size=[10,3,3],center=true);
|
||||
// arc_of(r=15, n=8, rot=false) cube(size=[10,3,3],center=true);
|
||||
// arc_copies(r=15, n=8, rot=false) cube(size=[10,3,3],center=true);
|
||||
//
|
||||
// Example:
|
||||
// #cube(size=[10,3,3],center=true);
|
||||
// arc_of(rx=20, ry=10, n=8) cube(size=[10,3,3],center=true);
|
||||
// arc_copies(rx=20, ry=10, n=8) cube(size=[10,3,3],center=true);
|
||||
// Example(2D): Using `$idx` to alternate shapes
|
||||
// arc_of(r=50, n=19, sa=0, ea=180)
|
||||
// arc_copies(r=50, n=19, sa=0, ea=180)
|
||||
// if ($idx % 2 == 0) rect(6);
|
||||
// else circle(d=6);
|
||||
module arc_of(
|
||||
|
||||
function arc_copies(n=6,r,rx,ry,d,dx,dy,sa=0,ea=360,rot=true) = no_function("arc_copies");
|
||||
module arc_of(n=6,r,rx,ry,d,dx,dy,sa=0,ea=360,rot=true){
|
||||
deprecate("arc_copies");
|
||||
arc_copies(n,r,rx,ry,d,dx,dy,sa,ea,rot);
|
||||
}
|
||||
module arc_copies(
|
||||
n=6,
|
||||
r=undef,
|
||||
rx=undef, ry=undef,
|
||||
|
@ -1046,61 +1066,6 @@ module path_copies(path, n, spacing, sp=undef, dist, rotate_children=true, dist,
|
|||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
// Module: mirror_copy()
|
||||
//
|
||||
// Description:
|
||||
// Makes a copy of the children, mirrored across the given plane.
|
||||
//
|
||||
// Usage:
|
||||
// mirror_copy(v, [cp], [offset]) CHILDREN;
|
||||
//
|
||||
// Arguments:
|
||||
// v = The normal vector of the plane to mirror across.
|
||||
// offset = distance to offset away from the plane.
|
||||
// cp = A point that lies on the mirroring plane.
|
||||
//
|
||||
// Side Effects:
|
||||
// `$orig` is true for the original instance of children. False for the copy.
|
||||
// `$idx` is set to the index value of each copy.
|
||||
//
|
||||
// Example:
|
||||
// mirror_copy([1,-1,0]) zrot(-45) yrot(90) cylinder(d1=10, d2=0, h=20);
|
||||
// color("blue",0.25) zrot(-45) cube([0.01,15,15], center=true);
|
||||
//
|
||||
// Example:
|
||||
// mirror_copy([1,1,0], offset=5) rot(a=90,v=[-1,1,0]) cylinder(d1=10, d2=0, h=20);
|
||||
// color("blue",0.25) zrot(45) cube([0.01,15,15], center=true);
|
||||
//
|
||||
// Example:
|
||||
// mirror_copy(UP+BACK, cp=[0,-5,-5]) rot(from=UP, to=BACK+UP) cylinder(d1=10, d2=0, h=20);
|
||||
// color("blue",0.25) translate([0,-5,-5]) rot(from=UP, to=BACK+UP) cube([15,15,0.01], center=true);
|
||||
module mirror_copy(v=[0,0,1], offset=0, cp)
|
||||
{
|
||||
req_children($children);
|
||||
cp = is_vector(v,4)? plane_normal(v) * v[3] :
|
||||
is_vector(cp)? cp :
|
||||
is_num(cp)? cp*unit(v) :
|
||||
[0,0,0];
|
||||
nv = is_vector(v,4)? plane_normal(v) : unit(v);
|
||||
off = nv*offset;
|
||||
if (cp == [0,0,0]) {
|
||||
translate(off) {
|
||||
$orig = true;
|
||||
$idx = 0;
|
||||
children();
|
||||
}
|
||||
mirror(nv) translate(off) {
|
||||
$orig = false;
|
||||
$idx = 1;
|
||||
children();
|
||||
}
|
||||
} else {
|
||||
translate(off) children();
|
||||
translate(cp) mirror(nv) translate(-cp) translate(off) children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Module: xflip_copy()
|
||||
//
|
||||
// Description:
|
||||
|
@ -1202,56 +1167,67 @@ module zflip_copy(offset=0, z=0)
|
|||
mirror_copy(v=[0,0,1], offset=offset, cp=[0,0,z]) children();
|
||||
}
|
||||
|
||||
////////////////////
|
||||
// Section: Distributing children individually along a line
|
||||
///////////////////
|
||||
|
||||
// Module: distribute()
|
||||
// Module: mirror_copy()
|
||||
//
|
||||
// Description:
|
||||
// Spreads out the children individually along the direction `dir`.
|
||||
// Every child is placed at a different position, in order.
|
||||
// This is useful for laying out groups of disparate objects
|
||||
// where you only really care about the spacing between them.
|
||||
// Makes a copy of the children, mirrored across the given plane.
|
||||
//
|
||||
// Usage:
|
||||
// distribute(spacing, sizes, dir) CHILDREN;
|
||||
// distribute(l=, [sizes=], [dir=]) CHILDREN;
|
||||
// mirror_copy(v, [cp], [offset]) CHILDREN;
|
||||
//
|
||||
// Arguments:
|
||||
// spacing = Spacing to add between each child. (Default: 10.0)
|
||||
// sizes = Array containing how much space each child will need.
|
||||
// dir = Vector direction to distribute copies along. Default: RIGHT
|
||||
// l = Length to distribute copies along.
|
||||
// v = The normal vector of the plane to mirror across.
|
||||
// offset = distance to offset away from the plane.
|
||||
// cp = A point that lies on the mirroring plane.
|
||||
//
|
||||
// Side Effects:
|
||||
// `$pos` is set to the relative centerpoint of each child copy, and can be used to modify each child individually.
|
||||
// `$idx` is set to the index number of each child being copied.
|
||||
// `$orig` is true for the original instance of children. False for the copy.
|
||||
// `$idx` is set to the index value of each copy.
|
||||
//
|
||||
// Example:
|
||||
// distribute(sizes=[100, 30, 50], dir=UP) {
|
||||
// sphere(r=50);
|
||||
// cube([10,20,30], center=true);
|
||||
// cylinder(d=30, h=50, center=true);
|
||||
// }
|
||||
module distribute(spacing=undef, sizes=undef, dir=RIGHT, l=undef)
|
||||
// mirror_copy([1,-1,0]) zrot(-45) yrot(90) cylinder(d1=10, d2=0, h=20);
|
||||
// color("blue",0.25) zrot(-45) cube([0.01,15,15], center=true);
|
||||
//
|
||||
// Example:
|
||||
// mirror_copy([1,1,0], offset=5) rot(a=90,v=[-1,1,0]) cylinder(d1=10, d2=0, h=20);
|
||||
// color("blue",0.25) zrot(45) cube([0.01,15,15], center=true);
|
||||
//
|
||||
// Example:
|
||||
// mirror_copy(UP+BACK, cp=[0,-5,-5]) rot(from=UP, to=BACK+UP) cylinder(d1=10, d2=0, h=20);
|
||||
// color("blue",0.25) translate([0,-5,-5]) rot(from=UP, to=BACK+UP) cube([15,15,0.01], center=true);
|
||||
module mirror_copy(v=[0,0,1], offset=0, cp)
|
||||
{
|
||||
req_children($children);
|
||||
gaps = ($children < 2)? [0] :
|
||||
!is_undef(sizes)? [for (i=[0:1:$children-2]) sizes[i]/2 + sizes[i+1]/2] :
|
||||
[for (i=[0:1:$children-2]) 0];
|
||||
spc = !is_undef(l)? ((l - sum(gaps)) / ($children-1)) : default(spacing, 10);
|
||||
gaps2 = [for (gap = gaps) gap+spc];
|
||||
spos = dir * -sum(gaps2)/2;
|
||||
spacings = cumsum([0, each gaps2]);
|
||||
for (i=[0:1:$children-1]) {
|
||||
$pos = spos + spacings[i] * dir;
|
||||
$idx = i;
|
||||
translate($pos) children(i);
|
||||
cp = is_vector(v,4)? plane_normal(v) * v[3] :
|
||||
is_vector(cp)? cp :
|
||||
is_num(cp)? cp*unit(v) :
|
||||
[0,0,0];
|
||||
nv = is_vector(v,4)? plane_normal(v) : unit(v);
|
||||
off = nv*offset;
|
||||
if (cp == [0,0,0]) {
|
||||
translate(off) {
|
||||
$orig = true;
|
||||
$idx = 0;
|
||||
children();
|
||||
}
|
||||
mirror(nv) translate(off) {
|
||||
$orig = false;
|
||||
$idx = 1;
|
||||
children();
|
||||
}
|
||||
} else {
|
||||
translate(off) children();
|
||||
translate(cp) mirror(nv) translate(-cp) translate(off) children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////
|
||||
// Section: Distributing children individually along a line
|
||||
///////////////////
|
||||
|
||||
// Module: xdistribute()
|
||||
//
|
||||
// Description:
|
||||
|
@ -1391,5 +1367,53 @@ module zdistribute(spacing=10, sizes=undef, l=undef)
|
|||
|
||||
|
||||
|
||||
// Module: distribute()
|
||||
//
|
||||
// Description:
|
||||
// Spreads out the children individually along the direction `dir`.
|
||||
// Every child is placed at a different position, in order.
|
||||
// This is useful for laying out groups of disparate objects
|
||||
// where you only really care about the spacing between them.
|
||||
//
|
||||
// Usage:
|
||||
// distribute(spacing, sizes, dir) CHILDREN;
|
||||
// distribute(l=, [sizes=], [dir=]) CHILDREN;
|
||||
//
|
||||
// Arguments:
|
||||
// spacing = Spacing to add between each child. (Default: 10.0)
|
||||
// sizes = Array containing how much space each child will need.
|
||||
// dir = Vector direction to distribute copies along. Default: RIGHT
|
||||
// l = Length to distribute copies along.
|
||||
//
|
||||
// Side Effects:
|
||||
// `$pos` is set to the relative centerpoint of each child copy, and can be used to modify each child individually.
|
||||
// `$idx` is set to the index number of each child being copied.
|
||||
//
|
||||
// Example:
|
||||
// distribute(sizes=[100, 30, 50], dir=UP) {
|
||||
// sphere(r=50);
|
||||
// cube([10,20,30], center=true);
|
||||
// cylinder(d=30, h=50, center=true);
|
||||
// }
|
||||
module distribute(spacing=undef, sizes=undef, dir=RIGHT, l=undef)
|
||||
{
|
||||
req_children($children);
|
||||
gaps = ($children < 2)? [0] :
|
||||
!is_undef(sizes)? [for (i=[0:1:$children-2]) sizes[i]/2 + sizes[i+1]/2] :
|
||||
[for (i=[0:1:$children-2]) 0];
|
||||
spc = !is_undef(l)? ((l - sum(gaps)) / ($children-1)) : default(spacing, 10);
|
||||
gaps2 = [for (gap = gaps) gap+spc];
|
||||
spos = dir * -sum(gaps2)/2;
|
||||
spacings = cumsum([0, each gaps2]);
|
||||
for (i=[0:1:$children-1]) {
|
||||
$pos = spos + spacings[i] * dir;
|
||||
$idx = i;
|
||||
translate($pos) children(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
|
|
@ -1595,9 +1595,9 @@ function reuleaux_polygon(n=3, r, d, anchor=CENTER, spin=0) =
|
|||
// text("Foobar", size=12, font="Helvetica");
|
||||
// text("Foobar", anchor=CENTER);
|
||||
// text("Foobar", anchor=str("baseline",CENTER));
|
||||
// Example: Using line_of() distributor
|
||||
// Example: Using line_copies() distributor
|
||||
// txt = "This is the string.";
|
||||
// line_of(spacing=[10,-5],n=len(txt))
|
||||
// line_copies(spacing=[10,-5],n=len(txt))
|
||||
// text(txt[$idx], size=10, anchor=CENTER);
|
||||
// Example: Using arc_of() distributor
|
||||
// txt = "This is the string";
|
||||
|
|
|
@ -403,10 +403,11 @@ cylinder(h=100, d=100, center=true)
|
|||
## Tagged Operations
|
||||
BOSL2 introduces the concept of tags. Tags are names that can be given to attachables, so that
|
||||
you can refer to them when performing `diff()`, `intersect()`, and `conv_hull()` operations.
|
||||
Each object can have no more than one tag at a time.
|
||||
|
||||
### `diff(remove, <keep>)`
|
||||
### `diff([remove], [keep])`
|
||||
The `diff()` operator is used to difference away all shapes marked with the tag(s) given to
|
||||
`remove=`, from the other shapes.
|
||||
`remove`, from the other shapes.
|
||||
|
||||
For example, to difference away a child cylinder from the middle of a parent cube, you can
|
||||
do this:
|
||||
|
@ -445,7 +446,7 @@ tag("keep")cube(100, center=true)
|
|||
```
|
||||
|
||||
|
||||
If you need to mark multiple children with a tag, you can use the `tag()` module.
|
||||
You can of course apply `tag()` to several children.
|
||||
|
||||
```openscad-3D
|
||||
include <BOSL2/std.scad>
|
||||
|
@ -458,14 +459,28 @@ cube(100, center=true)
|
|||
}
|
||||
```
|
||||
|
||||
Many of the modules that use tags have default values for their tags. For diff the default
|
||||
remove tag is "remove" and the default keep tag is "keep". In this example we rely on the
|
||||
default values:
|
||||
|
||||
```openscad-3D
|
||||
include <BOSL2/std.scad>
|
||||
diff()
|
||||
sphere(d=100) {
|
||||
tag("keep")xcyl(d=40, l=120);
|
||||
tag("remove")cuboid([40,120,100]);
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
The parent object can be differenced away from other shapes. Tags are inherited by children,
|
||||
though, so you will need to set the tags of the children as well as the parent.
|
||||
|
||||
```openscad-3D
|
||||
include <BOSL2/std.scad>
|
||||
diff("hole")
|
||||
cube([20,11,45], center=true, $tag="hole")
|
||||
cube([40,10,90], center=true, $tag="body");
|
||||
tag("hole")cube([20,11,45], center=true)
|
||||
tag("body")cube([40,10,90], center=true);
|
||||
```
|
||||
|
||||
Tags (and therefore tag-based operations like `diff()`) only work correctly with attachable
|
||||
|
@ -488,55 +503,62 @@ cuboid(50)
|
|||
square(10,center=true);
|
||||
```
|
||||
|
||||
### `intersect(a, <b>, <keep>)`
|
||||
### `intersect([intersect], [keep])`
|
||||
|
||||
To perform an intersection of attachables, you can use the `intersect()` module. If given one
|
||||
argument to `a=`, the parent and all children *not* tagged with that will be intersected by
|
||||
everything that *is* tagged with it.
|
||||
To perform an intersection of attachables, you can use the `intersect()` module. This is
|
||||
specifically intended to address the situation where you want intersections involving a parent
|
||||
and a child, something that is impossible with the native `intersection()` module. This module
|
||||
treats the children in three groups: objects matching the `intersect` tags, objects matching
|
||||
the tags listed in `keep` and the remaining objects that don't match any listed tags. The
|
||||
intersection is computed between the union of the `intersect` tagged objects and the union of
|
||||
the objects that don't match any listed tags. Finally the objects lsited in `keep` are union
|
||||
ed with the result.
|
||||
|
||||
In this example the parent is intersected with a conical bounding shape.
|
||||
|
||||
```openscad-3D
|
||||
include <BOSL2/std.scad>
|
||||
intersect("bounds")
|
||||
cube(100, center=true)
|
||||
cylinder(h=100, d1=120, d2=95, center=true, $fn=72, $tag="bounds");
|
||||
tag("bounds") cylinder(h=100, d1=120, d2=95, center=true, $fn=72);
|
||||
```
|
||||
|
||||
If given both the `a=` and `b=` arguments, then shapes marked with tags given to `a=` will be
|
||||
intersected with shapes marked with tags given to `b=`, then unioned with all other shapes.
|
||||
In this example the child objects are intersected with the bounding box parent.
|
||||
|
||||
```openscad-3D
|
||||
include <BOSL2/std.scad>
|
||||
intersect("pole", "cap")
|
||||
intersect("pole cap")
|
||||
cube(100, center=true)
|
||||
attach([TOP,RIGHT]) {
|
||||
cube([40,40,80],center=true, $tag="pole");
|
||||
sphere(d=40*sqrt(2), $tag="cap");
|
||||
tag("pole")cube([40,40,80],center=true);
|
||||
tag("cap")sphere(d=40*sqrt(2));
|
||||
}
|
||||
```
|
||||
|
||||
If the `keep=` argument is given, anything marked with tags passed to it will be unioned with
|
||||
the result of the union:
|
||||
The default `intersect` tag is "intersect" and the default `keep` tag is "keep". Here is an
|
||||
example where "keep" is used to keep the pole from being removed by the intersection.
|
||||
|
||||
```openscad-3D
|
||||
include <BOSL2/std.scad>
|
||||
intersect("bounds", keep="pole")
|
||||
intersect()
|
||||
cube(100, center=true) {
|
||||
cylinder(h=100, d1=120, d2=95, center=true, $fn=72, $tag="bounds");
|
||||
zrot(45) xcyl(h=140, d=20, $fn=36, $tag="pole");
|
||||
tag("intersect")cylinder(h=100, d1=120, d2=95, center=true, $fn=72);
|
||||
tag("keep")zrot(45) xcyl(h=140, d=20, $fn=36);
|
||||
}
|
||||
```
|
||||
|
||||
### `conv_hull(keep)`
|
||||
You can use the `conv_hull()` module to hull shapes together the
|
||||
shapes not marked with the keep tags, before unioning the keep shapes
|
||||
into the final result.
|
||||
### `conv_hull([keep])`
|
||||
You can use the `conv_hull()` module to hull shapes together. Objects
|
||||
marked with the keep tags are excluded from the hull and unioned into the final result.
|
||||
The default keep tag is "keep".
|
||||
|
||||
|
||||
```openscad-3D
|
||||
include <BOSL2/std.scad>
|
||||
conv_hull("pole")
|
||||
cube(50, center=true, $tag="hull") {
|
||||
conv_hull()
|
||||
cube(50, center=true) {
|
||||
cyl(h=100, d=20);
|
||||
xcyl(h=100, d=20, $tag="pole");
|
||||
tag("keep")xcyl(h=100, d=20);
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
@ -13,11 +13,11 @@ Transforms | Related Distributors
|
|||
`left()`, `right()` | `xcopies()`
|
||||
`fwd()`, `back()` | `ycopies()`
|
||||
`down()`, `up()` | `zcopies()`
|
||||
`move()`, `translate()` | `move_copies()`, `line_of()`, `grid_copies()`
|
||||
`move()`, `translate()` | `move_copies()`, `line_copies()`, `grid_copies()`
|
||||
`xrot()` | `xrot_copies()`
|
||||
`yrot()` | `yrot_copies()`
|
||||
`zrot()` | `zrot_copies()`
|
||||
`rot()`, `rotate()` | `rot_copies()`, `arc_of()`
|
||||
`rot()`, `rotate()` | `rot_copies()`, `arc_copies()`
|
||||
`xflip()` | `xflip_copy()`
|
||||
`yflip()` | `yflip_copy()`
|
||||
`zflip()` | `zflip_copy()`
|
||||
|
@ -106,24 +106,24 @@ zcopies(20, n=5, sp=[0,0,0]) sphere(d=10);
|
|||
```
|
||||
|
||||
If you need to distribute copies along an arbitrary line, you can use the
|
||||
`line_of()` command. You can give both the direction vector and the spacing
|
||||
`line_copies()` command. You can give both the direction vector and the spacing
|
||||
of the line of copies with the `spacing=` argument:
|
||||
```openscad-3D
|
||||
include <BOSL2/std.scad>
|
||||
line_of(spacing=(BACK+RIGHT)*20, n=5) sphere(d=10);
|
||||
line_copies(spacing=(BACK+RIGHT)*20, n=5) sphere(d=10);
|
||||
```
|
||||
|
||||
With the `p1=` argument, you can specify the starting point of the line:
|
||||
```openscad-3D
|
||||
include <BOSL2/std.scad>
|
||||
line_of(spacing=(BACK+RIGHT)*20, n=5, p1=[0,0,0]) sphere(d=10);
|
||||
line_copies(spacing=(BACK+RIGHT)*20, n=5, p1=[0,0,0]) sphere(d=10);
|
||||
```
|
||||
|
||||
If you give both `p1=` and `p2=`, you can nail down both the start and
|
||||
endpoints of the line of copies:
|
||||
```openscad-2D
|
||||
include <BOSL2/std.scad>
|
||||
line_of(p1=[0,100,0], p2=[100,0,0], n=4)
|
||||
line_copies(p1=[0,100,0], p2=[100,0,0], n=4)
|
||||
sphere(d=10);
|
||||
```
|
||||
|
||||
|
|
Loading…
Reference in a new issue