Merge pull request #1021 from adrianVmariano/master

Doc fixes & parameter fixes
This commit is contained in:
Revar Desmera 2023-01-16 21:21:27 -08:00 committed by GitHub
commit e8b9b33029
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 213 additions and 120 deletions

View file

@ -19,12 +19,12 @@ use <builtins.scad>
// Function&Module: cube() // Function&Module: cube()
// Topics: Shapes (3D), Attachable, VNF Generators // Topics: Shapes (3D), Attachable, VNF Generators
// Usage: As Module // Usage: As Module (as in native OpenSCAD)
// cube(size, [center], ...); // cube(size, [center]);
// Usage: With Attachments // Usage: With BOSL2 Attachment extensions
// cube(size, [center], ...) [ATTACHMENTS]; // cube(size, [center], [anchor=], [spin=], [orient=]) [ATTACHMENTS];
// Usage: As Function // Usage: As Function (BOSL2 extension)
// vnf = cube(size, [center], ...); // vnf = cube(size, ...);
// See Also: cuboid(), prismoid() // See Also: cuboid(), prismoid()
// Description: // Description:
// Creates a 3D cubic object with support for anchoring and attachments. // Creates a 3D cubic object with support for anchoring and attachments.
@ -646,7 +646,7 @@ module prismoid(
size1, size2, h, shift=[0,0], size1, size2, h, shift=[0,0],
rounding=0, rounding1, rounding2, rounding=0, rounding1, rounding2,
chamfer=0, chamfer1, chamfer2, chamfer=0, chamfer1, chamfer2,
l, center, l, height, length, center,
anchor, spin=0, orient=UP anchor, spin=0, orient=UP
) { ) {
checks = checks =
@ -691,7 +691,7 @@ function prismoid(
size1, size2, h, shift=[0,0], size1, size2, h, shift=[0,0],
rounding=0, rounding1, rounding2, rounding=0, rounding1, rounding2,
chamfer=0, chamfer1, chamfer2, chamfer=0, chamfer1, chamfer2,
l, center, l, height, length, center,
anchor=DOWN, spin=0, orient=UP anchor=DOWN, spin=0, orient=UP
) = ) =
assert(is_vector(size1,2)) assert(is_vector(size1,2))
@ -730,7 +730,7 @@ function prismoid(
) )
let( let(
eps = pow(2,-14), eps = pow(2,-14),
h = first_defined([h,l,1]), h = one_defined([h,l,length,height],"h,l,length,height",dflt=1),
shiftby = point3d(point2d(shift)), shiftby = point3d(point2d(shift)),
s1 = [max(size1.x, eps), max(size1.y, eps)], s1 = [max(size1.x, eps), max(size1.y, eps)],
s2 = [max(size2.x, eps), max(size2.y, eps)], s2 = [max(size2.x, eps), max(size2.y, eps)],
@ -834,7 +834,7 @@ function octahedron(size=1, anchor=CENTER, spin=0, orient=UP) =
// specify rounding and/or chamferring per-edge, and for top and bottom, inside and // specify rounding and/or chamferring per-edge, and for top and bottom, inside and
// outside separately. // outside separately.
// Arguments: // Arguments:
// h/l = The height or length of the rectangular tube. Default: 1 // h/l/height/length = The height or length of the rectangular tube. Default: 1
// size = The outer [X,Y] size of the rectangular tube. // size = The outer [X,Y] size of the rectangular tube.
// isize = The inner [X,Y] size of the rectangular tube. // isize = The inner [X,Y] size of the rectangular tube.
// center = If given, overrides `anchor`. A true value sets `anchor=CENTER`, false sets `anchor=UP`. // center = If given, overrides `anchor`. A true value sets `anchor=CENTER`, false sets `anchor=UP`.
@ -919,9 +919,9 @@ module rect_tube(
chamfer=0, chamfer1, chamfer2, chamfer=0, chamfer1, chamfer2,
ichamfer=0, ichamfer1, ichamfer2, ichamfer=0, ichamfer1, ichamfer2,
anchor, spin=0, orient=UP, anchor, spin=0, orient=UP,
l l, length, height
) { ) {
h = one_defined([h,l],"h,l"); h = one_defined([h,l,length,height],"h,l,length,height");
checks = checks =
assert(is_num(h), "l or h argument required.") assert(is_num(h), "l or h argument required.")
assert(is_vector(shift,2)); assert(is_vector(shift,2));
@ -997,7 +997,7 @@ function rect_tube(
chamfer=0, chamfer1, chamfer2, chamfer=0, chamfer1, chamfer2,
ichamfer=0, ichamfer1, ichamfer2, ichamfer=0, ichamfer1, ichamfer2,
anchor, spin=0, orient=UP, anchor, spin=0, orient=UP,
l l, length, height
) = no_function("rect_tube"); ) = no_function("rect_tube");
@ -1063,16 +1063,19 @@ function wedge(size=[1,1,1], center, anchor, spin=0, orient=UP) =
// Function&Module: cylinder() // Function&Module: cylinder()
// Topics: Shapes (3D), Attachable, VNF Generators // Topics: Shapes (3D), Attachable, VNF Generators
// Usage: As Module // Usage: As Module (as in Native OpenSCAD)
// cylinder(h, r=/d=, [center=], ...) [ATTACHMENTS]; // cylinder(h, r=/d=, [center=]);
// cylinder(h, r1/d1=, r2/d2=, [center=], ...) [ATTACHMENTS]; // cylinder(h, r1/d1=, r2/d2=, [center=]);
// Usage: As Function // Usage: With BOSL2 anchoring and attachment extensions
// vnf = cylinder(h, r=/d=, [center=], ...); // cylinder(h, r=/d=, [center=], [anchor=], [spin=], [orient=]) [ATTACHMENTS];
// vnf = cylinder(h, r1/d1=, r2/d2=, [center=], ...); // cylinder(h, r1/d1=, r2/d2=, [center=], [anchor=], [spin=], [orient=]) [ATTACHMENTS];
// Usage: As Function (BOSL2 extension)
// vnf = cylinder(h, r=/d=, ...);
// vnf = cylinder(h, r1/d1=, r2/d2=, ...);
// See Also: cyl() // See Also: cyl()
// Description: // Description:
// Creates a 3D cylinder or conic object with support for anchoring and attachments. // Creates a 3D cylinder or conic object with support for anchoring and attachments.
// This can be used as a drop-in replacement for the built-in `cylinder()` module. // This modules extends the built-in `cylinder()` module by adding support for attachment.
// When called as a function, returns a [VNF](vnf.scad) for a cylinder. // When called as a function, returns a [VNF](vnf.scad) for a cylinder.
// Arguments: // Arguments:
// l / h = The height of the cylinder. // l / h = The height of the cylinder.
@ -1145,27 +1148,27 @@ function cylinder(h, r1, r2, center, l, r, d, d1, d2, anchor, spin=0, orient=UP)
// Function&Module: cyl() // Function&Module: cyl()
// //
// Usage: Normal Cylinders // Usage: Normal Cylinders
// cyl(l|h, r, [center], [circum=], [realign=]) [ATTACHMENTS]; // cyl(l|h|length|height, r, [center], [circum=], [realign=]) [ATTACHMENTS];
// cyl(l|h, d=, ...) [ATTACHMENTS]; // cyl(l|h|length|height, d=, ...) [ATTACHMENTS];
// cyl(l|h, r1=, r2=, ...) [ATTACHMENTS]; // cyl(l|h|length|height, r1=, r2=, ...) [ATTACHMENTS];
// cyl(l|h, d1=, d2=, ...) [ATTACHMENTS]; // cyl(l|h|length|height, d1=, d2=, ...) [ATTACHMENTS];
// //
// Usage: Chamferred Cylinders // Usage: Chamferred Cylinders
// cyl(l|h, r|d, chamfer=, [chamfang=], [from_end=], ...); // cyl(l|h|length|height, r|d, chamfer=, [chamfang=], [from_end=], ...);
// cyl(l|h, r|d, chamfer1=, [chamfang1=], [from_end=], ...); // cyl(l|h|length|height, r|d, chamfer1=, [chamfang1=], [from_end=], ...);
// cyl(l|h, r|d, chamfer2=, [chamfang2=], [from_end=], ...); // cyl(l|h|length|height, r|d, chamfer2=, [chamfang2=], [from_end=], ...);
// cyl(l|h, r|d, chamfer1=, chamfer2=, [chamfang1=], [chamfang2=], [from_end=], ...); // cyl(l|h|length|height, r|d, chamfer1=, chamfer2=, [chamfang1=], [chamfang2=], [from_end=], ...);
// //
// Usage: Rounded End Cylinders // Usage: Rounded End Cylinders
// cyl(l|h, r|d, rounding=, ...); // cyl(l|h|length|height, r|d, rounding=, ...);
// cyl(l|h, r|d, rounding1=, ...); // cyl(l|h|length|height, r|d, rounding1=, ...);
// cyl(l|h, r|d, rounding2=, ...); // cyl(l|h|length|height, r|d, rounding2=, ...);
// cyl(l|h, r|d, rounding1=, rounding2=, ...); // cyl(l|h|length|height, r|d, rounding1=, rounding2=, ...);
// //
// Usage: Textured Cylinders // Usage: Textured Cylinders
// cyl(l|h, r|d, texture=, [tex_size=]|[tex_counts=], [tex_scale=], [tex_rot=], [tex_samples=], [tex_style=], [tex_taper=], [tex_inset=], ...); // cyl(l|h|length|height, r|d, texture=, [tex_size=]|[tex_counts=], [tex_scale=], [tex_rot=], [tex_samples=], [tex_style=], [tex_taper=], [tex_inset=], ...);
// cyl(l|h, r1=, r2=, texture=, [tex_size=]|[tex_counts=], [tex_scale=], [tex_rot=], [tex_samples=], [tex_style=], [tex_taper=], [tex_inset=], ...); // cyl(l|h|length|height, r1=, r2=, texture=, [tex_size=]|[tex_counts=], [tex_scale=], [tex_rot=], [tex_samples=], [tex_style=], [tex_taper=], [tex_inset=], ...);
// cyl(l|h, d1=, d2=, texture=, [tex_size=]|[tex_counts=], [tex_scale=], [tex_rot=], [tex_samples=], [tex_style=], [tex_taper=], [tex_inset=], ...); // cyl(l|h|length|height, d1=, d2=, texture=, [tex_size=]|[tex_counts=], [tex_scale=], [tex_rot=], [tex_samples=], [tex_style=], [tex_taper=], [tex_inset=], ...);
// //
// Topics: Cylinders, Textures, Rounding, Chamfers // Topics: Cylinders, Textures, Rounding, Chamfers
// //
@ -1206,7 +1209,7 @@ function cylinder(h, r1, r2, center, l, r, d, d1, d2, anchor, spin=0, orient=UP)
// stroke(arc(cp=[r2+8,-10], angle=[180-30,180], n=20, r=5), width=.18, endcaps="arrow2"); // stroke(arc(cp=[r2+8,-10], angle=[180-30,180], n=20, r=5), width=.18, endcaps="arrow2");
// } // }
// Arguments: // Arguments:
// l / h = Length of cylinder along oriented axis. Default: 1 // l / h / length / height = Length of cylinder along oriented axis. Default: 1
// r = Radius of cylinder. Default: 1 // r = Radius of cylinder. Default: 1
// center = If given, overrides `anchor`. A true value sets `anchor=CENTER`, false sets `anchor=DOWN`. // center = If given, overrides `anchor`. A true value sets `anchor=CENTER`, false sets `anchor=DOWN`.
// --- // ---
@ -1376,12 +1379,12 @@ function cyl(
from_end, from_end1, from_end2, from_end, from_end1, from_end2,
texture, tex_size=[5,5], tex_counts, texture, tex_size=[5,5], tex_counts,
tex_inset=false, tex_rot=false, tex_inset=false, tex_rot=false,
tex_scale=1, tex_samples, tex_scale=1, tex_samples, length, height,
tex_taper, tex_style="min_edge", tex_taper, tex_style="min_edge",
anchor, spin=0, orient=UP anchor, spin=0, orient=UP
) = ) =
let( let(
l = first_defined([l, h, length, height, 1]), l = one_defined([l, h, length, height],"l,h,length,height",dflt=1),
_r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=1), _r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=1),
_r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=1), _r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=1),
sides = segs(max(_r1,_r2)), sides = segs(max(_r1,_r2)),
@ -1497,11 +1500,11 @@ module cyl(
from_end, from_end1, from_end2, from_end, from_end1, from_end2,
texture, tex_size=[5,5], tex_counts, texture, tex_size=[5,5], tex_counts,
tex_inset=false, tex_rot=false, tex_inset=false, tex_rot=false,
tex_scale=1, tex_samples, tex_scale=1, tex_samples, length, height,
tex_taper, tex_style="min_edge", tex_taper, tex_style="min_edge",
anchor, spin=0, orient=UP anchor, spin=0, orient=UP
) { ) {
l = first_defined([l, h, 1]); l = one_defined([l, h, length, height],"l,h,length,height",dflt=1);
_r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=1); _r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=1);
_r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=1); _r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=1);
sides = segs(max(_r1,_r2)); sides = segs(max(_r1,_r2));
@ -1544,11 +1547,11 @@ module cyl(
// Creates a cylinder oriented along the X axis. // Creates a cylinder oriented along the X axis.
// //
// Usage: Typical // Usage: Typical
// xcyl(l|h, r|d=, [anchor=], ...) [ATTACHMENTS]; // xcyl(l|h|length|height, r|d=, [anchor=], ...) [ATTACHMENTS];
// xcyl(l|h, r1=|d1=, r2=|d2=, [anchor=], ...) [ATTACHMENTS]; // xcyl(l|h|length|height, r1=|d1=, r2=|d2=, [anchor=], ...) [ATTACHMENTS];
// //
// Arguments: // Arguments:
// l / h = Length of cylinder along oriented axis. Default: 1 // l / h / length / height = Length of cylinder along oriented axis. Default: 1
// r = Radius of cylinder. Default: 1 // r = Radius of cylinder. Default: 1
// --- // ---
// r1 = Optional radius of left (X-) end of cylinder. // r1 = Optional radius of left (X-) end of cylinder.
@ -1584,17 +1587,26 @@ module cyl(
// xcyl(l=35, d1=30, d2=10); // xcyl(l=35, d1=30, d2=10);
// } // }
module xcyl( function xcyl(
h, r, d, r1, r2, d1, d2, l, h, r, d, r1, r2, d1, d2, l,
chamfer, chamfer1, chamfer2, chamfer, chamfer1, chamfer2,
chamfang, chamfang1, chamfang2, chamfang, chamfang1, chamfang2,
rounding, rounding1, rounding2, rounding, rounding1, rounding2,
circum=false, realign=false, from_end=false, circum=false, realign=false, from_end=false, length, height,
anchor=CENTER, spin=0, orient=UP
) = no_function("xcyl");
module xcyl(
h, r, d, r1, r2, d1, d2, l,
chamfer, chamfer1, chamfer2,
chamfang, chamfang1, chamfang2,
rounding, rounding1, rounding2,
circum=false, realign=false, from_end=false, length, height,
anchor=CENTER, spin=0, orient=UP anchor=CENTER, spin=0, orient=UP
) { ) {
r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=1); r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=1);
r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=1); r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=1);
l = first_defined([l, h, 1]); l = one_defined([l,h,length,height],"l,h,length,height",1);
attachable(anchor,spin,orient, r1=r1, r2=r2, l=l, axis=RIGHT) { attachable(anchor,spin,orient, r1=r1, r2=r2, l=l, axis=RIGHT) {
cyl( cyl(
l=l, r1=r1, r2=r2, l=l, r1=r1, r2=r2,
@ -1615,11 +1627,11 @@ module xcyl(
// Creates a cylinder oriented along the Y axis. // Creates a cylinder oriented along the Y axis.
// //
// Usage: Typical // Usage: Typical
// ycyl(l|h, r|d=, [anchor=], ...) [ATTACHMENTS]; // ycyl(l|h|length|height, r|d=, [anchor=], ...) [ATTACHMENTS];
// ycyl(l|h, r1=|d1=, r2=|d2=, [anchor=], ...) [ATTACHMENTS]; // ycyl(l|h|length|height, r1=|d1=, r2=|d2=, [anchor=], ...) [ATTACHMENTS];
// //
// Arguments: // Arguments:
// l / h = Length of cylinder along oriented axis. (Default: `1.0`) // l / h / length / height = Length of cylinder along oriented axis. (Default: `1.0`)
// r = Radius of cylinder. // r = Radius of cylinder.
// --- // ---
// r1 = Radius of front (Y-) end of cone. // r1 = Radius of front (Y-) end of cone.
@ -1655,17 +1667,27 @@ module xcyl(
// ycyl(l=35, d1=30, d2=10); // ycyl(l=35, d1=30, d2=10);
// } // }
function ycyl(
h, r, d, r1, r2, d1, d2, l,
chamfer, chamfer1, chamfer2,
chamfang, chamfang1, chamfang2,
rounding, rounding1, rounding2,
circum=false, realign=false, from_end=false,height,length,
anchor=CENTER, spin=0, orient=UP
) = no_function("ycyl");
module ycyl( module ycyl(
h, r, d, r1, r2, d1, d2, l, h, r, d, r1, r2, d1, d2, l,
chamfer, chamfer1, chamfer2, chamfer, chamfer1, chamfer2,
chamfang, chamfang1, chamfang2, chamfang, chamfang1, chamfang2,
rounding, rounding1, rounding2, rounding, rounding1, rounding2,
circum=false, realign=false, from_end=false, circum=false, realign=false, from_end=false,height,length,
anchor=CENTER, spin=0, orient=UP anchor=CENTER, spin=0, orient=UP
) { ) {
r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=1); r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=1);
r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=1); r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=1);
l = first_defined([l, h, 1]); l = one_defined([l,h,length,height],"l,h,length,height",1);
attachable(anchor,spin,orient, r1=r1, r2=r2, l=l, axis=BACK) { attachable(anchor,spin,orient, r1=r1, r2=r2, l=l, axis=BACK) {
cyl( cyl(
l=l, r1=r1, r2=r2, l=l, r1=r1, r2=r2,
@ -1687,11 +1709,11 @@ module ycyl(
// Creates a cylinder oriented along the Z axis. // Creates a cylinder oriented along the Z axis.
// //
// Usage: Typical // Usage: Typical
// zcyl(l|h, r|d=, [anchor=],...) [ATTACHMENTS]; // zcyl(l|h|length|height, r|d=, [anchor=],...) [ATTACHMENTS];
// zcyl(l|h, r1=|d1=, r2=|d2=, [anchor=],...); // zcyl(l|h|length|height, r1=|d1=, r2=|d2=, [anchor=],...);
// //
// Arguments: // Arguments:
// l / h = Length of cylinder along oriented axis. (Default: 1.0) // l / h / length / height = Length of cylinder along oriented axis. (Default: 1.0)
// r = Radius of cylinder. // r = Radius of cylinder.
// --- // ---
// r1 = Radius of front (Y-) end of cone. // r1 = Radius of front (Y-) end of cone.
@ -1727,17 +1749,26 @@ module ycyl(
// zcyl(l=35, d1=30, d2=10); // zcyl(l=35, d1=30, d2=10);
// } // }
function zcyl(
h, r, d, r1, r2, d1, d2, l,
chamfer, chamfer1, chamfer2,
chamfang, chamfang1, chamfang2,
rounding, rounding1, rounding2,
circum=false, realign=false, from_end=false, length, height,
anchor=CENTER, spin=0, orient=UP
) = no_function("zcyl");
module zcyl( module zcyl(
h, r, d, r1, r2, d1, d2, l, h, r, d, r1, r2, d1, d2, l,
chamfer, chamfer1, chamfer2, chamfer, chamfer1, chamfer2,
chamfang, chamfang1, chamfang2, chamfang, chamfang1, chamfang2,
rounding, rounding1, rounding2, rounding, rounding1, rounding2,
circum=false, realign=false, from_end=false, circum=false, realign=false, from_end=false, length, height,
anchor=CENTER, spin=0, orient=UP anchor=CENTER, spin=0, orient=UP
) { ) {
r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=1); r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=1);
r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=1); r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=1);
l = first_defined([l, h, 1]); l = one_defined([l,h,length,height],"l,h,length,height",1);
attachable(anchor,spin,orient, r1=r1, r2=r2, l=l) { attachable(anchor,spin,orient, r1=r1, r2=r2, l=l) {
cyl( cyl(
l=l, r1=r1, r2=r2, l=l, r1=r1, r2=r2,
@ -1802,15 +1833,24 @@ module zcyl(
// Example: Standard Connectors // Example: Standard Connectors
// tube(h=30, or=40, wall=5) show_anchors(); // tube(h=30, or=40, wall=5) show_anchors();
function tube(
h, or, ir, center,
od, id, wall,
or1, or2, od1, od2,
ir1, ir2, id1, id2,
realign=false, l, length, height,
anchor, spin=0, orient=UP
) = no_function("tube");
module tube( module tube(
h, or, ir, center, h, or, ir, center,
od, id, wall, od, id, wall,
or1, or2, od1, od2, or1, or2, od1, od2,
ir1, ir2, id1, id2, ir1, ir2, id1, id2,
realign=false, l, realign=false, l, length, height,
anchor, spin=0, orient=UP anchor, spin=0, orient=UP
) { ) {
h = first_defined([h,l,1]); h = one_defined([h,l,height,length],"h,l,height,length",dflt=1);
orr1 = get_radius(r1=or1, r=or, d1=od1, d=od, dflt=undef); orr1 = get_radius(r1=or1, r=or, d1=od1, d=od, dflt=undef);
orr2 = get_radius(r1=or2, r=or, d1=od2, d=od, dflt=undef); orr2 = get_radius(r1=or2, r=or, d1=od2, d=od, dflt=undef);
irr1 = get_radius(r1=ir1, r=ir, d1=id1, d=id, dflt=undef); irr1 = get_radius(r1=ir1, r=ir, d1=id1, d=id, dflt=undef);
@ -1845,18 +1885,18 @@ module tube(
// Creates a pie slice shape. // Creates a pie slice shape.
// //
// Usage: As Module // Usage: As Module
// pie_slice(l|h, r, ang, [center]); // pie_slice(l|h=|height=|length=, r, ang, [center]);
// pie_slice(l|h, d=, ang=, ...); // pie_slice(l|h=|height=|length=, d=, ang=, ...);
// pie_slice(l|h, r1=|d1=, r2=|d2=, ang=, ...); // pie_slice(l|h=|height=|length=, r1=|d1=, r2=|d2=, ang=, ...);
// Usage: As Function // Usage: As Function
// vnf = pie_slice(l|h, r, ang, [center]); // vnf = pie_slice(l|h=|height=|length=, r, ang, [center]);
// vnf = pie_slice(l|h, d=, ang=, ...); // vnf = pie_slice(l|h=|height=|length=, d=, ang=, ...);
// vnf = pie_slice(l|h, r1=|d1=, r2=|d2=, ang=, ...); // vnf = pie_slice(l|h=|height=|length=, r1=|d1=, r2=|d2=, ang=, ...);
// Usage: Attaching Children // Usage: Attaching Children
// pie_slice(l|h, r, ang, ...) ATTACHMENTS; // pie_slice(l|h, r, ang, ...) ATTACHMENTS;
// //
// Arguments: // Arguments:
// h / l = height of pie slice. // h / l / height / length = height of pie slice.
// r = radius of pie slice. // r = radius of pie slice.
// ang = pie slice angle in degrees. // ang = pie slice angle in degrees.
// center = If given, overrides `anchor`. A true value sets `anchor=CENTER`, false sets `anchor=UP`. // center = If given, overrides `anchor`. A true value sets `anchor=CENTER`, false sets `anchor=UP`.
@ -1882,10 +1922,10 @@ module tube(
module pie_slice( module pie_slice(
h, r, ang=30, center, h, r, ang=30, center,
r1, r2, d, d1, d2, l, r1, r2, d, d1, d2, l, length, height,
anchor, spin=0, orient=UP anchor, spin=0, orient=UP
) { ) {
l = first_defined([l, h, 1]); l = one_defined([l, h,height,length],"l,h,height,length",dflt=1);
r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=10); r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=10);
r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=10); r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=10);
maxd = max(r1,r2)+0.1; maxd = max(r1,r2)+0.1;
@ -1905,11 +1945,11 @@ module pie_slice(
function pie_slice( function pie_slice(
h, r, ang=30, center, h, r, ang=30, center,
r1, r2, d, d1, d2, l, r1, r2, d, d1, d2, l, length, height,
anchor, spin=0, orient=UP anchor, spin=0, orient=UP
) = let( ) = let(
anchor = get_anchor(anchor, center, BOT, BOT), anchor = get_anchor(anchor, center, BOT, BOT),
l = first_defined([l, h, 1]), l = one_defined([l, h,height,length],"l,h,height,length",dflt=1),
r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=10), r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=10),
r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=10), r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=10),
maxd = max(r1,r2)+0.1, maxd = max(r1,r2)+0.1,
@ -2478,18 +2518,18 @@ function torus(
// Note that with caps, the chamfer must not be so big that it makes the cap height illegal. // Note that with caps, the chamfer must not be so big that it makes the cap height illegal.
// //
// Usage: Typical // Usage: Typical
// teardrop(h|l|length|height, r, [ang], [cap_h], [chamfer=], ...) [ATTACHMENTS]; // teardrop(h|l=|length=|height=, r, [ang], [cap_h], [chamfer=], ...) [ATTACHMENTS];
// teardrop(h|l|length|height, d=, [ang=], [cap_h=], [chamfer=], ...) [ATTACHMENTS]; // teardrop(h|l=|length=|height=, d=, [ang=], [cap_h=], [chamfer=], ...) [ATTACHMENTS];
// Usage: Psuedo-Conical // Usage: Psuedo-Conical
// teardrop(h|l, r1=, r2=, [ang=], [cap_h1=], [cap_h2=], ...) [ATTACHMENTS]; // teardrop(h|l=|height=|length=, r1=, r2=, [ang=], [cap_h1=], [cap_h2=], ...) [ATTACHMENTS];
// teardrop(h|l, d1=, d2=, [ang=], [cap_h1=], [cap_h2=], ...) [ATTACHMENTS]; // teardrop(h|l=|height=|length=, d1=, d2=, [ang=], [cap_h1=], [cap_h2=], ...) [ATTACHMENTS];
// Usage: As Function // Usage: As Function
// vnf = teardrop(h|l=, r|d=, [ang=], [cap_h=], ...); // vnf = teardrop(h|l=|height=|length=, r|d=, [ang=], [cap_h=], ...);
// vnf = teardrop(h|l=, r1=|d1=, r2=|d2=, [ang=], [cap_h=], ...); // vnf = teardrop(h|l=|height=|length=, r1=|d1=, r2=|d2=, [ang=], [cap_h=], ...);
// vnf = teardrop(h|l=, r1=|d1=, r2=|d2=, [ang=], [cap_h1=], [cap_h2=], ...); // vnf = teardrop(h|l=|height=|length=, r1=|d1=, r2=|d2=, [ang=], [cap_h1=], [cap_h2=], ...);
// //
// Arguments: // Arguments:
// h / l = Thickness of teardrop. Default: 1 // h / l / height / length = Thickness of teardrop. Default: 1
// r = Radius of circular part of teardrop. Default: 1 // r = Radius of circular part of teardrop. Default: 1
// ang = Angle of hat walls from the Z axis. Default: 45 degrees // ang = Angle of hat walls from the Z axis. Default: 45 degrees
// cap_h = If given, height above center where the shape will be truncated. Default: `undef` (no truncation) // cap_h = If given, height above center where the shape will be truncated. Default: `undef` (no truncation)
@ -2721,7 +2761,7 @@ function onion(r, ang=45, cap_h, d, anchor=CENTER, spin=0, orient=UP) =
// go to the Help menu and select "Font List". // go to the Help menu and select "Font List".
// Arguments: // Arguments:
// text = Text to create. // text = Text to create.
// h = Extrusion height for the text. Default: 1 // h / height / thickness = Extrusion height for the text. Default: 1
// size = The font will be created at this size divided by 0.72. Default: 10 // size = The font will be created at this size divided by 0.72. Default: 10
// font = Font to use. Default: "Liberation Sans" // font = Font to use. Default: "Liberation Sans"
// --- // ---
@ -2745,8 +2785,11 @@ function onion(r, ang=45, cap_h, d, anchor=CENTER, spin=0, orient=UP) =
// text3d("Foobar", h=2, anchor=str("baseline",CENTER)); // text3d("Foobar", h=2, anchor=str("baseline",CENTER));
// text3d("Foobar", h=2, anchor=str("baseline",BOTTOM+RIGHT)); // text3d("Foobar", h=2, anchor=str("baseline",BOTTOM+RIGHT));
module text3d(text, h=1, size=10, font="Helvetica", halign, valign, spacing=1.0, direction="ltr", language="em", script="latin", anchor="baseline[-1,0,-1]", spin=0, orient=UP) { module text3d(text, h, size=10, font="Helvetica", halign, valign, spacing=1.0, direction="ltr", language="em", script="latin",
height, thickness,
anchor="baseline[-1,0,-1]", spin=0, orient=UP) {
no_children($children); no_children($children);
h = one_defined([h,height,thickness],"h,height,thickness",dflt=1);
dummy1 = dummy1 =
assert(is_undef(anchor) || is_vector(anchor) || is_string(anchor), str("Got: ",anchor)) assert(is_undef(anchor) || is_vector(anchor) || is_string(anchor), str("Got: ",anchor))
assert(is_undef(spin) || is_vector(spin,3) || is_num(spin), str("Got: ",spin)) assert(is_undef(spin) || is_vector(spin,3) || is_num(spin), str("Got: ",spin))
@ -2814,7 +2857,7 @@ function _cut_interp(pathcut, path, data) =
// Module: path_text() // Module: path_text()
// Usage: // Usage:
// path_text(path, text, [size], [thickness], [font], [lettersize], [offset], [reverse], [normal], [top], [textmetrics], [kern]) // path_text(path, text, [size], [thickness], [font], [lettersize=], [offset=], [reverse=], [normal=], [top=], [textmetrics=], [kern=])
// Description: // Description:
// Place the text letter by letter onto the specified path using textmetrics (if available and requested) // Place the text letter by letter onto the specified path using textmetrics (if available and requested)
// or user specified letter spacing. The path can be 2D or 3D. In 2D the text appears along the path with letters upright // or user specified letter spacing. The path can be 2D or 3D. In 2D the text appears along the path with letters upright
@ -2866,8 +2909,8 @@ function _cut_interp(pathcut, path, data) =
// Arguments: // Arguments:
// path = path to place the text on // path = path to place the text on
// text = text to create // text = text to create
// size = The font will be created at this size divided by 0.72. Default: 10 // size = The font will be created at this size divided by 0.72.
// thickness = thickness of letters (not allowed for 2D path) // thickness / h / height = thickness of letters (not allowed for 2D path)
// font = font to use. Default: "Liberation Sans" // font = font to use. Default: "Liberation Sans"
// --- // ---
// lettersize = scalar or array giving size of letters // lettersize = scalar or array giving size of letters
@ -2940,22 +2983,23 @@ function _cut_interp(pathcut, path, data) =
// kern = [1,1.2,1,1,.3,-.2,1,0,.8,1,1.1,1]; // kern = [1,1.2,1,1,.3,-.2,1,0,.8,1,1.1,1];
// path_text(path, "Example text", font="Courier", size=5, lettersize = 5/1.2, kern=kern, normal=UP); // path_text(path, "Example text", font="Courier", size=5, lettersize = 5/1.2, kern=kern, normal=UP);
module path_text(path, text, font, size, thickness, lettersize, offset=0, reverse=false, normal, top, center=false, textmetrics=false, kern=0) module path_text(path, text, font, size, thickness, lettersize, offset=0, reverse=false, normal, top, center=false, textmetrics=false, kern=0, height,h)
{ {
no_children($children); no_children($children);
dummy2=assert(is_path(path,[2,3]),"Must supply a 2d or 3d path") dummy2=assert(is_path(path,[2,3]),"Must supply a 2d or 3d path")
assert(num_defined([normal,top])<=1, "Cannot define both \"normal\" and \"top\""); assert(num_defined([normal,top])<=1, "Cannot define both \"normal\" and \"top\"")
assert(all_positive([size]), "Must give positive text size");
dim = len(path[0]); dim = len(path[0]);
normalok = is_undef(normal) || is_vector(normal,3) || (is_path(normal,3) && len(normal)==len(path)); normalok = is_undef(normal) || is_vector(normal,3) || (is_path(normal,3) && len(normal)==len(path));
topok = is_undef(top) || is_vector(top,dim) || (dim==2 && is_vector(top,3) && top[2]==0) topok = is_undef(top) || is_vector(top,dim) || (dim==2 && is_vector(top,3) && top[2]==0)
|| (is_path(top,dim) && len(top)==len(path)); || (is_path(top,dim) && len(top)==len(path));
dummy4 = assert(dim==3 || is_undef(thickness), "Cannot give a thickness with 2d path") dummy4 = assert(dim==3 || !any_defined([thickness,h,height]), "Cannot give a thickness or height with 2d path")
assert(dim==3 || !reverse, "Reverse not allowed with 2d path") assert(dim==3 || !reverse, "Reverse not allowed with 2d path")
assert(dim==3 || offset==0, "Cannot give offset with 2d path") assert(dim==3 || offset==0, "Cannot give offset with 2d path")
assert(dim==3 || is_undef(normal), "Cannot define \"normal\" for a 2d path, only \"top\"") assert(dim==3 || is_undef(normal), "Cannot define \"normal\" for a 2d path, only \"top\"")
assert(normalok,"\"normal\" must be a vector or path compatible with the given path") assert(normalok,"\"normal\" must be a vector or path compatible with the given path")
assert(topok,"\"top\" must be a vector or path compatible with the given path"); assert(topok,"\"top\" must be a vector or path compatible with the given path");
thickness = first_defined([thickness,1]); thickness = one_defined([thickness,h,height],"thickness,h,height",dflt=1);
normal = is_vector(normal) ? repeat(normal, len(path)) normal = is_vector(normal) ? repeat(normal, len(path))
: is_def(normal) ? normal : is_def(normal) ? normal
: undef; : undef;
@ -3031,10 +3075,10 @@ module path_text(path, text, font, size, thickness, lettersize, offset=0, revers
// //
// Usage: Typical // Usage: Typical
// interior_fillet(l, r, [ang], [overlap], ...) [ATTACHMENTS]; // interior_fillet(l, r, [ang], [overlap], ...) [ATTACHMENTS];
// interior_fillet(l, d=, [ang=], [overlap=], ...) [ATTACHMENTS]; // interior_fillet(l|length=|h=|height=, d=, [ang=], [overlap=], ...) [ATTACHMENTS];
// //
// Arguments: // Arguments:
// l = Length of edge to fillet. // l / length / h / height = Length of edge to fillet.
// r = Radius of fillet. // r = Radius of fillet.
// ang = Angle between faces to fillet. // ang = Angle between faces to fillet.
// overlap = Overlap size for unioning with faces. // overlap = Overlap size for unioning with faces.
@ -3070,7 +3114,8 @@ module path_text(path, text, font, size, thickness, lettersize, offset=0, revers
// interior_fillet(l=50, r=10, spin=180, orient=RIGHT); // interior_fillet(l=50, r=10, spin=180, orient=RIGHT);
// } // }
module interior_fillet(l=1.0, r, ang=90, overlap=0.01, d, anchor=CENTER, spin=0, orient=UP) { module interior_fillet(l=1.0, r, ang=90, overlap=0.01, d, length, h, height, anchor=CENTER, spin=0, orient=UP) {
l = one_defined([l,length,h,height],"l,length,h,height");
r = get_radius(r=r, d=d, dflt=1); r = get_radius(r=r, d=d, dflt=1);
steps = ceil(segs(r)*(180-ang)/360); steps = ceil(segs(r)*(180-ang)/360);
arc = arc(n=steps+1, r=r, corner=[polar_to_xy(r,ang),[0,0],[r,0]]); arc = arc(n=steps+1, r=r, corner=[polar_to_xy(r,ang),[0,0],[r,0]]);
@ -3224,9 +3269,9 @@ function heightfield(data, size=[100,100], bottom=-20, maxz=100, xrange=[-1:0.04
// Function&Module: cylindrical_heightfield() // Function&Module: cylindrical_heightfield()
// Usage: As Function // Usage: As Function
// vnf = cylindrical_heightfield(data, l, r|d=, [base=], [transpose=], [aspect=]); // vnf = cylindrical_heightfield(data, l|length=|h=|height=, r|d=, [base=], [transpose=], [aspect=]);
// Usage: As Module // Usage: As Module
// cylindrical_heightfield(data, l, r|d=, [base=], [transpose=], [aspect=]) [ATTACHMENTS]; // cylindrical_heightfield(data, l|length=|h=|height=, r|d=, [base=], [transpose=], [aspect=]) [ATTACHMENTS];
// Topics: Extrusion, Textures, Knurling, Heightfield // Topics: Extrusion, Textures, Knurling, Heightfield
// Description: // Description:
// Given a regular rectangular 2D grid of scalar values, or a function literal of signature (x,y), generates // Given a regular rectangular 2D grid of scalar values, or a function literal of signature (x,y), generates
@ -3236,7 +3281,7 @@ function heightfield(data, size=[100,100], bottom=-20, maxz=100, xrange=[-1:0.04
// https://raw.githubusercontent.com/revarbat/BOSL2/master/scripts/img2scad.py // https://raw.githubusercontent.com/revarbat/BOSL2/master/scripts/img2scad.py
// Arguments: // Arguments:
// data = This is either the 2D rectangular array of heights, or a function literal of signature `(x, y)`. // data = This is either the 2D rectangular array of heights, or a function literal of signature `(x, y)`.
// l = The length of the cylinder to wrap around. // l / length / h / height = The length of the cylinder to wrap around.
// r = The radius of the cylinder to wrap around. // r = The radius of the cylinder to wrap around.
// --- // ---
// r1 = The radius of the bottom of the cylinder to wrap around. // r1 = The radius of the bottom of the cylinder to wrap around.
@ -3286,11 +3331,11 @@ function cylindrical_heightfield(
style="min_edge", maxh=99, style="min_edge", maxh=99,
xrange=[-1:0.01:1], xrange=[-1:0.01:1],
yrange=[-1:0.01:1], yrange=[-1:0.01:1],
r1, r2, d, d1, d2, h, height, r1, r2, d, d1, d2, h, height, length,
anchor=CTR, spin=0, orient=UP anchor=CTR, spin=0, orient=UP
) = ) =
let( let(
l = first_defined([l, h, height]), l = one_defined([l, h, height, length], "l,h,height,l"),
r1 = get_radius(r1=r1, r=r, d1=d1, d=d), r1 = get_radius(r1=r1, r=r, d1=d1, d=d),
r2 = get_radius(r1=r2, r=r, d1=d2, d=d) r2 = get_radius(r1=r2, r=r, d1=d2, d=d)
) )
@ -3349,10 +3394,10 @@ module cylindrical_heightfield(
transpose=false, aspect=1, transpose=false, aspect=1,
style="min_edge", convexity=10, style="min_edge", convexity=10,
xrange=[-1:0.01:1], yrange=[-1:0.01:1], xrange=[-1:0.01:1], yrange=[-1:0.01:1],
maxh=99, r1, r2, d, d1, d2, h, height, maxh=99, r1, r2, d, d1, d2, h, height, length,
anchor=CTR, spin=0, orient=UP anchor=CTR, spin=0, orient=UP
) { ) {
l = first_defined([l, h, height]); l = one_defined([l, h, height, length], "l,h,height,length");
r1 = get_radius(r1=r1, r=r, d1=d1, d=d); r1 = get_radius(r1=r1, r=r, d1=d1, d=d);
r2 = get_radius(r1=r2, r=r, d1=d2, d=d); r2 = get_radius(r1=r2, r=r, d1=d2, d=d);
vnf = cylindrical_heightfield( vnf = cylindrical_heightfield(

View file

@ -518,7 +518,7 @@ function skin(profiles, slices, refine=1, method="direct", sampling, caps, close
// twisted extrusions by using `maxseg` to subsample flat faces. // twisted extrusions by using `maxseg` to subsample flat faces.
// Arguments: // Arguments:
// region = The 2D [Region](regions.scad) or polygon that is to be extruded. // region = The 2D [Region](regions.scad) or polygon that is to be extruded.
// h / height = The height to extrude the region. Default: 1 // h / height / l / length = The height to extrude the region. Default: 1
// center = If true, the created polyhedron will be vertically centered. If false, it will be extruded upwards from the XY plane. Default: `false` // center = If true, the created polyhedron will be vertically centered. If false, it will be extruded upwards from the XY plane. Default: `false`
// --- // ---
// twist = The number of degrees to rotate the top of the shape, clockwise around the Z axis, relative to the bottom. Default: 0 // twist = The number of degrees to rotate the top of the shape, clockwise around the Z axis, relative to the bottom. Default: 0
@ -625,28 +625,61 @@ function skin(profiles, slices, refine=1, method="direct", sampling, caps, close
// ] // ]
// ]; // ];
// linear_sweep(path, texture=tex, tex_size=[5,5], h=40); // linear_sweep(path, texture=tex, tex_size=[5,5], h=40);
// Example: VNF tile that has no top/bottom edges and produces a disconnected result
// shape = skin([
// rect(2/5),
// rect(2/3),
// rect(2/5)
// ],
// z=[0,1/2,1],
// slices=0,
// caps=false);
// tile = move([0,1/2,2/3],yrot(90,shape));
// linear_sweep(
// circle(20), texture=tile,
// tex_size=[10,10],tex_scale=5,
// h=40,convexity=4);
// Example: As Function // Example: As Function
// path = glued_circles(r=15, spread=40, tangent=45); // path = glued_circles(r=15, spread=40, tangent=45);
// vnf = linear_sweep( // vnf = linear_sweep(
// path, h=40, texture="trunc_pyramids", tex_size=[5,5], // path, h=40, texture="trunc_pyramids", tex_size=[5,5],
// tex_scale=1, style="convex"); // tex_scale=1, style="convex");
// vnf_polyhedron(vnf, convexity=10); // vnf_polyhedron(vnf, convexity=10);
// Example: VNF tile that has no top/bottom edges and produces a disconnected result
// shape = skin([rect(2/5),
// rect(2/3),
// rect(2/5)],
// z=[0,1/2,1],
// slices=0,
// caps=false);
// tile = move([0,1/2,2/3],yrot(90,shape));
// linear_sweep(circle(20), texture=tile,
// tex_size=[10,10],tex_scale=5,
// h=40,convexity=4);
// Example: The same tile from above, turned 90 degrees, creates problems at the ends, because the end cap is not a connected polygon. When the ends are disconnected you may find that some parts of the end cap are missing and spurious polygons included.
// shape = skin([rect(2/5),
// rect(2/3),
// rect(2/5)],
// z=[0,1/2,1],
// slices=0,
// caps=false);
// tile = move([1/2,1,2/3],xrot(90,shape));
// linear_sweep(circle(20), texture=tile,
// tex_size=[30,20],tex_scale=15,
// h=40,convexity=4);
// Example: This example shoes some endcap polygons missing and a spurious triangle
// shape = skin([rect(2/5),
// rect(2/3),
// rect(2/5)],
// z=[0,1/2,1],
// slices=0,
// caps=false);
// tile = xscale(.5,move([1/2,1,2/3],xrot(90,shape)));
// doubletile = vnf_join([tile, right(.5,tile)]);
// linear_sweep(circle(20), texture=doubletile,
// tex_size=[45,45],tex_scale=15, h=40);
// Example: You can fix ends for disconnected cases using {{top_half()}} and {{bottom_half()}}
// shape = skin([rect(2/5),
// rect(2/3),
// rect(2/5)],
// z=[0,1/2,1],
// slices=0,
// caps=false);
// tile = move([1/2,1,2/3],xrot(90,shape));
// vnf_polyhedron(
// top_half(
// bottom_half(
// linear_sweep(circle(20), texture=tile,
// tex_size=[30,20],tex_scale=15,
// h=40.2,caps=false),
// z=20),
// z=-20));
module linear_sweep( module linear_sweep(
region, height, center, region, height, center,
@ -655,10 +688,10 @@ module linear_sweep(
texture, tex_size=[5,5], tex_counts, texture, tex_size=[5,5], tex_counts,
tex_inset=false, tex_rot=false, tex_inset=false, tex_rot=false,
tex_scale=1, tex_samples, tex_scale=1, tex_samples,
cp, atype="hull", h, cp, atype="hull", h,l,length,
anchor, spin=0, orient=UP anchor, spin=0, orient=UP
) { ) {
h = first_defined([h, height, 1]); h = one_defined([h, height,l,length],"h,height,l,length",dflt=1);
region = force_region(region); region = force_region(region);
check = assert(is_region(region),"Input is not a region"); check = assert(is_region(region),"Input is not a region");
anchor = center==true? "origin" : anchor = center==true? "origin" :
@ -706,7 +739,7 @@ function linear_sweep(
cp, atype="hull", h, cp, atype="hull", h,
texture, tex_size=[5,5], tex_counts, texture, tex_size=[5,5], tex_counts,
tex_inset=false, tex_rot=false, tex_inset=false, tex_rot=false,
tex_scale=1, tex_samples, tex_scale=1, tex_samples, h, l, length,
anchor, spin=0, orient=UP anchor, spin=0, orient=UP
) = ) =
let( region = force_region(region) ) let( region = force_region(region) )
@ -715,7 +748,7 @@ function linear_sweep(
assert(is_vector(shift, 2), str(shift)) assert(is_vector(shift, 2), str(shift))
assert(is_bool(caps) || is_bool_list(caps,2), "caps must be boolean or a list of two booleans") assert(is_bool(caps) || is_bool_list(caps,2), "caps must be boolean or a list of two booleans")
let( let(
h = first_defined([h, height, 1]) h = one_defined([h, height,l,length],"h,height,l,length",dflt=1)
) )
!is_undef(texture)? _textured_linear_sweep( !is_undef(texture)? _textured_linear_sweep(
region, h=h, caps=caps, region, h=h, caps=caps,

View file

@ -1023,7 +1023,11 @@ function _vnf_centroid(vnf,eps=EPSILON) =
// vnf as usual (with closed=false) and boundary is a list giving each connected component of the cut // vnf as usual (with closed=false) and boundary is a list giving each connected component of the cut
// boundary surface. Each entry in boundary is a list of index values that index into the vnf vertex list (vnf[0]). // boundary surface. Each entry in boundary is a list of index values that index into the vnf vertex list (vnf[0]).
// This makes it possible to construct mating shapes, e.g. with {{skin()}} or {{vnf_vertex_array()}} that // This makes it possible to construct mating shapes, e.g. with {{skin()}} or {{vnf_vertex_array()}} that
// can be combined using {{vnf_join()}} to make a valid polyhedron. // can be combined using {{vnf_join()}} to make a valid polyhedron.
// .
// Note that the input to vnf_halfspace() does not need to be a closed, manifold polyhedron.
// Because it adds the faces on the cut surface, you can use vnf_halfspace() to cap off an open shape if you
// slice through a region that excludes all of the gaps in the input VNF.
// Arguments: // Arguments:
// plane = plane defining the boundary of the half space // plane = plane defining the boundary of the half space
// vnf = vnf to cut // vnf = vnf to cut
@ -1088,6 +1092,17 @@ function _vnf_centroid(vnf,eps=EPSILON) =
// vnf=bezier_vnf(patch); // vnf=bezier_vnf(patch);
// vnfcut = vnf_halfspace([-.8,0,-1,-14],vnf,closed=false); // vnfcut = vnf_halfspace([-.8,0,-1,-14],vnf,closed=false);
// vnf_polyhedron(vnfcut); // vnf_polyhedron(vnfcut);
// Example: Here is a VNF that has holes, so it is not a valid manifold.
// outside = linear_sweep(circle(r=30), h=100, caps=false);
// inside = yrot(7,linear_sweep(circle(r=10), h=120, caps=false));
// open_vnf=vnf_join([outside, vnf_reverse_faces(inside)]);
// vnf_polyhedron(open_vnf);
// Example: By cutting it at each end we can create closing faces, resulting in a valid manifold without holes.
// outside = linear_sweep(circle(r=30), h=100, caps=false);
// inside = yrot(11,linear_sweep(circle(r=10), h=120, caps=false));
// open_vnf=vnf_join([outside, vnf_reverse_faces(inside)]);
// vnf = vnf_halfspace([0,0,1,5], vnf_halfspace([0,.7,-1,-75], open_vnf));
// vnf_polyhedron(vnf);
// Example: If boundary=true then the return is a list with the VNF and boundary data. // Example: If boundary=true then the return is a list with the VNF and boundary data.
// vnf = path_sweep(circle(r=4, $fn=16), // vnf = path_sweep(circle(r=4, $fn=16),
// circle(r=20, $fn=64),closed=true); // circle(r=20, $fn=64),closed=true);