mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2025-01-01 09:49:45 +00:00
Merge pull request #806 from adrianVmariano/master
add force_tags() and streamline diff()
This commit is contained in:
commit
70ab47012b
2 changed files with 204 additions and 60 deletions
224
attachments.scad
224
attachments.scad
|
@ -17,6 +17,27 @@
|
|||
$tags = "";
|
||||
$overlap = 0;
|
||||
$color = undef;//"yellow";
|
||||
$save_color = undef; // Saved color to revert back for children
|
||||
$color_scheme = "cornfield"; // Default color scheme
|
||||
|
||||
_default_colors = [
|
||||
["cornfield", "#f9d72c"],
|
||||
["metallic", "#ddddff"],
|
||||
["sunset", "#ffaaaa"],
|
||||
["starnight", "#ffffe0"],
|
||||
["beforedawn", "#cccccc"],
|
||||
["nature", "#16a085"],
|
||||
["deepocean", "#eeeeee"],
|
||||
["solarized", "#b58800"],
|
||||
["tomorrow", "#4271ae"],
|
||||
["tomorrow night", "#81a2be"],
|
||||
["monotone", "#f9d72c"]
|
||||
];
|
||||
|
||||
function _default_color() =
|
||||
let(ind = search([downcase($color_scheme)], _default_colors, 1, 0))
|
||||
assert(ind[0]!=[], str("$color_scheme set to unknown value ",$color_scheme))
|
||||
_default_colors[ind[0]][1];
|
||||
|
||||
$attach_to = undef;
|
||||
$attach_anchor = [CENTER, CENTER, UP, 0];
|
||||
|
@ -538,12 +559,44 @@ module attach(from, to, overlap, norot=false)
|
|||
// Usage:
|
||||
// tags(tags) {...}
|
||||
// Topics: Attachments
|
||||
// See Also: recolor(), hide(), show(), diff(), intersect()
|
||||
// See Also: force_tags(), recolor(), hide(), show(), diff(), intersect()
|
||||
// Description:
|
||||
// Marks all children with the given tags, so that they will `hide()`/`show()`/`diff()` correctly.
|
||||
// This is especially useful for working with children that are not attachment enhanced, such as:
|
||||
// Sets the `$tags` variable as specified for all its children. This makes it easy to set the tags
|
||||
// on multiple items without having to repeat the tag setting for each one. Note that if you want
|
||||
// to apply tags to non-tag-aware objects you need to use {{force_tags()}} instead.
|
||||
// .
|
||||
// For a more step-by-step explanation of attachments, see the [[Attachments Tutorial|Tutorial-Attachments]].
|
||||
// Arguments:
|
||||
// tags = String containing space delimited set of tags to apply.
|
||||
// Example(3D): Applies the tags to both cuboids instead of having to repeat `$tags="remove"` for each one.
|
||||
// diff("remove")
|
||||
// cuboid(10){
|
||||
// position(TOP) cuboid(3);
|
||||
// tags("remove")
|
||||
// {
|
||||
// position(FRONT) cuboid(3);
|
||||
// position(RIGHT) cuboid(3);
|
||||
// }
|
||||
// }
|
||||
module tags(tags)
|
||||
{
|
||||
$tags = tags;
|
||||
children();
|
||||
}
|
||||
|
||||
|
||||
// Module: force_tags()
|
||||
// Usage:
|
||||
// force_tags([tags]) {...}
|
||||
// Topics: Attachments
|
||||
// See Also: tags(), recolor(), hide(), show(), diff(), intersect()
|
||||
// Description:
|
||||
// You use this module when you want to make a non-attachable or non-BOSL2 module respect tags.
|
||||
// It applies to its children the tags specified (or the tags currently in force if you don't specify any tags),
|
||||
// making a final determination about whether to show or hide the children. This means that tagging in children's children will be ignored.
|
||||
// This module is specifically provided for operating on children that are not tag aware such as modules
|
||||
// that don't use {{attachable()}} or built in modules such as
|
||||
// - `polygon()`
|
||||
// - `text()`
|
||||
// - `projection()`
|
||||
// - `polyhedron()` (or use [`vnf_polyhedron()`](vnf.scad#vnf_polyhedron))
|
||||
// - `linear_extrude()` (or use [`linear_sweep()`](regions.scad#linear_sweep))
|
||||
|
@ -551,42 +604,60 @@ module attach(from, to, overlap, norot=false)
|
|||
// - `surface()`
|
||||
// - `import()`
|
||||
// .
|
||||
// When you use tag-based modules like {{diff()}} with a non-attachable module, the result may be puzzling.
|
||||
// Any time a test occurs for display of child() that test will succeed. This means that when diff() checks
|
||||
// to see if it should show a module it will show it, and when diff() checks to see if it should subtract the module
|
||||
// it will subtract it. The result will be a hole, possibly with zero-thickness edges or faces. In order to
|
||||
// get the correct behavior, every non-attachable module needs an invocation of force_tags, even ones that are not
|
||||
// .
|
||||
// For a more step-by-step explanation of attachments, see the [[Attachments Tutorial|Tutorial-Attachments]].
|
||||
// Arguments:
|
||||
// tags = String containing space delimited set of tags to apply.
|
||||
module tags(tags)
|
||||
// Example(NoRender): This program produces no output because the objects are created and then differenced away. The specified tag is ignored.
|
||||
// diff("remove")
|
||||
// {
|
||||
// polygon(square(10));
|
||||
// move(-[.01,.01])polygon(square(5),$tags="remove");
|
||||
// }
|
||||
// Example(2D): Adding force_tags() fixed the model. Note you need to add it to *every* non-attachable module, even the untagged ones.
|
||||
// diff("remove")
|
||||
// {
|
||||
// force_tags()
|
||||
// polygon(square(10));
|
||||
// force_tags("remove")
|
||||
// move(-[.01,.01])polygon(square(5));
|
||||
// }
|
||||
module force_tags(tags)
|
||||
{
|
||||
$tags = tags;
|
||||
if(_attachment_is_shown(tags)) {
|
||||
$tags = is_def(tags) ? tags : $tags;
|
||||
if(_attachment_is_shown($tags)) {
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Module: diff()
|
||||
// Usage:
|
||||
// diff(neg, [keep]) {...}
|
||||
// diff(neg, pos, [keep]) {...}
|
||||
// Topics: Attachments
|
||||
// See Also: tags(), recolor(), show(), hide(), intersect()
|
||||
// Description:
|
||||
// If `neg` is given, takes the union of all children with tags that are in `neg`, and differences
|
||||
// them from the union of all children with tags in `pos`. If `pos` is not given, then all items in
|
||||
// `neg` are differenced from all items not in `neg`. If `keep` is given, all children with tags in
|
||||
// `keep` are then unioned with the result. If `keep` is not given, all children without tags in
|
||||
// `pos` or `neg` are then unioned with the result.
|
||||
// Perform a differencing operation using tags to control what happens. The children are grouped into
|
||||
// three categories. The `neg` argument is a space delimited list of tags specifying objects to
|
||||
// subtract. The `keep` argument, if given, is a similar list of tags giving objects to be kept.
|
||||
// Objects not matching `neg` or `keep` form the third category of base objects.
|
||||
// To produce its output, diff() forms the union of all the base objects, which don't match any tags.
|
||||
// Next it subtracts all the objects with tags in `neg`. Finally it adds in objects listed in `keep`.
|
||||
// .
|
||||
// Cannot be used in conjunction with `intersect()` or `hulling()` on the same parent object.
|
||||
// .
|
||||
// For a more step-by-step explanation of attachments, see the [[Attachments Tutorial|Tutorial-Attachments]].
|
||||
// Arguments:
|
||||
// neg = String containing space delimited set of tag names of children to difference away.
|
||||
// pos = String containing space delimited set of tag names of children to be differenced away from.
|
||||
// keep = String containing space delimited set of tag names of children to keep whole.
|
||||
// keep = String containing space delimited set of tag names of children to keep, that is, to union into the model after differencing is completed.
|
||||
// Example:
|
||||
// diff("neg", "pos", keep="axle")
|
||||
// sphere(d=100, $tags="pos") {
|
||||
// diff("neg", keep="axle")
|
||||
// sphere(d=100) {
|
||||
// attach(CENTER) xcyl(d=40, l=120, $tags="axle");
|
||||
// attach(CENTER) cube([40,120,100], anchor=CENTER, $tags="neg");
|
||||
// }
|
||||
|
@ -596,7 +667,40 @@ module tags(tags)
|
|||
// edge_mask(FWD)
|
||||
// rounding_edge_mask(l=max($parent_size)*1.01, r=25);
|
||||
// }
|
||||
// Example: Working with Non-Attachables Like rotate_extrude()
|
||||
// Example(3D,VPR=[104,0,200], VPT=[-0.9,3.03, -0.74], VPD=19,NoAxes,NoScales): A pipe module that subtracts its interior when you call it using diff(). Normally if you union two pipes together, you'll get interfering walls at the intersection, but not here:
|
||||
// $fn=16;
|
||||
// // This module must be called by subtracting with "diff"
|
||||
// module pipe(length, od, id) {
|
||||
// // Strip the tag the user is using to subtract
|
||||
// cylinder(h=length, d=od, center=true,$tags="");
|
||||
// // Leave the tag along here, so this one is removed
|
||||
// cylinder(h=length+.02, d=id, center=true);
|
||||
// }
|
||||
// // Draw some intersecting pipes
|
||||
// diff("rem",keep="keep"){
|
||||
// pipe(length=5, od=2, id=1.9, $tags="rem");
|
||||
// zrot(10)xrot(75)
|
||||
// pipe(length=5, od=2, id=1.9, $tags="rem");
|
||||
// // The orange bar has its center removed
|
||||
// color("orange") down(1) xcyl(h=8, d=1);
|
||||
// // "keep" prevents interior of the blue bar intact
|
||||
// recolor("blue") up(1) xcyl(h=8, d=1,$tags="keep");
|
||||
// }
|
||||
// // Objects outside the diff don't have pipe interiors removed
|
||||
// color("purple") down(2.2) ycyl(h=8, d=0.3,$tags="keep");
|
||||
// Example(3D,NoScales,NoAxes): Nested diff() calls work as expected, but be careful of reusing tag names, even hidden in submodules.
|
||||
// $fn=16;
|
||||
// diff("rem1")
|
||||
// cyl(r=10,h=10){
|
||||
// diff("rem2",$tags="rem1"){
|
||||
// cyl(r=8,h=11);
|
||||
// diff("rem3", $tags="rem2"){
|
||||
// cyl(r=6,h=12);
|
||||
// cyl(r=4,h=13,$tags="rem3");
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// Example(3D,NoAxes,NoScales): Working with Non-Attachables like rotate_extrude() you must apply {{force_tags()}} to every non-attachable object.
|
||||
// back_half()
|
||||
// diff("remove")
|
||||
// cuboid(40) {
|
||||
|
@ -604,33 +708,27 @@ module tags(tags)
|
|||
// recolor("lightgreen")
|
||||
// cyl(l=10,d=30);
|
||||
// position(TOP+RIGHT)
|
||||
// tags("remove")
|
||||
// force_tags("remove")
|
||||
// xrot(90)
|
||||
// rotate_extrude()
|
||||
// right(20)
|
||||
// circle(5);
|
||||
// }
|
||||
module diff(neg, pos, keep)
|
||||
module diff(neg, keep)
|
||||
{
|
||||
// Don't perform the operation if the current tags are hidden
|
||||
if (_attachment_is_shown($tags)) {
|
||||
difference() {
|
||||
if (pos != undef) {
|
||||
show(pos) children();
|
||||
if (keep == undef) {
|
||||
hide(neg) children();
|
||||
} else {
|
||||
if (keep == undef) {
|
||||
hide(neg) children();
|
||||
} else {
|
||||
hide(str(neg," ",keep)) children();
|
||||
}
|
||||
hide(str(neg," ",keep)) children();
|
||||
}
|
||||
show(neg) children();
|
||||
}
|
||||
}
|
||||
if (keep!=undef) {
|
||||
show(keep) children();
|
||||
} else if (pos!=undef) {
|
||||
hide(str(pos," ",neg)) children();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -733,23 +831,67 @@ module hulling(a)
|
|||
|
||||
// Module: recolor()
|
||||
// Usage:
|
||||
// recolor(c) {...}
|
||||
// recolor([c]) {...}
|
||||
// Topics: Attachments
|
||||
// See Also: tags(), hide(), show(), diff(), intersect()
|
||||
// See Also: color_this(), tags(), hide(), show(), diff(), intersect()
|
||||
// Description:
|
||||
// Sets the color for children that can use the $color special variable. For a more step-by-step
|
||||
// explanation of attachments, see the [[Attachments Tutorial|Tutorial-Attachments]].
|
||||
// Sets the color for children that can use the $color special variable. For this to work
|
||||
// you cannot have any color() modules above it in any parents, only other recolor() or color_this() modules.
|
||||
// Not ethat recolor() affects its children and all their descendants.
|
||||
// For a more step-by-step explanation of attachments, see the [[Attachments Tutorial|Tutorial-Attachments]].
|
||||
// Arguments:
|
||||
// c = Color name or RGBA vector.
|
||||
// c = Color name or RGBA vector. Default: The standard OpenSCAD yellow
|
||||
// Example:
|
||||
// recolor("red") cyl(l=20, d=10);
|
||||
// cuboid([10,10,5])
|
||||
// recolor("green")attach(TOP,BOT) cuboid([9,9,4.5])
|
||||
// attach(TOP,BOT) cuboid([8,8,4])
|
||||
// recolor("purple") attach(TOP,BOT) cuboid([7,7,3.5])
|
||||
// attach(TOP,BOT) cuboid([6,6,3])
|
||||
// recolor("cyan")attach(TOP,BOT) cuboid([5,5,2.5])
|
||||
// attach(TOP,BOT) cuboid([4,4,2]);
|
||||
module recolor(c)
|
||||
{
|
||||
$color = c;
|
||||
$color = default(c,_default_color());
|
||||
children();
|
||||
}
|
||||
|
||||
|
||||
// Module: color_this()
|
||||
// Usage:
|
||||
// color_this([c]) {...}
|
||||
// Topics: Attachments
|
||||
// See Also: tags(), recolor()
|
||||
// Description:
|
||||
// Sets the color for children at one level, reverting to the previous color for further descendants.
|
||||
// This works only with attachables and you cannot have any color() modules above it in any parents,
|
||||
// only recolor() or other color_this() modules.
|
||||
// .
|
||||
// This module works by saving the current color, which means it needs to know the current color. If you have
|
||||
// not yet set the color with {{recolor()}} then the current color is the default color.
|
||||
// OpenSCAD provides no method for learning the value of the default color, so if you don't use the default
|
||||
// "cornfield" color scheme you should set $color_scheme to the color scheme you are using.
|
||||
// Alternatively, always use {{recolor()}} on a parent before using color_this().
|
||||
// .
|
||||
// For a more step-by-step explanation of attachments, see the [[Attachments Tutorial|Tutorial-Attachments]].
|
||||
// Arguments:
|
||||
// c = Color name or RGBA vector. Default: the standard OpenSCAD yellow
|
||||
// Example:
|
||||
// $color_scheme = "cornfield"; // Change this if necessary
|
||||
// cuboid([10,10,5])
|
||||
// color_this("green")attach(TOP,BOT) cuboid([9,9,4.5])
|
||||
// attach(TOP,BOT) cuboid([8,8,4])
|
||||
// color_this("purple") attach(TOP,BOT) cuboid([7,7,3.5])
|
||||
// attach(TOP,BOT) cuboid([6,6,3])
|
||||
// color_this("cyan")attach(TOP,BOT) cuboid([5,5,2.5])
|
||||
// attach(TOP,BOT) cuboid([4,4,2]);
|
||||
module color_this(c)
|
||||
{
|
||||
$save_color=default($color, _default_color());
|
||||
$color=default(c, _default_color());
|
||||
children();
|
||||
}
|
||||
|
||||
|
||||
// Module: hide()
|
||||
// Usage:
|
||||
// hide(tags) {...}
|
||||
|
@ -1306,11 +1448,15 @@ module attachable(
|
|||
children(0);
|
||||
}
|
||||
}
|
||||
if (is_def($save_color)) {
|
||||
$color=$save_color;
|
||||
$save_color=undef;
|
||||
children(1);
|
||||
} else
|
||||
children(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Function: reorient()
|
||||
//
|
||||
// Usage: Square/Trapezoid Geometry
|
||||
|
|
|
@ -404,12 +404,9 @@ cylinder(h=100, d=100, center=true)
|
|||
BOSL2 introduces the concept of tags. Tags are names that can be given to attachables, so that
|
||||
you can refer to them when performing `diff()`, `intersect()`, and `hulling()` operations.
|
||||
|
||||
### `diff(neg, <pos>, <keep>)`
|
||||
### `diff(neg, <keep>)`
|
||||
The `diff()` operator is used to difference away all shapes marked with the tag(s) given to
|
||||
`neg=`, from shapes marked with the tag(s) given to `pos=`. Anything marked with a tag given
|
||||
to `keep=` will be unioned onto the result. If no `pos=` argument is given, then everything
|
||||
marked with a tag given to `neg=` will be differenced from all shapes *not* marked with that
|
||||
tag.
|
||||
`neg=`, from the other shapes.
|
||||
|
||||
For example, to difference away a child cylinder from the middle of a parent cube, you can
|
||||
do this:
|
||||
|
@ -421,20 +418,6 @@ cube(100, center=true)
|
|||
cylinder(h=101, d=50, center=true, $tags="hole");
|
||||
```
|
||||
|
||||
If you give both the `neg=` and `pos=` arguments to `diff()`, then the shapes marked by tags
|
||||
given to `neg=` will be differenced away from the shapes marked with tags given to `pos=`.
|
||||
Everything else will be unioned to the result.
|
||||
|
||||
```openscad-3D
|
||||
include <BOSL2/std.scad>
|
||||
diff("hole", "post")
|
||||
cube(100, center=true)
|
||||
attach([RIGHT,TOP]) {
|
||||
cylinder(d=95, h=5, $tags="post");
|
||||
cylinder(d=50, h=11, anchor=CTR, $tags="hole");
|
||||
}
|
||||
```
|
||||
|
||||
The `keep=` argument takes tags for shapes that you want to keep in the output.
|
||||
|
||||
```openscad-3D
|
||||
|
@ -447,6 +430,21 @@ cube(100, center=true)
|
|||
}
|
||||
```
|
||||
|
||||
Remember that tags are inherited by children. In this case, we need to explicitly
|
||||
untag the first cylinder (or change its tag to something else), or it
|
||||
will inherit the "keep" tag and get kept.
|
||||
|
||||
```openscad-3D
|
||||
include <BOSL2/std.scad>
|
||||
diff("hole", "keep")
|
||||
cube(100, center=true, $tags="keep")
|
||||
attach([RIGHT,TOP]) {
|
||||
cylinder(d=95, h=5, $tags="");
|
||||
cylinder(d=50, h=11, anchor=CTR, $tags="hole");
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
If you need to mark multiple children with a tag, you can use the `tags()` module.
|
||||
|
||||
```openscad-3D
|
||||
|
@ -477,14 +475,14 @@ Some notable non-attachable modules are `text()`, `linear_extrude()`, `rotate_ex
|
|||
`intersection()`, `offset()`, `hull()`, and `minkowski()`.
|
||||
|
||||
To allow you to use tags-based operations with non-attachable shapes, you can wrap them with the
|
||||
`tags()` module to specify their tags. For example:
|
||||
`force_tags()` module to specify their tags. For example:
|
||||
|
||||
```openscad-3D
|
||||
include <BOSL2/std.scad>
|
||||
diff("hole")
|
||||
cuboid(50)
|
||||
attach(TOP)
|
||||
tags("hole")
|
||||
force_tags("hole")
|
||||
rotate_extrude()
|
||||
right(15)
|
||||
square(10,center=true);
|
||||
|
|
Loading…
Reference in a new issue