mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2024-12-29 16:29:40 +00:00
Enable use of attach with 2D shapes.
This commit is contained in:
parent
06a460f757
commit
76fb8ffac5
4 changed files with 68 additions and 21 deletions
|
@ -67,7 +67,8 @@ function anchorpt(name, pos=[0,0,0], dir=UP, rot=0) = [name, pos, dir, rot];
|
|||
// shift = The [X,Y] amount to shift the center of the top with respect to the center of the bottom.
|
||||
// geometry = One of "cube", "cylinder", or "sphere" to denote the overall geometry of the shape. Cones are "cylinder", and prismoids are "cube" for this purpose. Default: "cube"
|
||||
// extra_anchors = A list of extra non-standard named anchors.
|
||||
function find_anchor(anchor, h, size, size2=undef, shift=[0,0], extra_anchors=[], geometry="cube") =
|
||||
// two_d = If true, object will be treated as 2D.
|
||||
function find_anchor(anchor, h, size, size2=undef, shift=[0,0], extra_anchors=[], geometry="cube", two_d=false) =
|
||||
is_string(anchor)? (
|
||||
let(found = search([anchor], extra_anchors, num_returns_per_match=1)[0])
|
||||
assert(found!=[], str("Unknown anchor: ",anchor))
|
||||
|
@ -78,6 +79,7 @@ function find_anchor(anchor, h, size, size2=undef, shift=[0,0], extra_anchors=[]
|
|||
size2 = (size2!=undef)? point2d(size2) : size,
|
||||
shift = point2d(shift),
|
||||
oang = (
|
||||
two_d? 0 :
|
||||
anchor == UP? 0 :
|
||||
anchor == DOWN? 0 :
|
||||
(norm([anchor.x,anchor.y]) < EPSILON)? 0 :
|
||||
|
@ -99,15 +101,16 @@ function find_anchor(anchor, h, size, size2=undef, shift=[0,0], extra_anchors=[]
|
|||
botpt = point3d(vmul(size/2,xyal))+DOWN*h/2,
|
||||
toppt = point3d(vmul(size2/2,xyal)+shift)+UP*h/2,
|
||||
pos = lerp(botpt, toppt, (anchor.z+1)/2),
|
||||
sidevec = rotate_points3d([point3d(xyal)], from=UP, to=toppt-botpt)[0],
|
||||
sidevec = two_d? point3d(xyal) : rotate_points3d([point3d(xyal)], from=UP, to=toppt-botpt)[0],
|
||||
vec = (
|
||||
two_d? sidevec :
|
||||
anchor==CENTER? UP :
|
||||
norm([anchor.x,anchor.y]) < EPSILON? anchor :
|
||||
abs(anchor.z) < EPSILON? sidevec :
|
||||
anchor.z>0? (UP+sidevec)/2 :
|
||||
(DOWN+sidevec)/2
|
||||
)
|
||||
) [anchor, pos, vec, oang]
|
||||
) echo(anchor=anchor, pos=pos, vec=vec, oang=oang) [anchor, pos, vec, oang]
|
||||
);
|
||||
|
||||
|
||||
|
@ -148,6 +151,7 @@ function _str_char_split(s,delim,n=0,acc=[],word="") =
|
|||
// orig_anchor = The original anchor of the part. Default: `CENTER`.
|
||||
// geometry = One of "cube", "cylinder", or "sphere" to denote the overall geometry of the shape. Cones are "cylinder", and prismoids are "cube" for this purpose. Default: "cube"
|
||||
// anchors = A list of extra, non-standard optional anchors.
|
||||
// two_d = If true, object will be treated as 2D.
|
||||
// chain = If true, allow attachable children.
|
||||
//
|
||||
// Side Effects:
|
||||
|
@ -168,7 +172,7 @@ module orient_and_anchor(
|
|||
orig_orient=ORIENT_Z, orig_anchor=CENTER,
|
||||
size2=undef, shift=[0,0],
|
||||
anchors=[], chain=false,
|
||||
geometry="cube"
|
||||
geometry="cube", two_d=false
|
||||
) {
|
||||
size2 = point2d(default(size2, size));
|
||||
shift = point2d(shift);
|
||||
|
@ -186,19 +190,21 @@ module orient_and_anchor(
|
|||
],
|
||||
($attach_to!=undef)? (
|
||||
let(
|
||||
anch = find_anchor($attach_to, size.z, size, size2=size2, shift=shift, geometry=geometry),
|
||||
anch = find_anchor($attach_to, size.z, size, size2=size2, shift=shift, geometry=geometry, two_d=two_d),
|
||||
ang = vector_angle(anch[2], DOWN),
|
||||
axis = vector_axis(anch[2], DOWN),
|
||||
ang2 = (anch[2]==UP || anch[2]==DOWN)? 0 : 180-anch[3],
|
||||
axis2 = rotate_points3d([axis],[0,0,ang2])[0]
|
||||
) [
|
||||
matrix4_translate(-anch[1]),
|
||||
) concat(
|
||||
[matrix4_translate(-anch[1])],
|
||||
$attach_norot? [] : [
|
||||
matrix4_zrot(ang2),
|
||||
matrix4_rot_by_axis(axis2, ang)
|
||||
]
|
||||
)
|
||||
) : concat(
|
||||
(anchor==CENTER)? [] : [
|
||||
let(anch = find_anchor(anchor, size.z, size, size2=size2, shift=shift, extra_anchors=anchors, geometry=geometry))
|
||||
let(anch = find_anchor(anchor, size.z, size, size2=size2, shift=shift, extra_anchors=anchors, geometry=geometry, two_d=two_d))
|
||||
matrix4_translate(-anch[1])
|
||||
],
|
||||
(orient==ORIENT_Z)? [] : [
|
||||
|
@ -214,6 +220,7 @@ module orient_and_anchor(
|
|||
$parent_shift = shift;
|
||||
$parent_geom = geometry;
|
||||
$parent_orient = orient;
|
||||
$parent_2d = two_d;
|
||||
$parent_anchor = anchor;
|
||||
$parent_anchors = anchors;
|
||||
tags = _str_char_split($tags, " ");
|
||||
|
@ -254,16 +261,18 @@ module attach(name, to=undef, overlap=undef, norot=false)
|
|||
{
|
||||
assert($parent_size != undef, "No object to attach to!");
|
||||
overlap = (overlap!=undef)? overlap : $overlap;
|
||||
anch = find_anchor(name, $parent_size.z, point2d($parent_size), size2=$parent_size2, shift=$parent_shift, extra_anchors=$parent_anchors, geometry=$parent_geom);
|
||||
anch = find_anchor(name, $parent_size.z, point2d($parent_size), size2=$parent_size2, shift=$parent_shift, extra_anchors=$parent_anchors, geometry=$parent_geom, two_d=$parent_2d);
|
||||
pos = anch[1];
|
||||
vec = anch[2];
|
||||
ang = anch[3];
|
||||
$attach_to = to;
|
||||
$attach_anchor = anch;
|
||||
$attach_norot = norot;
|
||||
if (norot || (norm(vec-UP)<1e-9 && ang==0)) {
|
||||
translate(pos) translate([0,0,-overlap]) children();
|
||||
} else {
|
||||
translate(pos) rot(ang,from=UP,to=vec) translate([0,0,-overlap]) children();
|
||||
fromvec = $parent_2d? BACK : UP;
|
||||
translate(pos) rot(ang,from=fromvec,to=vec) translate([0,0,-overlap]) children();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -308,6 +308,7 @@ $color = undef;
|
|||
$overlap = 0.01;
|
||||
$attach_to = undef;
|
||||
$attach_anchor = [CENTER, CENTER, UP, 0];
|
||||
$attach_norot = false;
|
||||
$parent_size = undef;
|
||||
$parent_size2 = undef;
|
||||
$parent_shift = [0,0];
|
||||
|
|
7
foo.scad
7
foo.scad
|
@ -1,7 +0,0 @@
|
|||
include <BOSL2/std.scad>
|
||||
|
||||
cube([20,4,4], anchor=TOP+FRONT) {
|
||||
attach(FRONT, BACK) cube([20,20,4]);
|
||||
attach(TOP, BOTTOM) cube([20,4,20]);
|
||||
attach(TOP+FRONT, norot=true) recolor("green") interior_fillet(l=20, r=10, orient=ORIENT_XNEG);
|
||||
}
|
|
@ -38,6 +38,50 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
|
||||
|
||||
// Section: 2D Primitives
|
||||
|
||||
|
||||
// Module: square()
|
||||
// Usage:
|
||||
// square(size, [center], [anchor])
|
||||
// Description:
|
||||
// Creates a 2D square of the given size.
|
||||
// Arguments:
|
||||
// size = The size of the square to create. If given as a scalar, both X and Y will be the same size.
|
||||
// center = If given and true, overrides `anchor` to be `CENTER`. If given and false, overrides `anchor` to be `FRONT+LEFT`.
|
||||
// anchor = The side of the square to center on the origin. Default: `FRONT+LEFT`
|
||||
module square(size, center=undef, anchor=FRONT+LEFT) {
|
||||
size = is_num(size)? [size,size] : point2d(size);
|
||||
s = size/2;
|
||||
pts = [[-s.x,-s.y], [-s.x,s.y], [s.x,s.y], [s.x,-s.y]];
|
||||
orient_and_anchor(point3d(size), ORIENT_Z, anchor, center, noncentered=FRONT+LEFT, two_d=true, chain=true) {
|
||||
polygon(pts);
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Module: circle()
|
||||
// Usage:
|
||||
// circle(r|d, [anchor])
|
||||
// Description:
|
||||
// Creates a 2D circle of the given size.
|
||||
// Arguments:
|
||||
// r = The radius of the circle to create.
|
||||
// d = The diameter of the circle to create.
|
||||
// anchor = The side of the circle to center on the origin. Default: `CENTER`
|
||||
module circle(r=undef, d=undef, anchor=CENTER) {
|
||||
r = get_radius(r=r, d=d, dflt=1);
|
||||
sides = segs(r);
|
||||
pts = [for (a=[0:360/sides:360-EPSILON]) r*[cos(a),sin(a)]];
|
||||
orient_and_anchor([2*r,2*r,0], ORIENT_Z, anchor, geometry="cylinder", two_d=true, chain=true) {
|
||||
polygon(pts);
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Section: Primitive Shapes
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue