mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2025-01-01 09:49:45 +00:00
Merge pull request #1439 from hvegh/master
rect: enhanced rounding and chamfer options
This commit is contained in:
commit
fa7ca74dd6
1 changed files with 13 additions and 8 deletions
|
@ -94,6 +94,7 @@ module square(size=1, center, anchor, spin) {
|
||||||
// ---
|
// ---
|
||||||
// rounding = The rounding radius for the corners. If negative, produces external roundover spikes on the X axis. If given as a list of four numbers, gives individual radii for each corner, in the order [X+Y+,X-Y+,X-Y-,X+Y-]. Default: 0 (no rounding)
|
// rounding = The rounding radius for the corners. If negative, produces external roundover spikes on the X axis. If given as a list of four numbers, gives individual radii for each corner, in the order [X+Y+,X-Y+,X-Y-,X+Y-]. Default: 0 (no rounding)
|
||||||
// chamfer = The chamfer size for the corners. If negative, produces external chamfer spikes on the X axis. If given as a list of four numbers, gives individual chamfers for each corner, in the order [X+Y+,X-Y+,X-Y-,X+Y-]. Default: 0 (no chamfer)
|
// chamfer = The chamfer size for the corners. If negative, produces external chamfer spikes on the X axis. If given as a list of four numbers, gives individual chamfers for each corner, in the order [X+Y+,X-Y+,X-Y-,X+Y-]. Default: 0 (no chamfer)
|
||||||
|
// corner_flip = Flips the direction of the rouding curve or roudover and chamfer spikes. If true it produces spikes on the Y axis. If false it produces spikes on the X axis. If given as a list of four booleans it flips the direction for each corner, in the order [X+Y+,X-Y+,X-Y-,X+Y-]. Default: false (no flip)
|
||||||
// atype = The type of anchoring to use with `anchor=`. Valid opptions are "box" and "perim". This lets you choose between putting anchors on the rounded or chamfered perimeter, or on the square bounding box of the shape. Default: "box"
|
// atype = The type of anchoring to use with `anchor=`. Valid opptions are "box" and "perim". This lets you choose between putting anchors on the rounded or chamfered perimeter, or on the square bounding box of the shape. Default: "box"
|
||||||
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
|
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
|
||||||
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
|
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
|
||||||
|
@ -114,6 +115,8 @@ module square(size=1, center, anchor, spin) {
|
||||||
// rect([40,30], chamfer=-5);
|
// rect([40,30], chamfer=-5);
|
||||||
// Example(2D): Negative-Rounded Rect
|
// Example(2D): Negative-Rounded Rect
|
||||||
// rect([40,30], rounding=-5);
|
// rect([40,30], rounding=-5);
|
||||||
|
// Example(2D): Combined Rounded-Chamfered Rect with corner flips
|
||||||
|
// rect(chamfer = 0.25*[0,1,-1,0], rounding=.25*[1,0,0,-1], corner_flip = true);
|
||||||
// Example(2D): Default "box" Anchors
|
// Example(2D): Default "box" Anchors
|
||||||
// color("red") rect([40,30]);
|
// color("red") rect([40,30]);
|
||||||
// rect([40,30], rounding=10)
|
// rect([40,30], rounding=10)
|
||||||
|
@ -130,7 +133,7 @@ module square(size=1, center, anchor, spin) {
|
||||||
// path = rect([40,30], chamfer=5, anchor=FRONT, spin=30);
|
// path = rect([40,30], chamfer=5, anchor=FRONT, spin=30);
|
||||||
// stroke(path, closed=true);
|
// stroke(path, closed=true);
|
||||||
// move_copies(path) color("blue") circle(d=2,$fn=8);
|
// move_copies(path) color("blue") circle(d=2,$fn=8);
|
||||||
module rect(size=1, rounding=0, atype="box", chamfer=0, anchor=CENTER, spin=0) {
|
module rect(size=1, rounding=0, atype="box", chamfer=0, anchor=CENTER, spin=0, corner_flip = false) {
|
||||||
errchk = assert(in_list(atype, ["box", "perim"]));
|
errchk = assert(in_list(atype, ["box", "perim"]));
|
||||||
size = [for (c = force_list(size,2)) max(0,c)];
|
size = [for (c = force_list(size,2)) max(0,c)];
|
||||||
if (!all_positive(size)) {
|
if (!all_positive(size)) {
|
||||||
|
@ -144,7 +147,7 @@ module rect(size=1, rounding=0, atype="box", chamfer=0, anchor=CENTER, spin=0) {
|
||||||
children();
|
children();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
pts_over = rect(size=size, rounding=rounding, chamfer=chamfer, atype=atype, _return_override=true);
|
pts_over = rect(size=size, rounding=rounding, chamfer=chamfer, atype=atype, corner_flip = corner_flip, _return_override=true);
|
||||||
pts = pts_over[0];
|
pts = pts_over[0];
|
||||||
override = pts_over[1];
|
override = pts_over[1];
|
||||||
attachable(anchor, spin, two_d=true, size=size,override=override) {
|
attachable(anchor, spin, two_d=true, size=size,override=override) {
|
||||||
|
@ -156,7 +159,7 @@ module rect(size=1, rounding=0, atype="box", chamfer=0, anchor=CENTER, spin=0) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function rect(size=1, rounding=0, chamfer=0, atype="box", anchor=CENTER, spin=0, _return_override) =
|
function rect(size=1, rounding=0, chamfer=0, atype="box", anchor=CENTER, spin=0, _return_override, corner_flip = false) =
|
||||||
assert(is_num(size) || is_vector(size,2))
|
assert(is_num(size) || is_vector(size,2))
|
||||||
assert(is_num(chamfer) || is_vector(chamfer,4))
|
assert(is_num(chamfer) || is_vector(chamfer,4))
|
||||||
assert(is_num(rounding) || is_vector(rounding,4))
|
assert(is_num(rounding) || is_vector(rounding,4))
|
||||||
|
@ -164,6 +167,7 @@ function rect(size=1, rounding=0, chamfer=0, atype="box", anchor=CENTER, spin=0,
|
||||||
let(
|
let(
|
||||||
anchor=_force_anchor_2d(anchor),
|
anchor=_force_anchor_2d(anchor),
|
||||||
size = [for (c = force_list(size,2)) max(0,c)],
|
size = [for (c = force_list(size,2)) max(0,c)],
|
||||||
|
corner_flip = [for (c = force_list(corner_flip,4)) c ? true : false],
|
||||||
chamfer = force_list(chamfer,4),
|
chamfer = force_list(chamfer,4),
|
||||||
rounding = force_list(rounding,4)
|
rounding = force_list(rounding,4)
|
||||||
)
|
)
|
||||||
|
@ -201,23 +205,24 @@ function rect(size=1, rounding=0, chamfer=0, atype="box", anchor=CENTER, spin=0,
|
||||||
qround = rounding[quad],
|
qround = rounding[quad],
|
||||||
cverts = quant(segs(abs(qinset)),4)/4,
|
cverts = quant(segs(abs(qinset)),4)/4,
|
||||||
step = 90/cverts,
|
step = 90/cverts,
|
||||||
cp = v_mul(size/2-[qinset,abs(qinset)], qpos),
|
cp = v_mul(size/2 + (corner_flip[quad] ? (qinset > 0 ? 0 : 1) : -1)*[qinset,abs(qinset)], qpos),
|
||||||
qpts = abs(qchamf) >= eps? [[0,abs(qinset)], [qinset,0]] :
|
qpts = abs(qchamf) >= eps? [[0,abs(qinset)], [qinset,0]] :
|
||||||
abs(qround) >= eps? [for (j=[0:1:cverts]) let(a=90-j*step) v_mul(polar_to_xy(abs(qinset),a),[sign(qinset),1])] :
|
abs(qround) >= eps? [for (j=[0:1:cverts]) let(a=90-j*step) v_mul(polar_to_xy(abs(qinset),a),[sign(qinset),1])] :
|
||||||
[[0,0]],
|
[[0,0]],
|
||||||
qfpts = [for (p=qpts) v_mul(p,qpos)],
|
qfpts = [for (p=qpts) v_mul(p,corner_flip[quad] ? -qpos : qpos)],
|
||||||
qrpts = qpos.x*qpos.y < 0? reverse(qfpts) : qfpts,
|
qrpts = (corner_flip[quad] && qinset > 0 ? -1 : 1) * qpos.x*qpos.y < 0? reverse(qfpts) : qfpts,
|
||||||
cornerpt = atype=="box" || (qround==0 && qchamf==0) ? undef
|
cornerpt = atype=="box" || (qround==0 && qchamf==0) ? undef
|
||||||
: qround<0 || qchamf<0 ? [[0,-qpos.y*min(qround,qchamf)]]
|
: qround<0 || qchamf<0 ? [[0,-qpos.y*min(qround,qchamf)]]
|
||||||
: [for(seg=pair(qrpts)) let(isect=line_intersection(seg, [[0,0],qpos],SEGMENT,LINE)) if (is_def(isect) && isect!=seg[0]) isect]
|
: [for(seg=pair(qrpts)) let(isect=line_intersection(seg, [[0,0],qpos],SEGMENT,LINE)) if (is_def(isect) && isect!=seg[0]) isect]
|
||||||
)
|
)
|
||||||
assert(is_undef(cornerpt) || len(cornerpt)==1,"Cannot find corner point to anchor")
|
assert(is_undef(cornerpt) || len(cornerpt)==1,"Cannot find corner point to anchor")
|
||||||
[move(cp, p=qrpts), is_undef(cornerpt)? undef : move(cp,p=cornerpt[0])]
|
[move(cp, p=qrpts), is_undef(cornerpt)? undef : move(cp,p=
|
||||||
|
(min(chamfer[quad],rounding[quad])<0 && corner_flip[quad] ? [quadpos[quad].x*quadpos[quad].y*cornerpt[0].y, cornerpt[0].x] : cornerpt[0]))]
|
||||||
],
|
],
|
||||||
path = deduplicate(flatten(column(corners,0)),closed=true),
|
path = deduplicate(flatten(column(corners,0)),closed=true),
|
||||||
override = [for(i=[0:3])
|
override = [for(i=[0:3])
|
||||||
let(quad=quadorder[i])
|
let(quad=quadorder[i])
|
||||||
if (is_def(corners[i][1])) [quadpos[quad], [corners[i][1], min(chamfer[quad],rounding[quad])<0 ? [quadpos[quad].x,0] : undef]]]
|
if (is_def(corners[i][1])) [quadpos[quad], [corners[i][1], min(chamfer[quad],rounding[quad])<0 ? (corner_flip[quad] ? [0, quadpos[quad].y] : [quadpos[quad].x, 0]) : undef]]]
|
||||||
) _return_override ? [reorient(anchor,spin, two_d=true, size=size, p=path, override=override), override]
|
) _return_override ? [reorient(anchor,spin, two_d=true, size=size, p=path, override=override), override]
|
||||||
: reorient(anchor,spin, two_d=true, size=size, p=path, override=override);
|
: reorient(anchor,spin, two_d=true, size=size, p=path, override=override);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue