mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2025-01-01 09:49:45 +00:00
Merge pull request #537 from revarbat/revarbat_dev
Attachments bugfixes and tutorial updates
This commit is contained in:
commit
9819599a29
2 changed files with 243 additions and 12 deletions
|
@ -1057,11 +1057,12 @@ module attach(from, to, overlap, norot=false)
|
|||
$attach_to = to;
|
||||
$attach_anchor = anch;
|
||||
$attach_norot = norot;
|
||||
olap = two_d? [0,-overlap,0] : [0,0,-overlap];
|
||||
if (norot || (norm(anch[2]-UP)<1e-9 && anch[3]==0)) {
|
||||
translate(anch[1]) translate([0,0,-overlap]) children();
|
||||
translate(anch[1]) translate(olap) children();
|
||||
} else {
|
||||
fromvec = two_d? BACK : UP;
|
||||
translate(anch[1]) rot(anch[3],from=fromvec,to=anch[2]) translate([0,0,-overlap]) children();
|
||||
translate(anch[1]) rot(anch[3],from=fromvec,to=anch[2]) translate(olap) children();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1223,8 +1224,18 @@ module corner_profile(corners=CORNERS_ALL, except=[], r, d, convexity=10) {
|
|||
// Topics: Attachments
|
||||
// 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.
|
||||
// For a more step-by-step explanation of attachments, see the [[Attachments Tutorial|Tutorial-Attachments]].
|
||||
// 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. For a more
|
||||
// step-by-step explanation of attachments, see the [[Attachments Tutorial|Tutorial-Attachments]].
|
||||
// Figure: A Typical Edge Rounding Mask
|
||||
// module roundit(l,r) difference() {
|
||||
// translate([-1,-1,-l/2])
|
||||
// cube([r+1,r+1,l]);
|
||||
// translate([r,r])
|
||||
// cylinder(h=l+1,r=r,center=true, $fn=quantup(segs(r),4));
|
||||
// }
|
||||
// roundit(l=30,r=10);
|
||||
// Arguments:
|
||||
// edges = Edges to mask. See the docs for [`edges()`](edges.scad#edges) to see acceptable values. Default: All edges.
|
||||
// except = Edges to explicitly NOT mask. See the docs for [`edges()`](edges.scad#edges) to see acceptable values. Default: No edges.
|
||||
|
|
|
@ -91,6 +91,23 @@ overrides the `anchor=` argument. A `center=true` argument is the same as `anch
|
|||
A `center=false` argument can mean `anchor=[-1,-1,-1]` for a cube, or `anchor=BOTTOM` for a
|
||||
cylinder.
|
||||
|
||||
Many 2D shapes provided by BOSL2 are also anchorable. Due to technical limitations of OpenSCAD,
|
||||
however, `square()` and `circle()` are *not*. BOSL2 provides `rect()` and `oval()` as attachable
|
||||
and anchorable equivalents. You can only anchor on the XY plane, of course, but you can use the
|
||||
same `FRONT`, `BACK`, `LEFT`, `RIGHT`, and `CENTER` anchor constants.
|
||||
|
||||
```openscad-2D
|
||||
rect([40,30], anchor=BACK+LEFT);
|
||||
```
|
||||
|
||||
```openscad-2D
|
||||
oval(d=50, anchor=FRONT);
|
||||
```
|
||||
|
||||
```openscad-2D
|
||||
hexagon(d=50, anchor=BACK);
|
||||
```
|
||||
|
||||
|
||||
## Spin
|
||||
Attachable shapes also can be spun in place as you create them. You can do this by passing in
|
||||
|
@ -107,6 +124,17 @@ vector, like [Xang,Yang,Zang]:
|
|||
cube([20,20,40], center=true, spin=[10,20,30]);
|
||||
```
|
||||
|
||||
You can also apply spin to 2D shapes from BOSL2. Again, you should use `rect()` and `oval()`
|
||||
instead of `square()` and `circle()`:
|
||||
|
||||
```openscad-2D
|
||||
rect([40,30], spin=30);
|
||||
```
|
||||
|
||||
```openscad-2D
|
||||
oval(d=[40,30], spin=30);
|
||||
```
|
||||
|
||||
|
||||
## Orientation
|
||||
Another way to specify a rotation for an attachable shape, is to pass a 3D vector via the
|
||||
|
@ -117,6 +145,9 @@ For example, you can make a cone that is tilted up and to the right like this:
|
|||
cylinder(h=100, r1=50, r2=20, orient=UP+RIGHT);
|
||||
```
|
||||
|
||||
You can *not* use `orient=` with 2D shapes.
|
||||
|
||||
|
||||
## Mixing Anchoring, Spin, and Orientation
|
||||
When giving `anchor=`, `spin=`, and `orient=`, they are applied anchoring first, spin second,
|
||||
then orient last. For example, here's a cube:
|
||||
|
@ -150,8 +181,14 @@ However, since spin is applied *after* anchoring, it can actually have a signifi
|
|||
cylinder(d=50, l=40, anchor=FWD, spin=-30);
|
||||
```
|
||||
|
||||
For 2D shapes, you can mix `anchor=` with `spin=`, but not with `orient=`.
|
||||
|
||||
## Attaching Children
|
||||
```openscad-2D
|
||||
rect([40,30], anchor=BACK+LEFT, spin=30);
|
||||
```
|
||||
|
||||
|
||||
## Attaching 3D Children
|
||||
The reason attachables are called that, is because they can be attached to each other.
|
||||
You can do that by making one attachable shape be a child of another attachable shape.
|
||||
By default, the child of an attachable is attached to the center of the parent shape.
|
||||
|
@ -178,13 +215,21 @@ cube(50,center=true)
|
|||
attach(TOP,TOP) cylinder(d1=50,d2=20,l=20);
|
||||
```
|
||||
|
||||
By default, `attach()` causes the child to overlap the parent by 0.01, to let CGAL correctly
|
||||
join the parts. If you need the child to have no overlap, or a different overlap, you can use
|
||||
the `overlap=` argument:
|
||||
By default, `attach()` places the child exactly flush with the surface of the parent. Sometimes
|
||||
it's useful to have the child overlap the parent by insetting a bit. You can do this with the
|
||||
`overlap=` argument to `attach()`. A positive value will inset the child into the parent, and
|
||||
a negative value will outset out from the parent:
|
||||
|
||||
```openscad
|
||||
cube(50,center=true)
|
||||
attach(TOP,TOP,overlap=0) cylinder(d1=50,d2=20,l=20);
|
||||
attach(TOP,overlap=10)
|
||||
cylinder(d=20,l=20);
|
||||
```
|
||||
|
||||
```openscad
|
||||
cube(50,center=true)
|
||||
attach(TOP,overlap=-20)
|
||||
cylinder(d=20,l=20);
|
||||
```
|
||||
|
||||
If you want to position the child at the parent's anchorpoint, without re-orienting, you can
|
||||
|
@ -217,6 +262,23 @@ cube(50, center=true)
|
|||
position([TOP,RIGHT,FRONT]) cylinder(d1=50,d2=20,l=20);
|
||||
```
|
||||
|
||||
## Attaching 2D Children
|
||||
You can use attachments in 2D as well, but only in the XY plane. Also, the built-in `square()`
|
||||
and `circle()` 2D modules do not support attachments. Instead, you should use the `rect()` and
|
||||
`oval()` modules:
|
||||
|
||||
```openscad-2D
|
||||
rect(50,center=true)
|
||||
attach(RIGHT,FRONT)
|
||||
trapezoid(w1=30,w2=0,h=30);
|
||||
```
|
||||
|
||||
```openscad-2D
|
||||
oval(d=50)
|
||||
attach(BACK,FRONT,overlap=5)
|
||||
trapezoid(w1=30,w2=0,h=30);
|
||||
```
|
||||
|
||||
## Anchor Arrows
|
||||
One way that is useful to show the position and orientation of an anchorpoint is by attaching
|
||||
an anchor arrow to that anchor.
|
||||
|
@ -259,6 +321,7 @@ cylinder(h=100, d=100, center=true)
|
|||
show_anchors(s=30);
|
||||
```
|
||||
|
||||
|
||||
## Tagged Operations
|
||||
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.
|
||||
|
@ -372,12 +435,169 @@ cube(50, center=true, $tags="hull") {
|
|||
```
|
||||
|
||||
|
||||
## Masking Children
|
||||
TBW
|
||||
## 3D Masking Attachments
|
||||
To make it easier to mask away shapes from various edges of an attachable parent shape, there
|
||||
are a few specialized alternatives to the `attach()` and `position()` modules.
|
||||
|
||||
### `edge_mask()`
|
||||
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,
|
||||
here's a shape for rounding an edge:
|
||||
|
||||
```openscad
|
||||
module round_edge(l,r) difference() {
|
||||
translate([-1,-1,-l/2])
|
||||
cube([r+1,r+1,l]);
|
||||
translate([r,r])
|
||||
cylinder(h=l+1,r=r,center=true, $fn=quantup(segs(r),4));
|
||||
}
|
||||
round_edge(l=30, r=19);
|
||||
```
|
||||
|
||||
You can use that mask to round various edges of a cube:
|
||||
|
||||
```openscad
|
||||
module round_edge(l,r) difference() {
|
||||
translate([-1,-1,-l/2])
|
||||
cube([r+1,r+1,l]);
|
||||
translate([r,r])
|
||||
cylinder(h=l+1,r=r,center=true, $fn=quantup(segs(r),4));
|
||||
}
|
||||
diff("mask")
|
||||
cube([50,60,70],center=true)
|
||||
edge_mask([TOP,"Z"],except=[BACK,TOP+LEFT])
|
||||
round_edge(l=71,r=10);
|
||||
```
|
||||
|
||||
### `corner_mask()`
|
||||
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
|
||||
rounding a corner:
|
||||
|
||||
```openscad
|
||||
module round_corner(r) difference() {
|
||||
translate(-[1,1,1])
|
||||
cube(r+1);
|
||||
translate([r,r,r])
|
||||
sphere(r=r, style="aligned", $fn=quantup(segs(r),4));
|
||||
}
|
||||
round_corner(r=10);
|
||||
```
|
||||
|
||||
You can use that mask to round various corners of a cube:
|
||||
|
||||
```openscad
|
||||
module round_corner(r) difference() {
|
||||
translate(-[1,1,1])
|
||||
cube(r+1);
|
||||
translate([r,r,r])
|
||||
sphere(r=r, style="aligned", $fn=quantup(segs(r),4));
|
||||
}
|
||||
diff("mask")
|
||||
cube([50,60,70],center=true)
|
||||
corner_mask([TOP,FRONT],LEFT+FRONT+TOP)
|
||||
round_corner(r=10);
|
||||
```
|
||||
|
||||
### Mix and Match Masks
|
||||
You can use `edge_mask()` and `corner_mask()` together as well:
|
||||
|
||||
```openscad
|
||||
module round_corner(r) difference() {
|
||||
translate(-[1,1,1])
|
||||
cube(r+1);
|
||||
translate([r,r,r])
|
||||
sphere(r=r, style="aligned", $fn=quantup(segs(r),4));
|
||||
}
|
||||
module round_edge(l,r) difference() {
|
||||
translate([-1,-1,-l/2])
|
||||
cube([r+1,r+1,l]);
|
||||
translate([r,r])
|
||||
cylinder(h=l+1,r=r,center=true, $fn=quantup(segs(r),4));
|
||||
}
|
||||
diff("mask")
|
||||
cube([50,60,70],center=true) {
|
||||
edge_mask("ALL") round_edge(l=71,r=10);
|
||||
corner_mask("ALL") round_corner(r=10);
|
||||
}
|
||||
```
|
||||
|
||||
## 2D Profile Mask Attachments
|
||||
While 3D mask shapes give you a great deal of control, you need to make sure they are correctly
|
||||
sized, and you need to provide separate mask shapes for corners and edges. Often, a single 2D
|
||||
profile could be used to describe the edge mask shape (via `linear_extrude()`), and the corner
|
||||
mask shape (via `rotate_extrude()`). This is where `edge_profile()`, `corner_profile()`, and
|
||||
`face_profile()` come in.
|
||||
|
||||
### `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
|
||||
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:
|
||||
|
||||
```openscad
|
||||
mask2d_roundover(10);
|
||||
```
|
||||
|
||||
Using that mask profile, you can mask the edges of a cube like:
|
||||
|
||||
```openscad
|
||||
diff("mask")
|
||||
cube([50,60,70],center=true)
|
||||
edge_profile("ALL")
|
||||
mask2d_roundover(10);
|
||||
```
|
||||
|
||||
### `corner_profile()`
|
||||
You can use the same profile to make a rounded corner mask as well:
|
||||
|
||||
```openscad
|
||||
diff("mask")
|
||||
cube([50,60,70],center=true)
|
||||
corner_profile("ALL", r=10)
|
||||
mask2d_roundover(10);
|
||||
```
|
||||
|
||||
### `face_profile()`
|
||||
As a simple shortcut to apply a profile mask to all edges and corners of a face, you can use the
|
||||
`face_profile()` module:
|
||||
|
||||
```openscad
|
||||
diff("mask")
|
||||
cube([50,60,70],center=true)
|
||||
face_profile(TOP, r=10)
|
||||
mask2d_roundover(10);
|
||||
```
|
||||
|
||||
|
||||
## Coloring Attachables
|
||||
TBW
|
||||
Usually, when coloring a shape with the `color()` module, the parent color overrides the colors of
|
||||
all children. This is often not what you want:
|
||||
|
||||
```openscad
|
||||
color("red") spheroid(d=3) {
|
||||
attach(CENTER,BOT) color("white") cyl(h=10, d=1) {
|
||||
attach(TOP,BOT) color("green") cyl(h=5, d1=3, d2=0);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
If you use the `recolor()` module, however, the child's color overrides the color of the parent.
|
||||
This is probably easier to understand by example:
|
||||
|
||||
```openscad
|
||||
recolor("red") spheroid(d=3) {
|
||||
attach(CENTER,BOT) recolor("white") cyl(h=10, d=1) {
|
||||
attach(TOP,BOT) recolor("green") cyl(h=5, d1=3, d2=0);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Making Attachables
|
||||
|
|
Loading…
Reference in a new issue