mirror of
https://github.com/revarbat/BOSL2.git
synced 2025-01-16 13:50:23 +01:00
Multiple bugfixes for and argument re-arrangement. Added vfloor() and vceil().
This commit is contained in:
parent
7292250162
commit
6b4fb3184c
@ -400,19 +400,17 @@ module zdistribute(spacing=10, sizes=undef, l=undef)
|
||||
// Makes a square or hexagonal grid of copies of children.
|
||||
//
|
||||
// Usage:
|
||||
// grid2d(size, spacing, [stagger], [scale], [in_poly]) ...
|
||||
// grid2d(size, cols, rows, [stagger], [scale], [in_poly]) ...
|
||||
// grid2d(spacing, cols, rows, [stagger], [scale], [in_poly]) ...
|
||||
// grid2d(spacing, size, [stagger], [scale], [in_poly]) ...
|
||||
// grid2d(n, size, [stagger], [scale], [in_poly]) ...
|
||||
// grid2d(spacing, n, [stagger], [scale], [in_poly]) ...
|
||||
// grid2d(spacing, in_poly, [stagger], [scale]) ...
|
||||
// grid2d(cols, rows, in_poly, [stagger], [scale]) ...
|
||||
// grid2d(n, in_poly, [stagger], [scale]) ...
|
||||
//
|
||||
// Arguments:
|
||||
// size = The [X,Y] size to spread the copies over.
|
||||
// spacing = Distance between copies in [X,Y] or scalar distance.
|
||||
// cols = How many columns of copies to make. If staggered, count both staggered and unstaggered columns.
|
||||
// rows = How many rows of copies to make. If staggered, count both staggered and unstaggered rows.
|
||||
// n = How many columns and rows of copies to make. Can be given as `[COLS,ROWS]`, or just as a scalar that specifies both. If staggered, count both staggered and unstaggered columns and rows. Default: 2 (3 if staggered)
|
||||
// stagger = If true, make a staggered (hexagonal) grid. If false, make square grid. If `"alt"`, makes alternate staggered pattern. Default: false
|
||||
// scale = [X,Y] scaling factors to reshape grid.
|
||||
// in_poly = If given a list of polygon points, only creates copies whose center would be inside the polygon. Polygon can be concave and/or self crossing.
|
||||
//
|
||||
// Side Effects:
|
||||
@ -421,10 +419,11 @@ module zdistribute(spacing=10, sizes=undef, l=undef)
|
||||
// `$row` is set to the integer row number for each child.
|
||||
//
|
||||
// Examples:
|
||||
// grid2d(size=50, spacing=10, stagger=false) cylinder(d=10, h=1);
|
||||
// grid2d(spacing=10, rows=7, cols=13, stagger=true) cylinder(d=6, h=5);
|
||||
// grid2d(spacing=10, rows=7, cols=13, stagger="alt") cylinder(d=6, h=5);
|
||||
// grid2d(size=50, rows=11, cols=11, stagger=true) cylinder(d=5, h=1);
|
||||
// grid2d(size=50, spacing=10) cylinder(d=10, h=1);
|
||||
// grid2d(size=50, spacing=[10,15]) cylinder(d=10, h=1);
|
||||
// grid2d(spacing=10, n=[13,7], stagger=true) cylinder(d=6, h=5);
|
||||
// grid2d(spacing=10, n=[13,7], stagger="alt") cylinder(d=6, h=5);
|
||||
// grid2d(size=50, n=11, stagger=true) cylinder(d=5, h=1);
|
||||
//
|
||||
// Example:
|
||||
// poly = [[-25,-25], [25,25], [-25,25], [25,-25]];
|
||||
@ -433,7 +432,7 @@ module zdistribute(spacing=10, sizes=undef, l=undef)
|
||||
// %polygon(poly);
|
||||
//
|
||||
// Example: Using `$row` and `$col`
|
||||
// grid2d(spacing=[8,8], cols=8, rows=8)
|
||||
// grid2d(spacing=8], n=8)
|
||||
// color(($row+$col)%2?"black":"red")
|
||||
// cube([8,8,0.01], center=false);
|
||||
//
|
||||
@ -449,60 +448,62 @@ module zdistribute(spacing=10, sizes=undef, l=undef)
|
||||
// zrot(180/6)
|
||||
// cylinder(h=20, d=10/cos(180/6)+0.01, $fn=6);
|
||||
// }
|
||||
module grid2d(size=undef, spacing=undef, cols=undef, rows=undef, stagger=false, scale=[1,1,1], in_poly=undef)
|
||||
module grid2d(spacing, n, size, stagger=false, in_poly=undef)
|
||||
{
|
||||
assert(in_list(stagger, [false, true, "alt"]));
|
||||
scl = vmul(scalar_vec3(scale, 1), (stagger!=false? [0.5, sin(60), 1] : [1,1,1]));
|
||||
if (!is_undef(size)) {
|
||||
siz = scalar_vec3(size);
|
||||
if (!is_undef(spacing)) {
|
||||
spc = vmul(scalar_vec3(spacing), scl);
|
||||
maxcols = ceil(siz.x/spc.x);
|
||||
maxrows = ceil(siz.y/spc.y);
|
||||
grid2d(spacing=spacing, cols=maxcols, rows=maxrows, stagger=stagger, scale=scale, in_poly=in_poly) children();
|
||||
} else {
|
||||
spc = [siz.x/cols, siz.y/rows];
|
||||
grid2d(spacing=spc, cols=cols, rows=rows, stagger=stagger, scale=scale, in_poly=in_poly) children();
|
||||
bounds = is_undef(in_poly)? undef : pointlist_bounds(in_poly);
|
||||
size = is_num(size)? [size, size] :
|
||||
is_vector(size)? assert(len(size)==2) size :
|
||||
bounds!=undef? [
|
||||
for (i=[0:1]) 2*max(abs(bounds[0][i]),bounds[1][i])
|
||||
] : undef;
|
||||
spacing = is_num(spacing)? (
|
||||
stagger!=false? polar_to_xy(spacing,60) :
|
||||
[spacing,spacing]
|
||||
) :
|
||||
is_vector(spacing)? assert(len(spacing)==2) spacing :
|
||||
size!=undef? (
|
||||
is_num(n)? vdiv(size,(n-1)*[1,1]) :
|
||||
is_vector(n)? assert(len(n)==2) vdiv(size,n-[1,1]) :
|
||||
vdiv(size,(stagger==false? [1,1] : [2,2]))
|
||||
) :
|
||||
undef;
|
||||
n = is_num(n)? [n,n] :
|
||||
is_vector(n)? assert(len(n)==2) n :
|
||||
size!=undef && spacing!=undef? vfloor(vdiv(size,spacing))+[1,1] :
|
||||
[2,2];
|
||||
offset = vmul(spacing, n-[1,1])/2;
|
||||
if (stagger == false) {
|
||||
for (row = [0:1:n.y-1]) {
|
||||
for (col = [0:1:n.x-1]) {
|
||||
pos = vmul([col,row],spacing) - offset;
|
||||
if (is_undef(in_poly) || point_in_polygon(pos, in_poly)>=0) {
|
||||
$col = col;
|
||||
$row = row;
|
||||
$pos = pos;
|
||||
translate(pos) children();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
spc = is_list(spacing)? point3d(spacing) : vmul(scalar_vec3(spacing), scl);
|
||||
bounds = !is_undef(in_poly)? pointlist_bounds(in_poly) : undef;
|
||||
bnds = !is_undef(bounds)? [for (a=[0,1]) 2*max(vabs([ for (i=[0,1]) bounds[i][a] ]))+1 ] : undef;
|
||||
mcols = !is_undef(cols)? cols : (!is_undef(spc) && !is_undef(bnds))? quantup(ceil(bnds[0]/spc[0])-1, 4)+1 : undef;
|
||||
mrows = !is_undef(rows)? rows : (!is_undef(spc) && !is_undef(bnds))? quantup(ceil(bnds[1]/spc[1])-1, 4)+1 : undef;
|
||||
siz = vmul(spc, [mcols-1, mrows-1, 0])+[0,0,0.01];
|
||||
// stagger == true or stagger == "alt"
|
||||
staggermod = (stagger == "alt")? 1 : 0;
|
||||
if (stagger == false) {
|
||||
for (row = [0:1:mrows-1]) {
|
||||
for (col = [0:1:mcols-1]) {
|
||||
pos = [col*spc.x, row*spc.y] - point2d(siz/2);
|
||||
cols1 = ceil(n.x/2);
|
||||
cols2 = n.x - cols1;
|
||||
for (row = [0:1:n.y-1]) {
|
||||
rowcols = ((row%2) == staggermod)? cols1 : cols2;
|
||||
if (rowcols > 0) {
|
||||
for (col = [0:1:rowcols-1]) {
|
||||
rowdx = (row%2 != staggermod)? spacing.x : 0;
|
||||
pos = vmul([2*col,row],spacing) + [rowdx,0] - offset;
|
||||
if (is_undef(in_poly) || point_in_polygon(pos, in_poly)>=0) {
|
||||
$col = col;
|
||||
$col = col * 2 + ((row%2!=staggermod)? 1 : 0);
|
||||
$row = row;
|
||||
$pos = pos;
|
||||
translate(pos) children();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// stagger == true or stagger == "alt"
|
||||
cols1 = ceil(mcols/2);
|
||||
cols2 = mcols - cols1;
|
||||
for (row = [0:1:mrows-1]) {
|
||||
rowcols = ((row%2) == staggermod)? cols1 : cols2;
|
||||
if (rowcols > 0) {
|
||||
for (col = [0:1:rowcols-1]) {
|
||||
rowdx = (row%2 != staggermod)? spc[0] : 0;
|
||||
pos = [2*col*spc[0]+rowdx, row*spc[1]] - point2d(siz/2);
|
||||
if (is_undef(in_poly) || point_in_polygon(pos, in_poly)>=0) {
|
||||
$col = col * 2 + ((row%2!=staggermod)? 1 : 0);
|
||||
$row = row;
|
||||
$pos = pos;
|
||||
translate(pos) children();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
124
tutorials/Distributors.md
Normal file
124
tutorials/Distributors.md
Normal file
@ -0,0 +1,124 @@
|
||||
# BOSL2 Distributors Tutorial
|
||||
|
||||
## Distributors
|
||||
|
||||
Distributors are modules that are useful for placing multiple copies of a child
|
||||
across a line, area, volume, or ring. Many transforms also have one or more
|
||||
distributive variation.
|
||||
|
||||
Transforms | Related Distributors
|
||||
----------------------- | ---------------------
|
||||
`left()`, `right()` | `xcopies()`
|
||||
`fwd()`, `back()` | `ycopies()`
|
||||
`down()`, `up()` | `zcopies()`
|
||||
`move()`, `translate()` | `move_copies()`, `line_of()`, `grid2d()`, `grid3d()`
|
||||
`xrot()` | `xrot_copies()`
|
||||
`yrot()` | `yrot_copies()`
|
||||
`zrot()` | `zrot_copies()`
|
||||
`rot()`, `rotate()` | `rot_copies()`, `arc_of()`
|
||||
`xflip()` | `xflip_copy()`
|
||||
`yflip()` | `yflip_copy()`
|
||||
`zflip()` | `zflip_copy()`
|
||||
`mirror()` | `mirror_copy()`
|
||||
|
||||
|
||||
### Transform Distributors
|
||||
Using `xcopies()`, you can make a line of evenly spaced copies of a shape
|
||||
centered along the X axis. To make a line of 5 spheres, spaced every 20
|
||||
units along the X axis, do:
|
||||
```openscad
|
||||
xcopies(20, n=5) sphere(d=10);
|
||||
```
|
||||
Note that the first expected argument to `xcopies()` is the spacing argument,
|
||||
so you do not need to supply the `spacing=` argument name.
|
||||
|
||||
Similarly, `ycopies()` makes a line of evenly spaced copies centered along the
|
||||
Y axis. To make a line of 5 spheres, spaced every 20 units along the Y
|
||||
axis, do:
|
||||
```openscad
|
||||
ycopies(20, n=5) sphere(d=10);
|
||||
```
|
||||
|
||||
And, `zcopies()` makes a line of evenly spaced copies centered along the Z axis.
|
||||
To make a line of 5 spheres, spaced every 20 units along the Z axis, do:
|
||||
```openscad
|
||||
zcopies(20, n=5) sphere(d=10);
|
||||
```
|
||||
|
||||
If you don't give the `n=` argument to `xcopies()`, `ycopies()` or `zcopies()`,
|
||||
then it defaults to 2 (two) copies:
|
||||
```openscad
|
||||
xcopies(20) sphere(d=10);
|
||||
```
|
||||
|
||||
```openscad
|
||||
ycopies(20) sphere(d=10);
|
||||
```
|
||||
|
||||
```openscad
|
||||
zcopies(20) sphere(d=10);
|
||||
```
|
||||
|
||||
If you don't know the spacing you want, but instead know how long a line you want
|
||||
the copies distributed over, you can use the `l=` argument instead of the `spacing=`
|
||||
argument:
|
||||
```openscad
|
||||
xcopies(l=100, n=5) sphere(d=10);
|
||||
```
|
||||
|
||||
```openscad
|
||||
ycopies(l=100, n=5) sphere(d=10);
|
||||
```
|
||||
|
||||
```openscad
|
||||
zcopies(l=100, n=5) sphere(d=10);
|
||||
```
|
||||
|
||||
If you don't want the line of copies centered on the origin, you can give a starting
|
||||
point, `sp=`, and the line of copies will start there. For `xcopies()`, the line of
|
||||
copies will extend to the right of the starting point.
|
||||
```openscad
|
||||
xcopies(20, n=5, sp=[0,0,0]) sphere(d=10);
|
||||
```
|
||||
|
||||
For `ycopies()`, the line of copies will extend to the back of the starting point.
|
||||
```openscad
|
||||
ycopies(20, n=5, sp=[0,0,0]) sphere(d=10);
|
||||
```
|
||||
|
||||
For `zcopies()`, the line of copies will extend upwards from the starting point.
|
||||
```openscad
|
||||
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
|
||||
of the line of copies with the `spacing=` argument:
|
||||
```openscad
|
||||
line_of(spacing=(BACK+RIGHT)*20, n=5) sphere(d=10);
|
||||
```
|
||||
|
||||
With the `p1=` argument, you can specify the starting point of the line:
|
||||
```openscad
|
||||
line_of(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
|
||||
line_of(p1=[0,100,0], p2=[100,0,0], n=4)
|
||||
sphere(d=10);
|
||||
```
|
||||
|
||||
You can also spread copies across a 2D area using the `grid2d()`
|
||||
|
||||
|
||||
### Rotational Distributors
|
||||
You can make six copies of a cone, rotated around a center:
|
||||
```openscad
|
||||
zrot_copies(n=6) yrot(90) cylinder(h=50,d1=0,d2=20);
|
||||
```
|
||||
|
||||
To Be Completed
|
||||
|
||||
|
@ -233,119 +233,3 @@ skew(szy=0.5) cube(10,center=false);
|
||||
```
|
||||
|
||||
|
||||
## Distributors
|
||||
|
||||
Distributors are modules that are useful for placing multiple copies of a child
|
||||
across a line, area, volume, or ring. Many transforms also distributive variation.
|
||||
|
||||
Transforms | Related Distributors
|
||||
----------------------- | ---------------------
|
||||
`left()`, `right()` | `xcopies()`
|
||||
`fwd()`, `back()` | `ycopies()`
|
||||
`down()`, `up()` | `zcopies()`
|
||||
`move()`, `translate()` | `move_copies()`, `line_of()`, `grid2d()`, `grid3d()`
|
||||
`xrot()` | `xrot_copies()`
|
||||
`yrot()` | `yrot_copies()`
|
||||
`zrot()` | `zrot_copies()`
|
||||
`rot()`, `rotate()` | `rot_copies()`, `arc_of()`
|
||||
|
||||
|
||||
### Transform Distributors
|
||||
Using `xcopies()`, you can make a line of evenly spaced copies of a shape
|
||||
centered along the X axis. To make a line of 5 spheres, spaced every 20
|
||||
units along the X axis, do:
|
||||
```openscad
|
||||
xcopies(20, n=5) sphere(d=10);
|
||||
```
|
||||
Note that the first expected argument to `xcopies()` is the spacing argument,
|
||||
so you do not need to supply the `spacing=` argument name.
|
||||
|
||||
Similarly, `ycopies()` makes a line of evenly spaced copies centered along the
|
||||
Y axis. To make a line of 5 spheres, spaced every 20 units along the Y
|
||||
axis, do:
|
||||
```openscad
|
||||
ycopies(20, n=5) sphere(d=10);
|
||||
```
|
||||
|
||||
And, `zcopies()` makes a line of evenly spaced copies centered along the Z axis.
|
||||
To make a line of 5 spheres, spaced every 20 units along the Z axis, do:
|
||||
```openscad
|
||||
zcopies(20, n=5) sphere(d=10);
|
||||
```
|
||||
|
||||
If you don't give the `n=` argument to `xcopies()`, `ycopies()` or `zcopies()`,
|
||||
then it defaults to 2 (two) copies:
|
||||
```openscad
|
||||
xcopies(20) sphere(d=10);
|
||||
```
|
||||
|
||||
```openscad
|
||||
ycopies(20) sphere(d=10);
|
||||
```
|
||||
|
||||
```openscad
|
||||
zcopies(20) sphere(d=10);
|
||||
```
|
||||
|
||||
If you don't know the spacing you want, but instead know how long a line you want
|
||||
the copies distributed over, you can use the `l=` argument instead of the `spacing=`
|
||||
argument:
|
||||
```openscad
|
||||
xcopies(l=100, n=5) sphere(d=10);
|
||||
```
|
||||
|
||||
```openscad
|
||||
ycopies(l=100, n=5) sphere(d=10);
|
||||
```
|
||||
|
||||
```openscad
|
||||
zcopies(l=100, n=5) sphere(d=10);
|
||||
```
|
||||
|
||||
If you don't want the line of copies centered on the origin, you can give a starting
|
||||
point, `sp=`, and the line of copies will start there. For `xcopies()`, the line of
|
||||
copies will extend to the right of the starting point.
|
||||
```openscad
|
||||
xcopies(20, n=5, sp=[0,0,0]) sphere(d=10);
|
||||
```
|
||||
|
||||
For `ycopies()`, the line of copies will extend to the back of the starting point.
|
||||
```openscad
|
||||
ycopies(20, n=5, sp=[0,0,0]) sphere(d=10);
|
||||
```
|
||||
|
||||
For `zcopies()`, the line of copies will extend upwards from the starting point.
|
||||
```openscad
|
||||
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
|
||||
of the line of copies with the `spacing=` argument:
|
||||
```openscad
|
||||
line_of(spacing=(BACK+RIGHT)*20, n=5) sphere(d=10);
|
||||
```
|
||||
|
||||
With the `p1=` argument, you can specify the starting point of the line:
|
||||
```openscad
|
||||
line_of(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
|
||||
line_of(p1=[0,100,0], p2=[100,0,0], n=4)
|
||||
sphere(d=10);
|
||||
```
|
||||
|
||||
|
||||
|
||||
### Rotational Distributors
|
||||
You can make six copies of a cone, rotated around a center:
|
||||
```openscad
|
||||
zrot_copies(n=6) yrot(90) cylinder(h=50,d1=0,d2=20);
|
||||
```
|
||||
|
||||
To Be Completed
|
||||
|
||||
|
||||
|
11
vectors.scad
11
vectors.scad
@ -95,6 +95,17 @@ function vdiv(v1, v2) = [for (i = [0:1:len(v1)-1]) v1[i]/v2[i]];
|
||||
function vabs(v) = [for (x=v) abs(x)];
|
||||
|
||||
|
||||
// Function: vfloor()
|
||||
// Description:
|
||||
// Returns the given vector after performing a `floor()` on all items.
|
||||
function vfloor(v) = [for (x=v) floor(x)];
|
||||
|
||||
|
||||
// Function: vceil()
|
||||
// Description:
|
||||
// Returns the given vector after performing a `ceil()` on all items.
|
||||
function vceil(v) = [for (x=v) ceil(x)];
|
||||
|
||||
|
||||
// Function: unit()
|
||||
// Description:
|
||||
|
@ -8,7 +8,7 @@
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
BOSL_VERSION = [2,0,229];
|
||||
BOSL_VERSION = [2,0,230];
|
||||
|
||||
|
||||
// Section: BOSL Library Version Functions
|
||||
|
Loading…
x
Reference in New Issue
Block a user