mirror of
https://github.com/revarbat/BOSL2.git
synced 2025-08-29 10:59:59 +02:00
Break up attahcment tutorial into sections
This commit is contained in:
533
tutorials/Attachment-Making.md
Normal file
533
tutorials/Attachment-Making.md
Normal file
@@ -0,0 +1,533 @@
|
||||
# Making Attachables
|
||||
|
||||
To make a shape attachable, you just need to wrap it with an `attachable()` module with a
|
||||
basic description of the shape's geometry. By default, the shape is expected to be centered
|
||||
at the origin. This fact is important, as this is how the
|
||||
`attachable()` module knows the dimensions of your part: it assumes it
|
||||
is symetric around the origin. The `attachable()` module expects
|
||||
exactly two children. The first will bethe shape to make attachable,
|
||||
and the second will be `children()`, literally.
|
||||
|
||||
### Pass-through Attachables
|
||||
The simplest way to make your own attachable module is to simply pass
|
||||
through to a pre-existing attachable submodule. This could be
|
||||
appropriate if you want to rename a module, or if the anchors of an
|
||||
existing module are suited to (or good enough for) your object. In
|
||||
order for your attachable module to work properly you need to accept
|
||||
the `anchor`, `spin` and `orient` parameters, give them suitable
|
||||
defaults, and pass them to the attachable submodule. Don't forget to
|
||||
pass the children to the attachable submodule as well, or your new
|
||||
module will ignore its children.
|
||||
|
||||
```openscad-3D
|
||||
include <BOSL2/std.scad>
|
||||
$fn=32;
|
||||
module cutcube(anchor=CENTER,spin=0,orient=UP)
|
||||
{
|
||||
tag_scope(){
|
||||
diff()
|
||||
cuboid(15, rounding=2, anchor=anchor,spin=spin,orient=orient){
|
||||
tag("remove")attach(TOP)cuboid(5);
|
||||
children();
|
||||
}
|
||||
}
|
||||
}
|
||||
diff()
|
||||
cutcube()
|
||||
tag("remove")attach(RIGHT) cyl(d=2,h=8);
|
||||
```
|
||||
|
||||
### Prismoidal/Cuboidal Attachables
|
||||
To make a cuboidal or prismoidal shape attachable, you use the `size`, `size2`, and `offset`
|
||||
arguments of `attachable()`.
|
||||
|
||||
In the most basic form, where the shape is fully cuboid, with top and bottom of the same size,
|
||||
and directly over one another, you can just use `size=`.
|
||||
|
||||
```openscad-3D;Big
|
||||
include <BOSL2/std.scad>
|
||||
module cubic_barbell(s=100, anchor=CENTER, spin=0, orient=UP) {
|
||||
attachable(anchor,spin,orient, size=[s*3,s,s]) {
|
||||
union() {
|
||||
xcopies(2*s) cube(s, center=true);
|
||||
xcyl(h=2*s, d=s/4);
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
cubic_barbell(100) show_anchors(60);
|
||||
```
|
||||
|
||||
When the shape is prismoidal, where the top is a different size from the bottom, you can use
|
||||
the `size2=` argument as well. While `size=` takes all three axes sizes, the `size2=` argument
|
||||
only takes the [X,Y] sizes of the top of the shape.
|
||||
|
||||
```openscad-3D;Big
|
||||
include <BOSL2/std.scad>
|
||||
module prismoidal(size=[100,100,100], scale=0.5, anchor=CENTER, spin=0, orient=UP) {
|
||||
attachable(anchor,spin,orient, size=size, size2=[size.x, size.y]*scale) {
|
||||
hull() {
|
||||
up(size.z/2-0.005)
|
||||
linear_extrude(height=0.01, center=true)
|
||||
square([size.x,size.y]*scale, center=true);
|
||||
down(size.z/2-0.005)
|
||||
linear_extrude(height=0.01, center=true)
|
||||
square([size.x,size.y], center=true);
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
prismoidal([100,60,30], scale=0.5) show_anchors(20);
|
||||
```
|
||||
|
||||
When the top of the prismoid can be shifted away from directly above the bottom, you can use
|
||||
the `shift=` argument. The `shift=` argument takes an [X,Y] vector of the offset of the center
|
||||
of the top from the XY center of the bottom of the shape.
|
||||
|
||||
```openscad-3D;Big
|
||||
include <BOSL2/std.scad>
|
||||
module prismoidal(size=[100,100,100], scale=0.5, shift=[0,0], anchor=CENTER, spin=0, orient=UP) {
|
||||
attachable(anchor,spin,orient, size=size, size2=[size.x, size.y]*scale, shift=shift) {
|
||||
hull() {
|
||||
translate([shift.x, shift.y, size.z/2-0.005])
|
||||
linear_extrude(height=0.01, center=true)
|
||||
square([size.x,size.y]*scale, center=true);
|
||||
down(size.z/2-0.005)
|
||||
linear_extrude(height=0.01, center=true)
|
||||
square([size.x,size.y], center=true);
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
prismoidal([100,60,30], scale=0.5, shift=[-30,20]) show_anchors(20);
|
||||
```
|
||||
|
||||
In the case that the prismoid is not oriented vertically, (ie, where the `shift=` or `size2=`
|
||||
arguments should refer to a plane other than XY) you can use the `axis=` argument. This lets
|
||||
you make prismoids naturally oriented forwards/backwards or sideways.
|
||||
|
||||
```openscad-3D;Big
|
||||
include <BOSL2/std.scad>
|
||||
module yprismoidal(
|
||||
size=[100,100,100], scale=0.5, shift=[0,0],
|
||||
anchor=CENTER, spin=0, orient=UP
|
||||
) {
|
||||
attachable(
|
||||
anchor, spin, orient,
|
||||
size=size, size2=point2d(size)*scale,
|
||||
shift=shift, axis=BACK
|
||||
) {
|
||||
xrot(-90) hull() {
|
||||
translate([shift.x, shift.y, size.z/2-0.005])
|
||||
linear_extrude(height=0.01, center=true)
|
||||
square([size.x,size.y]*scale, center=true);
|
||||
down(size.z/2-0.005)
|
||||
linear_extrude(height=0.01, center=true)
|
||||
square([size.x,size.y], center=true);
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
yprismoidal([100,60,30], scale=1.5, shift=[20,20]) show_anchors(20);
|
||||
```
|
||||
|
||||
|
||||
### Cylindrical Attachables
|
||||
To make a cylindrical shape attachable, you use the `l`, and `r`/`d`, args of `attachable()`.
|
||||
|
||||
```openscad-3D;Big
|
||||
include <BOSL2/std.scad>
|
||||
module twistar(l,r,d, anchor=CENTER, spin=0, orient=UP) {
|
||||
r = get_radius(r=r,d=d,dflt=1);
|
||||
attachable(anchor,spin,orient, r=r, l=l) {
|
||||
linear_extrude(height=l, twist=90, slices=20, center=true, convexity=4)
|
||||
star(n=20, r=r, ir=r*0.9);
|
||||
children();
|
||||
}
|
||||
}
|
||||
twistar(l=100, r=40) show_anchors(20);
|
||||
```
|
||||
|
||||
If the cylinder is elipsoidal in shape, you can pass the unequal X/Y sizes as a 2-item vector
|
||||
to the `r=` or `d=` argument.
|
||||
|
||||
```openscad-3D
|
||||
include <BOSL2/std.scad>
|
||||
module ovalstar(l,rx,ry, anchor=CENTER, spin=0, orient=UP) {
|
||||
attachable(anchor,spin,orient, r=[rx,ry], l=l) {
|
||||
linear_extrude(height=l, center=true, convexity=4)
|
||||
scale([1,ry/rx,1])
|
||||
star(n=20, r=rx, ir=rx*0.9);
|
||||
children();
|
||||
}
|
||||
}
|
||||
ovalstar(l=100, rx=50, ry=30) show_anchors(20);
|
||||
```
|
||||
|
||||
For cylindrical shapes that aren't oriented vertically, use the `axis=` argument.
|
||||
|
||||
```openscad-3D
|
||||
include <BOSL2/std.scad>
|
||||
module ytwistar(l,r,d, anchor=CENTER, spin=0, orient=UP) {
|
||||
r = get_radius(r=r,d=d,dflt=1);
|
||||
attachable(anchor,spin,orient, r=r, l=l, axis=BACK) {
|
||||
xrot(-90)
|
||||
linear_extrude(height=l, twist=90, slices=20, center=true, convexity=4)
|
||||
star(n=20, r=r, ir=r*0.9);
|
||||
children();
|
||||
}
|
||||
}
|
||||
ytwistar(l=100, r=40) show_anchors(20);
|
||||
```
|
||||
|
||||
### Conical Attachables
|
||||
To make a conical shape attachable, you use the `l`, `r1`/`d1`, and `r2`/`d2`, args of
|
||||
`attachable()`.
|
||||
|
||||
```openscad-3D;Big
|
||||
include <BOSL2/std.scad>
|
||||
module twistar(l, r,r1,r2, d,d1,d2, anchor=CENTER, spin=0, orient=UP) {
|
||||
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);
|
||||
attachable(anchor,spin,orient, r1=r1, r2=r2, l=l) {
|
||||
linear_extrude(height=l, twist=90, scale=r2/r1, slices=20, center=true, convexity=4)
|
||||
star(n=20, r=r1, ir=r1*0.9);
|
||||
children();
|
||||
}
|
||||
}
|
||||
twistar(l=100, r1=40, r2=20) show_anchors(20);
|
||||
```
|
||||
|
||||
If the cone is ellipsoidal in shape, you can pass the unequal X/Y sizes as a 2-item vectors
|
||||
to the `r1=`/`r2=` or `d1=`/`d2=` arguments.
|
||||
|
||||
```openscad-3D;Big
|
||||
include <BOSL2/std.scad>
|
||||
module ovalish(l,rx1,ry1,rx2,ry2, anchor=CENTER, spin=0, orient=UP) {
|
||||
attachable(anchor,spin,orient, r1=[rx1,ry1], r2=[rx2,ry2], l=l) {
|
||||
hull() {
|
||||
up(l/2-0.005)
|
||||
linear_extrude(height=0.01, center=true)
|
||||
ellipse([rx2,ry2]);
|
||||
down(l/2-0.005)
|
||||
linear_extrude(height=0.01, center=true)
|
||||
ellipse([rx1,ry1]);
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
ovalish(l=100, rx1=50, ry1=30, rx2=30, ry2=50) show_anchors(20);
|
||||
```
|
||||
|
||||
For conical shapes that are not oriented vertically, use the `axis=` argument to indicate the
|
||||
direction of the primary shape axis:
|
||||
|
||||
```openscad-3D;Big
|
||||
include <BOSL2/std.scad>
|
||||
module ytwistar(l, r,r1,r2, d,d1,d2, anchor=CENTER, spin=0, orient=UP) {
|
||||
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);
|
||||
attachable(anchor,spin,orient, r1=r1, r2=r2, l=l, axis=BACK) {
|
||||
xrot(-90)
|
||||
linear_extrude(height=l, twist=90, scale=r2/r1, slices=20, center=true, convexity=4)
|
||||
star(n=20, r=r1, ir=r1*0.9);
|
||||
children();
|
||||
}
|
||||
}
|
||||
ytwistar(l=100, r1=40, r2=20) show_anchors(20);
|
||||
```
|
||||
|
||||
### Spherical Attachables
|
||||
To make a spherical shape attachable, you use the `r`/`d` args of `attachable()`.
|
||||
|
||||
```openscad-3D;Big
|
||||
include <BOSL2/std.scad>
|
||||
module spikeball(r, d, anchor=CENTER, spin=0, orient=UP) {
|
||||
r = get_radius(r=r,d=d,dflt=1);
|
||||
attachable(anchor,spin,orient, r=r*1.1) {
|
||||
union() {
|
||||
sphere_copies(r=r, n=512, cone_ang=180) cylinder(r1=r/10, r2=0, h=r/10);
|
||||
sphere(r=r);
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
spikeball(r=50) show_anchors(20);
|
||||
```
|
||||
|
||||
If the shape is an ellipsoid, you can pass a 3-item vector of sizes to `r=` or `d=`.
|
||||
|
||||
```openscad-3D
|
||||
include <BOSL2/std.scad>
|
||||
module spikeball(r, d, scale, anchor=CENTER, spin=0, orient=UP) {
|
||||
r = get_radius(r=r,d=d,dflt=1);
|
||||
attachable(anchor,spin,orient, r=r*1.1*scale) {
|
||||
union() {
|
||||
sphere_copies(r=r, n=512, scale=scale, cone_ang=180) cylinder(r1=r/10, r2=0, h=r/10);
|
||||
scale(scale) sphere(r=r);
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
spikeball(r=50, scale=[0.75,1,1.5]) show_anchors(20);
|
||||
```
|
||||
|
||||
### VNF Attachables
|
||||
If the shape just doesn't fit into any of the above categories, and you constructed it as a
|
||||
[VNF](vnf.scad), you can use the VNF itself to describe the geometry with the `vnf=` argument.
|
||||
|
||||
There are two variations to how anchoring can work for VNFs. When `extent=true`, (the default)
|
||||
then a plane is projected out from the origin, perpendicularly in the direction of the anchor,
|
||||
to the furthest distance that intersects with the VNF shape. The anchor point is then the
|
||||
center of the points that still intersect that plane.
|
||||
|
||||
```openscad-FlatSpin,VPD=500
|
||||
include <BOSL2/std.scad>
|
||||
module stellate_cube(s=100, anchor=CENTER, spin=0, orient=UP) {
|
||||
s2 = 3 * s;
|
||||
verts = [
|
||||
[0,0,-s2*sqrt(2)/2],
|
||||
each down(s/2, p=path3d(square(s,center=true))),
|
||||
each zrot(45, p=path3d(square(s2,center=true))),
|
||||
each up(s/2, p=path3d(square(s,center=true))),
|
||||
[0,0,s2*sqrt(2)/2]
|
||||
];
|
||||
faces = [
|
||||
[0,2,1], [0,3,2], [0,4,3], [0,1,4],
|
||||
[1,2,6], [1,6,9], [6,10,9], [2,10,6],
|
||||
[1,5,4], [1,9,5], [9,12,5], [5,12,4],
|
||||
[4,8,3], [4,12,8], [12,11,8], [11,3,8],
|
||||
[2,3,7], [3,11,7], [7,11,10], [2,7,10],
|
||||
[9,10,13], [10,11,13], [11,12,13], [12,9,13]
|
||||
];
|
||||
vnf = [verts, faces];
|
||||
attachable(anchor,spin,orient, vnf=vnf) {
|
||||
vnf_polyhedron(vnf);
|
||||
children();
|
||||
}
|
||||
}
|
||||
stellate_cube(25) {
|
||||
attach(UP+RIGHT) {
|
||||
anchor_arrow(20);
|
||||
%cube([100,100,0.1],center=true);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
When `extent=false`, then the anchor point will be the furthest intersection of the VNF with
|
||||
the anchor ray from the origin. The orientation of the anchor point will be the normal of the
|
||||
face at the intersection. If the intersection is at an edge or corner, then the orientation
|
||||
will bisect the angles between the faces.
|
||||
|
||||
```openscad-VPD=1250
|
||||
include <BOSL2/std.scad>
|
||||
module stellate_cube(s=100, anchor=CENTER, spin=0, orient=UP) {
|
||||
s2 = 3 * s;
|
||||
verts = [
|
||||
[0,0,-s2*sqrt(2)/2],
|
||||
each down(s/2, p=path3d(square(s,center=true))),
|
||||
each zrot(45, p=path3d(square(s2,center=true))),
|
||||
each up(s/2, p=path3d(square(s,center=true))),
|
||||
[0,0,s2*sqrt(2)/2]
|
||||
];
|
||||
faces = [
|
||||
[0,2,1], [0,3,2], [0,4,3], [0,1,4],
|
||||
[1,2,6], [1,6,9], [6,10,9], [2,10,6],
|
||||
[1,5,4], [1,9,5], [9,12,5], [5,12,4],
|
||||
[4,8,3], [4,12,8], [12,11,8], [11,3,8],
|
||||
[2,3,7], [3,11,7], [7,11,10], [2,7,10],
|
||||
[9,10,13], [10,11,13], [11,12,13], [12,9,13]
|
||||
];
|
||||
vnf = [verts, faces];
|
||||
attachable(anchor,spin,orient, vnf=vnf, extent=false) {
|
||||
vnf_polyhedron(vnf);
|
||||
children();
|
||||
}
|
||||
}
|
||||
stellate_cube() show_anchors(50);
|
||||
```
|
||||
|
||||
```openscad-3D
|
||||
include <BOSL2/std.scad>
|
||||
$fn=32;
|
||||
R = difference(circle(10), right(2, circle(9)));
|
||||
linear_sweep(R,height=10,atype="hull")
|
||||
attach(RIGHT) anchor_arrow();
|
||||
```
|
||||
|
||||
|
||||
## Making Named Anchors
|
||||
While vector anchors are often useful, sometimes there are logically extra attachment points that
|
||||
aren't on the perimeter of the shape. This is what named string anchors are for. For example,
|
||||
the `teardrop()` shape uses a cylindrical geometry for it's vector anchors, but it also provides
|
||||
a named anchor "cap" that is at the tip of the hat of the teardrop shape.
|
||||
|
||||
Named anchors are passed as an array of `named_anchor()`s to the `anchors=` argument of `attachable()`.
|
||||
The `named_anchor()` call takes a name string, a positional point, an orientation vector, and a spin.
|
||||
The name is the name of the anchor. The positional point is where the anchor point is at. The
|
||||
orientation vector is the direction that a child attached at that anchor point should be oriented.
|
||||
The spin is the number of degrees that an attached child should be rotated counter-clockwise around
|
||||
the orientation vector. Spin is optional, and defaults to 0.
|
||||
|
||||
To make a simple attachable shape similar to a `teardrop()` that provides a "cap" anchor, you may
|
||||
define it like this:
|
||||
|
||||
```openscad-3D
|
||||
include <BOSL2/std.scad>
|
||||
module raindrop(r, thick, anchor=CENTER, spin=0, orient=UP) {
|
||||
anchors = [
|
||||
named_anchor("cap", [0,r/sin(45),0], BACK, 0)
|
||||
];
|
||||
attachable(anchor,spin,orient, r=r, l=thick, anchors=anchors) {
|
||||
linear_extrude(height=thick, center=true) {
|
||||
circle(r=r);
|
||||
back(r*sin(45)) zrot(45) square(r, center=true);
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
raindrop(r=25, thick=20, anchor="cap");
|
||||
```
|
||||
|
||||
If you want multiple named anchors, just add them to the list of anchors:
|
||||
|
||||
```openscad-FlatSpin,VPD=150
|
||||
include <BOSL2/std.scad>
|
||||
module raindrop(r, thick, anchor=CENTER, spin=0, orient=UP) {
|
||||
anchors = [
|
||||
named_anchor("captop", [0,r/sin(45), thick/2], BACK+UP, 0),
|
||||
named_anchor("cap", [0,r/sin(45), 0 ], BACK, 0),
|
||||
named_anchor("capbot", [0,r/sin(45),-thick/2], BACK+DOWN, 0)
|
||||
];
|
||||
attachable(anchor,spin,orient, r=r, l=thick, anchors=anchors) {
|
||||
linear_extrude(height=thick, center=true) {
|
||||
circle(r=r);
|
||||
back(r*sin(45)) zrot(45) square(r, center=true);
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
raindrop(r=15, thick=10) show_anchors();
|
||||
```
|
||||
|
||||
Sometimes the named anchor you want to add may be at a point that is reached through a complicated
|
||||
set of translations and rotations. One quick way to calculate that point is to reproduce those
|
||||
transformations in a transformation matrix chain. This is simplified by how you can use the
|
||||
function forms of almost all the transformation modules to get the transformation matrices, and
|
||||
chain them together with matrix multiplication. For example, if you have:
|
||||
|
||||
```
|
||||
scale([1.1, 1.2, 1.3]) xrot(15) zrot(25) right(20) sphere(d=1);
|
||||
```
|
||||
|
||||
and you want to calculate the center point of the sphere, you can do it like:
|
||||
|
||||
```
|
||||
sphere_pt = apply(
|
||||
scale([1.1, 1.2, 1.3]) * xrot(15) * zrot(25) * right(20),
|
||||
[0,0,0]
|
||||
);
|
||||
```
|
||||
|
||||
|
||||
## Overriding Standard Anchors
|
||||
|
||||
Sometimes you may want to use the standard anchors but override some
|
||||
of them. Returning to the square barebell example above, the anchors
|
||||
at the right and left sides are on the cubes at each end, but the
|
||||
anchors at x=0 are in floating in space. For prismoidal/cubic anchors
|
||||
in 3D and trapezoidal/rectangular anchors in 2D we can override a single anchor by
|
||||
specifying the override option and giving the anchor that is being
|
||||
overridden, and then the replacement in the form
|
||||
`[position, direction, spin]`. Most often you will only want to
|
||||
override the position. If you omit the other list items then the
|
||||
value drived from the standard anchor will be used. Below we override
|
||||
position of the FWD anchor:
|
||||
|
||||
```openscad-3D;Big
|
||||
include<BOSL2/std.scad>
|
||||
module cubic_barbell(s=100, anchor=CENTER, spin=0, orient=UP) {
|
||||
override = [
|
||||
[FWD, [[0,-s/8,0]]]
|
||||
];
|
||||
attachable(anchor,spin,orient, size=[s*3,s,s],override=override) {
|
||||
union() {
|
||||
xcopies(2*s) cube(s, center=true);
|
||||
xcyl(h=2*s, d=s/4);
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
cubic_barbell(100) show_anchors(60);
|
||||
```
|
||||
|
||||
Note how the FWD anchor is now rooted on the cylindrical portion. If
|
||||
you wanted to also change its direction and spin you could do it like
|
||||
this:
|
||||
|
||||
```openscad-3D;Big
|
||||
include<BOSL2/std.scad>
|
||||
module cubic_barbell(s=100, anchor=CENTER, spin=0, orient=UP) {
|
||||
override = [
|
||||
[FWD, [[0,-s/8,0], FWD+LEFT, 225]]
|
||||
];
|
||||
attachable(anchor,spin,orient, size=[s*3,s,s],override=override) {
|
||||
union() {
|
||||
xcopies(2*s) cube(s, center=true);
|
||||
xcyl(h=2*s, d=s/4);
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
cubic_barbell(100) show_anchors(60);
|
||||
```
|
||||
|
||||
In the above example we give three values for the override. As
|
||||
before, the first one places the anchor on the cylinder. We have
|
||||
added the second entry which points the anchor off to the left.
|
||||
The third entry gives a spin override, whose effect is shown by the
|
||||
position of the red flag on the arrow. If you want to override all of
|
||||
the x=0 anchors to be on the cylinder, with their standard directions,
|
||||
you can do that by supplying a list:
|
||||
|
||||
```openscad-3D;Big
|
||||
include<BOSL2/std.scad>
|
||||
module cubic_barbell(s=100, anchor=CENTER, spin=0, orient=UP) {
|
||||
override = [
|
||||
for(j=[-1:1:1], k=[-1:1:1])
|
||||
if ([j,k]!=[0,0]) [[0,j,k], [s/8*unit([0,j,k])]]
|
||||
];
|
||||
attachable(anchor,spin,orient, size=[s*3,s,s],override=override) {
|
||||
union() {
|
||||
xcopies(2*s) cube(s, center=true);
|
||||
xcyl(h=2*s, d=s/4);
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
cubic_barbell(100) show_anchors(30);
|
||||
```
|
||||
|
||||
Now all of the anchors in the middle are all rooted to the cylinder. Another
|
||||
way to do the same thing is to use a function literal for override.
|
||||
It will be called with the anchor as its argument and needs to return undef to just use
|
||||
the default, or a `[position, direction, spin]` triple to override the
|
||||
default. As before, you can omit values to keep their default.
|
||||
Here is the same example using a function literal for the override:
|
||||
|
||||
```openscad-3D;Big
|
||||
include<BOSL2/std.scad>
|
||||
module cubic_barbell(s=100, anchor=CENTER, spin=0, orient=UP) {
|
||||
override = function (anchor)
|
||||
anchor.x!=0 || anchor==CTR ? undef // Keep these
|
||||
: [s/8*unit(anchor)];
|
||||
attachable(anchor,spin,orient, size=[s*3,s,s],override=override) {
|
||||
union() {
|
||||
xcopies(2*s) cube(s, center=true);
|
||||
xcyl(h=2*s, d=s/4);
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
cubic_barbell(100) show_anchors(30);
|
||||
```
|
Reference in New Issue
Block a user