From 49dbed3eb4810c24ef3831734a2e8c26cbb430d6 Mon Sep 17 00:00:00 2001 From: Alex Matulich Date: Sun, 6 Jul 2025 21:10:41 -0700 Subject: [PATCH 1/5] xcyl(), ycyl(), zcyl() pass through all parameters to cyl() --- shapes3d.scad | 338 +++++++++++++++++++++++++++++--------------------- 1 file changed, 194 insertions(+), 144 deletions(-) diff --git a/shapes3d.scad b/shapes3d.scad index 50f4def5..20241811 100644 --- a/shapes3d.scad +++ b/shapes3d.scad @@ -2516,49 +2516,25 @@ module cyl( -// Module: xcyl() -// Synopsis: creates a cylinder oriented along the X axis. -// SynTags: Geom +// Function&Module: xcyl() +// Synopsis: Creates a cylinder oriented along the X axis. +// SynTags: Geom, VNF // Topics: Cylinders, Textures, Rounding, Chamfers // See Also: texture(), rotate_sweep(), cyl() -// Description: -// Creates an attachable cylinder with roundovers and chamfering oriented along the X axis. -// // Usage: Typical // xcyl(l|h|length|height, r|d=, [anchor=], ...) [ATTACHMENTS]; // xcyl(l|h|length|height, r1=|d1=, r2=|d2=, [anchor=], ...) [ATTACHMENTS]; -// -// Arguments: -// l / h / length / height = Length of cylinder along oriented axis. Default: 1 -// r = Radius of cylinder. Default: 1 -// --- -// r1 = Optional radius of left (X-) end of cylinder. -// r2 = Optional radius of right (X+) end of cylinder. -// d = Optional diameter of cylinder. (use instead of `r`) -// d1 = Optional diameter of left (X-) end of cylinder. -// d2 = Optional diameter of right (X+) end of cylinder. -// circum = If true, cylinder should circumscribe the circle of the given size. Otherwise inscribes. Default: `false` -// chamfer = The size of the chamfers on the ends of the cylinder. Default: none. -// chamfer1 = The size of the chamfer on the left end of the cylinder. Default: none. -// chamfer2 = The size of the chamfer on the right end of the cylinder. Default: none. -// chamfang = The angle in degrees of the chamfers on the ends of the cylinder. -// chamfang1 = The angle in degrees of the chamfer on the left end of the cylinder. -// chamfang2 = The angle in degrees of the chamfer on the right end of the cylinder. -// from_end = If true, chamfer is measured from the end of the cylinder, instead of inset from the edge. Default: `false`. -// rounding = The radius of the rounding on the ends of the cylinder. Default: none. -// rounding1 = The radius of the rounding on the left end of the cylinder. -// rounding2 = The radius of the rounding on the right end of the cylinder. -// realign = If true, rotate the cylinder by half the angle of one face. -// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER` -// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0` -// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP` -// +// Description: +// Creates an attachable cylinder with roundovers, chamfering, and optional texture, oriented along the X axis. +// . +// This is a shortcut for `cyl()` with `orient=RIGHT`, but otherwise using the same arguments. +// . +// See [cyl()] for more detailed usage and arguments. // Example: By Radius // ydistribute(50) { // xcyl(l=35, r=10); // xcyl(l=35, r1=15, r2=5); // } -// // Example: By Diameter // ydistribute(50) { // xcyl(l=35, d=20); @@ -2566,82 +2542,98 @@ module cyl( // } function xcyl( - h, r, d, r1, r2, d1, d2, l, + h, r, center, + l, r1, r2, + d, d1, d2, + length, height, 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("xcyl"); + circum=false, realign=false, shift=[0,0], + teardrop=false, clip_angle, + from_end, from_end1, from_end2, + texture, tex_size=[5,5], tex_reps, tex_counts, + tex_inset=false, tex_rot=0, + tex_scale, tex_depth, tex_samples, length, height, + tex_taper, style, tex_style, + extra, extra1, extra2, + anchor, spin=0 +) = cyl(h, r, center, + l, r1, r2, + d, d1, d2, + length, height, + chamfer, chamfer1, chamfer2, + chamfang, chamfang1, chamfang2, + rounding, rounding1, rounding2, + circum, realign, shift, + teardrop, clip_angle, + from_end, from_end1, from_end2, + texture, tex_size, tex_reps, tex_counts, + tex_inset, tex_rot, + tex_scale, tex_depth, tex_samples, length, height, + tex_taper, style, tex_style, + extra, extra1, extra2, + anchor, spin, orient=RIGHT); module xcyl( - h, r, d, r1, r2, d1, d2, l, + h, r, center, + l, r1, r2, + d, d1, d2, chamfer, chamfer1, chamfer2, chamfang, chamfang1, chamfang2, rounding, rounding1, rounding2, - circum=false, realign=false, from_end=false, length, height, - anchor=CENTER, spin=0, orient=UP + circum=false, realign=false, shift=[0,0], + teardrop=false, clip_angle, + from_end, from_end1, from_end2, + texture, tex_size=[5,5], tex_reps, tex_counts, + tex_inset=false, tex_rot=0, + tex_scale, tex_depth, tex_samples, length, height, + tex_taper, style, tex_style, + extra, extra1, extra2, + anchor, spin=0 ) { 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); 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=UP, r1=r1, r2=r2, l=l, axis=RIGHT) { cyl( - l=l, r1=r1, r2=r2, - chamfer=chamfer, chamfer1=chamfer1, chamfer2=chamfer2, - chamfang=chamfang, chamfang1=chamfang1, chamfang2=chamfang2, - rounding=rounding, rounding1=rounding1, rounding2=rounding2, - circum=circum, realign=realign, from_end=from_end, - anchor=CENTER, orient=RIGHT + undef, undef, center, // h,r,center + l, r1, r2, + undef, undef, undef, // d,d1,d2 + chamfer, chamfer1, chamfer2, + chamfang, chamfang1, chamfang2, + rounding, rounding1, rounding2, + circum, realign, shift, + teardrop, clip_angle, + from_end, from_end1, from_end2, + texture, tex_size, tex_reps, tex_counts, + tex_inset, tex_rot, + tex_scale, tex_depth, tex_samples, length, height, + tex_taper, style, tex_style, + extra, extra1, extra2, + anchor, spin, orient=RIGHT ); children(); } } -// Module: ycyl() +// Function&Module: ycyl() // Synopsis: Creates a cylinder oriented along the y axis. -// SynTags: Geom +// SynTags: Geom, VNF // Topics: Cylinders, Textures, Rounding, Chamfers // See Also: texture(), rotate_sweep(), cyl() // Description: -// Creates an attachable cylinder with roundovers and chamfering oriented along the y axis. -// -// Usage: Typical -// ycyl(l|h|length|height, r|d=, [anchor=], ...) [ATTACHMENTS]; -// ycyl(l|h|length|height, r1=|d1=, r2=|d2=, [anchor=], ...) [ATTACHMENTS]; -// -// Arguments: -// l / h / length / height = Length of cylinder along oriented axis. (Default: `1.0`) -// r = Radius of cylinder. -// --- -// r1 = Radius of front (Y-) end of cone. -// r2 = Radius of back (Y+) end of one. -// d = Diameter of cylinder. -// d1 = Diameter of front (Y-) end of one. -// d2 = Diameter of back (Y+) end of one. -// circum = If true, cylinder should circumscribe the circle of the given size. Otherwise inscribes. Default: `false` -// chamfer = The size of the chamfers on the ends of the cylinder. Default: none. -// chamfer1 = The size of the chamfer on the front end of the cylinder. Default: none. -// chamfer2 = The size of the chamfer on the back end of the cylinder. Default: none. -// chamfang = The angle in degrees of the chamfers on the ends of the cylinder. -// chamfang1 = The angle in degrees of the chamfer on the front end of the cylinder. -// chamfang2 = The angle in degrees of the chamfer on the back end of the cylinder. -// from_end = If true, chamfer is measured from the end of the cylinder, instead of inset from the edge. Default: `false`. -// rounding = The radius of the rounding on the ends of the cylinder. Default: none. -// rounding1 = The radius of the rounding on the front end of the cylinder. -// rounding2 = The radius of the rounding on the back end of the cylinder. -// realign = If true, rotate the cylinder by half the angle of one face. -// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER` -// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0` -// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP` -// +// Creates an attachable cylinder with roundovers, chamfering, and optional texture, oriented along the Y axis. +// . +// This is a shortcut for `cyl()` with `orient=BACK`, but otherwise using the same arguments. +// . +// See [cyl()] for more detailed usage and arguments. // Example: By Radius // xdistribute(50) { // ycyl(l=35, r=10); // ycyl(l=35, r1=15, r2=5); // } -// // Example: By Diameter // xdistribute(50) { // ycyl(l=35, d=20); @@ -2649,84 +2641,99 @@ module xcyl( // } function ycyl( - h, r, d, r1, r2, d1, d2, l, + h, r, center, + l, r1, r2, + d, d1, d2, + length, height, 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"); + circum=false, realign=false, shift=[0,0], + teardrop=false, clip_angle, + from_end, from_end1, from_end2, + texture, tex_size=[5,5], tex_reps, tex_counts, + tex_inset=false, tex_rot=0, + tex_scale, tex_depth, tex_samples, length, height, + tex_taper, style, tex_style, + extra, extra1, extra2, + anchor, spin=0 +) = cyl(h, r, center, + l, r1, r2, + d, d1, d2, + length, height, + chamfer, chamfer1, chamfer2, + chamfang, chamfang1, chamfang2, + rounding, rounding1, rounding2, + circum, realign, shift, + teardrop, clip_angle, + from_end, from_end1, from_end2, + texture, tex_size, tex_reps, tex_counts, + tex_inset, tex_rot, + tex_scale, tex_depth, tex_samples, length, height, + tex_taper, style, tex_style, + extra, extra1, extra2, + anchor, spin, orient=BACK); module ycyl( - h, r, d, r1, r2, d1, d2, l, + h, r, center, + l, r1, r2, + d, d1, d2, chamfer, chamfer1, chamfer2, chamfang, chamfang1, chamfang2, rounding, rounding1, rounding2, - circum=false, realign=false, from_end=false,height,length, - anchor=CENTER, spin=0, orient=UP + circum=false, realign=false, shift=[0,0], + teardrop=false, clip_angle, + from_end, from_end1, from_end2, + texture, tex_size=[5,5], tex_reps, tex_counts, + tex_inset=false, tex_rot=0, + tex_scale, tex_depth, tex_samples, length, height, + tex_taper, style, tex_style, + extra, extra1, extra2, + anchor, spin=0 ) { 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); 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=UP, r1=r1, r2=r2, l=l, axis=BACK) { cyl( - l=l, r1=r1, r2=r2, - chamfer=chamfer, chamfer1=chamfer1, chamfer2=chamfer2, - chamfang=chamfang, chamfang1=chamfang1, chamfang2=chamfang2, - rounding=rounding, rounding1=rounding1, rounding2=rounding2, - circum=circum, realign=realign, from_end=from_end, - anchor=CENTER, orient=BACK + undef, undef, center, // h,r,center + l, r1, r2, + undef, undef, undef, // d,d1,d2 + chamfer, chamfer1, chamfer2, + chamfang, chamfang1, chamfang2, + rounding, rounding1, rounding2, + circum, realign, shift, + teardrop, clip_angle, + from_end, from_end1, from_end2, + texture, tex_size, tex_reps, tex_counts, + tex_inset, tex_rot, + tex_scale, tex_depth, tex_samples, length, height, + tex_taper, style, tex_style, + extra, extra1, extra2, + anchor, orient=BACK ); children(); } } - // Module: zcyl() -// Synopsis: Creates a cylinder oriented along the Z axis. -// SynTags: Geom +// Synopsis: Creates a cylinder oriented along the y axis. +// SynTags: Geom, VNF // Topics: Cylinders, Textures, Rounding, Chamfers // See Also: texture(), rotate_sweep(), cyl() // Description: -// Creates an attachable cylinder with roundovers and chamfering oriented along the Z axis. -// -// Usage: Typical -// zcyl(l|h|length|height, r|d=, [anchor=],...) [ATTACHMENTS]; -// zcyl(l|h|length|height, r1=|d1=, r2=|d2=, [anchor=],...); -// -// Arguments: -// l / h / length / height = Length of cylinder along oriented axis. (Default: 1.0) -// r = Radius of cylinder. -// --- -// r1 = Radius of front (Y-) end of cone. -// r2 = Radius of back (Y+) end of one. -// d = Diameter of cylinder. -// d1 = Diameter of front (Y-) end of one. -// d2 = Diameter of back (Y+) end of one. -// circum = If true, cylinder should circumscribe the circle of the given size. Otherwise inscribes. Default: `false` -// chamfer = The size of the chamfers on the ends of the cylinder. Default: none. -// chamfer1 = The size of the chamfer on the bottom end of the cylinder. Default: none. -// chamfer2 = The size of the chamfer on the top end of the cylinder. Default: none. -// chamfang = The angle in degrees of the chamfers on the ends of the cylinder. -// chamfang1 = The angle in degrees of the chamfer on the bottom end of the cylinder. -// chamfang2 = The angle in degrees of the chamfer on the top end of the cylinder. -// from_end = If true, chamfer is measured from the end of the cylinder, instead of inset from the edge. Default: `false`. -// rounding = The radius of the rounding on the ends of the cylinder. Default: none. -// rounding1 = The radius of the rounding on the bottom end of the cylinder. -// rounding2 = The radius of the rounding on the top end of the cylinder. -// realign = If true, rotate the cylinder by half the angle of one face. -// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER` -// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0` -// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP` -// +// Pass-through to [cyl()]. Creates an attachable cylinder with roundovers, chamfering, and optional texture, oriented along the Z axis. +// . +// This is a shortcut for `cyl()` with `orient=UP` (which is also the default for [cyl()]), but otherwise using the same arguments. +// . +// See [cyl()] for more detailed usage and arguments. // Example: By Radius // xdistribute(50) { // zcyl(l=35, r=10); // zcyl(l=35, r1=15, r2=5); // } -// // Example: By Diameter // xdistribute(50) { // zcyl(l=35, d=20); @@ -2734,33 +2741,76 @@ module ycyl( // } function zcyl( - h, r, d, r1, r2, d1, d2, l, + h, r, center, + l, r1, r2, + d, d1, d2, + length, height, 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"); + circum=false, realign=false, shift=[0,0], + teardrop=false, clip_angle, + from_end, from_end1, from_end2, + texture, tex_size=[5,5], tex_reps, tex_counts, + tex_inset=false, tex_rot=0, + tex_scale, tex_depth, tex_samples, length, height, + tex_taper, style, tex_style, + extra, extra1, extra2, + anchor, spin=0 +) = cyl(h, r, center, + l, r1, r2, + d, d1, d2, + length, height, + chamfer, chamfer1, chamfer2, + chamfang, chamfang1, chamfang2, + rounding, rounding1, rounding2, + circum, realign, shift, + teardrop, clip_angle, + from_end, from_end1, from_end2, + texture, tex_size, tex_reps, tex_counts, + tex_inset, tex_rot, + tex_scale, tex_depth, tex_samples, length, height, + tex_taper, style, tex_style, + extra, extra1, extra2, + anchor, spin, orient=UP); module zcyl( - h, r, d, r1, r2, d1, d2, l, + h, r, center, + l, r1, r2, + d, d1, d2, chamfer, chamfer1, chamfer2, chamfang, chamfang1, chamfang2, rounding, rounding1, rounding2, - circum=false, realign=false, from_end=false, length, height, - anchor=CENTER, spin=0, orient=UP + circum=false, realign=false, shift=[0,0], + teardrop=false, clip_angle, + from_end, from_end1, from_end2, + texture, tex_size=[5,5], tex_reps, tex_counts, + tex_inset=false, tex_rot=0, + tex_scale, tex_depth, tex_samples, length, height, + tex_taper, style, tex_style, + extra, extra1, extra2, + anchor, spin=0 ) { 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); 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=UP, r1=r1, r2=r2, l=l) { cyl( - l=l, r1=r1, r2=r2, - chamfer=chamfer, chamfer1=chamfer1, chamfer2=chamfer2, - chamfang=chamfang, chamfang1=chamfang1, chamfang2=chamfang2, - rounding=rounding, rounding1=rounding1, rounding2=rounding2, - circum=circum, realign=realign, from_end=from_end, - anchor=CENTER + undef, undef, center, // h,r,center + l, r1, r2, + undef, undef, undef, // d,d1,d2 + chamfer, chamfer1, chamfer2, + chamfang, chamfang1, chamfang2, + rounding, rounding1, rounding2, + circum, realign, shift, + teardrop, clip_angle, + from_end, from_end1, from_end2, + texture, tex_size, tex_reps, tex_counts, + tex_inset, tex_rot, + tex_scale, tex_depth, tex_samples, length, height, + tex_taper, style, tex_style, + extra, extra1, extra2, + anchor, orient=UP ); children(); } From 49abf7af4b027c4426bf1646a1859cbdb7534ec7 Mon Sep 17 00:00:00 2001 From: Alex Matulich Date: Mon, 7 Jul 2025 18:49:54 -0700 Subject: [PATCH 2/5] made arg list more robust to changes --- shapes3d.scad | 236 +++++++++++++++++++++++--------------------------- 1 file changed, 107 insertions(+), 129 deletions(-) diff --git a/shapes3d.scad b/shapes3d.scad index 20241811..086bdea2 100644 --- a/shapes3d.scad +++ b/shapes3d.scad @@ -1757,7 +1757,6 @@ function rect_tube( // anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `FRONT+LEFT+BOTTOM` // spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0` // orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP` -// // Named Anchors: // "hypot" = Center of angled wedge face, perpendicular to that face. // "hypot_left" = Left side of angled wedge face, bisecting the angle between the left side and angled faces. @@ -2101,20 +2100,16 @@ function cylinder(h, r1, r2, center, r, d, d1, d2, anchor, spin=0, orient=UP) = // anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER` // spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0` // orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP` -// -// -// Example: By Radius +// Example: By radius // xdistribute(30) { // cyl(l=40, r=10); // cyl(l=40, r1=10, r2=5); // } -// -// Example: By Diameter +// Example: By diameter // xdistribute(30) { // cyl(l=40, d=25); // cyl(l=40, d1=25, d2=10); // } -// // Example: Chamferring // xdistribute(60) { // // Shown Left to right. @@ -2122,16 +2117,12 @@ function cylinder(h, r1, r2, center, r, d, d1, d2, anchor, spin=0, orient=UP) = // cyl(l=40, d=40, chamfer=7, chamfang=30, from_end=false); // cyl(l=40, d=40, chamfer=7, chamfang=30, from_end=true); // } -// // Example: Rounding // cyl(l=40, d=40, rounding=10); -// // Example(VPD=175;VPR=[90,0,0]): Teardrop Bottom Rounding // cyl(l=40, d=40, rounding=10, teardrop=true); -// // Example(VPD=175;VPR=[90,0,0]): Clipped Bottom Rounding // cyl(l=40, d=40, rounding=10, clip_angle=40); -// // Example: Heterogenous Chamfers and Rounding // ydistribute(80) { // // Shown Front to Back. @@ -2139,63 +2130,50 @@ function cylinder(h, r1, r2, center, r, d, d1, d2, anchor, spin=0, orient=UP) = // cyl(l=40, d=40, chamfer2=5, orient=UP); // cyl(l=40, d=40, chamfer1=12, rounding2=10, orient=UP); // } -// // Example: Putting it all together // cyl( // l=20, d1=25, d2=15, // chamfer1=5, chamfang1=60, // from_end=true, rounding2=5 // ); -// -// Example: External Chamfers +// Example: External chamfers // cyl(l=50, r=30, chamfer=-5, chamfang=30, $fa=1, $fs=1); -// // Example: External Roundings // cyl(l=50, r=30, rounding1=-5, rounding2=5, $fa=1, $fs=1); -// // Example(Med): Standard Connectors // xdistribute(40) { // cyl(l=30, d=25) show_anchors(); // cyl(l=30, d1=25, d2=10) show_anchors(); // } -// // Example: Texturing with heightfield diamonds // cyl(h=40, r=20, texture="diamonds", tex_size=[5,5]); -// // Example: Texturing with heightfield pyramids // cyl(h=40, r1=20, r2=15, // texture="pyramids", tex_size=[5,5], // style="convex"); -// // Example: Texturing with heightfield truncated pyramids // cyl(h=40, r1=20, r2=15, chamfer=5, // texture="trunc_pyramids", // tex_size=[5,5], style="convex"); -// // Example: Texturing with VNF tile "dots" // cyl(h=40, r1=20, r2=15, rounding=9, // texture="dots", tex_size=[5,5], // tex_samples=6); -// // Example: Texturing with VNF tile "bricks_vnf" // cyl(h=50, r1=25, r2=20, shift=[0,10], rounding1=-10, // texture="bricks_vnf", tex_size=[10,10], // tex_depth=0.5, style="concave"); -// // Example: No Texture Taper // cyl(d1=25, d2=20, h=30, rounding=5, // texture="trunc_ribs", tex_size=[5,1]); -// // Example: Taper Texure at Extreme Ends // cyl(d1=25, d2=20, h=30, rounding=5, // texture="trunc_ribs", tex_taper=0, // tex_size=[5,1]); -// // Example: Taper Texture over First and Last 10% // cyl(d1=25, d2=20, h=30, rounding=5, // texture="trunc_ribs", tex_taper=0.1, // tex_size=[5,1]); -// // Example(3D,Med,NoAxes): Making a Clay Pattern Roller // tex = [ // [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,], @@ -2347,7 +2325,7 @@ function cyl( from_end, from_end1, from_end2, texture, tex_size=[5,5], tex_reps, tex_counts, tex_inset=false, tex_rot=0, - tex_scale, tex_depth, tex_samples, length, height, + tex_scale, tex_depth, tex_samples, tex_taper, style, tex_style, extra, extra1, extra2, anchor, spin=0, orient=UP @@ -2455,6 +2433,7 @@ module cyl( h, r, center, l, r1, r2, d, d1, d2, + length, height, chamfer, chamfer1, chamfer2, chamfang, chamfang1, chamfang2, rounding, rounding1, rounding2, @@ -2463,7 +2442,7 @@ module cyl( from_end, from_end1, from_end2, texture, tex_size=[5,5], tex_reps, tex_counts, tex_inset=false, tex_rot=0, - tex_scale, tex_depth, tex_samples, length, height, + tex_scale, tex_depth, tex_samples, tex_taper, style, tex_style, extra, extra1, extra2, anchor, spin=0, orient=UP @@ -2530,12 +2509,12 @@ module cyl( // This is a shortcut for `cyl()` with `orient=RIGHT`, but otherwise using the same arguments. // . // See [cyl()] for more detailed usage and arguments. -// Example: By Radius +// Example: By radius // ydistribute(50) { // xcyl(l=35, r=10); // xcyl(l=35, r1=15, r2=5); // } -// Example: By Diameter +// Example: By diameter // ydistribute(50) { // xcyl(l=35, d=20); // xcyl(l=35, d1=30, d2=10); @@ -2554,31 +2533,32 @@ function xcyl( from_end, from_end1, from_end2, texture, tex_size=[5,5], tex_reps, tex_counts, tex_inset=false, tex_rot=0, - tex_scale, tex_depth, tex_samples, length, height, + tex_scale, tex_depth, tex_samples, tex_taper, style, tex_style, extra, extra1, extra2, anchor, spin=0 -) = cyl(h, r, center, - l, r1, r2, - d, d1, d2, - length, height, - chamfer, chamfer1, chamfer2, - chamfang, chamfang1, chamfang2, - rounding, rounding1, rounding2, - circum, realign, shift, - teardrop, clip_angle, - from_end, from_end1, from_end2, - texture, tex_size, tex_reps, tex_counts, - tex_inset, tex_rot, - tex_scale, tex_depth, tex_samples, length, height, - tex_taper, style, tex_style, - extra, extra1, extra2, - anchor, spin, orient=RIGHT); +) = cyl(h=h, r=r, center=center, + l=l, r1=r1, r2=r2, + d=d, d1=d1, d2=d2, + length=length, height=height, + chamfer=chamfer, chamfer1=chamfer1, chamfer2=chamfer2, + chamfang=chamfang, chamfang1=chamfang1, chamfang2=chamfang2, + rounding=rounding, rounding1=rounding1, rounding2=rounding2, + circum=circum, realign=realign, shift=shift, + teardrop=teardrop, clip_angle=clip_angle, + from_end=from_end, from_end1=from_end1, from_end2=from_end2, + texture=texture, tex_size=tex_size, tex_reps=tex_reps, tex_counts=tex_counts, + tex_inset=tex_inset, tex_rot=tex_rot, + tex_scale=tex_scale, tex_depth=tex_depth, tex_samples=tex_samples, + tex_taper=tex_taper, style=style, tex_style=tex_style, + extra=extra, extra1=extra1, extra2=extra2, + anchor=anchor, spin=spin, orient=RIGHT); module xcyl( h, r, center, l, r1, r2, d, d1, d2, + length, height, chamfer, chamfer1, chamfer2, chamfang, chamfang1, chamfang2, rounding, rounding1, rounding2, @@ -2587,7 +2567,7 @@ module xcyl( from_end, from_end1, from_end2, texture, tex_size=[5,5], tex_reps, tex_counts, tex_inset=false, tex_rot=0, - tex_scale, tex_depth, tex_samples, length, height, + tex_scale, tex_depth, tex_samples, tex_taper, style, tex_style, extra, extra1, extra2, anchor, spin=0 @@ -2597,21 +2577,20 @@ module xcyl( l = one_defined([l,h,length,height],"l,h,length,height",1); attachable(anchor,spin,orient=UP, r1=r1, r2=r2, l=l, axis=RIGHT) { cyl( - undef, undef, center, // h,r,center - l, r1, r2, - undef, undef, undef, // d,d1,d2 - chamfer, chamfer1, chamfer2, - chamfang, chamfang1, chamfang2, - rounding, rounding1, rounding2, - circum, realign, shift, - teardrop, clip_angle, - from_end, from_end1, from_end2, - texture, tex_size, tex_reps, tex_counts, - tex_inset, tex_rot, - tex_scale, tex_depth, tex_samples, length, height, - tex_taper, style, tex_style, - extra, extra1, extra2, - anchor, spin, orient=RIGHT + center=center, + l=l, r1=r1, r2=r2, + chamfer=chamfer, chamfer1=chamfer1, chamfer2=chamfer2, + chamfang=chamfang, chamfang1=chamfang1, chamfang2=chamfang2, + rounding=rounding, rounding1=rounding1, rounding2=rounding2, + circum=circum, realign=realign, shift=shift, + teardrop=teardrop, clip_angle=clip_angle, + from_end=from_end, from_end1=from_end1, from_end2=from_end2, + texture=texture, tex_size=tex_size, tex_reps=tex_reps, tex_counts=tex_counts, + tex_inset=tex_inset, tex_rot=tex_rot, + tex_scale=tex_scale, tex_depth=tex_depth, tex_samples=tex_samples, + tex_taper=tex_taper, style=style, tex_style=tex_style, + extra=extra, extra1=extra1, extra2=extra2, + anchor=anchor, spin=spin, orient=RIGHT ); children(); } @@ -2629,12 +2608,12 @@ module xcyl( // This is a shortcut for `cyl()` with `orient=BACK`, but otherwise using the same arguments. // . // See [cyl()] for more detailed usage and arguments. -// Example: By Radius +// Example: By radius // xdistribute(50) { // ycyl(l=35, r=10); // ycyl(l=35, r1=15, r2=5); // } -// Example: By Diameter +// Example: By diameter // xdistribute(50) { // ycyl(l=35, d=20); // ycyl(l=35, d1=30, d2=10); @@ -2657,28 +2636,29 @@ function ycyl( tex_taper, style, tex_style, extra, extra1, extra2, anchor, spin=0 -) = cyl(h, r, center, - l, r1, r2, - d, d1, d2, - length, height, - chamfer, chamfer1, chamfer2, - chamfang, chamfang1, chamfang2, - rounding, rounding1, rounding2, - circum, realign, shift, - teardrop, clip_angle, - from_end, from_end1, from_end2, - texture, tex_size, tex_reps, tex_counts, - tex_inset, tex_rot, - tex_scale, tex_depth, tex_samples, length, height, - tex_taper, style, tex_style, - extra, extra1, extra2, - anchor, spin, orient=BACK); +) = cyl(h=h, r=r, center=center, + l=l, r1=r1, r2=r2, + d=d, d1=d1, d2=d2, + length=length, height=height, + chamfer=chamfer, chamfer1=chamfer1, chamfer2=chamfer2, + chamfang=chamfang, chamfang1=chamfang1, chamfang2=chamfang2, + rounding=rounding, rounding1=rounding1, rounding2=rounding2, + circum=circum, realign=realign, shift=shift, + teardrop=teardrop, clip_angle=clip_angle, + from_end=from_end, from_end1=from_end1, from_end2=from_end2, + texture=texture, tex_size=tex_size, tex_reps=tex_reps, tex_counts=tex_counts, + tex_inset=tex_inset, tex_rot=tex_rot, + tex_scale=tex_scale, tex_depth=tex_depth, tex_samples=tex_samples, + tex_taper=tex_taper, style=style, tex_style=tex_style, + extra=extra, extra1=extra1, extra2=extra2, + anchor=anchor, spin=spin, orient=BACK); module ycyl( h, r, center, l, r1, r2, d, d1, d2, + length, height, chamfer, chamfer1, chamfer2, chamfang, chamfang1, chamfang2, rounding, rounding1, rounding2, @@ -2687,7 +2667,7 @@ module ycyl( from_end, from_end1, from_end2, texture, tex_size=[5,5], tex_reps, tex_counts, tex_inset=false, tex_rot=0, - tex_scale, tex_depth, tex_samples, length, height, + tex_scale, tex_depth, tex_samples, tex_taper, style, tex_style, extra, extra1, extra2, anchor, spin=0 @@ -2697,21 +2677,20 @@ module ycyl( l = one_defined([l,h,length,height],"l,h,length,height",1); attachable(anchor,spin,orient=UP, r1=r1, r2=r2, l=l, axis=BACK) { cyl( - undef, undef, center, // h,r,center - l, r1, r2, - undef, undef, undef, // d,d1,d2 - chamfer, chamfer1, chamfer2, - chamfang, chamfang1, chamfang2, - rounding, rounding1, rounding2, - circum, realign, shift, - teardrop, clip_angle, - from_end, from_end1, from_end2, - texture, tex_size, tex_reps, tex_counts, - tex_inset, tex_rot, - tex_scale, tex_depth, tex_samples, length, height, - tex_taper, style, tex_style, - extra, extra1, extra2, - anchor, orient=BACK + center=center, + l=l, r1=r1, r2=r2, + chamfer=chamfer, chamfer1=chamfer1, chamfer2=chamfer2, + chamfang=chamfang, chamfang1=chamfang1, chamfang2=chamfang2, + rounding=rounding, rounding1=rounding1, rounding2=rounding2, + circum=circum, realign=realign, shift=shift, + teardrop=teardrop, clip_angle=clip_angle, + from_end=from_end, from_end1=from_end1, from_end2=from_end2, + texture=texture, tex_size=tex_size, tex_reps=tex_reps, tex_counts=tex_counts, + tex_inset=tex_inset, tex_rot=tex_rot, + tex_scale=tex_scale, tex_depth=tex_depth, tex_samples=tex_samples, + tex_taper=tex_taper, style=style, tex_style=tex_style, + extra=extra, extra1=extra1, extra2=extra2, + anchor=anchor, spin=spin, orient=BACK ); children(); } @@ -2729,12 +2708,12 @@ module ycyl( // This is a shortcut for `cyl()` with `orient=UP` (which is also the default for [cyl()]), but otherwise using the same arguments. // . // See [cyl()] for more detailed usage and arguments. -// Example: By Radius +// Example: By radius // xdistribute(50) { // zcyl(l=35, r=10); // zcyl(l=35, r1=15, r2=5); // } -// Example: By Diameter +// Example: By diameter // xdistribute(50) { // zcyl(l=35, d=20); // zcyl(l=35, d1=30, d2=10); @@ -2757,22 +2736,22 @@ function zcyl( tex_taper, style, tex_style, extra, extra1, extra2, anchor, spin=0 -) = cyl(h, r, center, - l, r1, r2, - d, d1, d2, - length, height, - chamfer, chamfer1, chamfer2, - chamfang, chamfang1, chamfang2, - rounding, rounding1, rounding2, - circum, realign, shift, - teardrop, clip_angle, - from_end, from_end1, from_end2, - texture, tex_size, tex_reps, tex_counts, - tex_inset, tex_rot, - tex_scale, tex_depth, tex_samples, length, height, - tex_taper, style, tex_style, - extra, extra1, extra2, - anchor, spin, orient=UP); +) = cyl(h=h, r=r, center=center, + l=l, r1=r1, r2=r2, + d=d, d1=d1, d2=d2, + length=length, height=height, + chamfer=chamfer, chamfer1=chamfer1, chamfer2=chamfer2, + chamfang=chamfang, chamfang1=chamfang1, chamfang2=chamfang2, + rounding=rounding, rounding1=rounding1, rounding2=rounding2, + circum=circum, realign=realign, shift=shift, + teardrop=teardrop, clip_angle=clip_angle, + from_end=from_end, from_end1=from_end1, from_end2=from_end2, + texture=texture, tex_size=tex_size, tex_reps=tex_reps, tex_counts=tex_counts, + tex_inset=tex_inset, tex_rot=tex_rot, + tex_scale=tex_scale, tex_depth=tex_depth, tex_samples=tex_samples, + tex_taper=tex_taper, style=style, tex_style=tex_style, + extra=extra, extra1=extra1, extra2=extra2, + anchor=anchor, spin=spin, orient=UP); module zcyl( h, r, center, @@ -2796,21 +2775,20 @@ module zcyl( l = one_defined([l,h,length,height],"l,h,length,height",1); attachable(anchor,spin,orient=UP, r1=r1, r2=r2, l=l) { cyl( - undef, undef, center, // h,r,center - l, r1, r2, - undef, undef, undef, // d,d1,d2 - chamfer, chamfer1, chamfer2, - chamfang, chamfang1, chamfang2, - rounding, rounding1, rounding2, - circum, realign, shift, - teardrop, clip_angle, - from_end, from_end1, from_end2, - texture, tex_size, tex_reps, tex_counts, - tex_inset, tex_rot, - tex_scale, tex_depth, tex_samples, length, height, - tex_taper, style, tex_style, - extra, extra1, extra2, - anchor, orient=UP + center=center, + l=l, r1=r1, r2=r2, + chamfer=chamfer, chamfer1=chamfer1, chamfer2=chamfer2, + chamfang=chamfang, chamfang1=chamfang1, chamfang2=chamfang2, + rounding=rounding, rounding1=rounding1, rounding2=rounding2, + circum=circum, realign=realign, shift=shift, + teardrop=teardrop, clip_angle=clip_angle, + from_end=from_end, from_end1=from_end1, from_end2=from_end2, + texture=texture, tex_size=tex_size, tex_reps=tex_reps, tex_counts=tex_counts, + tex_inset=tex_inset, tex_rot=tex_rot, + tex_scale=tex_scale, tex_depth=tex_depth, tex_samples=tex_samples, + tex_taper=tex_taper, style=style, tex_style=tex_style, + extra=extra, extra1=extra1, extra2=extra2, + anchor=anchor, spin=spin, orient=UP ); children(); } From c1efe89711ab26fb436b43787e7cb0974c127c30 Mon Sep 17 00:00:00 2001 From: Alex Matulich Date: Thu, 10 Jul 2025 18:25:06 -0700 Subject: [PATCH 3/5] Clarified anchoring for x/y/cyl() in docs and examples --- shapes3d.scad | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/shapes3d.scad b/shapes3d.scad index 086bdea2..c78cc383 100644 --- a/shapes3d.scad +++ b/shapes3d.scad @@ -2506,13 +2506,20 @@ module cyl( // Description: // Creates an attachable cylinder with roundovers, chamfering, and optional texture, oriented along the X axis. // . -// This is a shortcut for `cyl()` with `orient=RIGHT`, but otherwise using the same arguments. +// Used as a function, this is a shortcut for `cyl()` with `orient=RIGHT`, but otherwise using the same arguments. +// Used as a module, the difference from cyl() is in the anchors, which don't get reoriented with the cylinder but maintain +// the orientations you specify. +// For example, top and right anchors on xcyl() would be on the top curved surface and the right (positive x) end, +// respectively, whereas with cyl() these anchors would be associated with the top end and right side. // . // See [cyl()] for more detailed usage and arguments. -// Example: By radius +// Example: By radius. The cone shows anchor arrows for `TOP` and `RIGHT`. // ydistribute(50) { // xcyl(l=35, r=10); -// xcyl(l=35, r1=15, r2=5); +// xcyl(l=35, r1=15, r2=5) { +// attach(TOP) anchor_arrow(); +// attach(RIGHT) anchor_arrow(); +// } // } // Example: By diameter // ydistribute(50) { @@ -2605,13 +2612,20 @@ module xcyl( // Description: // Creates an attachable cylinder with roundovers, chamfering, and optional texture, oriented along the Y axis. // . -// This is a shortcut for `cyl()` with `orient=BACK`, but otherwise using the same arguments. +// Used as a function, this is a shortcut for `cyl()` with `orient=BACK`, but otherwise using the same arguments. +// Used as a module, the difference from cyl() is in the anchors, which don't get reoriented with the cylinder but maintain +// the orientations you specify. +// For example, top and right anchors on ycyl() would be on the top and right of the curved cylinder surface, +// respectively, whereas with cyl() these anchors would be associated with the top end and right side. // . // See [cyl()] for more detailed usage and arguments. -// Example: By radius +// Example: By radius. The cone shows anchor arrows for `TOP` and `RIGHT`. // xdistribute(50) { // ycyl(l=35, r=10); -// ycyl(l=35, r1=15, r2=5); +// ycyl(l=35, r1=15, r2=5) { +// attach(TOP) anchor_arrow(); +// attach(RIGHT) anchor_arrow(); +// } // } // Example: By diameter // xdistribute(50) { @@ -2705,13 +2719,16 @@ module ycyl( // Description: // Pass-through to [cyl()]. Creates an attachable cylinder with roundovers, chamfering, and optional texture, oriented along the Z axis. // . -// This is a shortcut for `cyl()` with `orient=UP` (which is also the default for [cyl()]), but otherwise using the same arguments. +// This is a shortcut for `cyl()` with `orient=UP` (which is also the default for [cyl()]), but otherwise using the same arguments. Unlike `xcyl()` and `ycyl()`, anchoring for `zcyl()` works the same as for `cyl()`. // . // See [cyl()] for more detailed usage and arguments. -// Example: By radius +// Example: By radius. The cone shows anchor arrows for `TOP` and `RIGHT`, which for `zcyl()` work the same as for `cyl()`. // xdistribute(50) { // zcyl(l=35, r=10); -// zcyl(l=35, r1=15, r2=5); +// zcyl(l=35, r1=15, r2=5) { +// attach(TOP) anchor_arrow(); +// attach(RIGHT) anchor_arrow(); +// } // } // Example: By diameter // xdistribute(50) { From 7c48054ca475919a78b8e99c012f1303008a9e21 Mon Sep 17 00:00:00 2001 From: Alex Matulich Date: Wed, 16 Jul 2025 07:44:44 -0700 Subject: [PATCH 4/5] doc changes --- shapes3d.scad | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/shapes3d.scad b/shapes3d.scad index c78cc383..d42d17a7 100644 --- a/shapes3d.scad +++ b/shapes3d.scad @@ -659,7 +659,7 @@ function cuboid( // prismoid(size1=[100,75], h=30, xang=50, yang=70); // Example: Specifying top, height and angle, with asymmetric angles // prismoid(size2=[100,75], h=30, xang=[50,60], yang=[70,40]); -// Example: Specifying top, bottom and angle for X and using that to define height. Note that giving yang here would likely give a conflicting height calculation, which is not allowed. +// Example: Specifying top, bottom and angle for X and using that to define height. Giving yang here would likely give a conflicting height calculation, which is not allowed. // prismoid(size1=[100,75], size2=[75,35], xang=50); // Example: The same as the previous example but we give a shift in Y. Note that shift.x must be undef because you cannot give combine an angle with a shift, so a shift.x value would conflict with xang being defined. // prismoid(size1=[100,75], size2=[75,35], xang=50, shift=[undef,20]); @@ -2091,7 +2091,7 @@ function cylinder(h, r1, r2, center, r, d, d1, d2, anchor, spin=0, orient=UP) = // texture = A texture name string, or a rectangular array of scalar height values (0.0 to 1.0), or a VNF tile that defines the texture to apply to vertical surfaces. See {{texture()}} for what named textures are supported. // tex_size = An optional 2D target size (2-vector or scalar) for the textures. Actual texture sizes will be scaled somewhat to evenly fit the available surface. Default: `[5,5]` // tex_reps = If given instead of tex_size, a scalar or 2-vector giving the integer number of texture tile repetitions in the horizontal and vertical directions. -// tex_inset = If numeric, lowers the texture into the surface by the specified proportion, e.g. 0.5 would lower it half way into the surface. If `true`, insets by exactly its full depth. Default: `false` +// tex_inset = If numeric, lowers the texture into the surface by the specified proportion, e.g. 0.5 would lower it halfway into the surface. If `true`, insets by exactly its full depth. Default: `false` // tex_rot = Rotate texture by specified angle, which must be a multiple of 90 degrees. Default: 0 // tex_depth = Specify texture depth; if negative, invert the texture. Default: 1. // tex_samples = Minimum number of "bend points" to have in VNF texture tiles. Default: 8 @@ -2506,11 +2506,11 @@ module cyl( // Description: // Creates an attachable cylinder with roundovers, chamfering, and optional texture, oriented along the X axis. // . -// Used as a function, this is a shortcut for `cyl()` with `orient=RIGHT`, but otherwise using the same arguments. +// Used as a function, this is a shortcut for `cyl()` with `orient=RIGHT`, but otherwise using the same arguments excluding `orient`, which is not accepted. // Used as a module, the difference from cyl() is in the anchors, which don't get reoriented with the cylinder but maintain // the orientations you specify. -// For example, top and right anchors on xcyl() would be on the top curved surface and the right (positive x) end, -// respectively, whereas with cyl() these anchors would be associated with the top end and right side. +// For example, top and right anchors on xcyl() are on the top curved surface and the right (positive x) end, +// respectively, whereas with cyl() these anchors are associated with the top end and right side. // . // See [cyl()] for more detailed usage and arguments. // Example: By radius. The cone shows anchor arrows for `TOP` and `RIGHT`. @@ -2612,11 +2612,11 @@ module xcyl( // Description: // Creates an attachable cylinder with roundovers, chamfering, and optional texture, oriented along the Y axis. // . -// Used as a function, this is a shortcut for `cyl()` with `orient=BACK`, but otherwise using the same arguments. +// Used as a function, this is a shortcut for `cyl()` with `orient=BACK`, but otherwise using the same arguments excluding `orient`, which is not accepted. // Used as a module, the difference from cyl() is in the anchors, which don't get reoriented with the cylinder but maintain // the orientations you specify. -// For example, top and right anchors on ycyl() would be on the top and right of the curved cylinder surface, -// respectively, whereas with cyl() these anchors would be associated with the top end and right side. +// For example, top and right anchors on ycyl() are on the top and right of the curved cylinder surface, +// respectively, whereas with cyl() these anchors are associated with the top end and right side. // . // See [cyl()] for more detailed usage and arguments. // Example: By radius. The cone shows anchor arrows for `TOP` and `RIGHT`. @@ -2719,7 +2719,7 @@ module ycyl( // Description: // Pass-through to [cyl()]. Creates an attachable cylinder with roundovers, chamfering, and optional texture, oriented along the Z axis. // . -// This is a shortcut for `cyl()` with `orient=UP` (which is also the default for [cyl()]), but otherwise using the same arguments. Unlike `xcyl()` and `ycyl()`, anchoring for `zcyl()` works the same as for `cyl()`. +// This is a shortcut for `cyl()` with `orient=UP` (which is also the default for [cyl()]), but otherwise using the same arguments excluding `orient`, which is not accepted. Unlike `xcyl()` and `ycyl()`, anchoring for `zcyl()` works the same as for `cyl()`. // . // See [cyl()] for more detailed usage and arguments. // Example: By radius. The cone shows anchor arrows for `TOP` and `RIGHT`, which for `zcyl()` work the same as for `cyl()`. @@ -3238,7 +3238,7 @@ function sphere(r, d, anchor=CENTER, spin=0, orient=UP) = // With style="align", the circumscribed sphere has its maximum radius on the X and Y axes // but is undersized on the Z axis. With style="octa" the circumscribed sphere has faces at each axis, so // the radius on the axes is equal to the specified radius, which is the *minimum* radius of the circumscribed sphere. -// The same thing is true for style="icosa" when $fn is a multiple of 10. This would enable you to create spherical +// The same thing is true for style="icosa" when $fn is a multiple of 10. This enables you to create spherical // holes with guaranteed on-axis dimensions. // Arguments: // r = Radius of the spheroid. @@ -3870,7 +3870,7 @@ function teardrop(h, r, ang=45, cap_h, r1, r2, d, d1, d2, cap_h1, cap_h2, chamf // // Named Anchors: // "cap" = The center of the top of the cap, oriented with the cap face normal. -// "tip" = The position where an un-capped onion would come to a point, oriented in the direction the point is from the center. +// "tip" = The position where an un-capped onion comes to a point, oriented in the direction the point is from the center. // // Example: Typical Shape // onion(r=30, ang=30); From 78a06f63ab3c71700e5434dfdaa63bcb6a8a5bd5 Mon Sep 17 00:00:00 2001 From: Alex Matulich Date: Wed, 16 Jul 2025 11:49:13 -0700 Subject: [PATCH 5/5] corrected x/y/zcyl() reorient() issue in shapes3d, commented echo and added newlines to assert messages in attachments --- attachments.scad | 270 +++++++++++++++++++++++------------------------ shapes3d.scad | 121 ++++++++++++--------- 2 files changed, 204 insertions(+), 187 deletions(-) diff --git a/attachments.scad b/attachments.scad index 9131e0c7..86db9449 100644 --- a/attachments.scad +++ b/attachments.scad @@ -509,10 +509,10 @@ module position(at,from) if (is_def(from)){ echo("'from' argument of position() has changed to 'at' and will be removed in a future version"); } - dummy0=assert(num_defined([at,from])==1, "Cannot give both `at` argument and the deprectated `from` argument to position()"); + dummy0=assert(num_defined([at,from])==1, "\nCannot give both `at` argument and the deprectated `from` argument to position()."); at = first_defined([at,from]); req_children($children); - dummy1=assert($parent_geom != undef, "No object to position relative to."); + dummy1=assert($parent_geom != undef, "\nNo object to position relative to."); anchors = (is_vector(at)||is_string(at))? [at] : at; two_d = _attach_geom_2d($parent_geom); for (anchr = anchors) { @@ -563,7 +563,7 @@ module position(at,from) module orient(anchor, spin) { req_children($children); check= - assert($parent_geom != undef, "No parent to orient from!") + assert($parent_geom != undef, "\nNo parent to orient from!") assert(is_string(anchor) || is_vector(anchor)); anch = _find_anchor(anchor, $parent_geom); two_d = _attach_geom_2d($parent_geom); @@ -700,8 +700,8 @@ module align(anchor,align=CENTER,inside=false,inset=0,shiftout=0,overlap) { req_children($children); overlap = (overlap!=undef)? overlap : $overlap; - dummy1=assert($parent_geom != undef, "No object to align to.") - assert(is_undef($attach_to), "Cannot use align() as a child of attach()"); + dummy1=assert($parent_geom != undef, "\nNo object to align to.") + assert(is_undef($attach_to), "\nCannot use align() as a child of attach()."); anchor = is_vector(anchor) ? [anchor] : anchor; align = is_vector(align) ? [align] : align; two_d = _attach_geom_2d($parent_geom); @@ -712,19 +712,19 @@ module align(anchor,align=CENTER,inside=false,inset=0,shiftout=0,overlap) $anchor=face; dummy= assert(!is_string(face), - str("Named anchor \"",face,"\" given for anchor, but align() does not support named anchors")) + str("\nNamed anchor \"",face,"\" given for anchor, but align() does not support named anchors.")) assert(is_vector(face) && (len(face)==2 || len(face)==3), - str("Invalid face ",face, ". Must be a 2-vector or 3-vector")); + str("\nInvalid face ",face, ". Must be a 2-vector or 3-vector.")); thisface = two_d? _force_anchor_2d(face) : point3d(face); for(j = idx(align)) { edge=align[j]; $idx = j+len(align)*i; $align=edge; dummy1=assert(is_vector(edge) && (len(edge)==2 || len(edge)==3), - "align direction must be a 2-vector or 3-vector"); + "\nalign direction must be a 2-vector or 3-vector."); thisedge = two_d? _force_anchor_2d(edge) : point3d(edge); dummy=assert(all_zero(v_mul(thisedge,thisface)), - str("align (",thisedge,") cannot include component parallel to anchor ",thisface)); + str("\nalign (",thisedge,") cannot include component parallel to anchor ",thisface,".")); thisface_anch = _find_anchor(thisface, $parent_geom); inset_dir = two_d ? -thisface : unit(thisface_anch[1]-_find_anchor([thisedge.x,0,0]+thisface, $parent_geom)[1],CTR) @@ -931,10 +931,10 @@ function _make_anchor_legal(anchor,geom) = module attach(parent, child, overlap, align, spin=0, norot, inset=0, shiftout=0, inside=false, from, to) { dummy3= - assert(num_defined([to,child])<2, "Cannot combine deprecated 'to' argument with 'child' parameter") - assert(num_defined([from,parent])<2, "Cannot combine deprecated 'from' argument with 'parent' parameter") - assert(spin!="align" || is_def(align), "Can only set spin to \"align\" when the 'align' parameter is given") - assert(is_finite(spin) || spin=="align", "Spin must be a number (unless align is given)") + assert(num_defined([to,child])<2, "\nCannot combine deprecated 'to' argument with 'child' parameter.") + assert(num_defined([from,parent])<2, "\nCannot combine deprecated 'from' argument with 'parent' parameter.") + assert(spin!="align" || is_def(align), "\nCan only set spin to \"align\" when the 'align' parameter is given.") + assert(is_finite(spin) || spin=="align", "\nSpin must be a number (unless align is given).") assert((is_undef(overlap) || is_finite(overlap)) && (is_def(overlap) || is_undef($overlap) || is_finite($overlap)), str("Provided ",is_def(overlap)?"":"$","overlap is not valid.")); removetag = inside; @@ -947,10 +947,10 @@ module attach(parent, child, overlap, align, spin=0, norot, inset=0, shiftout=0, echo("The 'norot' option to attach() is deprecated and will be removed in the future. Use position() instead."); req_children($children); - dummy=assert($parent_geom != undef, "No object to attach to!") + dummy=assert($parent_geom != undef, "\nNo object to attach to!") assert(is_undef(child) || is_string(child) || (is_vector(child) && (len(child)==2 || len(child)==3)), - "child must be a named anchor (a string) or a 2-vector or 3-vector") - assert(is_undef(align) || !is_string(child), "child is a named anchor. Named anchors are not supported with align="); + "\nChild must be a named anchor (a string) or a 2-vector or 3-vector.") + assert(is_undef(align) || !is_string(child), "\nChild is a named anchor. Named anchors are not supported with align=."); two_d = _attach_geom_2d($parent_geom); basegeom = $parent_geom[0]=="conoid" ? attach_geom(r=2,h=2,axis=$parent_geom[5]) @@ -963,22 +963,22 @@ module attach(parent, child, overlap, align, spin=0, norot, inset=0, shiftout=0, anchors = is_vector(parent) || is_string(parent) ? [parent] : parent; align_list = is_undef(align) ? [undef] : is_vector(align) || is_string(align) ? [align] : align; - dummy4 = assert(is_string(parent) || is_list(parent), "Invalid parent anchor or anchor list") - assert(spin==0 || (!two_d || is_undef(child)), "spin is not allowed for 2d objects when 'child' is given"); + dummy4 = assert(is_string(parent) || is_list(parent), "\nInvalid parent anchor or anchor list.") + assert(spin==0 || (!two_d || is_undef(child)), "\nspin is not allowed for 2d objects when 'child' is given."); child_temp = first_defined([child,to]); child = two_d ? _force_anchor_2d(child_temp) : child_temp; - dummy2=assert(align_list==[undef] || is_def(child), "Cannot use 'align' without 'child'") - assert(!inside || is_def(child), "Cannot use 'inside' without 'child'") - assert(inset==0 || is_def(child), "Cannot specify 'inset' without 'child'") - assert(inset==0 || is_def(align), "Cannot specify 'inset' without 'align'") - assert(shiftout==0 || is_def(child), "Cannot specify 'shiftout' without 'child'"); + dummy2=assert(align_list==[undef] || is_def(child), "\nCannot use 'align' without 'child'.") + assert(!inside || is_def(child), "\nCannot use 'inside' without 'child'.") + assert(inset==0 || is_def(child), "\nCannot specify 'inset' without 'child'.") + assert(inset==0 || is_def(align), "\nCannot specify 'inset' without 'align'.") + assert(shiftout==0 || is_def(child), "\nCannot specify 'shiftout' without 'child'."); factor = inside?-1:1; $attach_to = child; for (anch_ind = idx(anchors)) { dummy=assert(is_string(anchors[anch_ind]) || (is_vector(anchors[anch_ind]) && (len(anchors[anch_ind])==2 || len(anchors[anch_ind])==3)), - str("parent[",anch_ind,"] is ",anchors[anch_ind]," but it must be a named anchor (string) or a 2-vector or 3-vector")) + str("\nParent[",anch_ind,"] is ",anchors[anch_ind]," but it must be a named anchor (string), a 2-vector, or 3-vector.")) assert(align_list==[undef] || !is_string(anchors[anch_ind]), - str("parent[",anch_ind,"] is a named anchor (",anchors[anch_ind],"), but named anchors are not supported with align=")); + str("\nParent[",anch_ind,"] is a named anchor (",anchors[anch_ind],"), but named anchors are not supported with align=.")); anchor = is_string(anchors[anch_ind])? anchors[anch_ind] : two_d?_force_anchor_2d(anchors[anch_ind]) : point3d(anchors[anch_ind]); @@ -995,7 +995,7 @@ module attach(parent, child, overlap, align, spin=0, norot, inset=0, shiftout=0, parent_abstract_anchor = is_vector(anchor) && !two_d ? _find_anchor(_make_anchor_legal(anchor,basegeom),basegeom) : undef; for(align_ind = idx(align_list)){ align = is_undef(align_list[align_ind]) ? undef - : assert(is_vector(align_list[align_ind],2) || is_vector(align_list[align_ind],3), "align direction must be a 2-vector or 3-vector") + : assert(is_vector(align_list[align_ind],2) || is_vector(align_list[align_ind],3), "\nAlign direction must be a 2-vector or 3-vector.") two_d ? _force_anchor_2d(align_list[align_ind]) : point3d(align_list[align_ind]); spin = is_num(spin) ? spin @@ -1024,10 +1024,10 @@ module attach(parent, child, overlap, align, spin=0, norot, inset=0, shiftout=0, badcorner = !in_list($parent_geom[0],["conoid","spheroid"]) && !is_undef(align) && align!=CTR && sum(v_abs(anchor))==3; badsphere = $parent_geom[0]=="spheroid" && !is_undef(align) && align!=CTR; dummy=assert(is_undef(align) || all_zero(v_mul(anchor,align)), - str("Invalid alignment: align value (",align,") includes component parallel to parent anchor (",anchor,")")) - assert(goodcyl, str("Cannot use align with an anchor on a curved edge or surface of a cylinder at parent anchor (",anchor,")")) - assert(!badcorner, str("Cannot use align at a corner anchor (",anchor,")")) - assert(!badsphere, "Cannot use align on spheres."); + str("\nInvalid alignment: align value (",align,") includes component parallel to parent anchor (",anchor,").")) + assert(goodcyl, str("\nCannot use align with an anchor on a curved edge or surface of a cylinder at parent anchor (",anchor,").")) + assert(!badcorner, str("\nCannot use align at a corner anchor (",anchor,").")) + assert(!badsphere, "\nCannot use align on spheres."); // Now compute position on the parent (including alignment but not inset) where the child will be anchored pos = is_undef(align) ? anchor_data[1] : _find_anchor(anchor+align, $parent_geom)[1]; $attach_anchor = list_set(anchor_data, 1, pos); // Never used; For user informational use? Should this be set at all? @@ -1100,9 +1100,9 @@ module attach(parent, child, overlap, align, spin=0, norot, inset=0, shiftout=0, module attach_part(name) { req_children($children); - dummy=assert(!is_undef($parent_parts), "Parent does not exist or does not have any parts"); + dummy=assert(!is_undef($parent_parts), "\nParent does not exist or does not have any parts."); ind = search([name], $parent_parts, 1,0)[0]; - dummy2 = assert(ind!=[], str("Parent does not have a part named ",name)); + dummy2 = assert(ind!=[], str("\nParent does not have a part named \"",name,"\".")); $parent_geom = $parent_parts[ind][1]; $anchor_inside = $parent_parts[ind][2]; T = $parent_parts[ind][3]; @@ -1145,8 +1145,8 @@ module tag(tag) { req_children($children); check= - assert(is_string(tag),"tag must be a string") - assert(undef==str_find(tag," "),str("Tag string \"",tag,"\" contains a space, which is not allowed")); + assert(is_string(tag),"\n'tag' must be a string.") + assert(undef==str_find(tag," "),str("\nTag string \"",tag,"\" contains a space, which is not allowed.")); $tag = str($tag_prefix,tag); children(); } @@ -1178,8 +1178,8 @@ module tag_this(tag) { req_children($children); check= - assert(is_string(tag),"tag must be a string") - assert(undef==str_find(tag," "),str("Tag string \"",tag,"\" contains a space, which is not allowed")); + assert(is_string(tag),"\n'tag' must be a string.") + assert(undef==str_find(tag," "),str("\nTag string \"",tag,"\" contains a space, which is not allowed.")); $save_tag=default($tag,""); $tag = str($tag_prefix,tag); children(); @@ -1239,9 +1239,9 @@ module tag_this(tag) module force_tag(tag) { req_children($children); - check1=assert(is_undef(tag) || is_string(tag),"tag must be a string"); + check1=assert(is_undef(tag) || is_string(tag),"\n'tag' must be a string."); $tag = str($tag_prefix,default(tag,$tag)); - assert(undef==str_find($tag," "),str("Tag string \"",$tag,"\" contains a space, which is not allowed")); + assert(undef==str_find($tag," "),str("\nTag string \"",$tag,"\" contains a space, which is not allowed.")); if(_is_shown()) show_all() children(); @@ -1382,8 +1382,8 @@ module default_tag(tag,do_tag=true) module tag_scope(scope){ req_children($children); scope = is_undef(scope) ? rand_str(20) : scope; - assert(is_string(scope), "scope must be a string"); - assert(undef==str_find(scope," "),str("Scope string \"",scope,"\" contains a space, which is not allowed")); + assert(is_string(scope), "\n'scope' must be a string."); + assert(undef==str_find(scope," "),str("\nScope string \"",scope,"\" contains a space, which is not allowed.")); $tag_prefix=scope; children(); } @@ -1569,8 +1569,8 @@ module tag_scope(scope){ module diff(remove="remove", keep="keep") { req_children($children); - assert(is_string(remove),"remove must be a string of tags"); - assert(is_string(keep),"keep must be a string of tags"); + assert(is_string(remove),"\n'remove' must be a string of tags."); + assert(is_string(keep),"\n'keep' must be a string of tags."); if (_is_shown()) { difference() { @@ -1637,10 +1637,10 @@ module diff(remove="remove", keep="keep") module tag_diff(tag="",remove="remove", keep="keep") { req_children($children); - assert(is_string(remove),"remove must be a string of tags"); - assert(is_string(keep),"keep must be a string of tags"); - assert(is_string(tag),"tag must be a string"); - assert(undef==str_find(tag," "),str("Tag string \"",tag,"\" contains a space, which is not allowed")); + assert(is_string(remove),"\n'remove' must be a string of tags."); + assert(is_string(keep),"\n'keep' must be a string of tags."); + assert(is_string(tag),"\n'tag' must be a string."); + assert(undef==str_find(tag," "),str("\nTag string \"",tag,"\" contains a space, which is not allowed.")); $tag=str($tag_prefix,tag); if (_is_shown()) show_all(){ @@ -1715,8 +1715,8 @@ module tag_diff(tag="",remove="remove", keep="keep") // } module intersect(intersect="intersect",keep="keep") { - assert(is_string(intersect),"intersect must be a string of tags"); - assert(is_string(keep),"keep must be a string of tags"); + assert(is_string(intersect),"\n'intersect' must be a string of tags."); + assert(is_string(keep),"\n'keep' must be a string of tags."); intersection(){ show_only(intersect) children(); hide(str(intersect," ",keep)) children(); @@ -1765,10 +1765,10 @@ module intersect(intersect="intersect",keep="keep") // } module tag_intersect(tag="",intersect="intersect",keep="keep") { - assert(is_string(intersect),"intersect must be a string of tags"); - assert(is_string(keep),"keep must be a string of tags"); - assert(is_string(tag),"tag must be a string"); - assert(undef==str_find(tag," "),str("Tag string \"",tag,"\" contains a space, which is not allowed")); + assert(is_string(intersect),"\n'intersect' must be a string of tags."); + assert(is_string(keep),"\n'keep' must be a string of tags."); + assert(is_string(tag),"\n'tag' must be a string."); + assert(undef==str_find(tag," "),str("\nTag string \"",tag,"\" contains a space, which is not allowed.")); $tag=str($tag_prefix,tag); if (_is_shown()) show_all(){ @@ -1813,7 +1813,7 @@ module tag_intersect(tag="",intersect="intersect",keep="keep") module conv_hull(keep="keep") { req_children($children); - assert(is_string(keep),"keep must be a string of tags"); + assert(is_string(keep),"\n'keep' must be a string of tags."); if (_is_shown()) hull() hide(keep) children(); show_int(keep) children(); @@ -1860,9 +1860,9 @@ module conv_hull(keep="keep") module tag_conv_hull(tag="",keep="keep") { req_children($children); - assert(is_string(keep),"keep must be a string of tags"); - assert(is_string(tag),"tag must be a string"); - assert(undef==str_find(tag," "),str("Tag string \"",tag,"\" contains a space, which is not allowed")); + assert(is_string(keep),"\n'keep' must be a string of tags."); + assert(is_string(tag),"\n'tag' must be a string."); + assert(undef==str_find(tag," "),str("\nTag string \"",tag,"\" contains a space, which is not allowed.")); $tag=str($tag_prefix,tag); if (_is_shown()) show_all(){ @@ -1900,7 +1900,7 @@ module tag_conv_hull(tag="",keep="keep") module hide(tags) { req_children($children); - dummy=assert(is_string(tags), "tags must be a string"); + dummy=assert(is_string(tags), "\n'tags' must be a string."); taglist = [for(s=str_split(tags," ",keep_nulls=false)) str($tag_prefix,s)]; $tags_hidden = concat($tags_hidden,taglist); children(); @@ -1961,7 +1961,7 @@ module hide_this() module show_only(tags) { req_children($children); - dummy=assert(is_string(tags), str("tags must be a string",tags)); + dummy=assert(is_string(tags), str("\n'tags' must be a string.",tags)); taglist = [for(s=str_split(tags," ",keep_nulls=false)) str($tag_prefix,s)]; $tags_shown = taglist; children(); @@ -2004,7 +2004,7 @@ module show_all() module show_int(tags) { req_children($children); - dummy=assert(is_string(tags), str("tags must be a string",tags)); + dummy=assert(is_string(tags), str("\n'tags' must be a string.",tags)); taglist = [for(s=str_split(tags," ",keep_nulls=false)) str($tag_prefix,s)]; $tags_shown = $tags_shown == "ALL" ? taglist : set_intersection($tags_shown,taglist); children(); @@ -2049,8 +2049,8 @@ module show_int(tags) module face_mask(faces=[LEFT,RIGHT,FRONT,BACK,BOT,TOP]) { req_children($children); faces = is_vector(faces)? [faces] : faces; - assert(all([for (face=faces) is_vector(face) && sum([for (x=face) x!=0? 1 : 0])==1]), "Vector in faces doesn't point at a face."); - assert($parent_geom != undef, "No object to attach to!"); + assert(all([for (face=faces) is_vector(face) && sum([for (x=face) x!=0? 1 : 0])==1]), "\nVector in faces doesn't point at a face."); + assert($parent_geom != undef, "\nNo object to attach to!"); attach(faces) { default_tag("remove") children(); } @@ -2094,7 +2094,7 @@ module face_mask(faces=[LEFT,RIGHT,FRONT,BACK,BOT,TOP]) { // rounding_edge_mask(l=71,r=10); module edge_mask(edges=EDGES_ALL, except=[]) { req_children($children); - assert($parent_geom != undef, "No object to attach to!"); + assert($parent_geom != undef, "\nNo object to attach to!"); edges = _edges(edges, except=except); vecs = [ for (i = [0:3], axis=[0:2]) @@ -2104,7 +2104,7 @@ module edge_mask(edges=EDGES_ALL, except=[]) { for ($idx = idx(vecs)) { vec = vecs[$idx]; vcount = (vec.x?1:0) + (vec.y?1:0) + (vec.z?1:0); - dummy=assert(vcount == 2, "Not an edge vector!"); + dummy=assert(vcount == 2, "\nNot an edge vector!"); anch = _find_anchor(vec, $parent_geom); $edge_angle = len(anch)==5 ? struct_val(anch[4],"edge_angle") : undef; $edge_length = len(anch)==5 ? struct_val(anch[4],"edge_length") : undef; @@ -2151,13 +2151,13 @@ module edge_mask(edges=EDGES_ALL, except=[]) { // } module corner_mask(corners=CORNERS_ALL, except=[]) { req_children($children); - assert($parent_geom != undef, "No object to attach to!"); + assert($parent_geom != undef, "\nNo object to attach to!"); corners = _corners(corners, except=except); vecs = [for (i = [0:7]) if (corners[i]>0) CORNER_OFFSETS[i]]; for ($idx = idx(vecs)) { vec = vecs[$idx]; vcount = (vec.x?1:0) + (vec.y?1:0) + (vec.z?1:0); - dummy=assert(vcount == 3, "Not an edge vector!"); + dummy=assert(vcount == 3, "\nNot an edge vector!"); anch = _find_anchor(vec, $parent_geom); $attach_to = undef; $attach_anchor = anch; @@ -2202,7 +2202,7 @@ module corner_mask(corners=CORNERS_ALL, except=[]) { module face_profile(faces=[], r, d, excess=0.01, convexity=10) { req_children($children); faces = is_vector(faces)? [faces] : faces; - assert(all([for (face=faces) is_vector(face) && sum([for (x=face) x!=0? 1 : 0])==1]), "Vector in faces doesn't point at a face."); + assert(all([for (face=faces) is_vector(face) && sum([for (x=face) x!=0? 1 : 0])==1]), "\nVector in faces doesn't point at a face."); r = get_radius(r=r, d=d, dflt=undef); assert(is_num(r) && r>=0); edge_profile(faces, excess=excess) children(); @@ -2256,11 +2256,11 @@ module face_profile(faces=[], r, d, excess=0.01, convexity=10) { module edge_profile(edges=EDGES_ALL, except=[], excess=0.01, convexity=10) { req_children($children); - check1 = assert($parent_geom != undef, "No object to attach to!"); + check1 = assert($parent_geom != undef, "\nNo object to attach to!"); conoid = $parent_geom[0] == "conoid"; edges = !conoid? _edges(edges, except=except) : edges==EDGES_ALL? [TOP,BOT] : - assert(all([for (e=edges) in_list(e,[TOP,BOT])]), "Invalid conoid edge spec.") + assert(all([for (e=edges) in_list(e,[TOP,BOT])]), "\nInvalid conoid edge spec.") edges; vecs = conoid ? [for (e=edges) e+FWD] @@ -2270,7 +2270,7 @@ module edge_profile(edges=EDGES_ALL, except=[], excess=0.01, convexity=10) { EDGE_OFFSETS[axis][i] ]; all_vecs_are_edges = all([for (vec = vecs) sum(v_abs(vec))==2]); - check2 = assert(all_vecs_are_edges, "All vectors must be edges."); + check2 = assert(all_vecs_are_edges, "\nAll vectors must be edges."); default_tag("remove") for ($idx = idx(vecs)) { vec = vecs[$idx]; @@ -2452,7 +2452,7 @@ module edge_profile_asym( [BACK+RIGHT, [TOP+BACK, BOT+BACK]], ], i = search([from], flip_edges, num_returns_per_match=1)[0], - check = assert(i!=[], "Bad edge vector.") + check = assert(i!=[], "\nBad edge vector.") ) in_list(to,flip_edges[i][1]); function _edge_corner_numbers(vec) = @@ -2467,7 +2467,7 @@ module edge_profile_asym( function _gather_contiguous_edges(edge_corners) = let( no_tri_corners = all([for(cn = [0:7]) len([for (ec=edge_corners) if(in_list(cn,ec[1])) 1])<3]), - check = assert(no_tri_corners, "Cannot have three edges that meet at the same corner.") + check = assert(no_tri_corners, "\nCannot have three edges that meet at the same corner.") ) _gather_contiguous_edges_r( [for (i=idx(edge_corners)) if(i) edge_corners[i]], @@ -2552,7 +2552,7 @@ module edge_profile_asym( [for (i=[0:2]) if (abs(e1[i])==1 && e1[i]==e2[i]) -e1[i] else 0]; req_children($children); - check1 = assert($parent_geom != undef, "No object to attach to!") + check1 = assert($parent_geom != undef, "\nNo object to attach to!") assert(in_list(corner_type, ["none", "round", "chamfer", "sharp"])) assert(is_bool(flip)); edges = _edges(edges, except=except); @@ -2562,7 +2562,7 @@ module edge_profile_asym( EDGE_OFFSETS[axis][i] ]; all_vecs_are_edges = all([for (vec = vecs) sum(v_abs(vec))==2]); - check2 = assert(all_vecs_are_edges, "All vectors must be edges."); + check2 = assert(all_vecs_are_edges, "\nAll vectors must be edges."); edge_corners = [for (vec = vecs) [vec, _edge_corner_numbers(vec)]]; edge_strings = _gather_contiguous_edges(edge_corners); default_tag("remove") @@ -2688,13 +2688,13 @@ module edge_profile_asym( // mask2d_teardrop(r=10, angle=40); // } module corner_profile(corners=CORNERS_ALL, except=[], r, d, convexity=10) { - check1 = assert($parent_geom != undef, "No object to attach to!"); + check1 = assert($parent_geom != undef, "\nNo object to attach to!"); r = max(0.01, get_radius(r=r, d=d, dflt=undef)); - check2 = assert(is_num(r), "Bad r/d argument."); + check2 = assert(is_num(r), "\nBad r/d argument."); corners = _corners(corners, except=except); vecs = [for (i = [0:7]) if (corners[i]>0) CORNER_OFFSETS[i]]; all_vecs_are_corners = all([for (vec = vecs) sum(v_abs(vec))==3]); - check3 = assert(all_vecs_are_corners, "All vectors must be corners."); + check3 = assert(all_vecs_are_corners, "\nAll vectors must be corners."); for ($idx = idx(vecs)) { vec = vecs[$idx]; anch = _find_anchor(vec, $parent_geom); @@ -3121,11 +3121,11 @@ module attachable( expose_tags=false, keep_color=false ) { dummy1 = - assert($children==2, "attachable() expects exactly two children; the shape to manage, and the union of all attachment candidates.") + assert($children==2, "\nattachable() expects exactly two children: the shape to manage, and the union of all attachment candidates.") assert(is_undef(anchor) || is_vector(anchor) || is_string(anchor), str("Invalid anchor: ",anchor)) - assert(is_undef(spin) || is_finite(spin), str("Invalid spin: ",spin)) - assert(is_undef(orient) || is_vector(orient,3), str("Invalid orient: ",orient)); - assert(in_list(v_abs(axis),[UP,RIGHT,BACK]), "axis must be a coordinate direction"); + assert(is_undef(spin) || is_finite(spin), str("\nInvalid spin: ",spin)) + assert(is_undef(orient) || is_vector(orient,3), str("\nInvalid orient: ",orient)); + assert(in_list(v_abs(axis),[UP,RIGHT,BACK]), "\n'axis' must be a coordinate direction."); anchor = default(anchor,CENTER); spin = default(spin,0); orient = is_def($anchor_override)? UP : default(orient, UP); @@ -3300,9 +3300,9 @@ function reorient( geom, p=undef ) = - assert(is_undef(anchor) || is_vector(anchor) || is_string(anchor), str("Invalid anchor: ",anchor)) - assert(is_undef(spin) || is_finite(spin), str("Invalid spin: ",spin)) - assert(is_undef(orient) || is_vector(orient,3), str("Invalid orient: ",orient)) + assert(is_undef(anchor) || is_vector(anchor) || is_string(anchor), str("\nInvalid anchor: ",anchor)) + assert(is_undef(spin) || is_finite(spin), str("\nInvalid spin: ",spin)) + assert(is_undef(orient) || is_vector(orient,3), str("\nInvalid orient: ",orient)) let( anchor = default(anchor, CENTER), spin = default(spin, 0), @@ -3348,15 +3348,15 @@ function reorient( // rot = A 4x4 rotations matrix, which may include a translation // flip = If true, flip the anchor the opposite direction. Default: false function named_anchor(name, pos, orient, spin, rot, flip, info) = - assert(num_defined([orient,spin])==0 || num_defined([rot,flip])==0, "Cannot mix orient or spin with rot or flip") - assert(num_defined([pos,rot])>0, "Must give pos or rot") + assert(num_defined([orient,spin])==0 || num_defined([rot,flip])==0, "\nCannot mix orient or spin with rot or flip.") + assert(num_defined([pos,rot])>0, "\nMust give pos or rot") is_undef(rot) ? [name, pos, default(orient,UP), default(spin,0), if (info) info] : let( flip = default(flip,false), pos = default(pos,apply(rot,CTR)), rotpart = _force_rot(rot), - dummy = assert(approx(det4(rotpart),1), "Input rotation is not a rotation matrix"), + dummy = assert(approx(det4(rotpart),1), "\nInput rotation is not a rotation matrix."), dir = flip ? apply(rotpart,DOWN) : apply(rotpart,UP), rot = flip? affine3d_rot_by_axis(apply(rotpart,BACK),180)*rot @@ -3540,11 +3540,11 @@ function attach_geom( assert(is_region(region),2) let( l = default(l, h) ) two_d==true - ? assert(is_undef(l), "Cannot give l/h with region anchor types (when two_d is set)") + ? assert(is_undef(l), "\nCannot give l/h with region anchor types (when two_d is set).") extent==true ? ["rgn_extent", region, cp, offset, anchors] : ["rgn_isect", region, cp, offset, anchors] - : assert(is_finite(l), "Must give l/h with extrusion anchor types (did you forget to set two_d?)") + : assert(is_finite(l), "\nMust give l/h with extrusion anchor types (did you forget to set two_d?).") let( shift = default(shift, [0,0]), scale = is_num(scale)? [scale,scale] : default(scale, [1,1]), @@ -3623,10 +3623,10 @@ function attach_geom( // } function define_part(name, geom, inside=false, T=IDENT) = - assert(is_string(name), "name must be a string") - assert(_is_geometry(geom), "geometry appears invalid") - assert(is_bool(inside), "inside must be boolean") - assert(is_matrix(T,4), "T must be a 4x4 transformation matrix") + assert(is_string(name), "\n'name' must be a string.") + assert(_is_geometry(geom), "\ngeometry appears invalid.") + assert(is_bool(inside), "\n'inside' must be boolean.") + assert(is_matrix(T,4), "\nT must be a 4×4 transformation matrix.") [name, geom, inside, T]; @@ -3714,7 +3714,7 @@ function _attach_geom_size(geom) = delt = mm[1]-mm[0] ) [delt.x, delt.y] ) : - assert(false, "Unknown attachment geometry type."); + assert(false, "\nUnknown attachment geometry type."); @@ -3727,7 +3727,7 @@ function _attach_geom_size(geom) = /// Returns the path and post-transform matrix of the indicated edge. /// If the edge is invalid for the geometry, returns `undef`. function _attach_geom_edge_path(geom, edge) = - assert(is_vector(edge),str("Invalid edge: edge=",edge)) + assert(is_vector(edge),str("\nInvalid edge: ",edge)) let( type = geom[0], cp = _get_cp(geom), @@ -3737,9 +3737,9 @@ function _attach_geom_edge_path(geom, edge) = ) type == "prismoid"? ( //size, size2, shift, axis let(all_comps_good = [for (c=edge) if (c!=sign(c)) 1]==[]) - assert(all_comps_good, "All components of an edge for a cuboid/prismoid must be -1, 0, or 1") + assert(all_comps_good, "\nAll components of an edge for a cuboid/prismoid must be -1, 0, or 1.") let(edge_good = len([for (c=edge) if(c) 1])==2) - assert(edge_good, "Invalid edge.") + assert(edge_good, "\nInvalid edge.") let( size = geom[1], size2 = geom[2], @@ -3776,7 +3776,7 @@ function _attach_geom_edge_path(geom, edge) = m = rot(from=UP,to=axis) * move(offset) ) [path, [vecs], m] ) : type == "conoid"? ( //r1, r2, l, shift, axis - assert(edge.z && edge.z == sign(edge.z), "The Z component of an edge for a cylinder/cone must be -1 or 1") + assert(edge.z && edge.z == sign(edge.z), "\nThe Z component of an edge for a cylinder/cone must be -1 or 1.") let( rr1 = geom[1], rr2 = geom[2], @@ -3830,9 +3830,9 @@ function _attach_geom_edge_path(geom, edge) = /// p = If given as a VNF, path, or point, applies the affine3d transformation matrix to it and returns the result. function _attach_transform(anchor, spin, orient, geom, p) = - assert(is_undef(anchor) || is_vector(anchor) || is_string(anchor), str("Invalid anchor: ",anchor)) - assert(is_undef(spin) || is_finite(spin), str("Invalid spin: ",spin)) - assert(is_undef(orient) || is_vector(orient,3), str("Invalid orient: ",orient)) + assert(is_undef(anchor) || is_vector(anchor) || is_string(anchor), str("\nInvalid anchor: ",anchor)) + assert(is_undef(spin) || is_finite(spin), str("\nInvalid spin: ",spin)) + assert(is_undef(orient) || is_vector(orient,3), str("\nInvalid orient: ",orient)) let( anchor=default(anchor,CENTER), spin=default(spin,0), @@ -3888,7 +3888,7 @@ function _get_cp(geom) = : in_list(geom[0],["extrusion_extent","extrusion_isect"]) ? "xpath" : "other" ) - assert(type!="other", "Invalid cp value") + assert(type!="other", "\nInvalid cp value.") cp=="centroid" ? ( type=="vnf" && (len(geom[1][0])==0 || len(geom[1][1])==0) ? [0,0,0] : [each centroid(geom[1]), if (type=="xpath") 0] @@ -3896,7 +3896,7 @@ function _get_cp(geom) = : let(points = type=="vnf"?geom[1][0]:flatten(force_region(geom[1]))) cp=="mean" ? [each mean(points), if (type=="xpath") 0] : cp=="box" ?[each mean(pointlist_bounds(points)), if (type=="xpath") 0] - : assert(false,"Invalid cp specification"); + : assert(false,"\nInvalid cp specification."); function _get_cp(geom) = @@ -3913,7 +3913,7 @@ function _get_cp(geom) = : let(points = is_vnf?geom[1][0]:flatten(force_region(geom[1]))) cp=="mean" ? mean(points) : cp=="box" ? mean(pointlist_bounds(points)) - : assert(false,"Invalid cp specification"); + : assert(false,"\nInvalid cp specification."); @@ -3949,7 +3949,7 @@ function _find_anchor(anchor, geom)= anchors = last(geom), found = search([anchor], anchors, num_returns_per_match=1)[0] ) - assert(found!=[], str("Unknown anchor: ",anchor)) + assert(found!=[], str("\nUnknown anchor: ",anchor)) anchors[found] ) : let( @@ -3958,7 +3958,7 @@ function _find_anchor(anchor, geom)= offset = [for (i=[0:2]) anchor[i]==0? 0 : offset_raw[i]], // prevents bad centering. type = geom[0] ) - assert(is_vector(anchor),str("Invalid anchor: anchor=",anchor)) + assert(is_vector(anchor),str("\nInvalid anchor: ",anchor)) let( anchor = point3d(anchor), oang = ( @@ -3968,7 +3968,7 @@ function _find_anchor(anchor, geom)= ) type == "prismoid"? ( //size, size2, shift, axis let(all_comps_good = [for (c=anchor) if (c!=sign(c)) 1]==[]) - assert(all_comps_good, "All components of an anchor for a cuboid/prismoid must be -1, 0, or 1") + assert(all_comps_good, "\nAll components of an anchor for a cuboid/prismoid must be -1, 0, or 1.") let( size=geom[1], size2=geom[2], @@ -4059,7 +4059,7 @@ function _find_anchor(anchor, geom)= : axis==RIGHT ? "X" : axis==BACK ? "Y" : "", - dummy = assert(anch.z == sign(anch.z), str("The ",axisname," component of an anchor for the cylinder/cone must be -1, 0, or 1")), + dummy = assert(anch.z == sign(anch.z), str("\nThe ",axisname," component of an anchor for the cylinder/cone must be -1, 0, or 1.")), offset = rot(from=axis, to=UP, p=offset), u = (anch.z+1)/2, // Returns [point,tangent_dir] @@ -4144,7 +4144,7 @@ function _find_anchor(anchor, geom)= for(pt=ptlist) [anchor * (pt-cp), n, pt] ] ) - assert(len(hits)>0, "Anchor vector does not intersect with the shape. Attachment failed.") + assert(len(hits)>0, "\nAnchor vector does not intersect with the shape. Attachment failed.") let( furthest = max_index(column(hits,0)), dist = hits[furthest][0], @@ -4169,8 +4169,8 @@ function _find_anchor(anchor, geom)= let( vnf=geom[1], override = geom[2](anchor) - ,fd=echo(cp=cp) - ) // CENTER anchors anchor on cp, "origin" anchors on [0,0] + //,fd=echo(cp=cp) + ) // CENTER anchors anchor on cp, "origin" anchors on [0,0] approx(anchor,CTR)? [anchor, default(override[0],cp),default(override[1],UP),default(override[2], 0)] : vnf==EMPTY_VNF? [anchor, [0,0,0], unit(anchor,UP), 0] : let( @@ -4236,7 +4236,7 @@ function _find_anchor(anchor, geom)= center = mean(plist) ) [center,anchor,basic_spin] - : len(vlist)==0 ? assert(false,"Cannot find anchor on the VNF") + : len(vlist)==0 ? assert(false,"\nCannot find anchor on the VNF.") : let( vlist = flatten(vlist), uind = unique_approx_indexed(select(vnf[0],vlist)), @@ -4266,7 +4266,7 @@ function _find_anchor(anchor, geom)= ) [anchor, default(override[0],res[0]),default(override[1],res[1]),default(override[2],res[2]),if (len(res)==3) res[2]] ) : type == "trapezoid"? ( //size, size2, shift, override let(all_comps_good = [for (c=anchor) if (c!=sign(c)) 1]==[]) - assert(all_comps_good, "All components of an anchor for a rectangle/trapezoid must be -1, 0, or 1") + assert(all_comps_good, "\nAll components of an anchor for a rectangle/trapezoid must be -1, 0, or 1.") let( anchor=_force_anchor_2d(anchor), size=geom[1], size2=geom[2], shift=geom[3], @@ -4318,7 +4318,7 @@ function _find_anchor(anchor, geom)= if(!is_undef(isect) && !approx(isect,t[0])) [norm(isect), isect, n2] ] ) - assert(len(isects)>0, "Anchor vector does not intersect with the shape. Attachment failed.") + assert(len(isects)>0, "\nAnchor vector does not intersect with the shape. Attachment failed.") let( maxidx = max_index(column(isects,0)), isect = isects[maxidx], @@ -4347,7 +4347,7 @@ function _find_anchor(anchor, geom)= [is_polygon_clockwise(path) ? -normal : normal, vector_angle(corner)] ) [anchor, pos, dir[0], 0, if(len(dir)>1) [["corner_angle",dir[1]]]] ) : type=="extrusion_extent" || type=="extrusion_isect" ? ( // extruded region - assert(in_list(anchor.z,[-1,0,1]), "The Z component of an anchor for an extruded 2D shape must be -1, 0, or 1.") + assert(in_list(anchor.z,[-1,0,1]), "\nThe Z component of an anchor for an extruded 2D shape must be -1, 0, or 1.") let( anchor_xy = point2d(anchor), rgn = geom[1], @@ -4379,7 +4379,7 @@ function _find_anchor(anchor, geom)= ) [anchor, pos, vec, oang] ) : - assert(false, "Unknown attachment geometry type."); + assert(false, "\nUnknown attachment geometry type."); /// Internal Function: _is_shown() @@ -4396,8 +4396,8 @@ function _is_shown() = dummy=is_undef($tags) ? 0 : echo("Use tag() instead of $tags for specifying an object's tag."), $tag = default($tag,$tags) ) - assert(is_string($tag), str("Tag value (",$tag,") is not a string")) - assert(undef==str_find($tag," "),str("Tag string \"",$tag,"\" contains a space, which is not allowed")) + assert(is_string($tag), str("\nTag value (",$tag,") is not a string")) + assert(undef==str_find($tag," "),str("\nTag string \"",$tag,"\" contains a space, which is not allowed.")) let( shown = $tags_shown=="ALL" || in_list($tag,$tags_shown), hidden = in_list($tag, $tags_hidden) @@ -4822,7 +4822,7 @@ function _edge_set(v) = let(valid_values = ["X", "Y", "Z", "ALL", "NONE"]) assert( in_list(v, valid_values), - str(v, " must be a vector, edge array, or one of ", valid_values) + str("\n", v, " must be a vector, edge array, or one of ", valid_values, ".") ) v ) : let(nonz = sum(v_abs(v))) @@ -4983,7 +4983,7 @@ function _corner_set(v) = let(valid_values = ["ALL", "NONE"]) assert( in_list(v, valid_values), - str(v, " must be a vector, corner array, or one of ", valid_values) + str("\n", v, " must be a vector, corner array, or one of ", valid_values, ".") ) v ) : all([for (i=[0:2]) !v[i] || (v[i]==v2[i])]) @@ -5114,14 +5114,14 @@ function _force_rot(T) = : 0]]; function _local_struct_val(struct, key)= - assert(is_def(key),"key is missing") + assert(is_def(key),"\nkey is missing.") let(ind = search([key],struct)[0]) ind == [] ? undef : struct[ind][1]; function _force_anchor_2d(anchor) = is_undef(anchor) || len(anchor)==2 || is_string(anchor) ? anchor : - assert(anchor.y==0 || anchor.z==0, "Anchor for a 2D shape cannot be fully 3D. It must have either Y or Z component equal to zero.") + assert(anchor.y==0 || anchor.z==0, "\nAnchor for a 2D shape cannot be fully 3D. It must have either Y or Z component equal to zero.") anchor.y==0 ? [anchor.x,anchor.z] : point2d(anchor); // Compute spin angle based on a anchor direction and desired spin direction @@ -5132,7 +5132,7 @@ function _compute_spin(anchor_dir, spin_dir) = let( native_dir = rot(from=UP, to=anchor_dir, p=BACK), spin_dir = spin_dir - (spin_dir*anchor_dir)*anchor_dir, // component of spin_dir perpendicular to anchor_dir - dummy = assert(!approx(spin_dir,[0,0,0]),"spin direction is parallel to anchor"), + dummy = assert(!approx(spin_dir,[0,0,0]),"\nSpin direction is parallel to anchor."), angle = vector_angle(native_dir,spin_dir), sign = cross(native_dir,spin_dir)*anchor_dir<0 ? -1 : 1 ) @@ -5216,11 +5216,11 @@ function parent() = // fillet=1); function parent_part(name) = - assert(!is_undef($parent_parts), "Parent does not exist or does not have any parts") + assert(!is_undef($parent_parts), "\nParent does not exist or does not have any parts.") let( ind = search([name], $parent_parts, 1,0)[0] ) - assert(ind!=[], str("Parent does not have a part named ",name)) + assert(ind!=[], str("\nParent does not have a part named \"",name,"\".")) [$transform * $parent_parts[ind][3], $parent_parts[ind][1]]; @@ -5251,7 +5251,7 @@ module restore(desc) multmatrix(T) children(); } else{ - check=assert(is_description(desc), "Invalid description"); + check=assert(is_description(desc), "\nInvalid description."); T = linear_solve($transform, desc[0]); $parent_geom = desc[1]; multmatrix(T) children(); @@ -5286,13 +5286,13 @@ module restore(desc) // stroke([[0,0,0], desc_point(desc,anchor=TOP+FWD+RIGHT)],width=.5,color="red"); function desc_point(desc, p, anchor) = is_undef(desc) ? - assert(is_undef(anchor), "Cannot give anchor withot desc") + assert(is_undef(anchor), "\nCannot give 'anchor' withot 'desc'.") let( T = matrix_inverse($transform) ) apply(T, default(p,UP)) - : assert(is_description(desc), "Invalid description") - assert(num_defined([anchor,p])<2, "Cannot give both anchor and p") + : assert(is_description(desc), "\nInvalid description.") + assert(num_defined([anchor,p])<2, "\nCannot give both anchor and p") let ( T = linear_solve($transform, desc[0]), p = is_def(p) ? p @@ -5328,14 +5328,14 @@ function desc_point(desc, p, anchor) = // position(TOP) cyl(d=2,h=15,orient=desc_dir(pris,anchor=FWD),anchor=LEFT); function desc_dir(desc, dir, anchor) = is_undef(desc) ? - assert(is_undef(anchor), "Cannot give anchor without desc") + assert(is_undef(anchor), "\nCannot give 'anchor' without 'desc'.") let( T = matrix_inverse($transform) ) move(-apply(T,CENTER), apply(T, default(dir,UP))) : assert(is_description(desc), "Invalid description") - assert(num_defined([dir,anchor])<2, "Cannot give both dir and anchor") + assert(num_defined([dir,anchor])<2, "\nCannot give both dir and anchor.") let( T = linear_solve($transform, desc[0]), dir = is_def(dir) ? dir @@ -5347,7 +5347,7 @@ function desc_dir(desc, dir, anchor) = move(-apply(T,CENTER),apply(T, dir)); function desc_attach(desc, anchor=UP, p, reverse=false) = - assert(is_description(desc), "Invalid description") + assert(is_description(desc), "\nInvalid description.") let( T = linear_solve($transform, desc[0]), anch = _find_anchor(anchor,desc[1]), @@ -5385,8 +5385,8 @@ function desc_attach(desc, anchor=UP, p, reverse=false) = // } function desc_dist(desc1,anchor1=CENTER, desc2, anchor2=CENTER)= - assert(is_description(desc1),"Invalid description: desc1") - assert(is_description(desc2),"Invalid description: desc2") + assert(is_description(desc1),str("\nInvalid description: desc1=",desc1)) + assert(is_description(desc2),str("\nInvalid description: desc2=",desc2)) let( anch1 = _find_anchor(anchor1, desc1[1]), anch2 = _find_anchor(anchor2, desc2[1]), @@ -5415,10 +5415,10 @@ function desc_dist(desc1,anchor1=CENTER, desc2, anchor2=CENTER)= // desc = description to transform function transform_desc(T,desc) = - assert(is_description(desc), "Invalid description") + assert(is_description(desc), "\nInvalid description.") is_consistent(T, ident(4)) ? [for(t=T) [t*desc[0], desc[1]]] : is_matrix(T,4,4) ? [T*desc[0], desc[1]] - : assert(false,"T must be a 4x4 matrix or list of 4x4 matrices"); + : assert(false,"\nT must be a 4×4 matrix or list of 4×4 matrices."); // Module: desc_copies() diff --git a/shapes3d.scad b/shapes3d.scad index d42d17a7..aa0fe99b 100644 --- a/shapes3d.scad +++ b/shapes3d.scad @@ -2544,22 +2544,27 @@ function xcyl( tex_taper, style, tex_style, extra, extra1, extra2, anchor, spin=0 -) = cyl(h=h, r=r, center=center, - l=l, r1=r1, r2=r2, - d=d, d1=d1, d2=d2, - length=length, height=height, - chamfer=chamfer, chamfer1=chamfer1, chamfer2=chamfer2, - chamfang=chamfang, chamfang1=chamfang1, chamfang2=chamfang2, - rounding=rounding, rounding1=rounding1, rounding2=rounding2, - circum=circum, realign=realign, shift=shift, - teardrop=teardrop, clip_angle=clip_angle, - from_end=from_end, from_end1=from_end1, from_end2=from_end2, - texture=texture, tex_size=tex_size, tex_reps=tex_reps, tex_counts=tex_counts, - tex_inset=tex_inset, tex_rot=tex_rot, - tex_scale=tex_scale, tex_depth=tex_depth, tex_samples=tex_samples, - tex_taper=tex_taper, style=style, tex_style=tex_style, - extra=extra, extra1=extra1, extra2=extra2, - anchor=anchor, spin=spin, orient=RIGHT); +) = let( + 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), + l = one_defined([l,h,length,height],"l,h,length,height",1), + vnf=cyl(h=h, r=r, center=center, + l=l, r1=r1, r2=r2, + d=d, d1=d1, d2=d2, + length=length, height=height, + chamfer=chamfer, chamfer1=chamfer1, chamfer2=chamfer2, + chamfang=chamfang, chamfang1=chamfang1, chamfang2=chamfang2, + rounding=rounding, rounding1=rounding1, rounding2=rounding2, + circum=circum, realign=realign, shift=shift, + teardrop=teardrop, clip_angle=clip_angle, + from_end=from_end, from_end1=from_end1, from_end2=from_end2, + texture=texture, tex_size=tex_size, tex_reps=tex_reps, tex_counts=tex_counts, + tex_inset=tex_inset, tex_rot=tex_rot, + tex_scale=tex_scale, tex_depth=tex_depth, tex_samples=tex_samples, + tex_taper=tex_taper, style=style, tex_style=tex_style, + extra=extra, extra1=extra1, extra2=extra2, + anchor=CENTER, spin=0, orient=RIGHT) + ) reorient(anchor, spin, UP, p=vnf, r1=r1, r2=r2, l=l, axis=RIGHT); module xcyl( h, r, center, @@ -2577,7 +2582,7 @@ module xcyl( tex_scale, tex_depth, tex_samples, tex_taper, style, tex_style, extra, extra1, extra2, - anchor, spin=0 + anchor=CENTER, spin=0 ) { 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); @@ -2597,7 +2602,7 @@ module xcyl( tex_scale=tex_scale, tex_depth=tex_depth, tex_samples=tex_samples, tex_taper=tex_taper, style=style, tex_style=tex_style, extra=extra, extra1=extra1, extra2=extra2, - anchor=anchor, spin=spin, orient=RIGHT + anchor=CENTER, spin=0, orient=RIGHT ); children(); } @@ -2650,22 +2655,28 @@ function ycyl( tex_taper, style, tex_style, extra, extra1, extra2, anchor, spin=0 -) = cyl(h=h, r=r, center=center, - l=l, r1=r1, r2=r2, - d=d, d1=d1, d2=d2, - length=length, height=height, - chamfer=chamfer, chamfer1=chamfer1, chamfer2=chamfer2, - chamfang=chamfang, chamfang1=chamfang1, chamfang2=chamfang2, - rounding=rounding, rounding1=rounding1, rounding2=rounding2, - circum=circum, realign=realign, shift=shift, - teardrop=teardrop, clip_angle=clip_angle, - from_end=from_end, from_end1=from_end1, from_end2=from_end2, - texture=texture, tex_size=tex_size, tex_reps=tex_reps, tex_counts=tex_counts, - tex_inset=tex_inset, tex_rot=tex_rot, - tex_scale=tex_scale, tex_depth=tex_depth, tex_samples=tex_samples, - tex_taper=tex_taper, style=style, tex_style=tex_style, - extra=extra, extra1=extra1, extra2=extra2, - anchor=anchor, spin=spin, orient=BACK); +) = let( + 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), + l = one_defined([l,h,length,height],"l,h,length,height",1), + vnf=cyl(h=h, r=r, center=center, + l=l, r1=r1, r2=r2, + d=d, d1=d1, d2=d2, + length=length, height=height, + chamfer=chamfer, chamfer1=chamfer1, chamfer2=chamfer2, + chamfang=chamfang, chamfang1=chamfang1, chamfang2=chamfang2, + rounding=rounding, rounding1=rounding1, rounding2=rounding2, + circum=circum, realign=realign, shift=shift, + teardrop=teardrop, clip_angle=clip_angle, + from_end=from_end, from_end1=from_end1, from_end2=from_end2, + texture=texture, tex_size=tex_size, tex_reps=tex_reps, tex_counts=tex_counts, + tex_inset=tex_inset, tex_rot=tex_rot, + tex_scale=tex_scale, tex_depth=tex_depth, tex_samples=tex_samples, + tex_taper=tex_taper, style=style, tex_style=tex_style, + extra=extra, extra1=extra1, extra2=extra2, + anchor=CENTER, spin=0, orient=BACK) + ) reorient(anchor, spin, UP, p=vnf, r1=r1, r2=r2, l=l, axis=BACK); + module ycyl( @@ -2704,7 +2715,7 @@ module ycyl( tex_scale=tex_scale, tex_depth=tex_depth, tex_samples=tex_samples, tex_taper=tex_taper, style=style, tex_style=tex_style, extra=extra, extra1=extra1, extra2=extra2, - anchor=anchor, spin=spin, orient=BACK + anchor=CENTER, spin=0, orient=BACK ); children(); } @@ -2753,22 +2764,28 @@ function zcyl( tex_taper, style, tex_style, extra, extra1, extra2, anchor, spin=0 -) = cyl(h=h, r=r, center=center, - l=l, r1=r1, r2=r2, - d=d, d1=d1, d2=d2, - length=length, height=height, - chamfer=chamfer, chamfer1=chamfer1, chamfer2=chamfer2, - chamfang=chamfang, chamfang1=chamfang1, chamfang2=chamfang2, - rounding=rounding, rounding1=rounding1, rounding2=rounding2, - circum=circum, realign=realign, shift=shift, - teardrop=teardrop, clip_angle=clip_angle, - from_end=from_end, from_end1=from_end1, from_end2=from_end2, - texture=texture, tex_size=tex_size, tex_reps=tex_reps, tex_counts=tex_counts, - tex_inset=tex_inset, tex_rot=tex_rot, - tex_scale=tex_scale, tex_depth=tex_depth, tex_samples=tex_samples, - tex_taper=tex_taper, style=style, tex_style=tex_style, - extra=extra, extra1=extra1, extra2=extra2, - anchor=anchor, spin=spin, orient=UP); +) = let( + 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), + l = one_defined([l,h,length,height],"l,h,length,height",1), + vnf=cyl(h=h, r=r, center=center, + l=l, r1=r1, r2=r2, + d=d, d1=d1, d2=d2, + length=length, height=height, + chamfer=chamfer, chamfer1=chamfer1, chamfer2=chamfer2, + chamfang=chamfang, chamfang1=chamfang1, chamfang2=chamfang2, + rounding=rounding, rounding1=rounding1, rounding2=rounding2, + circum=circum, realign=realign, shift=shift, + teardrop=teardrop, clip_angle=clip_angle, + from_end=from_end, from_end1=from_end1, from_end2=from_end2, + texture=texture, tex_size=tex_size, tex_reps=tex_reps, tex_counts=tex_counts, + tex_inset=tex_inset, tex_rot=tex_rot, + tex_scale=tex_scale, tex_depth=tex_depth, tex_samples=tex_samples, + tex_taper=tex_taper, style=style, tex_style=tex_style, + extra=extra, extra1=extra1, extra2=extra2, + anchor=CENTER, spin=0, orient=UP) + ) reorient(anchor, spin, UP, p=vnf, r1=r1, r2=r2, l=l, axis=UP); + module zcyl( h, r, center, @@ -2805,7 +2822,7 @@ module zcyl( tex_scale=tex_scale, tex_depth=tex_depth, tex_samples=tex_samples, tex_taper=tex_taper, style=style, tex_style=tex_style, extra=extra, extra1=extra1, extra2=extra2, - anchor=anchor, spin=spin, orient=UP + anchor=CENTER, spin=0, orient=UP ); children(); }