mirror of
https://github.com/revarbat/BOSL2.git
synced 2025-08-11 17:04:24 +02:00
Merge pull request #1717 from adrianVmariano/master
Add attach_part() and attachable_part() to support object part geometries
This commit is contained in:
@@ -33,6 +33,8 @@ $parent_orient = UP;
|
||||
$parent_size = undef;
|
||||
$parent_geom = undef;
|
||||
|
||||
$attach_inside = false; // If true, flip the meaning of the inside parameter for align() and attach()
|
||||
|
||||
$edge_angle = undef;
|
||||
$edge_length = undef;
|
||||
|
||||
@@ -700,12 +702,10 @@ module align(anchor,align=CENTER,inside=false,inset=0,shiftout=0,overlap)
|
||||
overlap = (overlap!=undef)? overlap : $overlap;
|
||||
dummy1=assert($parent_geom != undef, "No object to align to.")
|
||||
assert(is_undef($attach_to), "Cannot use align() as a child of attach()");
|
||||
if (is_undef($align_msg) || $align_msg)
|
||||
echo("ALERT: align() has changed, May 1, 2024. See the wiki and attach(align=). $align_msg=false disables this message");
|
||||
anchor = is_vector(anchor) ? [anchor] : anchor;
|
||||
align = is_vector(align) ? [align] : align;
|
||||
two_d = _attach_geom_2d($parent_geom);
|
||||
factor = inside?-1:1;
|
||||
factor = ($anchor_inside ? -1 : 1)*(inside?-1:1);
|
||||
for (i = idx(anchor)) {
|
||||
$align_msg=false; // Remove me when removing the message above
|
||||
face = anchor[i];
|
||||
@@ -938,6 +938,8 @@ module attach(parent, child, overlap, align, spin=0, norot, inset=0, shiftout=0,
|
||||
assert(is_finite(spin) || spin=="align", "Spin must be a number (unless align is given)")
|
||||
assert((is_undef(overlap) || is_finite(overlap)) && (is_def(overlap) || is_undef($overlap) || is_finite($overlap)),
|
||||
str("Provided ",is_def(overlap)?"":"$","overlap is not valid."));
|
||||
removetag = inside;
|
||||
inside = $anchor_inside ? !inside : inside;
|
||||
if (is_def(to))
|
||||
echo("The 'to' option to attach() is deprecated and will be removed in the future. Use 'child' instead.");
|
||||
if (is_def(from))
|
||||
@@ -1059,13 +1061,13 @@ 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);
|
||||
if (norot || (approx(anchor_dir,reference) && anchor_spin==0))
|
||||
translate(pos) rot(v=spinaxis,a=factor*spin) translate(olap) default_tag("remove",inside) children();
|
||||
translate(pos) rot(v=spinaxis,a=factor*spin) translate(olap) default_tag("remove",removetag) children();
|
||||
else
|
||||
translate(pos)
|
||||
rot(v=spinaxis,a=factor*spin)
|
||||
rot(anchor_spin,from=reference,to=anchor_dir)
|
||||
translate(olap)
|
||||
default_tag("remove",inside) children();
|
||||
default_tag("remove",removetag) children();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3065,6 +3067,7 @@ module corner_profile(corners=CORNERS_ALL, except=[], r, d, convexity=10) {
|
||||
// right(75) plug();
|
||||
|
||||
|
||||
|
||||
module attachable(
|
||||
anchor, spin, orient,
|
||||
size, size2, shift,
|
||||
@@ -3077,6 +3080,7 @@ module attachable(
|
||||
two_d=false,
|
||||
axis=UP,override,
|
||||
geom,
|
||||
parts=[],
|
||||
expose_tags=false, keep_color=false
|
||||
) {
|
||||
dummy1 =
|
||||
@@ -3110,6 +3114,8 @@ module attachable(
|
||||
$attach_to = undef;
|
||||
$anchor_override=undef;
|
||||
$attach_alignment=undef;
|
||||
$parent_parts = parts;
|
||||
$anchor_inside = false;
|
||||
if (expose_tags || _is_shown()){
|
||||
if (!keep_color)
|
||||
_color($color)
|
||||
@@ -3151,6 +3157,42 @@ module _show_ghost()
|
||||
}
|
||||
|
||||
|
||||
// Module: attach_part()
|
||||
// Synopsis: Select a named attachable part for subsequent attachment operations
|
||||
// Topics: Attachment
|
||||
// See Also: attach(), align(), attachable(), part_geometry()
|
||||
// Usage:
|
||||
// PARENT() attach_part(name) CHILDREN;
|
||||
// Description:
|
||||
// Selects an attachable part using a name defined by the parent object. Any operations
|
||||
// that use the parent geometry such as {{attach()}}, {{align()}}, {{position()}} or {{parent()}}
|
||||
// will reference the geometry for the specified part. This allows you to access the inner wall
|
||||
// of tubes, for example.
|
||||
// Example: This example shows attaching the light blue cube normally, on the outside of the tube, and the pink cube using the "inside" attachment part.
|
||||
// tube(ir1=10,ir2=20,h=20, wall=3){
|
||||
// color("lightblue")attach(RIGHT,BOT) cuboid(4);
|
||||
// color("pink")
|
||||
// attach_part("inside")
|
||||
// attach(BACK,BOT) cuboid(4);
|
||||
// }
|
||||
|
||||
module attach_part(name)
|
||||
{
|
||||
req_children($children);
|
||||
dummy=assert(!is_undef($parent_parts), "Parent does not exist or does not have any parts");
|
||||
ind = search([name], $parent_parts, 1,0)[0];
|
||||
dummy2 = assert(ind!=[], str("Parent does not have a part named ",name));
|
||||
$parent_geom = $parent_parts[ind][1];
|
||||
$anchor_inside = $parent_parts[ind][2];
|
||||
multmatrix($parent_parts[ind][3])
|
||||
children();
|
||||
}
|
||||
|
||||
|
||||
|
||||
function _is_geometry(entry) = is_list(entry) && is_string(entry[0]);
|
||||
|
||||
|
||||
// Function: reorient()
|
||||
// Synopsis: Calculates the transformation matrix needed to reorient an object.
|
||||
// SynTags: Trans, Path, VNF
|
||||
@@ -3539,6 +3581,43 @@ function attach_geom(
|
||||
: ["point", cp, offset, anchors];
|
||||
|
||||
|
||||
// Function: part_geometry()
|
||||
// Synopsis: Creates an attachable part data structure.
|
||||
// Topics: Attachments
|
||||
// See Also: attachable()
|
||||
// Usage:
|
||||
// part = part_geometry(name, geom, [inside=], [T=]);
|
||||
// Description:
|
||||
// Create a named attachable part that can be passed in the `parts` parameter of {{attachable()}}
|
||||
// and then selected using {{attach_part()}}.
|
||||
// Example(3D): This example shows how to create a custom object with two different parts that are both transformed away from the origin. The basic object is two cylinders with a cube shaped attachment geometry that doesn't match the object very well. The "left" and "right" parts attach to each of the two cylinders.
|
||||
// module twocyl(d, sep, h, ang=20)
|
||||
// {
|
||||
// parts = [
|
||||
// part_geometry("left", attach_geom(r=d/2,h=h), T=left(sep/2)*yrot(-ang)),
|
||||
// part_geometry("right", attach_geom(r=d/2,h=h), T=right(sep/2)*yrot(ang)),
|
||||
// ];
|
||||
// attachable(size=[sep+d,d,h], parts=parts){
|
||||
// union(){
|
||||
// left(sep/2) yrot(-ang) cyl(d=d,h=h);
|
||||
// right(sep/2) yrot(ang) cyl(d=d,h=h);
|
||||
// }
|
||||
// children();
|
||||
// }
|
||||
// }
|
||||
// twocyl(d=10,sep=30,h=10){
|
||||
// attach(TOP,TOP) cuboid(3);
|
||||
// color("pink")attach_part("left")attach(TOP,BOT) cuboid(3);
|
||||
// color("green")attach_part("right")attach(TOP,BOT) cuboid(3);
|
||||
// }
|
||||
|
||||
function part_geometry(name, geom, inside=false, T=IDENT) =
|
||||
assert(is_string(name), "name must be a string")
|
||||
assert(_is_geometry(geom), "geometry appears invalid")
|
||||
assert(is_bool(inside), "inside must be boolean")
|
||||
assert(is_matrix(T,4), "T must be a 4x4 transformation matrix")
|
||||
[name, geom, inside, T];
|
||||
|
||||
|
||||
|
||||
|
||||
|
@@ -1479,6 +1479,10 @@ function textured_tile(
|
||||
// width default will apply when the inner rounding and chamfer are both undef.
|
||||
// You can give an inner chamfer or rounding as a list with undef entries if you want to specify
|
||||
// some corner roundings and allow others to be computed.
|
||||
// .
|
||||
// Attachment to the rectangular tube will place objects on the **outside** of the tube.
|
||||
// If you need to anchor to the inside of a tube, use {{attach_part()}} with the part name "inside"
|
||||
// to switch goeomtry to the inside.
|
||||
// Arguments:
|
||||
// h/l/height/length = The height or length of the rectangular tube. Default: 1
|
||||
// size = The outer [X,Y] size of the rectangular tube.
|
||||
@@ -1565,7 +1569,14 @@ function textured_tile(
|
||||
// size=100, wall=10, h=30,
|
||||
// rounding=[0,10,20,30], ichamfer=[8,8,undef,undef]
|
||||
// );
|
||||
|
||||
// Example: An example from above with a cube attached to the inside using {{attach_part()}}.
|
||||
// rect_tube(
|
||||
// size=100, wall=10, h=30,
|
||||
// chamfer=[0,10,0,20],
|
||||
// rounding=[10,0,20,0]
|
||||
// )
|
||||
// attach_part("inside")
|
||||
// attach(BACK,BOT) cuboid(20);
|
||||
|
||||
|
||||
function _rect_tube_rounding(factor,ir,r,alternative,size,isize) =
|
||||
@@ -1677,7 +1688,10 @@ module rect_tube(
|
||||
ichamfer1 = _rect_tube_rounding(1/sqrt(2),ichamfer1_temp, chamfer1, irounding1_temp, size1, isize1);
|
||||
ichamfer2 = _rect_tube_rounding(1/sqrt(2),ichamfer2_temp, chamfer2, irounding2_temp, size2, isize2);
|
||||
anchor = get_anchor(anchor, center, BOT, BOT);
|
||||
attachable(anchor,spin,orient, size=[each size1, h], size2=size2, shift=shift) {
|
||||
parts = [
|
||||
part_geometry("inside", attach_geom(size=[each isize1, h], size2=isize2, shift=shift), inside=true)
|
||||
];
|
||||
attachable(anchor,spin,orient, size=[each size1, h], size2=size2, shift=shift, parts=parts) {
|
||||
down(h/2) {
|
||||
difference() {
|
||||
prismoid(
|
||||
@@ -2739,6 +2753,10 @@ module zcyl(
|
||||
// .
|
||||
// Chamfering and rounding lengths are measured based on the corners of the object except for the inner diameter when `circum=true`, in
|
||||
// which case chamfers and roundings are measured from the facets. This only matters when `$fn` is small.
|
||||
// .
|
||||
// Attachment to the tube will place objects on the **outside** of the tube.
|
||||
// If you need to anchor to the inside of a tube, use {{attach_part()}} with the part name "inside"
|
||||
// to switch goeomtry to the inside.
|
||||
// Usage: Basic cylindrical tube, specifying inner and outer radius or diameter
|
||||
// tube(h|l, or, ir, [center], [realign=], [anchor=], [spin=],[orient=]) [ATTACHMENTS];
|
||||
// tube(h|l, od=, id=, ...) [ATTACHMENTS];
|
||||
@@ -2835,6 +2853,13 @@ module zcyl(
|
||||
// half_of(v=[-1,1]) color("lightblue") cyl(d=9, h=12, $fn=32);
|
||||
// Example: Round ended hexagonal tube using `rounding_fn` to get sufficient facets on the roundings
|
||||
// tube(or=10, ir=7, h=10, $fn=6, rounding_fn=64, rounding=1.3, teardrop=true);
|
||||
// Example: This example shows a regular attachment to the outside of the tube in light blue and then using {{attach_part()}} to attach the pink cube to the inside of the tube.
|
||||
// tube(ir1=10,ir2=20,h=20, wall=3){
|
||||
// color("lightblue")attach(RIGHT,BOT) cuboid(4);
|
||||
// color("pink")
|
||||
// attach_part("inside")
|
||||
// attach(BACK,BOT) cuboid(4);
|
||||
// }
|
||||
|
||||
function tube(
|
||||
h, or, ir, center,
|
||||
@@ -2945,7 +2970,10 @@ module tube(
|
||||
last(ipath)+[0,1],
|
||||
[0,h/2+1]
|
||||
];
|
||||
attachable(anchor,spin,orient, r1=r1, r2=r2, l=h) {
|
||||
parts = [
|
||||
part_geometry("inside", attach_geom(r1=ir1, r2=ir2, l=h), inside=true)
|
||||
];
|
||||
attachable(anchor,spin,orient, r1=r1, r2=r2, l=h, parts=parts) {
|
||||
down(h/2) skew(sxz=shift.x/h, syz=shift.y/h) up(h/2)
|
||||
difference(){
|
||||
zrot(realign? 180/osides : 0)rotate_extrude($fn=osides,angle=360) polygon(outside);
|
||||
|
Reference in New Issue
Block a user