mirror of
https://github.com/revarbat/BOSL2.git
synced 2025-08-08 15:26:35 +02:00
Merge pull request #1725 from adrianVmariano/master
add attachable parts tutorial and improve tutorial links
This commit is contained in:
@@ -15,7 +15,7 @@ Requires OpenSCAD 2021.01 or later.
|
||||
|
||||
The BOSL2 library is an enormous library that provides many different kinds of capabilities to simplify the development of models in OpenSCAD, and to make things possible that are difficult in native OpenSCAD. Some of the things BOSL2 provides are:
|
||||
|
||||
* **Attachments.** Unless you make models containing just one object, the attachments features can revolutionize your modeling. They let you position components of a model relative to other components so you don't have to keep track of the positions and orientations of parts of the model. You can instead place something on the TOP of something else, perhaps aligned to the RIGHT. For a full introduction to attachments, consult the [Attachments Tutorial.](https://github.com/BelfrySCAD/BOSL2/wiki/Tutorial-Attachments)
|
||||
* **Attachments.** Unless you make models containing just one object, the attachments features can revolutionize your modeling. They let you position components of a model relative to other components so you don't have to keep track of the positions and orientations of parts of the model. You can instead place something on the TOP of something else, perhaps aligned to the RIGHT. For a full introduction to attachments, consult the [Attachments Tutorial.](https://github.com/BelfrySCAD/BOSL2/wiki/Tutorial-Attachment-Overview)
|
||||
* **Rounding and filleting.** Rounding and filleting is hard in OpenSCAD. The library provides modules like [cuboid()](https://github.com/BelfrySCAD/BOSL2/wiki/shapes3d.scad#module-cuboid) to make a cube with any of the edges rounded, [offset_sweep()](https://github.com/BelfrySCAD/BOSL2/wiki/rounding.scad#functionmodule-offset_sweep) to round the ends of a linear extrusion, and [prism_connector()](https://github.com/BelfrySCAD/BOSL2/wiki/rounding.scad#module-prism_connector) which works with the attachments feature to create filleted prisms between a variety of objects, or holes through a single object with rounded edges at the ends. You can also use [edge_profile()](https://github.com/BelfrySCAD/BOSL2/wiki/attachments.scad#module-edge_profile) to apply a variety of different mask profiles to chosen edges of a cubic shape, or you can directly subtract 3d mask shapes from an edge of objects that are not cubes.
|
||||
* **Shorthands.** The shorthands make your code a little shorter, and more importantly, they can make it significantly easier to read. Compare `up(z)` to `translate([0,0,z])`. The shorthands include operations for creating [copies of objects](https://github.com/BelfrySCAD/BOSL2/wiki/distributors.scad) and for applying [transformations](https://github.com/BelfrySCAD/BOSL2/wiki/transforms.scad) to objects, including [rot()](https://github.com/BelfrySCAD/BOSL2/wiki/transforms.scad#functionmodule-rot) which extends `rotate()` in some useful ways that are not easy to do directly.
|
||||
* **Complex object support.** The [path_sweep()](https://github.com/BelfrySCAD/BOSL2/wiki/skin.scad#functionmodule-path_sweep) function/module takes a 2d polygon moves it through space along a path and sweeps out a 3d shape as it moves. You can link together a series of arbitrary polygons with [skin()](https://github.com/BelfrySCAD/BOSL2/wiki/skin.scad#functionmodule-skin) or [vnf_vertex_array().](https://github.com/BelfrySCAD/BOSL2/wiki/vnf.scad#functionmodule-vnf_vertex_array) Support for [beziers](https://github.com/BelfrySCAD/BOSL2/wiki/beziers.scad) and [NURBS](https://github.com/BelfrySCAD/BOSL2/wiki/nurbs.scad) can help you construct the building blocks you need. [Metaballs](https://github.com/BelfrySCAD/BOSL2/wiki/isosurface.scad#functionmodule-metaballs) can create organic surfaces that blend shapes together.
|
||||
|
@@ -1046,6 +1046,7 @@ module attach(parent, child, overlap, align, spin=0, norot, inset=0, shiftout=0,
|
||||
// used when attachable() places the child
|
||||
$anchor_override = all_zero(child_adjustment)? inside?child:undef
|
||||
: child+child_adjustment;
|
||||
|
||||
reference = two_d? BACK : UP;
|
||||
// inset_dir is the direction for insetting when alignment is in effect
|
||||
inset_dir = is_undef(align) ? CTR
|
||||
@@ -1058,7 +1059,7 @@ module attach(parent, child, overlap, align, spin=0, norot, inset=0, shiftout=0,
|
||||
|
||||
|
||||
spinaxis = two_d? UP : anchor_dir;
|
||||
olap = - overlap * reference - inset*inset_dir + shiftout * (inset_dir + factor*reference);
|
||||
olap = - overlap * reference - inset*inset_dir + shiftout * (inset_dir + factor*reference*($anchor_inside?-1:1));
|
||||
if (norot || (approx(anchor_dir,reference) && anchor_spin==0))
|
||||
translate(pos) rot(v=spinaxis,a=factor*spin) translate(olap) default_tag("remove",removetag) children();
|
||||
else
|
||||
@@ -4168,6 +4169,7 @@ 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]
|
||||
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] :
|
||||
@@ -4448,15 +4450,15 @@ module show_anchors(s=10, std=true, custom=true) {
|
||||
if (std) {
|
||||
for (anchor=_standard_anchors(two_d=two_d)) {
|
||||
if(two_d) {
|
||||
attach(anchor) anchor_arrow2d(s);
|
||||
attach(anchor,BOT) anchor_arrow2d(s);
|
||||
} else {
|
||||
attach(anchor) anchor_arrow(s);
|
||||
attach(anchor,BOT) anchor_arrow(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (custom) {
|
||||
for (anchor=last($parent_geom)) {
|
||||
attach(anchor[0]) {
|
||||
attach(anchor[0],BOT) {
|
||||
if(two_d) {
|
||||
anchor_arrow2d(s, color="cyan");
|
||||
} else {
|
||||
|
@@ -1,3 +1,5 @@
|
||||
[Previous: Using position()](Tutorial-Attachment-Position)
|
||||
|
||||
# Aligning children with align()
|
||||
|
||||
You may have noticed that with position() and orient(), specifying the
|
||||
@@ -125,3 +127,5 @@ cyl(h=20,d=10,$fn=128)
|
||||
align([1,.3],TOP)
|
||||
color("lightblue")cuboid(5);
|
||||
```
|
||||
|
||||
[Next: Using attach()](Tutorial-Attachment-Attach)
|
||||
|
@@ -1,3 +1,5 @@
|
||||
[Prev: Using align()](Tutorial-Attachment-Align)
|
||||
|
||||
# Attachment using attach()
|
||||
|
||||
The `attach()` module can stick the child object to the parent object
|
||||
@@ -674,3 +676,5 @@ circle(d=50){
|
||||
trapezoid(w1=30,w2=0,h=30);
|
||||
}
|
||||
```
|
||||
|
||||
[Next: Attachable Parts](Tutorial-Attachment-Parts)
|
||||
|
@@ -1,3 +1,5 @@
|
||||
[Previous: Attachments Overview](Tutorial-Attachment-Overview)
|
||||
|
||||
# Basic Object Positioning: Anchor, Spin and Orient
|
||||
|
||||
When you create attachable objects using BOSL2 you have some options
|
||||
@@ -320,3 +322,5 @@ For 2D shapes, you can mix `anchor=` with `spin=`, but not with `orient=`.
|
||||
include <BOSL2/std.scad>
|
||||
square([40,30], anchor=BACK+LEFT, spin=30);
|
||||
```
|
||||
|
||||
[Next: Relative Positioning of Children](Tutorial-Attachment-Relative-Positioning)
|
||||
|
@@ -1,3 +1,5 @@
|
||||
[Prev: Attachable Parts](Tutorial-Attachment-Parts)
|
||||
|
||||
## Coloring Attachables
|
||||
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:
|
||||
@@ -57,3 +59,5 @@ affecting its descendents.
|
||||
As with all of the attachable features, these color, highlight and ghost modules only work
|
||||
on attachable objects, so they will have no effect on objects you
|
||||
create using `linear_extrude()` or `rotate_extrude()`.
|
||||
|
||||
[Next: Tagged Operations with Attachments](Tutorial-Attachment-Tags)
|
||||
|
@@ -1,3 +1,5 @@
|
||||
[Prev: Tagged Operations with Attachments](Tutorial-Attachment-Tags)
|
||||
|
||||
# Using Attachment for Edge Profiling
|
||||
|
||||
You can use attachment in various ways to create edge profiles on
|
||||
@@ -163,4 +165,4 @@ cube([50,60,70],center=true)
|
||||
mask2d_roundover(10);
|
||||
```
|
||||
|
||||
|
||||
[Next: Making Attachable Objects](Tutorial-Attachment-Making)
|
||||
|
@@ -1,3 +1,5 @@
|
||||
[Prev: Edge Profiling with Attachment](Tutorial-Attachment-Edge-Profiling)
|
||||
|
||||
# Making Attachables
|
||||
|
||||
To make a shape attachable, you just need to wrap it with an `attachable()` module with a
|
||||
@@ -531,3 +533,140 @@ module cubic_barbell(s=100, anchor=CENTER, spin=0, orient=UP) {
|
||||
}
|
||||
cubic_barbell(100) show_anchors(30);
|
||||
```
|
||||
|
||||
## Making Gometry With attach_geom()
|
||||
|
||||
Sometimes it may be advantageous to create the attachable geometry as
|
||||
a data structure. This can be particularly useful if you want to
|
||||
implement anchor types with an object, because it allows for an easy
|
||||
way to create different anchor options without having to repeat code.
|
||||
|
||||
Suppose we create a simple tetrahedron object:
|
||||
|
||||
```openscad-3D
|
||||
include<BOSL2/std.scad>
|
||||
module tetrahedron(base, height, spin=0, anchor=FWD+LEFT+BOT, orient=UP)
|
||||
{
|
||||
base_poly = path3d([[0,0],[0,base],[base,0]]);
|
||||
top = [0,0,height];
|
||||
vnf = vnf_vertex_array([base_poly, repeat(top,3)],col_wrap=true,cap1=true);
|
||||
attachable(anchor=anchor,orient=orient,spin=spin,vnf=vnf,cp="centroid"){
|
||||
vnf_polyhedron(vnf);
|
||||
children();
|
||||
}
|
||||
}
|
||||
tetrahedron(20,18) show_anchors();
|
||||
```
|
||||
|
||||
For this module we have used VNF anchors, but this tetrahedron is half
|
||||
related to a cuboid, so maybe sometimes you prefer to use anchors
|
||||
based on the bounding box. You could create a module with bounding
|
||||
box anchors like this, where we have had to explicitly center the VNF
|
||||
to make it work with the prismoid type anchoring:
|
||||
|
||||
```openscad-3D
|
||||
include<BOSL2/std.scad>
|
||||
module tetrahedron(base, height, spin=0, anchor=FWD+LEFT+BOT, orient=UP)
|
||||
{
|
||||
base_poly = path3d([[0,0],[0,base],[base,0]]);
|
||||
top = [0,0,height];
|
||||
vnf = move([-base/2,-base/2,-height/2],
|
||||
vnf_vertex_array([base_poly, repeat(top,3)],col_wrap=true,cap1=true));
|
||||
attachable(anchor=anchor,orient=orient,spin=spin,size=[base,base,height]){
|
||||
vnf_polyhedron(vnf);
|
||||
children();
|
||||
}
|
||||
}
|
||||
tetrahedron(20,18) show_anchors();
|
||||
```
|
||||
|
||||
The arguments needed to attachable are different in this case. If you
|
||||
want to conditionally switch between these two modes of operation,
|
||||
this presents a complication. While it is possible to work around
|
||||
this by conditionally setting parameters to `undef`, the resulting
|
||||
code will be more complex and harder to read. A better solution is to
|
||||
compute the geometry conditionally. Then the geometry can be passed
|
||||
to `attachable()`.
|
||||
|
||||
```openscad-3D;Big
|
||||
include<BOSL2/std.scad>
|
||||
module tetrahedron(base, height, atype="vnf", spin=0, anchor=FWD+LEFT+BOT, orient=UP)
|
||||
{
|
||||
assert(atype=="vnf" || atype=="box");
|
||||
base_poly = path3d([[0,0],[0,base],[base,0]]);
|
||||
top = [0,0,height];
|
||||
vnf = move([-base/2,-base/2,-height/2],
|
||||
vnf_vertex_array([base_poly, repeat(top,3)],col_wrap=true,cap1=true));
|
||||
geom = atype=="vnf" ? attach_geom(vnf=vnf,cp="centroid")
|
||||
: attach_geom(size=[base,base,height]);
|
||||
attachable(anchor=anchor,orient=orient,spin=spin,geom=geom){
|
||||
vnf_polyhedron(vnf);
|
||||
children();
|
||||
}
|
||||
}
|
||||
tetrahedron(20,18,atype="vnf")
|
||||
color("green")attach(TOP,BOT) cuboid(4);
|
||||
right(25)
|
||||
tetrahedron(20,18,atype="box")
|
||||
color("lightblue")attach(TOP,BOT) cuboid(4);
|
||||
```
|
||||
|
||||
Here we have created an `atype` argument that accepts two attachment
|
||||
types and we compute the geometry conditionally based on the atype
|
||||
setting. We can then invoke `attachable()` once with the `geom`
|
||||
parameter to specify the geometry.
|
||||
|
||||
|
||||
## Creating Attachable Parts
|
||||
|
||||
If your object has multiple distinct parts you may wish to create
|
||||
attachble parts for your object. In the library, `tube()` create
|
||||
an attachable part called "inside" that lets you attach to the inside
|
||||
of the tube.
|
||||
|
||||
Below we create an example where an object is made from two
|
||||
cylindrical parts, and we want to be able to attach to either one.
|
||||
In order to create attchable parts you must pass a list of the parts
|
||||
to `attachable()`. You create a part using the `define_part()`
|
||||
function which requires the part's name and its geometry. You can
|
||||
optionally provide a transformation using the `T=` parameter and give
|
||||
a flat with the `inside=` parameter.
|
||||
|
||||
```openscad-3D;Big
|
||||
include<BOSL2/std.scad>
|
||||
module twocyl(d1, d2, sep, h, ang=20)
|
||||
{
|
||||
parts = [
|
||||
define_part("left", attach_geom(r=d1/2,h=h),
|
||||
T=left(sep/2)*yrot(-ang)),
|
||||
define_part("right", attach_geom(r=d2/2,h=h),
|
||||
T=right(sep/2)*yrot(ang)),
|
||||
];
|
||||
attachable(size=[sep+d1/2+d2/2,max(d1,d2),h], parts=parts){
|
||||
union(){
|
||||
left(sep/2) yrot(-ang) cyl(d=d1,h=h);
|
||||
right(sep/2) yrot(ang) cyl(d=d2,h=h);
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
twocyl(d1=10,d2=13,sep=20,h=10){
|
||||
attach_part("left") attach(FWD,BOT)
|
||||
color("lightblue") cuboid(3);
|
||||
attach_part("right") attach(RIGHT,BOT)
|
||||
color("green") cuboid(3);
|
||||
}
|
||||
```
|
||||
|
||||
In the above example we create a parts list containing two parts named
|
||||
"left" and "right". Each part has its own geometry corresponding to
|
||||
the size of the cylinder, and it has a transformation specifying where
|
||||
the cylinder is located relative to the part's overall geometry.
|
||||
|
||||
If you create an "inside" part for a tube, the inside object will
|
||||
naturally have its anchors on the inner cylinder **pointing
|
||||
outward**. You can anchor on the inside by setting `inside=true` when
|
||||
invoking `attach()` or `align()`, but another option set `inside=true`
|
||||
when creating the part with `define_part()`. This cause `align()` and
|
||||
`attach()` to invert the meaning of the `inside` parameter so that
|
||||
objects will attach on the inside by default.
|
||||
|
@@ -24,4 +24,6 @@ tutorial. The non-attachables are `polyhedron()`, `linear_extrude()`,
|
||||
Some of these have attachable alternatives: `vnf_polyhedron()`,
|
||||
`linear_sweep()`, `rotate_sweep()`, and `region()`.
|
||||
|
||||
[Next: Basic Positioning](Tutorial-Attachment-Basic-Positioning)
|
||||
|
||||
|
||||
|
@@ -1,3 +1,5 @@
|
||||
[Previous: Relative Positioning of Children](Tutorial-Attachment-Relative-Positioning)
|
||||
|
||||
# Placing Children using position()
|
||||
|
||||
If you make an object a child of another object then the child object
|
||||
@@ -203,3 +205,5 @@ prismoid([50,50],[30,30],h=40)
|
||||
orient(RIGHT)
|
||||
anchor_arrow(40);
|
||||
```
|
||||
|
||||
[Next: Using align()](Tutorial-Attachment-Align)
|
||||
|
@@ -1,3 +1,5 @@
|
||||
[Prev: Basic Positioning](Tutorial-Attachment-Basic-Positioning)
|
||||
|
||||
# Relative Positioning: Placing Children using position(), align(), and attach()
|
||||
|
||||
Relative positioning is one of the most useful and powerful features
|
||||
@@ -17,3 +19,5 @@ Relative positioning means that since objects are positioned relative
|
||||
to other objects, you do not need to keep track of absolute positions
|
||||
and orientations of objects in your model. This makes models simpler,
|
||||
more intuitive, and easier to maintain.
|
||||
|
||||
[Next: Using position()](Tutorial-Attachment-Position)
|
||||
|
@@ -1,3 +1,5 @@
|
||||
[Prev: Using color with attachments](Tutorial-Attachment-Color)
|
||||
|
||||
# Tagged Operations
|
||||
|
||||
BOSL2 introduces the concept of tags. Tags are names that can be given to attachables, so that
|
||||
@@ -183,3 +185,5 @@ cube(50, center=true) {
|
||||
tag("keep")xcyl(h=100, d=20);
|
||||
}
|
||||
```
|
||||
|
||||
[Next: Edge Profiling with Attachment](Tutorial-Attachment-Edge-Profiling)
|
||||
|
Reference in New Issue
Block a user