mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2025-01-01 09:49:45 +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.
|
// 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"
|
// 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.
|
// 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)? (
|
is_string(anchor)? (
|
||||||
let(found = search([anchor], extra_anchors, num_returns_per_match=1)[0])
|
let(found = search([anchor], extra_anchors, num_returns_per_match=1)[0])
|
||||||
assert(found!=[], str("Unknown anchor: ",anchor))
|
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,
|
size2 = (size2!=undef)? point2d(size2) : size,
|
||||||
shift = point2d(shift),
|
shift = point2d(shift),
|
||||||
oang = (
|
oang = (
|
||||||
|
two_d? 0 :
|
||||||
anchor == UP? 0 :
|
anchor == UP? 0 :
|
||||||
anchor == DOWN? 0 :
|
anchor == DOWN? 0 :
|
||||||
(norm([anchor.x,anchor.y]) < EPSILON)? 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,
|
botpt = point3d(vmul(size/2,xyal))+DOWN*h/2,
|
||||||
toppt = point3d(vmul(size2/2,xyal)+shift)+UP*h/2,
|
toppt = point3d(vmul(size2/2,xyal)+shift)+UP*h/2,
|
||||||
pos = lerp(botpt, toppt, (anchor.z+1)/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 = (
|
vec = (
|
||||||
|
two_d? sidevec :
|
||||||
anchor==CENTER? UP :
|
anchor==CENTER? UP :
|
||||||
norm([anchor.x,anchor.y]) < EPSILON? anchor :
|
norm([anchor.x,anchor.y]) < EPSILON? anchor :
|
||||||
abs(anchor.z) < EPSILON? sidevec :
|
abs(anchor.z) < EPSILON? sidevec :
|
||||||
anchor.z>0? (UP+sidevec)/2 :
|
anchor.z>0? (UP+sidevec)/2 :
|
||||||
(DOWN+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`.
|
// 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"
|
// 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.
|
// 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.
|
// chain = If true, allow attachable children.
|
||||||
//
|
//
|
||||||
// Side Effects:
|
// Side Effects:
|
||||||
|
@ -168,7 +172,7 @@ module orient_and_anchor(
|
||||||
orig_orient=ORIENT_Z, orig_anchor=CENTER,
|
orig_orient=ORIENT_Z, orig_anchor=CENTER,
|
||||||
size2=undef, shift=[0,0],
|
size2=undef, shift=[0,0],
|
||||||
anchors=[], chain=false,
|
anchors=[], chain=false,
|
||||||
geometry="cube"
|
geometry="cube", two_d=false
|
||||||
) {
|
) {
|
||||||
size2 = point2d(default(size2, size));
|
size2 = point2d(default(size2, size));
|
||||||
shift = point2d(shift);
|
shift = point2d(shift);
|
||||||
|
@ -186,19 +190,21 @@ module orient_and_anchor(
|
||||||
],
|
],
|
||||||
($attach_to!=undef)? (
|
($attach_to!=undef)? (
|
||||||
let(
|
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),
|
ang = vector_angle(anch[2], DOWN),
|
||||||
axis = vector_axis(anch[2], DOWN),
|
axis = vector_axis(anch[2], DOWN),
|
||||||
ang2 = (anch[2]==UP || anch[2]==DOWN)? 0 : 180-anch[3],
|
ang2 = (anch[2]==UP || anch[2]==DOWN)? 0 : 180-anch[3],
|
||||||
axis2 = rotate_points3d([axis],[0,0,ang2])[0]
|
axis2 = rotate_points3d([axis],[0,0,ang2])[0]
|
||||||
) [
|
) concat(
|
||||||
matrix4_translate(-anch[1]),
|
[matrix4_translate(-anch[1])],
|
||||||
|
$attach_norot? [] : [
|
||||||
matrix4_zrot(ang2),
|
matrix4_zrot(ang2),
|
||||||
matrix4_rot_by_axis(axis2, ang)
|
matrix4_rot_by_axis(axis2, ang)
|
||||||
]
|
]
|
||||||
|
)
|
||||||
) : concat(
|
) : concat(
|
||||||
(anchor==CENTER)? [] : [
|
(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])
|
matrix4_translate(-anch[1])
|
||||||
],
|
],
|
||||||
(orient==ORIENT_Z)? [] : [
|
(orient==ORIENT_Z)? [] : [
|
||||||
|
@ -214,6 +220,7 @@ module orient_and_anchor(
|
||||||
$parent_shift = shift;
|
$parent_shift = shift;
|
||||||
$parent_geom = geometry;
|
$parent_geom = geometry;
|
||||||
$parent_orient = orient;
|
$parent_orient = orient;
|
||||||
|
$parent_2d = two_d;
|
||||||
$parent_anchor = anchor;
|
$parent_anchor = anchor;
|
||||||
$parent_anchors = anchors;
|
$parent_anchors = anchors;
|
||||||
tags = _str_char_split($tags, " ");
|
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!");
|
assert($parent_size != undef, "No object to attach to!");
|
||||||
overlap = (overlap!=undef)? overlap : $overlap;
|
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];
|
pos = anch[1];
|
||||||
vec = anch[2];
|
vec = anch[2];
|
||||||
ang = anch[3];
|
ang = anch[3];
|
||||||
$attach_to = to;
|
$attach_to = to;
|
||||||
$attach_anchor = anch;
|
$attach_anchor = anch;
|
||||||
|
$attach_norot = norot;
|
||||||
if (norot || (norm(vec-UP)<1e-9 && ang==0)) {
|
if (norot || (norm(vec-UP)<1e-9 && ang==0)) {
|
||||||
translate(pos) translate([0,0,-overlap]) children();
|
translate(pos) translate([0,0,-overlap]) children();
|
||||||
} else {
|
} 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;
|
$overlap = 0.01;
|
||||||
$attach_to = undef;
|
$attach_to = undef;
|
||||||
$attach_anchor = [CENTER, CENTER, UP, 0];
|
$attach_anchor = [CENTER, CENTER, UP, 0];
|
||||||
|
$attach_norot = false;
|
||||||
$parent_size = undef;
|
$parent_size = undef;
|
||||||
$parent_size2 = undef;
|
$parent_size2 = undef;
|
||||||
$parent_shift = [0,0];
|
$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
|
// Section: Primitive Shapes
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue