Enhanced oval() to allow actual oval shapes.

This commit is contained in:
Revar Desmera 2020-05-06 01:36:06 -07:00
parent c8394494bb
commit c03570ce3b
4 changed files with 367 additions and 64 deletions

View file

@ -121,12 +121,12 @@ function anchorpt(name, pos=[0,0,0], orient=UP, spin=0) = [name, pos, orient, sp
// size = If given as a 3D vector, contains the XY size of the bottom of the cuboidal/prismoidal volume, and the Z height. If given as a 2D vector, contains the front X width of the rectangular/trapezoidal shape, and the Y length. // size = If given as a 3D vector, contains the XY size of the bottom of the cuboidal/prismoidal volume, and the Z height. If given as a 2D vector, contains the front X width of the rectangular/trapezoidal shape, and the Y length.
// size2 = If given as a 2D vector, contains the XY size of the top of the prismoidal volume. If given as a number, contains the back width of the trapezoidal shape. // size2 = If given as a 2D vector, contains the XY size of the top of the prismoidal volume. If given as a number, contains the back width of the trapezoidal shape.
// shift = If given as a 2D vector, shifts the top of the prismoidal or conical shape by the given amount. If given as a number, shifts the back of the trapezoidal shape right by that amount. Default: No shift. // shift = If given as a 2D vector, shifts the top of the prismoidal or conical shape by the given amount. If given as a number, shifts the back of the trapezoidal shape right by that amount. Default: No shift.
// r = Radius of the cylindrical/conical volume. // r = Radius of the cylindrical/conical volume. Can be a scalar, or a list of sizes per axis.
// d = Diameter of the cylindrical/conical volume. // d = Diameter of the cylindrical/conical volume. Can be a scalar, or a list of sizes per axis.
// r1 = Radius of the bottom of the conical volume. // r1 = Radius of the bottom of the conical volume. Can be a scalar, or a list of sizes per axis.
// r2 = Radius of the top of the conical volume. // r2 = Radius of the top of the conical volume. Can be a scalar, or a list of sizes per axis.
// d1 = Diameter of the bottom of the conical volume. // d1 = Diameter of the bottom of the conical volume. Can be a scalar, a list of sizes per axis.
// d2 = Diameter of the top of the conical volume. // d2 = Diameter of the top of the conical volume. Can be a scalar, a list of sizes per axis.
// l = Length of the cylindrical/conical volume along axis. // l = Length of the cylindrical/conical volume along axis.
// vnf = The [VNF](vnf.scad) of the volume. // vnf = The [VNF](vnf.scad) of the volume.
// path = The path to generate a polygon from. // path = The path to generate a polygon from.
@ -220,20 +220,25 @@ function attach_geom(
r1 = get_radius(r1=r1,d1=d1,r=r,d=d,dflt=undef) r1 = get_radius(r1=r1,d1=d1,r=r,d=d,dflt=undef)
) )
!is_undef(r1)? ( !is_undef(r1)? (
assert(is_num(r1))
let( l = default(l, h) ) let( l = default(l, h) )
!is_undef(l)? ( !is_undef(l)? (
let( let(
shift = default(shift, [0,0]), shift = default(shift, [0,0]),
r2 = get_radius(r1=r2,d1=d2,r=r,d=d,dflt=undef) r2 = get_radius(r1=r2,d1=d2,r=r,d=d,dflt=undef)
) )
assert(is_num(r1) || is_vector(r1,2))
assert(is_num(r2) || is_vector(r2,2))
assert(is_num(l)) assert(is_num(l))
assert(is_num(r2))
assert(is_vector(shift,2)) assert(is_vector(shift,2))
["cyl", r1, r2, l, shift, offset, anchors] ["cyl", r1, r2, l, shift, offset, anchors]
) : ( ) : (
two_d? ["circle", r1, offset, anchors] : two_d? (
["spheroid", r1, offset, anchors] assert(is_num(r1) || is_vector(r1,2))
["circle", r1, offset, anchors]
) : (
assert(is_num(r1) || is_vector(r1,3))
["spheroid", r1, offset, anchors]
)
) )
) : ) :
assert(false, "Unrecognizable geometry description."); assert(false, "Unrecognizable geometry description.");
@ -268,10 +273,16 @@ function attach_geom_size(geom) =
) : type == "cyl"? ( //r1, r2, l, shift ) : type == "cyl"? ( //r1, r2, l, shift
let( let(
r1=geom[1], r2=geom[2], l=geom[3], shift=point2d(geom[4]), r1=geom[1], r2=geom[2], l=geom[3], shift=point2d(geom[4]),
maxr = max(r1,r2) rx1 = default(r1[0],r1),
) [2*maxr,2*maxr,l] ry1 = default(r1[1],r1),
rx2 = default(r2[0],r2),
ry2 = default(r2[1],r2),
maxxr = max(rx1,rx2),
maxyr = max(ry1,ry2)
) [2*maxxr,2*maxyr,l]
) : type == "spheroid"? ( //r ) : type == "spheroid"? ( //r
let( r=geom[1] ) [2,2,2]*r let( r=geom[1] )
is_num(r)? [2,2,2]*r : vmul([2,2,2],r)
) : type == "vnf_extent" || type=="vnf_isect"? ( //vnf ) : type == "vnf_extent" || type=="vnf_isect"? ( //vnf
let( let(
mm = pointlist_bounds(geom[1][0]), mm = pointlist_bounds(geom[1][0]),
@ -283,7 +294,8 @@ function attach_geom_size(geom) =
maxx = max(size.x,size2) maxx = max(size.x,size2)
) [maxx, size.y] ) [maxx, size.y]
) : type == "circle"? ( //r ) : type == "circle"? ( //r
let( r=geom[1] ) [2,2]*r let( r=geom[1] )
is_num(r)? [2,2]*r : vmul([2,2],r)
) : type == "path_isect" || type == "path_extent"? ( //path ) : type == "path_isect" || type == "path_extent"? ( //path
let( let(
mm = pointlist_bounds(geom[1]), mm = pointlist_bounds(geom[1]),
@ -414,11 +426,13 @@ function find_anchor(anchor, geom) =
) [anchor, pos, vec, oang] ) [anchor, pos, vec, oang]
) : type == "cyl"? ( //r1, r2, l, shift ) : type == "cyl"? ( //r1, r2, l, shift
let( let(
r1=geom[1], r2=geom[2], l=geom[3], shift=point2d(geom[4]), rr1=geom[1], rr2=geom[2], l=geom[3], shift=point2d(geom[4]),
r1 = is_num(rr1)? [rr1,rr1] : rr1,
r2 = is_num(rr2)? [rr2,rr2] : rr2,
u = (anchor.z+1)/2, u = (anchor.z+1)/2,
axy = unit(point2d(anchor)), axy = unit(point2d(anchor)),
bot = point3d(r1*axy,-l/2), bot = point3d(vmul(r1,axy), -l/2),
top = point3d(r2*axy+shift, l/2), top = point3d(vmul(r2,axy)+shift, l/2),
pos = lerp(bot,top,u)+offset, pos = lerp(bot,top,u)+offset,
sidevec = rot(from=UP, to=top-bot, p=point3d(axy)), sidevec = rot(from=UP, to=top-bot, p=point3d(axy)),
vvec = unit([0,0,anchor.z]), vvec = unit([0,0,anchor.z]),
@ -429,8 +443,10 @@ function find_anchor(anchor, geom) =
) [anchor, pos, vec, oang] ) [anchor, pos, vec, oang]
) : type == "spheroid"? ( //r ) : type == "spheroid"? ( //r
let( let(
r=geom[1] rr = geom[1],
) [anchor, r*unit(anchor)+offset, unit(anchor), oang] r = is_num(rr)? [rr,rr,rr] : rr,
anchor = unit(point3d(anchor))
) [anchor, vmul(r,anchor)+offset, unit(vmul(r,anchor)), oang]
) : type == "vnf_isect"? ( //vnf ) : type == "vnf_isect"? ( //vnf
let( let(
vnf=geom[1], vnf=geom[1],
@ -494,9 +510,10 @@ function find_anchor(anchor, geom) =
) [anchor, pos, vec, 0] ) [anchor, pos, vec, 0]
) : type == "circle"? ( //r ) : type == "circle"? ( //r
let( let(
r=geom[1], rr = geom[1],
r = is_num(rr)? [rr,rr] : rr,
anchor = unit(point2d(anchor)) anchor = unit(point2d(anchor))
) [anchor, r*anchor+offset, anchor, 0] ) [anchor, vmul(r,anchor)+offset, unit(vmul([r.y,r.x],anchor)), 0]
) : type == "path_isect"? ( //path ) : type == "path_isect"? ( //path
let( let(
path=geom[1], path=geom[1],
@ -590,12 +607,12 @@ function attachment_is_shown(tags) =
// size = If given as a 3D vector, contains the XY size of the bottom of the cuboidal/prismoidal volume, and the Z height. If given as a 2D vector, contains the front X width of the rectangular/trapezoidal shape, and the Y length. // size = If given as a 3D vector, contains the XY size of the bottom of the cuboidal/prismoidal volume, and the Z height. If given as a 2D vector, contains the front X width of the rectangular/trapezoidal shape, and the Y length.
// size2 = If given as a 2D vector, contains the XY size of the top of the prismoidal volume. If given as a number, contains the back width of the trapezoidal shape. // size2 = If given as a 2D vector, contains the XY size of the top of the prismoidal volume. If given as a number, contains the back width of the trapezoidal shape.
// shift = If given as a 2D vector, shifts the top of the prismoidal or conical shape by the given amount. If given as a number, shifts the back of the trapezoidal shape right by that amount. Default: No shift. // shift = If given as a 2D vector, shifts the top of the prismoidal or conical shape by the given amount. If given as a number, shifts the back of the trapezoidal shape right by that amount. Default: No shift.
// r = Radius of the cylindrical/conical volume. // r = Radius of the cylindrical/conical volume. Can be a scalar, or a list of sizes per axis.
// d = Diameter of the cylindrical/conical volume. // d = Diameter of the cylindrical/conical volume. Can be a scalar, or a list of sizes per axis.
// r1 = Radius of the bottom of the conical volume. // r1 = Radius of the bottom of the conical volume. Can be a scalar, or a list of sizes per axis.
// r2 = Radius of the top of the conical volume. // r2 = Radius of the top of the conical volume. Can be a scalar, or a list of sizes per axis.
// d1 = Diameter of the bottom of the conical volume. // d1 = Diameter of the bottom of the conical volume. Can be a scalar, a list of sizes per axis.
// d2 = Diameter of the top of the conical volume. // d2 = Diameter of the top of the conical volume. Can be a scalar, a list of sizes per axis.
// l = Length of the cylindrical/conical volume along axis. // l = Length of the cylindrical/conical volume along axis.
// vnf = The [VNF](vnf.scad) of the volume. // vnf = The [VNF](vnf.scad) of the volume.
// path = The path to generate a polygon from. // path = The path to generate a polygon from.
@ -677,12 +694,12 @@ function reorient(
// size = If given as a 3D vector, contains the XY size of the bottom of the cuboidal/prismoidal volume, and the Z height. If given as a 2D vector, contains the front X width of the rectangular/trapezoidal shape, and the Y length. // size = If given as a 3D vector, contains the XY size of the bottom of the cuboidal/prismoidal volume, and the Z height. If given as a 2D vector, contains the front X width of the rectangular/trapezoidal shape, and the Y length.
// size2 = If given as a 2D vector, contains the XY size of the top of the prismoidal volume. If given as a number, contains the back width of the trapezoidal shape. // size2 = If given as a 2D vector, contains the XY size of the top of the prismoidal volume. If given as a number, contains the back width of the trapezoidal shape.
// shift = If given as a 2D vector, shifts the top of the prismoidal or conical shape by the given amount. If given as a number, shifts the back of the trapezoidal shape right by that amount. Default: No shift. // shift = If given as a 2D vector, shifts the top of the prismoidal or conical shape by the given amount. If given as a number, shifts the back of the trapezoidal shape right by that amount. Default: No shift.
// r = Radius of the cylindrical/conical volume. // r = Radius of the cylindrical/conical volume. Can be a scalar, or a list of sizes per axis.
// d = Diameter of the cylindrical/conical volume. // d = Diameter of the cylindrical/conical volume. Can be a scalar, or a list of sizes per axis.
// r1 = Radius of the bottom of the conical volume. // r1 = Radius of the bottom of the conical volume. Can be a scalar, or a list of sizes per axis.
// r2 = Radius of the top of the conical volume. // r2 = Radius of the top of the conical volume. Can be a scalar, or a list of sizes per axis.
// d1 = Diameter of the bottom of the conical volume. // d1 = Diameter of the bottom of the conical volume. Can be a scalar, a list of sizes per axis.
// d2 = Diameter of the top of the conical volume. // d2 = Diameter of the top of the conical volume. Can be a scalar, a list of sizes per axis.
// l = Length of the cylindrical/conical volume along axis. // l = Length of the cylindrical/conical volume along axis.
// vnf = The [VNF](vnf.scad) of the volume. // vnf = The [VNF](vnf.scad) of the volume.
// path = The path to generate a polygon from. // path = The path to generate a polygon from.

View file

@ -730,14 +730,17 @@ function _turtle_command(command, parm, parm2, state, index) =
module rect(size=1, center, rounding=0, chamfer=0, anchor, spin=0) { module rect(size=1, center, rounding=0, chamfer=0, anchor, spin=0) {
size = is_num(size)? [size,size] : point2d(size); size = is_num(size)? [size,size] : point2d(size);
anchor = get_anchor(anchor, center, FRONT+LEFT, FRONT+LEFT); anchor = get_anchor(anchor, center, FRONT+LEFT, FRONT+LEFT);
attachable(anchor,spin, two_d=true, size=size) { if (rounding==0 && chamfer==0) {
if (rounding==0 && chamfer==0) { attachable(anchor,spin, two_d=true, size=size) {
square(size, center=true); square(size, center=true);
} else { children();
pts = rect(size=size, rounding=rounding, chamfer=chamfer, center=true); }
polygon(pts); } else {
pts = rect(size=size, rounding=rounding, chamfer=chamfer, center=true);
attachable(anchor,spin, two_d=true, path=pts) {
polygon(pts);
children();
} }
children();
} }
} }
@ -798,9 +801,9 @@ function rect(size=1, center, rounding=0, chamfer=0, anchor, spin=0) =
// When called as a module, creates a 2D polygon that approximates a circle of the given size. // When called as a module, creates a 2D polygon that approximates a circle of the given size.
// When called as a function, returns a 2D list of points (path) for a polygon that approximates a circle of the given size. // When called as a function, returns a 2D list of points (path) for a polygon that approximates a circle of the given size.
// Arguments: // Arguments:
// r = The radius of the circle to create. // r = Radius of the circle/oval to create. Can be a scalar, or a list of sizes per axis.
// d = The diameter of the circle to create. // d = Diameter of the circle/oval to create. Can be a scalar, or a list of sizes per axis.
// realign = If true, rotates the polygon that approximates the circle by half of one size. // realign = If true, rotates the polygon that approximates the circle/oval by half of one size.
// circum = If true, the polygon that approximates the circle will be upsized slightly to circumscribe the theoretical circle. If false, it inscribes the theoretical circle. Default: false // circum = If true, the polygon that approximates the circle will be upsized slightly to circumscribe the theoretical circle. If false, it inscribes the theoretical circle. Default: false
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER` // anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0` // spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
@ -816,10 +819,24 @@ function rect(size=1, center, rounding=0, chamfer=0, anchor, spin=0) =
// path = oval(d=50, anchor=FRONT, spin=45); // path = oval(d=50, anchor=FRONT, spin=45);
module oval(r, d, realign=false, circum=false, anchor=CENTER, spin=0) { module oval(r, d, realign=false, circum=false, anchor=CENTER, spin=0) {
r = get_radius(r=r, d=d, dflt=1); r = get_radius(r=r, d=d, dflt=1);
sides = segs(r); sides = segs(max(r));
rr = circum? r/cos(180/sides) : r; sc = circum? (1 / cos(180/sides)) : 1;
attachable(anchor,spin, two_d=true, r=rr) { rx = default(r[0],r) * sc;
zrot(realign? 180/sides : 0) circle(r=rr, $fn=sides); ry = default(r[1],r) * sc;
attachable(anchor,spin, two_d=true, r=[rx,ry]) {
if (rx < ry) {
xscale(rx/ry) {
zrot(realign? 180/sides : 0) {
circle(r=ry, $fn=sides);
}
}
} else {
yscale(ry/rx) {
zrot(realign? 180/sides : 0) {
circle(r=rx, $fn=sides);
}
}
}
children(); children();
} }
} }
@ -828,11 +845,13 @@ module oval(r, d, realign=false, circum=false, anchor=CENTER, spin=0) {
function oval(r, d, realign=false, circum=false, anchor=CENTER, spin=0) = function oval(r, d, realign=false, circum=false, anchor=CENTER, spin=0) =
let( let(
r = get_radius(r=r, d=d, dflt=1), r = get_radius(r=r, d=d, dflt=1),
sides = segs(r), sides = segs(max(r)),
offset = realign? 180/sides : 0, offset = realign? 180/sides : 0,
rr = r / (circum? cos(180/sides) : 1), sc = circum? (1 / cos(180/sides)) : 1,
pts = [for (i=[0:1:sides-1]) let(a=360-offset-i*360/sides) rr*[cos(a),sin(a)]] rx = default(r[0],r) * sc,
) reorient(anchor,spin, two_d=true, r=rr, p=pts); ry = default(r[1],r) * sc,
pts = [for (i=[0:1:sides-1]) let(a=360-offset-i*360/sides) [rx*cos(a), ry*sin(a)]]
) reorient(anchor,spin, two_d=true, r=[rx,ry], p=pts);

View file

@ -6,6 +6,7 @@ There are 5 built-in primitive shapes that OpenSCAD provides.
The BOSL2 library extends or provides alternative to these shapes so The BOSL2 library extends or provides alternative to these shapes so
that they support more features, and more ways to simply reorient them. that they support more features, and more ways to simply reorient them.
### 2D Squares ### 2D Squares
You can still use the built-in `square()` in the familiar ways that OpenSCAD provides: You can still use the built-in `square()` in the familiar ways that OpenSCAD provides:
@ -140,6 +141,7 @@ Anchoring or centering is performed before the spin:
rect([60,40], anchor=BACK, spin=30); rect([60,40], anchor=BACK, spin=30);
``` ```
### 2D Circles ### 2D Circles
The built-in `circle()` primitive can be used as expected: The built-in `circle()` primitive can be used as expected:
@ -192,6 +194,18 @@ Circumscribing the ideal circle:
} }
``` ```
The `oval()` module, as its name suggests, can be given separate X and Y radii
or diameters. To do this, just give `r=` or `d=` with a list of two radii or
diameters:
```openscad-2D
oval(r=[30,20]);
```
```openscad-2D
oval(d=[60,40]);
```
Another way that `oval()` is enhanced over `circle()`, is that you can anchor, Another way that `oval()` is enhanced over `circle()`, is that you can anchor,
spin and attach it. spin and attach it.
@ -207,11 +221,13 @@ Using spin on a circle may not make initial sense, until you remember that
anchoring is performed before spin: anchoring is performed before spin:
```openscad-2D ```openscad-2D
oval(r=50, anchor=FRONT, spin=30); oval(r=50, anchor=FRONT, spin=-30);
``` ```
### Enhanced 3D Cube
You can use enhanced `cube()` like the normal OpenSCAD built-in: ### 3D Cubes
BOSL2 overrides the built-in `cube()` module. It still can be used as you
expect from the built-in:
```openscad-3D ```openscad-3D
cube(100); cube(100);
@ -225,8 +241,11 @@ You can use enhanced `cube()` like the normal OpenSCAD built-in:
cube([50,40,20], center=true); cube([50,40,20], center=true);
``` ```
You can use `anchor` similarly to `square()`, except you can anchor vertically It is also enhanced to allow you to anchor, spin, orient, and attach it.
too, in 3D, allowing anchoring to faces, edges, and corners:
You can use `anchor=` similarly to how you use it with `square()` or `rect()`,
except you can also anchor vertically in 3D, allowing anchoring to faces, edges,
and corners:
```openscad-3D ```openscad-3D
cube([50,40,20], anchor=BOTTOM); cube([50,40,20], anchor=BOTTOM);
@ -240,36 +259,143 @@ too, in 3D, allowing anchoring to faces, edges, and corners:
cube([50,40,20], anchor=TOP+FRONT+LEFT); cube([50,40,20], anchor=TOP+FRONT+LEFT);
``` ```
You can use `spin` as well, to rotate around the Z axis: You can use `spin=` to rotate around the Z axis:
```openscad-3D ```openscad-3D
cube([50,40,20], anchor=FRONT, spin=30); cube([50,40,20], anchor=FRONT, spin=30);
``` ```
3D objects also gain the ability to use an extra trick with `spin`; 3D objects also gain the ability to use an extra trick with `spin=`;
if you pass a list of `[X,Y,Z]` rotation angles to `spin`, it will if you pass a list of `[X,Y,Z]` rotation angles to `spin=`, it will
rotate by the three given axis angles, similar to using `rotate()`: rotate by the three given axis angles, similar to using `rotate()`:
```openscad-3D ```openscad-3D
cube([50,40,20], anchor=FRONT, spin=[15,0,30]); cube([50,40,20], anchor=FRONT, spin=[15,0,30]);
``` ```
3D objects also can be given an `orient` argument that is given as a vector, 3D objects also can be given an `orient=` argument as a vector, pointing
pointing towards where the top of the shape should be rotated towards. to where the top of the shape should be rotated towards.
```openscad-3D ```openscad-3D
cube([50,40,20], orient=UP+BACK+RIGHT); cube([50,40,20], orient=UP+BACK+RIGHT);
``` ```
If you use `anchor`, `spin`, and `orient` together, the anchor is performed If you use `anchor=`, `spin=`, and `orient=` together, the anchor is performed
first, then the spin, then the orient: first, then the spin, then the orient:
```openscad-3D
cube([50,40,20], anchor=FRONT);
```
```openscad-3D
cube([50,40,20], anchor=FRONT, spin=45);
```
```openscad-3D ```openscad-3D
cube([50,40,20], anchor=FRONT, spin=45, orient=UP+FWD+RIGHT); cube([50,40,20], anchor=FRONT, spin=45, orient=UP+FWD+RIGHT);
``` ```
### Enhanced 3D Cylinder BOSL2 provides a `cuboid()` module that expands on `cube()`, by providing
You can use the enhanced `cylinder()` as normal for OpenSCAD: rounding and chamfering of edges. You can use it similarly to `cube()`,
except that `cuboid()` centers by default.
You can round the edges with the `rounding=` argument:
```openscad-3D
cuboid([100,80,60], rounding=20);
```
Similarly, you can chamfer the edges with the `chamfer=` argument:
```openscad-3D
cuboid([100,80,60], chamfer=10);
```
You can round only some edges, by using the `edges=` arguments. It can be
given a few types of arguments. If you gave it a vector pointed at a face,
it will only round the edges surrounding that face:
```openscad-3D
cuboid([100,80,60], rounding=20, edges=TOP);
```
```openscad-3D
cuboid([100,80,60], rounding=20, edges=RIGHT);
```
If you give `edges=` a vector pointing at a corner, it will round all edges
that meet at that corner:
```openscad-3D
cuboid([100,80,60], rounding=20, edges=RIGHT+FRONT+TOP);
```
```openscad-3D
cuboid([100,80,60], rounding=20, edges=LEFT+FRONT+TOP);
```
If you give `edges=` a vector pointing at an edge, it will round only that edge:
```openscad-3D
cuboid([100,80,60], rounding=10, edges=FRONT+TOP);
```
```openscad-3D
cuboid([100,80,60], rounding=10, edges=RIGHT+FRONT);
```
If you give the string "X", "Y", or "Z", then all edges aligned with the specified
axis will be rounded:
```openscad-3D
cuboid([100,80,60], rounding=10, edges="X");
```
```openscad-3D
cuboid([100,80,60], rounding=10, edges="Y");
```
```openscad-3D
cuboid([100,80,60], rounding=10, edges="Z");
```
If you give a list of edge specs, then all edges referenced in the list will
be rounded:
```openscad-3D
cuboid([100,80,60], rounding=10, edges=[TOP,"Z",BOTTOM+RIGHT]);
```
The default value for `edges=` is `EDGES_ALL`, which is all edges. You can also
give an `except_edges=` argument that specifies edges to NOT round:
```openscad-3D
cuboid([100,80,60], rounding=10, except_edges=BOTTOM+RIGHT);
```
You can give the `except_edges=` argument any type of argument that you can
give to `edges=`:
```openscad-3D
cuboid([100,80,60], rounding=10, except_edges=[BOTTOM,"Z",TOP+RIGHT]);
```
You can give both `edges=` and `except_edges=`, to simplify edge specs:
```openscad-3D
cuboid([100,80,60], rounding=10, edges=[TOP,FRONT], except_edges=TOP+FRONT);
```
You can specify what edges to chamfer similarly:
```openscad-3D
cuboid([100,80,60], chamfer=10, edges=[TOP,FRONT], except_edges=TOP+FRONT);
```
### 3D Cylinder
BOSL2 overrides the built-in `cylinder()` module. It still can be used as you
expect from the built-in:
```openscad-3D ```openscad-3D
cylinder(r=50,h=50); cylinder(r=50,h=50);
@ -287,3 +413,144 @@ You can use the enhanced `cylinder()` as normal for OpenSCAD:
cylinder(d1=100,d2=80,h=50,center=true); cylinder(d1=100,d2=80,h=50,center=true);
``` ```
You can also anchor, spin, orient, and attach like the `cuboid()` module:
```openscad-3D
cylinder(r=50, h=50, anchor=TOP+FRONT);
```
```openscad-3D
cylinder(r=50, h=50, anchor=BOTTOM+LEFT);
```
```openscad-3D
cylinder(r=50, h=50, anchor=BOTTOM+LEFT, spin=30);
```
```openscad-3D
cylinder(r=50, h=50, anchor=BOTTOM, orient=UP+BACK+RIGHT);
```
BOSL2 provides a `cyl()` module that expands on `cylinder()`, by providing
rounding and chamfering of edges. You can use it similarly to `cylinder()`,
except that `cyl()` centers the cylinder by default.
```openscad-3D
cyl(r=60, l=100);
```
```openscad-3D
cyl(d=100, l=100);
```
```openscad-3D
cyl(d=100, l=100, anchor=TOP);
```
You can round the edges with the `rounding=` argument:
```openscad-3D
cyl(d=100, l=100, rounding=20);
```
Similarly, you can chamfer the edges with the `chamfer=` argument:
```openscad-3D
cyl(d=100, l=100, chamfer=10);
```
You can specify rounding and chamfering for each end individually:
```openscad-3D
cyl(d=100, l=100, rounding1=20);
```
```openscad-3D
cyl(d=100, l=100, rounding2=20);
```
```openscad-3D
cyl(d=100, l=100, chamfer1=10);
```
```openscad-3D
cyl(d=100, l=100, chamfer2=10);
```
You can even mix and match rounding and chamfering:
```openscad-3D
cyl(d=100, l=100, rounding1=20, chamfer2=10);
```
```openscad-3D
cyl(d=100, l=100, rounding2=20, chamfer1=10);
```
### 3D Spheres
BOSL2 overrides the built-in `sphere()` module. It still can be used as you
expect from the built-in:
```openscad-3D
cylinder(r=50);
```
```openscad-3D
cylinder(d=100);
```
You can anchor, spin, and orient `sphere()`s, much like you can with `cylinder()`
and `cube()`:
```openscad-3D
sphere(d=100, anchor=FRONT);
```
```openscad-3D
sphere(d=100, anchor=FRONT, spin=30);
```
```openscad-3D
sphere(d=100, anchor=BOTTOM, orient=RIGHT+TOP);
```
BOSL2 also provides `spheroid()`, which enhances `sphere()` with a few features
like the `circum=` and `style=` arguments:
You can use the `circum=true` argument to force the sphere to circumscribe the
ideal sphere, as opposed to the default inscribing:
```openscad-3D
spheroid(d=100, circum=true);
```
The `style=` argument can choose the way that the sphere will be constructed:
The "orig" style matches the `sphere()` built-in's construction.
```openscad-3D
spheroid(d=100, style="orig");
```
The "aligned" style will ensure that there is a vertex at each axis extrama,
so long as `$fn` is a multiple of 4.
```openscad-3D
spheroid(d=100, style="aligned");
```
The "stagger" style will stagger the triangulation of the vertical rows:
```openscad-3D
spheroid(d=100, style="stagger");
```
The "icosa"` style will make for roughly equal-sized triangles for the entire
sphere surface:
```openscad-3D
spheroid(d=100, style="icosa");
```

View file

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