From ec1bab7274db19ee0036e7529cabbcde6a9530d6 Mon Sep 17 00:00:00 2001 From: Adrian Mariano Date: Sun, 26 Jun 2022 12:08:22 -0400 Subject: [PATCH] fix attachment scope problem, change default mask tag to "remove", applied only when user doesn't give a tag --- attachments.scad | 81 +++++++++++++++++++++------------------- tripod_mounts.scad | 38 ++++++++++--------- tutorials/Attachments.md | 21 ++++++----- 3 files changed, 75 insertions(+), 65 deletions(-) diff --git a/attachments.scad b/attachments.scad index 8d8ac8d..ac91f64 100644 --- a/attachments.scad +++ b/attachments.scad @@ -554,7 +554,7 @@ module attach(from, to, overlap, norot=false) // Arguments: // tag = tag string, which must not contain any spaces. // Side Effects: -// Sets `$tag` to the tag you specify. +// Sets `$tag` to the tag you specify, possibly with a scope prefix. // Example(3D): Applies the tag to both cuboids instead of having to repeat `$tag="remove"` for each one. // diff("remove") // cuboid(10){ @@ -609,7 +609,7 @@ module tag(tag) // Arguments: // tag = tag string, which must not contain any spaces // Side Effects: -// Sets `$tag` to the tag you specify. +// Sets `$tag` to the tag you specify, possibly with a scope prefix. // Example(2D): This example produces the full square without subtracting the "remove" item. When you use non-attachable modules with tags, results are unpredictable. // diff() // { @@ -628,8 +628,8 @@ module force_tag(tag) { req_children($children); assert(is_undef(tag) || is_string(tag),"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")); - $tag = str($tag_prefix,is_def(tag) ? tag : $tag); if(_is_shown()) show_all() children(); @@ -873,7 +873,7 @@ module diff(remove="remove", keep="keep") // remove = String containing space delimited set of tag names of children to difference away. Default: `"remove"` // keep = String containing space delimited set of tag names of children to keep; that is, to union into the model after differencing is completed. Default: `"keep"` // Side Effects: -// Sets `$tag` to the tag you specify. +// Sets `$tag` to the tag you specify, possibly with a scope prefix. // Example: In this example we have a difference with a kept object that is then subtracted from a cube, but we don't want the kept object to appear in the final output, so this result is wrong: // diff("rem"){ // cuboid([20,10,30],anchor=FRONT); @@ -914,7 +914,7 @@ module tag_diff(tag,remove="remove", keep="keep") 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")); - $tag=tag; + $tag=str($tag_prefix,tag); if (_is_shown()) show_all(){ difference() { @@ -1013,7 +1013,7 @@ module intersect(intersect="intersect",keep="keep") // intersect = String containing space delimited set of tag names of children to intersect. Default: "intersect" // keep = String containing space delimited set of tag names of children to keep whole. Default: "keep" // Side Effects: -// Sets `$tag` to the tag you specify. +// Sets `$tag` to the tag you specify, possibly with a scope prefix. // Example: Without `tag_intersect()` the kept object is not included in the difference. // $fn=32; // diff() @@ -1038,7 +1038,7 @@ module tag_intersect(tag,intersect="intersect",keep="keep") 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")); - $tag=tag; + $tag=str($tag_prefix,tag); if (_is_shown()) show_all(){ intersection(){ @@ -1102,7 +1102,7 @@ module conv_hull(keep="keep") // Arguments: // keep = String containing space delimited set of tag names of children to keep out of the hull. Default: "keep" // Side Effects: -// Sets `$tag` to the tag you specify. +// Sets `$tag` to the tag you specify, possibly with a scope prefix. // Example: With a regular tag, the kept object is not handled as desired: // diff(){ // cuboid([30,30,9]) @@ -1127,7 +1127,7 @@ module tag_conv_hull(tag,keep="keep") 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")); - $tag=tag; + $tag=str($tag_prefix,tag); if (_is_shown()) show_all(){ hull() hide(keep) children(); @@ -1244,8 +1244,9 @@ module show_int(tags) // See Also: attachable(), position(), attach(), face_profile(), edge_profile(), corner_mask() // Description: // Takes a 3D mask shape, and attaches it to the given edges, with the appropriate orientation to be -// `diff()`ed away. The mask shape should be vertically oriented (Z-aligned) with the back-right -// quadrant (X+Y+) shaped to be diffed away from the edge of parent attachable shape. +// differenced away. The mask shape should be vertically oriented (Z-aligned) with the back-right +// quadrant (X+Y+) shaped to be diffed away from the edge of parent attachable shape. If no tag is set +// then `edge_mask` sets the tag for children to "remove" so that it will work with the default {{diff()}} tag. // For details on specifying the edges to mask see [Specifying Edges](attachments.scad#subsection-specifying-edges). // For a step-by-step explanation of attachments, see the [[Attachments Tutorial|Tutorial-Attachments]]. // Figure: A Typical Edge Rounding Mask @@ -1260,9 +1261,9 @@ module show_int(tags) // edges = Edges to mask. See [Specifying Edges](attachments.scad#subsection-specifying-edges). Default: All edges. // except = Edges to explicitly NOT mask. See [Specifying Edges](attachments.scad#subsection-specifying-edges). Default: No edges. // Side Effects: -// Sets `$tag = "mask"` for all children. -// Example: -// diff("mask") +// Tags the children with "remove" (and hence sets `$tag`) if no tag is already set. +// Example: +// diff() // cube([50,60,70],center=true) // edge_mask([TOP,"Z"],except=[BACK,TOP+LEFT]) // rounding_edge_mask(l=71,r=10); @@ -1282,13 +1283,14 @@ module edge_mask(edges=EDGES_ALL, except=[]) { $attach_to = undef; $attach_anchor = anch; $attach_norot = true; - $tag = "mask"; rotang = vec.z<0? [90,0,180+v_theta(vec)] : vec.z==0 && sign(vec.x)==sign(vec.y)? 135+v_theta(vec) : vec.z==0 && sign(vec.x)!=sign(vec.y)? [0,180,45+v_theta(vec)] : [-90,0,180+v_theta(vec)]; - translate(anch[1]) rot(rotang) children(); + translate(anch[1]) rot(rotang) + if ($tag=="") tag("remove") children(); + else children(); } } @@ -1300,16 +1302,17 @@ module edge_mask(edges=EDGES_ALL, except=[]) { // See Also: attachable(), position(), attach(), face_profile(), edge_profile(), edge_mask() // Description: // Takes a 3D mask shape, and attaches it to the specified corners, with the appropriate orientation to -// be `diff()`ed away. The 3D corner mask shape should be designed to mask away the X+Y+Z+ octant. +// be differenced away. The 3D corner mask shape should be designed to mask away the X+Y+Z+ octant. If no tag is set +// then `corner_mask` sets the tag for children to "remove" so that it will work with the default {{diff()}} tag. // See [Specifying Corners](attachments.scad#subsection-specifying-corners) for information on how to specify corner sets. // For a step-by-step explanation of attachments, see the [[Attachments Tutorial|Tutorial-Attachments]]. // Arguments: // corners = Corners to mask. See [Specifying Corners](attachments.scad#subsection-specifying-corners). Default: All corners. // except = Corners to explicitly NOT mask. See [Specifying Corners](attachments.scad#subsection-specifying-corners). Default: No corners. // Side Effects: -// Sets `$tag = "mask"` for all children. +// Tags the children with "remove" (and hence sets `$tag`) if no tag is already set. // Example: -// diff("mask") +// diff() // cube(100, center=true) // corner_mask([TOP,FRONT],LEFT+FRONT+TOP) // difference() { @@ -1328,11 +1331,12 @@ module corner_mask(corners=CORNERS_ALL, except=[]) { $attach_to = undef; $attach_anchor = anch; $attach_norot = true; - $tag = "mask"; rotang = vec.z<0? [ 0,0,180+v_theta(vec)-45] : [180,0,-90+v_theta(vec)-45]; - translate(anch[1]) rot(rotang) children(); + translate(anch[1]) rot(rotang) + if ($tag=="") tag("remove") children(); + else children(); } } @@ -1343,7 +1347,8 @@ module corner_mask(corners=CORNERS_ALL, except=[]) { // Topics: Attachments // See Also: attachable(), position(), attach(), edge_profile(), corner_profile() // Description: -// Given a 2D edge profile, extrudes it into a mask for all edges and corners bounding each given face. +// Given a 2D edge profile, extrudes it into a mask for all edges and corners bounding each given face. If no tag is set +// then `face_profile` sets the tag for children to "remove" so that it will work with the default {{diff()}} tag. // See [Specifying Faces](attachments.scad#subsection-specifying-faces) for information on specifying faces. // For a step-by-step explanation of attachments, see the [[Attachments Tutorial|Tutorial-Attachments]]. // Arguments: @@ -1353,9 +1358,9 @@ module corner_mask(corners=CORNERS_ALL, except=[]) { // d = Diameter of corner mask. // convexity = Max number of times a line could intersect the perimeter of the mask shape. Default: 10 // Side Effects: -// Sets `$tag = "mask"` for all children. +// Tags the children with "remove" (and hence sets `$tag`) if no tag is already set. // Example: -// diff("mask") +// diff() // cube([50,60,70],center=true) // face_profile(TOP,r=10) // mask2d_roundover(r=10); @@ -1377,7 +1382,8 @@ module face_profile(faces=[], r, d, convexity=10) { // See Also: attachable(), position(), attach(), face_profile(), corner_profile() // Description: // Takes a 2D mask shape and attaches it to the selected edges, with the appropriate orientation and -// extruded length to be `diff()`ed away, to give the edge a matching profile. +// extruded length to be `diff()`ed away, to give the edge a matching profile. If no tag is set +// then `edge_profile` sets the tag for children to "remove" so that it will work with the default {{diff()}} tag. // For details on specifying the edges to mask see [Specifying Edges](attachments.scad#subsection-specifying-edges). // For a step-by-step // explanation of attachments, see the [[Attachments Tutorial|Tutorial-Attachments]]. @@ -1386,9 +1392,9 @@ module face_profile(faces=[], r, d, convexity=10) { // except = Edges to explicitly NOT mask. See [Specifying Edges](attachments.scad#subsection-specifying-edges). Default: No edges. // convexity = Max number of times a line could intersect the perimeter of the mask shape. Default: 10 // Side Effects: -// Sets `$tag = "mask"` for all children. +// Tags the children with "remove" (and hence sets `$tag`) if no tag is already set. // Example: -// diff("mask") +// diff() // cube([50,60,70],center=true) // edge_profile([TOP,"Z"],except=[BACK,TOP+LEFT]) // mask2d_roundover(r=10, inset=2); @@ -1408,7 +1414,6 @@ module edge_profile(edges=EDGES_ALL, except=[], convexity=10) { $attach_to = undef; $attach_anchor = anch; $attach_norot = true; - $tag = "mask"; psize = point3d($parent_size); length = [for (i=[0:2]) if(!vec[i]) psize[i]][0]+0.1; rotang = @@ -1419,7 +1424,8 @@ module edge_profile(edges=EDGES_ALL, except=[], convexity=10) { translate(anch[1]) { rot(rotang) { linear_extrude(height=length, center=true, convexity=convexity) { - children(); + if ($tag=="") tag("remove") children(); + else children(); } } } @@ -1433,8 +1439,8 @@ module edge_profile(edges=EDGES_ALL, except=[], convexity=10) { // See Also: attachable(), position(), attach(), face_profile(), edge_profile() // Description: // Takes a 2D mask shape, rotationally extrudes and converts it into a corner mask, and attaches it -// to the selected corners with the appropriate orientation. Tags it as a "mask" to allow it to be -// `diff()`ed away, to give the corner a matching profile. +// to the selected corners with the appropriate orientation. If no tag is set +// then `corner_profile` sets the tag for children to "remove" so that it will work with the default {{diff()}} tag. // See [Specifying Corners](attachments.scad#subsection-specifying-corners) for information on how to specify corner sets. // For a step-by-step explanation of attachments, see the [[Attachments Tutorial|Tutorial-Attachments]]. // Arguments: @@ -1445,9 +1451,9 @@ module edge_profile(edges=EDGES_ALL, except=[], convexity=10) { // d = Diameter of corner mask. // convexity = Max number of times a line could intersect the perimeter of the mask shape. Default: 10 // Side Effects: -// Sets `$tag = "mask"` for all children. +// Tags the children with "remove" (and hence sets $tag) if no tag is already set. // Example: -// diff("mask") +// diff() // cuboid([50,60,70],rounding=10,edges="Z",anchor=CENTER) { // corner_profile(BOT,r=10) // mask2d_teardrop(r=10, angle=40); @@ -1465,10 +1471,10 @@ module corner_profile(corners=CORNERS_ALL, except=[], r, d, convexity=10) { $attach_to = undef; $attach_anchor = anch; $attach_norot = true; - $tag = "mask"; rotang = vec.z<0? [ 0,0,180+v_theta(vec)-45] : [180,0,-90+v_theta(vec)-45]; + $tag = $tag=="" ? str($tag_prefix,"remove") : $tag; translate(anch[1]) { rot(rotang) { render(convexity=convexity) @@ -2576,14 +2582,13 @@ function _is_shown() = assert(is_list($tags_hidden)) let( dummy=is_undef($tags) ? 0 : echo("Use tag() instead of $tags for specifying an object's tag."), - $tags = default($tag,$tags) + $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")) let( - fulltag = $tag, - shown = $tags_shown=="ALL" || in_list(fulltag,$tags_shown), - hidden = in_list(fulltag, $tags_hidden) + shown = $tags_shown=="ALL" || in_list($tag,$tags_shown), + hidden = in_list($tag, $tags_hidden) ) shown && !hidden; diff --git a/tripod_mounts.scad b/tripod_mounts.scad index 7a9ca6b..9ed73d1 100644 --- a/tripod_mounts.scad +++ b/tripod_mounts.scad @@ -72,33 +72,35 @@ module manfrotto_rc2_plate(chamfer="all",anchor,orient,spin) left(10,back(-flat_height,select(pts,-3))) ]; - tag_scope() attachable(anchor,spin,orient,size=[botwid,length,thickness],size2=[topwid,length],shift=[.64115/2,0]){ + tag_scope() down(thickness/2) diff() linear_sweep(pts,h=length,convexity=4,orient=FWD,anchor=FWD){ - zflip_copy() - down(.01)fwd(.01)left(.01)position(LEFT+FRONT+BOT) - cuboid([corner_space,(length-innerlen)/2,thickness+.02], chamfer=-chsize, $tag="remove", - orient=FWD,anchor=TOP+LEFT+FWD,edges=chamf_top?"ALL":TOP); - fwd(left_top)position(LEFT+BACK)linear_sweep(h=cutout_len,facet,convexity=4,$tag="remove",anchor=RIGHT+BACK); + tag("remove"){ + zflip_copy() + down(.01)fwd(.01)left(.01)position(LEFT+FRONT+BOT) + cuboid([corner_space,(length-innerlen)/2,thickness+.02], chamfer=-chsize, + orient=FWD,anchor=TOP+LEFT+FWD,edges=chamf_top?"ALL":TOP); + fwd(left_top)position(LEFT+BACK)linear_sweep(h=cutout_len,facet,convexity=4,anchor=RIGHT+BACK); + } if (chamf_bot){ - edge_mask(FRONT+LEFT)chamfer_edge_mask(length,chsize,$tag="remove"); - edge_mask(FRONT+RIGHT)chamfer_edge_mask(length,chsize,$tag="remove"); - edge_mask(FRONT+TOP)chamfer_edge_mask(length,chsize,$tag="remove"); - edge_mask(FRONT+BOT)chamfer_edge_mask(length,chsize,$tag="remove"); - edge_mask(TOP+RIGHT)chamfer_edge_mask(length,chsize,$tag="remove"); - edge_mask(BOT+RIGHT)chamfer_edge_mask(length,chsize,$tag="remove"); + edge_mask(FRONT+LEFT)chamfer_edge_mask(length,chsize); + edge_mask(FRONT+RIGHT)chamfer_edge_mask(length,chsize); + edge_mask(FRONT+TOP)chamfer_edge_mask(length,chsize); + edge_mask(FRONT+BOT)chamfer_edge_mask(length,chsize); + edge_mask(TOP+RIGHT)chamfer_edge_mask(length,chsize); + edge_mask(BOT+RIGHT)chamfer_edge_mask(length,chsize); zflip_copy(){ - right(corner_space)edge_mask(TOP+LEFT) chamfer_edge_mask(length,chsize,$tag="remove"); - down((length-innerlen)/2)edge_mask(TOP+LEFT) chamfer_edge_mask(length,chsize,$tag="remove"); + right(corner_space)edge_mask(TOP+LEFT) chamfer_edge_mask(length,chsize); + down((length-innerlen)/2)edge_mask(TOP+LEFT) chamfer_edge_mask(length,chsize); } } if (chamf_top){ - edge_mask(BACK+LEFT)chamfer_edge_mask(length,chsize,$tag="remove"); - edge_mask(BACK+RIGHT)chamfer_edge_mask(length,chsize,$tag="remove"); - edge_mask(BACK+TOP)chamfer_edge_mask(length,chsize,$tag="remove"); - edge_mask(BACK+BOT)chamfer_edge_mask(length,chsize,$tag="remove"); + edge_mask(BACK+LEFT) chamfer_edge_mask(length,chsize); + edge_mask(BACK+RIGHT) chamfer_edge_mask(length,chsize); + edge_mask(BACK+TOP) chamfer_edge_mask(length,chsize); + edge_mask(BACK+BOT) chamfer_edge_mask(length,chsize); } } children(); diff --git a/tutorials/Attachments.md b/tutorials/Attachments.md index 5e4b8e0..6ab22eb 100644 --- a/tutorials/Attachments.md +++ b/tutorials/Attachments.md @@ -549,7 +549,8 @@ are a few specialized alternatives to the `attach()` and `position()` modules. If you have a 3D mask shape that you want to difference away from various edges, you can use the `edge_mask()` module. This module will take a vertically oriented shape, and will rotate and move it such that the BACK, RIGHT (X+,Y+) side of the shape will be aligned with the given -edges. The shape will be tagged as a "mask" so that you can use `diff("mask")`. For example, +edges. The shape will be tagged as a "remove" so that you can use +`diff()` with its default "remove" tag. For example, here's a shape for rounding an edge: ```openscad-3D @@ -573,7 +574,7 @@ module round_edge(l,r) difference() { translate([r,r]) cylinder(h=l+1,r=r,center=true, $fn=quantup(segs(r),4)); } -diff("mask") +diff() cube([50,60,70],center=true) edge_mask([TOP,"Z"],except=[BACK,TOP+LEFT]) round_edge(l=71,r=10); @@ -583,7 +584,8 @@ cube([50,60,70],center=true) If you have a 3D mask shape that you want to difference away from various corners, you can use the `corner_mask()` module. This module will take a shape and rotate and move it such that the BACK RIGHT TOP (X+,Y+,Z+) side of the shape will be aligned with the given corner. The shape -will be tagged as a "mask" so that you can use `diff("mask")`. For example, here's a shape for +will be tagged as a "remove" so that you can use `diff()` with its +default "remove" tag. For example, here's a shape for rounding a corner: ```openscad-3D @@ -607,7 +609,7 @@ module round_corner(r) difference() { translate([r,r,r]) sphere(r=r, style="aligned", $fn=quantup(segs(r),4)); } -diff("mask") +diff() cube([50,60,70],center=true) corner_mask([TOP,FRONT],LEFT+FRONT+TOP) round_corner(r=10); @@ -630,7 +632,7 @@ module round_edge(l,r) difference() { translate([r,r]) cylinder(h=l+1,r=r,center=true, $fn=quantup(segs(r),4)); } -diff("mask") +diff() cube([50,60,70],center=true) { edge_mask("ALL") round_edge(l=71,r=10); corner_mask("ALL") round_corner(r=10); @@ -647,7 +649,8 @@ mask shape (via `rotate_extrude()`). This is where `edge_profile()`, `corner_pr ### `edge_profile()` Using the `edge_profile()` module, you can provide a 2D profile shape and it will be linearly extruded to a mask of the apropriate length for each given edge. The resultant mask will be -tagged with "mask" so that you can difference it away with `diff("mask")`. The 2D profile is +tagged with "remove" so that you can difference it away with `diff()` +with the default "remove" tag. The 2D profile is assumed to be oriented with the BACK, RIGHT (X+,Y+) quadrant as the "cutter edge" that gets re-oriented towards the edges of the parent shape. A typical mask profile for chamfering an edge may look like: @@ -661,7 +664,7 @@ Using that mask profile, you can mask the edges of a cube like: ```openscad-3D include -diff("mask") +diff() cube([50,60,70],center=true) edge_profile("ALL") mask2d_roundover(10); @@ -672,7 +675,7 @@ You can use the same profile to make a rounded corner mask as well: ```openscad-3D include -diff("mask") +diff() cube([50,60,70],center=true) corner_profile("ALL", r=10) mask2d_roundover(10); @@ -684,7 +687,7 @@ As a simple shortcut to apply a profile mask to all edges and corners of a face, ```openscad-3D include -diff("mask") +diff() cube([50,60,70],center=true) face_profile(TOP, r=10) mask2d_roundover(10);