mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2025-01-04 03:09:45 +00:00
commit
a9e87638b8
5 changed files with 168 additions and 23 deletions
|
@ -3333,7 +3333,7 @@ function _find_anchor(anchor, geom) =
|
||||||
) [anchor, pos, vec, oang]
|
) [anchor, pos, vec, oang]
|
||||||
) : type == "vnf_isect"? ( //vnf
|
) : type == "vnf_isect"? ( //vnf
|
||||||
let( vnf=geom[1] )
|
let( vnf=geom[1] )
|
||||||
approx(anchor,CTR)? [anchor, [0,0,0], UP, 0] :
|
approx(anchor,CTR)? [anchor, cp, UP, 0] : // CENTER anchors anchor on cp, "origin" anchors on [0,0]
|
||||||
vnf==EMPTY_VNF? [anchor, [0,0,0], unit(anchor), 0] :
|
vnf==EMPTY_VNF? [anchor, [0,0,0], unit(anchor), 0] :
|
||||||
let(
|
let(
|
||||||
eps = 1/2048,
|
eps = 1/2048,
|
||||||
|
@ -3383,7 +3383,7 @@ function _find_anchor(anchor, geom) =
|
||||||
[anchor, pos, n, oang]
|
[anchor, pos, n, oang]
|
||||||
) : type == "vnf_extent"? ( //vnf
|
) : type == "vnf_extent"? ( //vnf
|
||||||
let( vnf=geom[1] )
|
let( vnf=geom[1] )
|
||||||
approx(anchor,CTR)? [anchor, [0,0,0], UP, 0] :
|
approx(anchor,CTR)? [anchor, cp, UP, 0] : // CENTER anchors anchor on cp, "origin" anchors on [0,0]
|
||||||
vnf==EMPTY_VNF? [anchor, [0,0,0], unit(anchor,UP), 0] :
|
vnf==EMPTY_VNF? [anchor, [0,0,0], unit(anchor,UP), 0] :
|
||||||
let(
|
let(
|
||||||
rpts = apply(rot(from=anchor, to=RIGHT) * move(point3d(-cp)), vnf[0]),
|
rpts = apply(rot(from=anchor, to=RIGHT) * move(point3d(-cp)), vnf[0]),
|
||||||
|
@ -3432,7 +3432,7 @@ function _find_anchor(anchor, geom) =
|
||||||
anchor = _force_anchor_2d(anchor),
|
anchor = _force_anchor_2d(anchor),
|
||||||
rgn = force_region(move(-point2d(cp), p=geom[1]))
|
rgn = force_region(move(-point2d(cp), p=geom[1]))
|
||||||
)
|
)
|
||||||
approx(anchor,[0,0])? [anchor, [0,0,0], BACK, 0] :
|
approx(anchor,[0,0])? [anchor, cp, BACK, 0] : // CENTER anchors anchor on cp, "origin" anchors on [0,0]
|
||||||
let(
|
let(
|
||||||
isects = [
|
isects = [
|
||||||
for (path=rgn, t=triplet(path,true)) let(
|
for (path=rgn, t=triplet(path,true)) let(
|
||||||
|
@ -3456,7 +3456,7 @@ function _find_anchor(anchor, geom) =
|
||||||
) [anchor, pos, vec, 0]
|
) [anchor, pos, vec, 0]
|
||||||
) : type == "rgn_extent"? ( //region
|
) : type == "rgn_extent"? ( //region
|
||||||
let( anchor = _force_anchor_2d(anchor) )
|
let( anchor = _force_anchor_2d(anchor) )
|
||||||
approx(anchor,[0,0])? [anchor, [0,0,0], BACK, 0] :
|
approx(anchor,[0,0])? [anchor, cp, BACK, 0] : // CENTER anchors anchor on cp, "origin" anchors on [0,0]
|
||||||
let(
|
let(
|
||||||
rgn = force_region(geom[1]),
|
rgn = force_region(geom[1]),
|
||||||
rpts = rot(from=anchor, to=RIGHT, p=flatten(rgn)),
|
rpts = rot(from=anchor, to=RIGHT, p=flatten(rgn)),
|
||||||
|
|
|
@ -1365,8 +1365,13 @@ module offset_stroke(path, width=1, rounded=true, start, end, check_valid=true,
|
||||||
// anchor = Translate so anchor point is at the origin. (module only) Default: "origin"
|
// anchor = Translate so anchor point is at the origin. (module only) Default: "origin"
|
||||||
// spin = Rotate this many degrees around Z axis after anchor. (module only) Default: 0
|
// spin = Rotate this many degrees around Z axis after anchor. (module only) Default: 0
|
||||||
// orient = Vector to rotate top towards after spin (module only)
|
// orient = Vector to rotate top towards after spin (module only)
|
||||||
// atype = Select "hull" or "intersect" anchor types. Default: "hull"
|
// atype = Select "hull", "intersect", "surf_hull" or "surf_intersect" anchor types. Default: "hull"
|
||||||
// cp = Centerpoint for determining "intersect" anchors or centering the shape. Determintes the base of the anchor vector. Can be "centroid", "mean", "box" or a 3D point. Default: "centroid"
|
// cp = Centerpoint for determining "intersect" anchors or centering the shape. Determintes the base of the anchor vector. Can be "centroid", "mean", "box" or a 3D point. Default: "centroid"
|
||||||
|
// Anchor Types:
|
||||||
|
// hull = Anchors to the convex hull of the linear sweep of the path, ignoring any end roundings.
|
||||||
|
// intersect = Anchors to the surface of the linear sweep of the path, ignoring any end roundings.
|
||||||
|
// surf_hull = Anchors to the convex hull of the offset_sweep shape, including end treatments.
|
||||||
|
// surf_intersect = Anchors to the surface of the offset_sweep shape, including any end treatments.
|
||||||
// Example: Rounding a star shaped prism with postive radius values
|
// Example: Rounding a star shaped prism with postive radius values
|
||||||
// star = star(5, r=22, ir=13);
|
// star = star(5, r=22, ir=13);
|
||||||
// rounded_star = round_corners(star, cut=flatten(repeat([.5,0],5)), $fn=24);
|
// rounded_star = round_corners(star, cut=flatten(repeat([.5,0],5)), $fn=24);
|
||||||
|
@ -1641,12 +1646,21 @@ module offset_sweep(path, height,
|
||||||
convexity=10,anchor="origin",cp="centroid",
|
convexity=10,anchor="origin",cp="centroid",
|
||||||
spin=0, orient=UP, atype="hull")
|
spin=0, orient=UP, atype="hull")
|
||||||
{
|
{
|
||||||
assert(in_list(atype, _ANCHOR_TYPES), "Anchor type must be \"hull\" or \"intersect\"");
|
assert(in_list(atype, ["intersect","hull","surf_hull","surf_intersect"]), "Anchor type must be \"hull\" or \"intersect\"");
|
||||||
vnf = offset_sweep(path=path, height=height, h=h, l=l, top=top, bottom=bottom, offset=offset, r=r, steps=steps,
|
vnf = offset_sweep(path=path, height=height, h=h, l=l, top=top, bottom=bottom, offset=offset, r=r, steps=steps,
|
||||||
quality=quality, check_valid=check_valid, extra=extra, cut=cut, chamfer_width=chamfer_width,
|
quality=quality, check_valid=check_valid, extra=extra, cut=cut, chamfer_width=chamfer_width,
|
||||||
chamfer_height=chamfer_height, joint=joint, k=k, angle=angle);
|
chamfer_height=chamfer_height, joint=joint, k=k, angle=angle);
|
||||||
vnf_polyhedron(vnf,convexity=convexity,anchor=anchor, spin=spin, orient=orient, atype=atype, cp=cp)
|
|
||||||
children();
|
if (in_list(atype,["hull","intersect"])){
|
||||||
|
h=first_defined([h,l,height]);
|
||||||
|
attachable(anchor,spin,orient,region=[path],h=h,extent=atype=="hull",cp=cp){
|
||||||
|
down(h/2)polyhedron(vnf[0],vnf[1],convexity=convexity);
|
||||||
|
children();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
vnf_polyhedron(vnf,convexity=convexity,anchor=anchor, spin=spin, orient=orient, atype=atype=="surf_hull"?"hull":"intersect", cp=cp)
|
||||||
|
children();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2012,6 +2026,11 @@ function _rp_compute_patches(top, bot, rtop, rsides, ktop, ksides, concave) =
|
||||||
// joint_top[1] is negative the shape will flare upward. At least one value must be non-negative. The same rules apply for joint_bot.
|
// joint_top[1] is negative the shape will flare upward. At least one value must be non-negative. The same rules apply for joint_bot.
|
||||||
// The joint_sides parameter must be entirely nonnegative.
|
// The joint_sides parameter must be entirely nonnegative.
|
||||||
// .
|
// .
|
||||||
|
// If the roundings at two adjacent side edges exceed the width of the face then the polyhedron will have self-intersecting faces, so it will be invalid.
|
||||||
|
// Similarly, if the roundings on the top or bottom edges cross the top face and intersect with each other, the resulting polyhedron is invalid:
|
||||||
|
// the top face after the roundings are applied must be a valid, non-degenerate polyhedron. There are two exceptions: it is permissible to
|
||||||
|
// construct a top that is a single point or two points. This means you can completely round a cube by setting the joint to half of
|
||||||
|
// the cube's width.
|
||||||
// If you set `debug` to true the module version will display the polyhedron even when it is invalid and it will show the bezier patches at the corners.
|
// If you set `debug` to true the module version will display the polyhedron even when it is invalid and it will show the bezier patches at the corners.
|
||||||
// This can help troubleshoot problems with your parameters. With the function form setting debug to true causes it to return [patches,vnf] where
|
// This can help troubleshoot problems with your parameters. With the function form setting debug to true causes it to return [patches,vnf] where
|
||||||
// patches is a list of the bezier control points for the corner patches.
|
// patches is a list of the bezier control points for the corner patches.
|
||||||
|
@ -2032,7 +2051,7 @@ function _rp_compute_patches(top, bot, rtop, rsides, ktop, ksides, concave) =
|
||||||
// k = continuous curvature rounding parameter for all edges. Default: 0.5
|
// k = continuous curvature rounding parameter for all edges. Default: 0.5
|
||||||
// k_top = continuous curvature rounding parameter for top
|
// k_top = continuous curvature rounding parameter for top
|
||||||
// k_bot = continuous curvature rounding parameter for bottom
|
// k_bot = continuous curvature rounding parameter for bottom
|
||||||
// k_bot = continuous curvature rounding parameter for bottom
|
// k_sides = continuous curvature rounding parameter side edges, a number or vector.
|
||||||
// splinesteps = number of segments to use for curved patches. Default: 16
|
// splinesteps = number of segments to use for curved patches. Default: 16
|
||||||
// debug = turn on debug mode which displays illegal polyhedra and shows the bezier corner patches for troubleshooting purposes. Default: False
|
// debug = turn on debug mode which displays illegal polyhedra and shows the bezier corner patches for troubleshooting purposes. Default: False
|
||||||
// convexity = convexity parameter for polyhedron(), only for module version. Default: 10
|
// convexity = convexity parameter for polyhedron(), only for module version. Default: 10
|
||||||
|
@ -2196,23 +2215,44 @@ function rounded_prism(bottom, top, joint_bot=0, joint_top=0, joint_sides=0, k_b
|
||||||
bot_patch = _rp_compute_patches(bottom, top, joint_bot, joint_sides_vec, k_bot, k_sides_vec, concave),
|
bot_patch = _rp_compute_patches(bottom, top, joint_bot, joint_sides_vec, k_bot, k_sides_vec, concave),
|
||||||
|
|
||||||
vertbad = [for(i=[0:N-1])
|
vertbad = [for(i=[0:N-1])
|
||||||
if (norm(top[i]-top_patch[i][4][2]) + norm(bottom[i]-bot_patch[i][4][2]) > norm(bottom[i]-top[i])) i],
|
if (norm(top[i]-top_patch[i][4][2]) + norm(bottom[i]-bot_patch[i][4][2]) > EPSILON + norm(bottom[i]-top[i])) i],
|
||||||
|
// Check that the patch fits on the polygon edge
|
||||||
topbad = [for(i=[0:N-1])
|
topbad = [for(i=[0:N-1])
|
||||||
if (norm(top_patch[i][2][4]-top_patch[i][2][2]) + norm(select(top_patch,i+1)[2][0]-select(top_patch,i+1)[2][2])
|
if (norm(top_patch[i][2][4]-top_patch[i][2][2]) + norm(select(top_patch,i+1)[2][0]-select(top_patch,i+1)[2][2])
|
||||||
> norm(top_patch[i][2][2] - select(top_patch,i+1)[2][2])) [i,(i+1)%N]],
|
> EPSILON + norm(top_patch[i][2][2] - select(top_patch,i+1)[2][2])) [i,(i+1)%N]],
|
||||||
botbad = [for(i=[0:N-1])
|
botbad = [for(i=[0:N-1])
|
||||||
if (norm(bot_patch[i][2][4]-bot_patch[i][2][2]) + norm(select(bot_patch,i+1)[2][0]-select(bot_patch,i+1)[2][2])
|
if (norm(bot_patch[i][2][4]-bot_patch[i][2][2]) + norm(select(bot_patch,i+1)[2][0]-select(bot_patch,i+1)[2][2])
|
||||||
> norm(bot_patch[i][2][2] - select(bot_patch,i+1)[2][2])) [i,(i+1)%N]],
|
> EPSILON + norm(bot_patch[i][2][2] - select(bot_patch,i+1)[2][2])) [i,(i+1)%N]],
|
||||||
topinbad = [for(i=[0:N-1])
|
// If top/bot is L-shaped, check that arms of L from adjacent patches don't cross
|
||||||
|
topLbad = [for(i=[0:N-1])
|
||||||
if (norm(top_patch[i][0][2]-top_patch[i][0][4]) + norm(select(top_patch,i+1)[0][0]-select(top_patch,i+1)[0][2])
|
if (norm(top_patch[i][0][2]-top_patch[i][0][4]) + norm(select(top_patch,i+1)[0][0]-select(top_patch,i+1)[0][2])
|
||||||
> norm(top_patch[i][0][2]-select(top_patch,i+1)[0][2])) [i,(i+1)%N]],
|
> EPSILON + norm(top_patch[i][0][2]-select(top_patch,i+1)[0][2])) [i,(i+1)%N]],
|
||||||
botinbad = [for(i=[0:N-1])
|
botLbad = [for(i=[0:N-1])
|
||||||
if (norm(bot_patch[i][0][2]-bot_patch[i][0][4]) + norm(select(bot_patch,i+1)[0][0]-select(bot_patch,i+1)[0][2])
|
if (norm(bot_patch[i][0][2]-bot_patch[i][0][4]) + norm(select(bot_patch,i+1)[0][0]-select(bot_patch,i+1)[0][2])
|
||||||
> norm(bot_patch[i][0][2]-select(bot_patch,i+1)[0][2])) [i,(i+1)%N]]
|
> EPSILON + norm(bot_patch[i][0][2]-select(bot_patch,i+1)[0][2])) [i,(i+1)%N]],
|
||||||
|
// Check that the inner edges of the patch don't cross
|
||||||
|
topinbad = [for(i=[0:N-1])
|
||||||
|
let(
|
||||||
|
line1 = project_plane(top,[top_patch[i][2][0],top_patch[i][0][0]]),
|
||||||
|
line2 = project_plane(top,[select(top_patch,i+1)[2][4],select(top_patch,i+1)[0][4]])
|
||||||
|
)
|
||||||
|
if (!approx(line1[0],line1[1]) && !approx(line2[0],line2[1]) &&
|
||||||
|
line_intersection(line1,line2, SEGMENT,SEGMENT))
|
||||||
|
[i,(i+1)%N]],
|
||||||
|
botinbad = [for(i=[0:N-1])
|
||||||
|
let(
|
||||||
|
line1 = project_plane(bottom,[bot_patch[i][2][0],bot_patch[i][0][0]]),
|
||||||
|
line2 = project_plane(bottom,[select(bot_patch,i+1)[2][4],select(bot_patch,i+1)[0][4]])
|
||||||
|
)
|
||||||
|
if (!approx(line1[0],line1[1]) && !approx(line2[0],line2[1]) &&
|
||||||
|
line_intersection(line1,line2, SEGMENT,SEGMENT))
|
||||||
|
[i,(i+1)%N]]
|
||||||
)
|
)
|
||||||
assert(debug || vertbad==[], str("Top and bottom joint lengths are too large; they interfere with each other at vertices: ",vertbad))
|
assert(debug || vertbad==[], str("Top and bottom joint lengths are too large; they interfere with each other at vertices: ",vertbad))
|
||||||
assert(debug || topbad==[], str("Joint lengths too large at top edges: ",topbad))
|
assert(debug || topbad==[], str("Joint lengths too large at top or side edges: ",topbad))
|
||||||
assert(debug || botbad==[], str("Joint lengths too large at bottom edges: ",botbad))
|
assert(debug || botbad==[], str("Joint lengths too large at bottom or side edges: ",botbad))
|
||||||
|
assert(debug || topLbad==[], str("Joint length too large on the top face or side at edges: ", topLbad))
|
||||||
|
assert(debug || botLbad==[], str("Joint length too large on the bottom face or side at edges: ", botLbad))
|
||||||
assert(debug || topinbad==[], str("Joint length too large on the top face at edges: ", topinbad))
|
assert(debug || topinbad==[], str("Joint length too large on the top face at edges: ", topinbad))
|
||||||
assert(debug || botinbad==[], str("Joint length too large on the bottom face at edges: ", botinbad))
|
assert(debug || botinbad==[], str("Joint length too large on the bottom face at edges: ", botinbad))
|
||||||
let(
|
let(
|
||||||
|
@ -2242,8 +2282,12 @@ function rounded_prism(bottom, top, joint_bot=0, joint_top=0, joint_sides=0, k_b
|
||||||
top_patch[i][4][4]
|
top_patch[i][4][4]
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
top_simple = is_path_simple(project_plane(faces[0],faces[0]),closed=true),
|
top_collinear = is_collinear(faces[0]),
|
||||||
bot_simple = is_path_simple(project_plane(faces[1],faces[1]),closed=true),
|
bot_collinear = is_collinear(faces[1]),
|
||||||
|
top_degen_ok = top_collinear && len(deduplicate(faces[0]))<=2,
|
||||||
|
bot_degen_ok = bot_collinear && len(deduplicate(faces[1]))<=2,
|
||||||
|
top_simple = top_degen_ok || (!top_collinear && is_path_simple(project_plane(faces[0],faces[0]),closed=true)),
|
||||||
|
bot_simple = bot_degen_ok || (!bot_collinear && is_path_simple(project_plane(faces[1],faces[1]),closed=true)),
|
||||||
// verify vertical edges
|
// verify vertical edges
|
||||||
verify_vert =
|
verify_vert =
|
||||||
[for(i=[0:N-1],j=[0:4])
|
[for(i=[0:N-1],j=[0:4])
|
||||||
|
|
|
@ -3349,7 +3349,11 @@ module fillet(l=1.0, r, ang=90, overlap=0.01, d, length, h, height, anchor=CENTE
|
||||||
arc[0] + polar_to_xy(overlap, 90+ang),
|
arc[0] + polar_to_xy(overlap, 90+ang),
|
||||||
each arc
|
each arc
|
||||||
];
|
];
|
||||||
attachable(anchor,spin,orient, size=[2*maxx,2*maxy,l]) {
|
override = function (anchor)
|
||||||
|
anchor.x>=0 && anchor.y>=0 ? undef
|
||||||
|
:
|
||||||
|
[[max(0,anchor.x)*maxx, max(0,anchor.y)*maxy, anchor.z*l/2]];
|
||||||
|
attachable(anchor,spin,orient, size=[2*maxx,2*maxy,l],override=override) {
|
||||||
if (l > 0) {
|
if (l > 0) {
|
||||||
linear_extrude(height=l, convexity=4, center=true) {
|
linear_extrude(height=l, convexity=4, center=true) {
|
||||||
polygon(path);
|
polygon(path);
|
||||||
|
|
|
@ -1262,7 +1262,7 @@ module cubic_barbell(s=100, anchor=CENTER, spin=0, orient=UP) {
|
||||||
children();
|
children();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cubic_barbell(100) show_anchors(30);
|
cubic_barbell(100) show_anchors(60);
|
||||||
```
|
```
|
||||||
|
|
||||||
When the shape is prismoidal, where the top is a different size from the bottom, you can use
|
When the shape is prismoidal, where the top is a different size from the bottom, you can use
|
||||||
|
@ -1637,3 +1637,99 @@ sphere_pt = apply(
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## 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:
|
||||||
|
|
||||||
|
```
|
||||||
|
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:
|
||||||
|
|
||||||
|
```
|
||||||
|
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:
|
||||||
|
```
|
||||||
|
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:
|
||||||
|
|
||||||
|
```
|
||||||
|
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);
|
||||||
|
```
|
||||||
|
|
|
@ -10,7 +10,8 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
BOSL_VERSION = [2,0,710];
|
BOSL_VERSION = [2,0,714];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Section: BOSL Library Version Functions
|
// Section: BOSL Library Version Functions
|
||||||
|
|
Loading…
Reference in a new issue