mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2025-01-06 04:09:47 +00:00
Merge branch 'master' into master
This commit is contained in:
commit
e9fe501652
4 changed files with 342 additions and 102 deletions
225
attachments.scad
225
attachments.scad
|
@ -1731,33 +1731,48 @@ module face_profile(faces=[], r, d, excess=0.01, convexity=10) {
|
||||||
module edge_profile(edges=EDGES_ALL, except=[], excess=0.01, convexity=10) {
|
module edge_profile(edges=EDGES_ALL, except=[], excess=0.01, convexity=10) {
|
||||||
req_children($children);
|
req_children($children);
|
||||||
check1 = assert($parent_geom != undef, "No object to attach to!");
|
check1 = assert($parent_geom != undef, "No object to attach to!");
|
||||||
edges = _edges(edges, except=except);
|
conoid = $parent_geom[0] == "conoid";
|
||||||
vecs = [
|
edges = !conoid? _edges(edges, except=except) :
|
||||||
for (i = [0:3], axis=[0:2])
|
edges==EDGES_ALL? [TOP,BOT] :
|
||||||
if (edges[axis][i]>0)
|
assert(all([for (e=edges) in_list(e,[TOP,BOT])]), "Invalid conoid edge spec.")
|
||||||
EDGE_OFFSETS[axis][i]
|
edges;
|
||||||
];
|
vecs = conoid
|
||||||
|
? [for (e=edges) e+FWD]
|
||||||
|
: [
|
||||||
|
for (i = [0:3], axis=[0:2])
|
||||||
|
if (edges[axis][i]>0)
|
||||||
|
EDGE_OFFSETS[axis][i]
|
||||||
|
];
|
||||||
all_vecs_are_edges = all([for (vec = vecs) sum(v_abs(vec))==2]);
|
all_vecs_are_edges = all([for (vec = vecs) sum(v_abs(vec))==2]);
|
||||||
check2 = assert(all_vecs_are_edges, "All vectors must be edges.");
|
check2 = assert(all_vecs_are_edges, "All vectors must be edges.");
|
||||||
|
default_tag("remove")
|
||||||
for ($idx = idx(vecs)) {
|
for ($idx = idx(vecs)) {
|
||||||
vec = vecs[$idx];
|
vec = vecs[$idx];
|
||||||
anch = _find_anchor(vec, $parent_geom);
|
anch = _find_anchor(vec, $parent_geom);
|
||||||
|
path_angs_T = _attach_geom_edge_path($parent_geom, vec);
|
||||||
|
path = path_angs_T[0];
|
||||||
|
vecs = path_angs_T[1];
|
||||||
|
post_T = path_angs_T[2];
|
||||||
$attach_to = undef;
|
$attach_to = undef;
|
||||||
$attach_anchor = anch;
|
$attach_anchor = anch;
|
||||||
$attach_norot = true;
|
$attach_norot = true;
|
||||||
$profile_type = "edge";
|
$profile_type = "edge";
|
||||||
psize = point3d($parent_size);
|
multmatrix(post_T) {
|
||||||
length = [for (i=[0:2]) if(!vec[i]) psize[i]][0] + excess;
|
for (i = idx(path,e=-2)) {
|
||||||
rotang =
|
pt1 = select(path,i);
|
||||||
vec.z<0? [90,0,180+v_theta(vec)] :
|
pt2 = select(path,i+1);
|
||||||
vec.z==0 && sign(vec.x)==sign(vec.y)? 135+v_theta(vec) :
|
cp = (pt1 + pt2) / 2;
|
||||||
vec.z==0 && sign(vec.x)!=sign(vec.y)? [0,180,45+v_theta(vec)] :
|
v1 = vecs[i][0];
|
||||||
[-90,0,180+v_theta(vec)];
|
v2 = vecs[i][1];
|
||||||
translate(anch[1]) {
|
$edge_angle = 180 - vector_angle(v1,v2);
|
||||||
rot(rotang) {
|
if (!approx(pt1,pt2)) {
|
||||||
linear_extrude(height=length, center=true, convexity=convexity) {
|
seglen = norm(pt2-pt1) + 2 * excess;
|
||||||
if ($tag=="") tag("remove") children();
|
move(cp) {
|
||||||
else children();
|
frame_map(y=-v1, z=unit(pt2-pt1)) {
|
||||||
|
linear_extrude(height=seglen, center=true, convexity=convexity)
|
||||||
|
children();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1787,6 +1802,7 @@ module edge_profile(edges=EDGES_ALL, except=[], excess=0.01, convexity=10) {
|
||||||
// convexity = Max number of times a line could intersect the perimeter of the mask shape. Default: 10
|
// convexity = Max number of times a line could intersect the perimeter of the mask shape. Default: 10
|
||||||
// flip = If true, reverses the orientation of any external profile parts at each edge. Default false
|
// flip = If true, reverses the orientation of any external profile parts at each edge. Default false
|
||||||
// corner_type = Specifies how exterior corners should be formed. Must be one of `"none"`, `"chamfer"`, `"round"`, or `"sharp"`. Default: `"none"`
|
// corner_type = Specifies how exterior corners should be formed. Must be one of `"none"`, `"chamfer"`, `"round"`, or `"sharp"`. Default: `"none"`
|
||||||
|
// size = If given the width and height of the 2D profile, will enable rounding and chamfering of internal corners when given a negative profile.
|
||||||
// Side Effects:
|
// Side Effects:
|
||||||
// Tags the children with "remove" (and hence sets `$tag`) if no tag is already set.
|
// Tags the children with "remove" (and hence sets `$tag`) if no tag is already set.
|
||||||
// `$idx` is set to the index number of each edge.
|
// `$idx` is set to the index number of each edge.
|
||||||
|
@ -1837,17 +1853,43 @@ module edge_profile(edges=EDGES_ALL, except=[], excess=0.01, convexity=10) {
|
||||||
// Example: More complicated edge sets
|
// Example: More complicated edge sets
|
||||||
// cuboid(50) {
|
// cuboid(50) {
|
||||||
// edge_profile_asym(
|
// edge_profile_asym(
|
||||||
// "ALL", except=[TOP+FWD+RIGHT, BOT+BACK+LEFT],
|
// [FWD,BACK,BOT+RIGHT], except=[FWD+RIGHT,BOT+BACK],
|
||||||
// corner_type="chamfer"
|
// corner_type="round"
|
||||||
|
// ) xflip() mask2d_roundover(10);
|
||||||
|
// }
|
||||||
|
// Example: Mixing it up a bit.
|
||||||
|
// diff()
|
||||||
|
// cuboid(60) {
|
||||||
|
// tag("keep") edge_profile_asym(LEFT, flip=true, corner_type="chamfer")
|
||||||
|
// xflip() mask2d_chamfer(10);
|
||||||
|
// edge_profile_asym(RIGHT)
|
||||||
|
// mask2d_roundover(10);
|
||||||
|
// }
|
||||||
|
// Example: Chamfering internal corners.
|
||||||
|
// cuboid(40) {
|
||||||
|
// edge_profile_asym(
|
||||||
|
// [FWD+DOWN,FWD+LEFT],
|
||||||
|
// corner_type="chamfer", size=[7,10]
|
||||||
|
// ) xflip() mask2d_chamfer(10);
|
||||||
|
// }
|
||||||
|
// Example: Rounding internal corners.
|
||||||
|
// cuboid(40) {
|
||||||
|
// edge_profile_asym(
|
||||||
|
// [FWD+DOWN,FWD+LEFT],
|
||||||
|
// corner_type="round", size=[10,10]
|
||||||
// ) xflip() mask2d_roundover(10);
|
// ) xflip() mask2d_roundover(10);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
module edge_profile_asym(edges=EDGES_ALL, except=[], excess=0.01, convexity=10, flip=false, corner_type="none") {
|
module edge_profile_asym(
|
||||||
|
edges=EDGES_ALL, except=[],
|
||||||
|
excess=0.01, convexity=10,
|
||||||
|
flip=false, corner_type="none",
|
||||||
|
size=[0,0]
|
||||||
|
) {
|
||||||
function _corner_orientation(pos,pvec) =
|
function _corner_orientation(pos,pvec) =
|
||||||
let(
|
let(
|
||||||
j = [for (i=[0:2]) if (pvec[i]) i][0],
|
j = [for (i=[0:2]) if (pvec[i]) i][0],
|
||||||
T =
|
T = (pos.x>0? xflip() : ident(4)) *
|
||||||
(pos.x>0? xflip() : ident(4)) *
|
|
||||||
(pos.y>0? yflip() : ident(4)) *
|
(pos.y>0? yflip() : ident(4)) *
|
||||||
(pos.z>0? zflip() : ident(4)) *
|
(pos.z>0? zflip() : ident(4)) *
|
||||||
rot(-120*(2-j), v=[1,1,1])
|
rot(-120*(2-j), v=[1,1,1])
|
||||||
|
@ -1989,6 +2031,7 @@ module edge_profile_asym(edges=EDGES_ALL, except=[], excess=0.01, convexity=10,
|
||||||
check2 = assert(all_vecs_are_edges, "All vectors must be edges.");
|
check2 = assert(all_vecs_are_edges, "All vectors must be edges.");
|
||||||
edge_corners = [for (vec = vecs) [vec, _edge_corner_numbers(vec)]];
|
edge_corners = [for (vec = vecs) [vec, _edge_corner_numbers(vec)]];
|
||||||
edge_strings = _gather_contiguous_edges(edge_corners);
|
edge_strings = _gather_contiguous_edges(edge_corners);
|
||||||
|
default_tag("remove")
|
||||||
for (edge_string = edge_strings) {
|
for (edge_string = edge_strings) {
|
||||||
inverts = _edge_transition_inversions(edge_string);
|
inverts = _edge_transition_inversions(edge_string);
|
||||||
flipverts = [for (x = inverts) flip? !x : x];
|
flipverts = [for (x = inverts) flip? !x : x];
|
||||||
|
@ -2006,11 +2049,37 @@ module edge_profile_asym(edges=EDGES_ALL, except=[], excess=0.01, convexity=10,
|
||||||
vp2 = select(vecpairs,i);
|
vp2 = select(vecpairs,i);
|
||||||
pvec = _edge_pair_perp_vec(e1,e2);
|
pvec = _edge_pair_perp_vec(e1,e2);
|
||||||
pos = [for (i=[0:2]) e1[i]? e1[i] : e2[i]];
|
pos = [for (i=[0:2]) e1[i]? e1[i] : e2[i]];
|
||||||
if (vp1.y == vp2.y) {
|
mirT = _corner_orientation(pos, pvec);
|
||||||
default_tag("remove")
|
$attach_to = undef;
|
||||||
position(pos) {
|
$attach_anchor = _find_anchor(pos, $parent_geom);
|
||||||
mirT = _corner_orientation(pos, pvec);
|
$attach_norot = true;
|
||||||
multmatrix(mirT) {
|
$profile_type = "corner";
|
||||||
|
position(pos) {
|
||||||
|
multmatrix(mirT) {
|
||||||
|
if (vp1.x == vp2.x && size.y > 0) {
|
||||||
|
zflip() {
|
||||||
|
if (corner_type=="chamfer") {
|
||||||
|
fn = $fn;
|
||||||
|
move([size.y,size.y]) {
|
||||||
|
rotate_extrude(angle=90, $fn=4)
|
||||||
|
left_half(planar=true, $fn=fn)
|
||||||
|
zrot(-90) fwd(size.y) children();
|
||||||
|
}
|
||||||
|
linear_extrude(height=size.x) {
|
||||||
|
mask2d_roundover(size.y, inset=0.01, $fn=4);
|
||||||
|
}
|
||||||
|
} else if (corner_type=="round") {
|
||||||
|
move([size.y,size.y]) {
|
||||||
|
rotate_extrude(angle=90)
|
||||||
|
left_half(planar=true)
|
||||||
|
zrot(-90) fwd(size.y) children();
|
||||||
|
}
|
||||||
|
linear_extrude(height=size.x) {
|
||||||
|
mask2d_roundover(size.y, inset=0.01);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (vp1.y == vp2.y) {
|
||||||
if (corner_type=="chamfer") {
|
if (corner_type=="chamfer") {
|
||||||
fn = $fn;
|
fn = $fn;
|
||||||
rotate_extrude(angle=90, $fn=4)
|
rotate_extrude(angle=90, $fn=4)
|
||||||
|
@ -2038,6 +2107,10 @@ module edge_profile_asym(edges=EDGES_ALL, except=[], excess=0.01, convexity=10,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (i = idx(edge_string)) {
|
for (i = idx(edge_string)) {
|
||||||
|
$attach_to = undef;
|
||||||
|
$attach_anchor = _find_anchor(edge_string[i], $parent_geom);
|
||||||
|
$attach_norot = true;
|
||||||
|
$profile_type = "edge";
|
||||||
edge_profile(edge_string[i], excess=excess, convexity=convexity) {
|
edge_profile(edge_string[i], excess=excess, convexity=convexity) {
|
||||||
if (flipverts[i]) {
|
if (flipverts[i]) {
|
||||||
mirror([-1,1]) children();
|
mirror([-1,1]) children();
|
||||||
|
@ -2050,6 +2123,7 @@ module edge_profile_asym(edges=EDGES_ALL, except=[], excess=0.01, convexity=10,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Module: corner_profile()
|
// Module: corner_profile()
|
||||||
// Synopsis: Rotationally extrudes a 2d edge profile into corner mask on the given corners of the parent.
|
// Synopsis: Rotationally extrudes a 2d edge profile into corner mask on the given corners of the parent.
|
||||||
// SynTags: Geom
|
// SynTags: Geom
|
||||||
|
@ -2886,6 +2960,101 @@ function _attach_geom_size(geom) =
|
||||||
assert(false, "Unknown attachment geometry type.");
|
assert(false, "Unknown attachment geometry type.");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// Internal Function: _attach_geom_edge_path()
|
||||||
|
/// Usage:
|
||||||
|
/// angle = _attach_geom_edge_path(geom, edge);
|
||||||
|
/// Topics: Attachments
|
||||||
|
/// See Also: reorient(), attachable()
|
||||||
|
/// Description:
|
||||||
|
/// Returns the path and post-transform matrix of the indicated edge.
|
||||||
|
/// If the edge is invalid for the geometry, returns `undef`.
|
||||||
|
function _attach_geom_edge_path(geom, edge) =
|
||||||
|
assert(is_vector(edge),str("Invalid edge: edge=",edge))
|
||||||
|
let(
|
||||||
|
type = geom[0],
|
||||||
|
cp = _get_cp(geom),
|
||||||
|
offset_raw = select(geom,-2),
|
||||||
|
offset = [for (i=[0:2]) edge[i]==0? 0 : offset_raw[i]], // prevents bad centering.
|
||||||
|
edge = point3d(edge)
|
||||||
|
)
|
||||||
|
type == "prismoid"? ( //size, size2, shift, axis
|
||||||
|
let(all_comps_good = [for (c=edge) if (c!=sign(c)) 1]==[])
|
||||||
|
assert(all_comps_good, "All components of an edge for a cuboid/prismoid must be -1, 0, or 1")
|
||||||
|
let(edge_good = len([for (c=edge) if(c) 1])==2)
|
||||||
|
assert(edge_good, "Invalid edge.")
|
||||||
|
let(
|
||||||
|
size = geom[1],
|
||||||
|
size2 = geom[2],
|
||||||
|
shift = point2d(geom[3]),
|
||||||
|
axis = point3d(geom[4]),
|
||||||
|
edge = rot(from=axis, to=UP, p=edge),
|
||||||
|
offset = rot(from=axis, to=UP, p=offset),
|
||||||
|
h = size.z,
|
||||||
|
cpos = function(vec) let(
|
||||||
|
u = (vec.z + 1) / 2,
|
||||||
|
siz = lerp(point2d(size), size2, u) / 2,
|
||||||
|
z = vec.z * h / 2,
|
||||||
|
pos = point3d(v_mul(siz, point2d(vec)) + shift * u, z)
|
||||||
|
) pos,
|
||||||
|
ep1 = cpos([for (c=edge) c? c : -1]),
|
||||||
|
ep2 = cpos([for (c=edge) c? c : 1]),
|
||||||
|
cp = (ep1 + ep2) / 2,
|
||||||
|
axy = point2d(edge),
|
||||||
|
bot = point3d(v_mul(point2d(size )/2, axy), -h/2),
|
||||||
|
top = point3d(v_mul(point2d(size2)/2, axy) + shift, h/2),
|
||||||
|
xang = atan2(h,(top-bot).x),
|
||||||
|
yang = atan2(h,(top-bot).y),
|
||||||
|
vecs = [
|
||||||
|
if (edge.x) yrot(90-xang, p=sign(axy.x)*RIGHT),
|
||||||
|
if (edge.y) xrot(yang-90, p=sign(axy.y)*BACK),
|
||||||
|
if (edge.z) [0,0,sign(edge.z)]
|
||||||
|
],
|
||||||
|
segvec = cross(unit(vecs[1]), unit(vecs[0])),
|
||||||
|
seglen = norm(ep2 - ep1),
|
||||||
|
path = [
|
||||||
|
cp - segvec * seglen/2,
|
||||||
|
cp + segvec * seglen/2
|
||||||
|
],
|
||||||
|
m = rot(from=UP,to=axis) * move(offset)
|
||||||
|
) [path, [vecs], m]
|
||||||
|
) : type == "conoid"? ( //r1, r2, l, shift, axis
|
||||||
|
assert(edge.z && edge.z == sign(edge.z), "The Z component of an edge for a cylinder/cone must be -1 or 1")
|
||||||
|
let(
|
||||||
|
rr1 = geom[1],
|
||||||
|
rr2 = geom[2],
|
||||||
|
l = geom[3],
|
||||||
|
shift = point2d(geom[4]),
|
||||||
|
axis = point3d(geom[5]),
|
||||||
|
r1 = is_num(rr1)? [rr1,rr1] : point2d(rr1),
|
||||||
|
r2 = is_num(rr2)? [rr2,rr2] : point2d(rr2),
|
||||||
|
edge = rot(from=axis, to=UP, p=edge),
|
||||||
|
offset = rot(from=axis, to=UP, p=offset),
|
||||||
|
maxr = max([each r1, each r2]),
|
||||||
|
sides = segs(maxr),
|
||||||
|
top = path3d(move(shift, p=ellipse(r=r2, $fn=sides)), l/2),
|
||||||
|
bot = path3d(ellipse(r=r1, $fn=sides), -l/2),
|
||||||
|
path = edge.z < 0 ? bot : top,
|
||||||
|
path2 = edge.z < 0 ? top : bot,
|
||||||
|
zed = edge.z<0? [0,0,-l/2] : point3d(shift,l/2),
|
||||||
|
vecs = [
|
||||||
|
for (i = idx(top)) let(
|
||||||
|
pt1 = (path[i] + select(path,i+1)) /2,
|
||||||
|
pt2 = (path2[i] + select(path2,i+1)) /2,
|
||||||
|
v1 = unit(zed - pt1),
|
||||||
|
v2 = unit(pt2 - pt1),
|
||||||
|
v3 = unit(cross(v1,v2)),
|
||||||
|
v4 = cross(v3,v2),
|
||||||
|
v5 = cross(v1,v3)
|
||||||
|
) [v4, v5]
|
||||||
|
],
|
||||||
|
m = rot(from=UP,to=axis) * move(offset)
|
||||||
|
) edge.z>0
|
||||||
|
? [reverse(list_wrap(path)), reverse(vecs), m]
|
||||||
|
: [list_wrap(path), vecs, m]
|
||||||
|
) : undef;
|
||||||
|
|
||||||
|
|
||||||
/// Internal Function: _attach_transform()
|
/// Internal Function: _attach_transform()
|
||||||
/// Usage: To Get a Transformation Matrix
|
/// Usage: To Get a Transformation Matrix
|
||||||
/// mat = _attach_transform(anchor, spin, orient, geom);
|
/// mat = _attach_transform(anchor, spin, orient, geom);
|
||||||
|
|
23
gears.scad
23
gears.scad
|
@ -284,6 +284,29 @@ module spur_gear(
|
||||||
// spur_gear2d(pitch=5, teeth=20, pressure_angle=20);
|
// spur_gear2d(pitch=5, teeth=20, pressure_angle=20);
|
||||||
// Example(2D): Partial Gear
|
// Example(2D): Partial Gear
|
||||||
// spur_gear2d(pitch=5, teeth=20, hide=15, pressure_angle=20);
|
// spur_gear2d(pitch=5, teeth=20, hide=15, pressure_angle=20);
|
||||||
|
// Example(2D): Planetary Gear Assembly
|
||||||
|
// rteeth=56; pteeth=16; cteeth=24;
|
||||||
|
// pitch=5; pa=20;
|
||||||
|
// prad = (pitch_radius(pitch,rteeth) +
|
||||||
|
// pitch_radius(pitch,cteeth)) / 2;
|
||||||
|
// rrad = outer_radius(pitch,rteeth,interior=true) + 5;
|
||||||
|
// difference() {
|
||||||
|
// circle(r=rrad);
|
||||||
|
// spur_gear2d(
|
||||||
|
// pitch=pitch, teeth=rteeth,
|
||||||
|
// pressure_angle=pa, interior=true);
|
||||||
|
// }
|
||||||
|
// for (a=[0:3]) {
|
||||||
|
// zrot(a*90) back(prad) {
|
||||||
|
// color("green")
|
||||||
|
// spur_gear2d(
|
||||||
|
// pitch=pitch, teeth=pteeth,
|
||||||
|
// pressure_angle=pa);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// color("orange")
|
||||||
|
// zrot(180/cteeth)
|
||||||
|
// spur_gear2d(pitch=pitch, teeth=cteeth, pressure_angle=pa);
|
||||||
// Example(2D): Called as a Function
|
// Example(2D): Called as a Function
|
||||||
// path = spur_gear2d(pitch=8, teeth=16);
|
// path = spur_gear2d(pitch=8, teeth=16);
|
||||||
// polygon(path);
|
// polygon(path);
|
||||||
|
|
156
masks2d.scad
156
masks2d.scad
|
@ -15,22 +15,23 @@
|
||||||
// Section: 2D Masking Shapes
|
// Section: 2D Masking Shapes
|
||||||
|
|
||||||
// Function&Module: mask2d_roundover()
|
// Function&Module: mask2d_roundover()
|
||||||
// Synopsis: Creates a 2D beading mask shape useful for rounding 90° edges.
|
// Synopsis: Creates a 2D beading mask shape useful for rounding edges.
|
||||||
// SynTags: Geom, Path
|
// SynTags: Geom, Path
|
||||||
// Topics: Shapes (2D), Paths (2D), Path Generators, Attachable, Masks (2D)
|
// Topics: Shapes (2D), Paths (2D), Path Generators, Attachable, Masks (2D)
|
||||||
// See Also: corner_profile(), edge_profile(), face_profile(), fillet()
|
// See Also: corner_profile(), edge_profile(), face_profile(), fillet()
|
||||||
// Usage: As module
|
// Usage: As module
|
||||||
// mask2d_roundover(r|d=, [inset], [excess]) [ATTACHMENTS];
|
// mask2d_roundover(r|d=, [inset], [mask_angle], [excess]) [ATTACHMENTS];
|
||||||
// Usage: As function
|
// Usage: As function
|
||||||
// path = mask2d_roundover(r|d=, [inset], [excess]);
|
// path = mask2d_roundover(r|d=, [inset], [mask_angle], [excess]);
|
||||||
// Description:
|
// Description:
|
||||||
// Creates a 2D roundover/bead mask shape that is useful for extruding into a 3D mask for a 90° edge.
|
// Creates a 2D roundover/bead mask shape that is useful for extruding into a 3D mask for an edge.
|
||||||
// Conversely, you can use that same extruded shape to make an interior fillet between two walls at a 90º angle.
|
// Conversely, you can use that same extruded shape to make an interior fillet between two walls.
|
||||||
// As a 2D mask, this is designed to be differenced away from the edge of a shape that is in the first (X+Y+) quadrant.
|
// As a 2D mask, this is designed to be differenced away from the edge of a shape that is in the first (X+Y+) quadrant.
|
||||||
// If called as a function, this just returns a 2D path of the outline of the mask shape.
|
// If called as a function, this just returns a 2D path of the outline of the mask shape.
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// r = Radius of the roundover.
|
// r = Radius of the roundover.
|
||||||
// inset = Optional bead inset size. Default: 0
|
// inset = Optional bead inset size. Default: 0
|
||||||
|
// mask_angle = Number of degrees in the corner angle to mask. Default: 90
|
||||||
// excess = Extra amount of mask shape to creates on the X- and Y- sides of the shape. Default: 0.01
|
// excess = Extra amount of mask shape to creates on the X- and Y- sides of the shape. Default: 0.01
|
||||||
// ---
|
// ---
|
||||||
// d = Diameter of the roundover.
|
// d = Diameter of the roundover.
|
||||||
|
@ -40,6 +41,10 @@
|
||||||
// mask2d_roundover(r=10);
|
// mask2d_roundover(r=10);
|
||||||
// Example(2D): 2D Bead Mask
|
// Example(2D): 2D Bead Mask
|
||||||
// mask2d_roundover(r=10,inset=2);
|
// mask2d_roundover(r=10,inset=2);
|
||||||
|
// Example(2D): 2D Bead Mask for a Non-Right Edge.
|
||||||
|
// mask2d_roundover(r=10, inset=2, mask_angle=75);
|
||||||
|
// Example(2D): Increasing the Excess
|
||||||
|
// mask2d_roundover(r=10, inset=2, mask_angle=75, excess=2);
|
||||||
// Example: Masking by Edge Attachment
|
// Example: Masking by Edge Attachment
|
||||||
// diff()
|
// diff()
|
||||||
// cube([50,60,70],center=true)
|
// cube([50,60,70],center=true)
|
||||||
|
@ -53,29 +58,36 @@
|
||||||
// xrot(90)
|
// xrot(90)
|
||||||
// linear_extrude(height=30, center=true)
|
// linear_extrude(height=30, center=true)
|
||||||
// mask2d_roundover(r=10);
|
// mask2d_roundover(r=10);
|
||||||
module mask2d_roundover(r, inset=0, excess=0.01, d, anchor=CENTER,spin=0) {
|
module mask2d_roundover(r, inset=0, mask_angle=90, excess=0.01, d, anchor=CENTER,spin=0) {
|
||||||
path = mask2d_roundover(r=r,d=d,excess=excess,inset=inset);
|
path = mask2d_roundover(r=r, d=d, inset=inset, mask_angle=mask_angle, excess=excess);
|
||||||
attachable(anchor,spin, two_d=true, path=path) {
|
attachable(anchor,spin, two_d=true, path=path) {
|
||||||
polygon(path);
|
polygon(path);
|
||||||
children();
|
children();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function mask2d_roundover(r, inset=0, excess=0.01, d, anchor=CENTER,spin=0) =
|
function mask2d_roundover(r, inset=0, mask_angle=90, excess=0.01, d, anchor=CENTER, spin=0) =
|
||||||
assert(is_finite(r)||is_finite(d))
|
assert(is_finite(r)||is_finite(d))
|
||||||
assert(is_finite(excess))
|
assert(is_finite(excess))
|
||||||
|
assert(is_finite(mask_angle) && mask_angle>0 && mask_angle<180)
|
||||||
assert(is_finite(inset)||(is_vector(inset)&&len(inset)==2))
|
assert(is_finite(inset)||(is_vector(inset)&&len(inset)==2))
|
||||||
let(
|
let(
|
||||||
inset = is_list(inset)? inset : [inset,inset],
|
inset = is_list(inset)? inset : [inset,inset],
|
||||||
r = get_radius(r=r,d=d,dflt=1),
|
r = get_radius(r=r,d=d,dflt=1),
|
||||||
steps = quantup(segs(r),4)/4,
|
avec = polar_to_xy(inset.x,mask_angle-90),
|
||||||
step = 90/steps,
|
line1 = [[0,inset.y], [100,inset.y]],
|
||||||
path = [
|
line2 = [avec, polar_to_xy(100,mask_angle)+avec],
|
||||||
[r+inset.x,-excess],
|
corner = line_intersection(line1,line2),
|
||||||
|
arcpts = arc(r=r, corner=[line2.y, corner, line1.y]),
|
||||||
|
ipath = [
|
||||||
|
arcpts[0] + polar_to_xy(inset.x+excess, mask_angle+90),
|
||||||
|
each arcpts,
|
||||||
|
last(arcpts) + polar_to_xy(inset.y+excess, -90),
|
||||||
|
[0,-excess],
|
||||||
[-excess,-excess],
|
[-excess,-excess],
|
||||||
[-excess, r+inset.y],
|
[-excess,0]
|
||||||
for (i=[0:1:steps]) [r,r] + inset + polar_to_xy(r,180+i*step)
|
],
|
||||||
]
|
path = deduplicate(ipath)
|
||||||
) reorient(anchor,spin, two_d=true, path=path, extent=false, p=path);
|
) reorient(anchor,spin, two_d=true, path=path, extent=false, p=path);
|
||||||
|
|
||||||
|
|
||||||
|
@ -85,17 +97,18 @@ function mask2d_roundover(r, inset=0, excess=0.01, d, anchor=CENTER,spin=0) =
|
||||||
// Topics: Shapes (2D), Paths (2D), Path Generators, Attachable, Masks (2D)
|
// Topics: Shapes (2D), Paths (2D), Path Generators, Attachable, Masks (2D)
|
||||||
// See Also: corner_profile(), edge_profile(), face_profile()
|
// See Also: corner_profile(), edge_profile(), face_profile()
|
||||||
// Usage: As module
|
// Usage: As module
|
||||||
// mask2d_cove(r|d=, [inset], [excess]) [ATTACHMENTS];
|
// mask2d_cove(r|d=, [inset], [mask_angle], [excess]) [ATTACHMENTS];
|
||||||
// Usage: As function
|
// Usage: As function
|
||||||
// path = mask2d_cove(r|d=, [inset], [excess]);
|
// path = mask2d_cove(r|d=, [inset], [mask_angle], [excess]);
|
||||||
// Description:
|
// Description:
|
||||||
// Creates a 2D cove mask shape that is useful for extruding into a 3D mask for a 90° edge.
|
// Creates a 2D cove mask shape that is useful for extruding into a 3D mask for an edge.
|
||||||
// Conversely, you can use that same extruded shape to make an interior rounded shelf decoration between two walls at a 90º angle.
|
// Conversely, you can use that same extruded shape to make an interior rounded shelf decoration between two walls.
|
||||||
// As a 2D mask, this is designed to be differenced away from the edge of a shape that is in the first (X+Y+) quadrant.
|
// As a 2D mask, this is designed to be differenced away from the edge of a shape that is in the first (X+Y+) quadrant.
|
||||||
// If called as a function, this just returns a 2D path of the outline of the mask shape.
|
// If called as a function, this just returns a 2D path of the outline of the mask shape.
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// r = Radius of the cove.
|
// r = Radius of the cove.
|
||||||
// inset = Optional amount to inset code from corner. Default: 0
|
// inset = Optional amount to inset code from corner. Default: 0
|
||||||
|
// mask_angle = Number of degrees in the corner angle to mask. Default: 90
|
||||||
// excess = Extra amount of mask shape to creates on the X- and Y- sides of the shape. Default: 0.01
|
// excess = Extra amount of mask shape to creates on the X- and Y- sides of the shape. Default: 0.01
|
||||||
// ---
|
// ---
|
||||||
// d = Diameter of the cove.
|
// d = Diameter of the cove.
|
||||||
|
@ -105,6 +118,10 @@ function mask2d_roundover(r, inset=0, excess=0.01, d, anchor=CENTER,spin=0) =
|
||||||
// mask2d_cove(r=10);
|
// mask2d_cove(r=10);
|
||||||
// Example(2D): 2D Inset Cove Mask
|
// Example(2D): 2D Inset Cove Mask
|
||||||
// mask2d_cove(r=10,inset=3);
|
// mask2d_cove(r=10,inset=3);
|
||||||
|
// Example(2D): 2D Inset Cove Mask for a Non-Right Edge
|
||||||
|
// mask2d_cove(r=10,inset=3,mask_angle=75);
|
||||||
|
// Example(2D): Increasing the Excess
|
||||||
|
// mask2d_cove(r=10,inset=3,mask_angle=75, excess=2);
|
||||||
// Example: Masking by Edge Attachment
|
// Example: Masking by Edge Attachment
|
||||||
// diff()
|
// diff()
|
||||||
// cube([50,60,70],center=true)
|
// cube([50,60,70],center=true)
|
||||||
|
@ -118,29 +135,36 @@ function mask2d_roundover(r, inset=0, excess=0.01, d, anchor=CENTER,spin=0) =
|
||||||
// xrot(90)
|
// xrot(90)
|
||||||
// linear_extrude(height=30, center=true)
|
// linear_extrude(height=30, center=true)
|
||||||
// mask2d_cove(r=5, inset=5);
|
// mask2d_cove(r=5, inset=5);
|
||||||
module mask2d_cove(r, inset=0, excess=0.01, d, anchor=CENTER,spin=0) {
|
module mask2d_cove(r, inset=0, mask_angle=90, excess=0.01, d, anchor=CENTER, spin=0) {
|
||||||
path = mask2d_cove(r=r,d=d,excess=excess,inset=inset);
|
path = mask2d_cove(r=r, d=d, inset=inset, mask_angle=mask_angle, excess=excess);
|
||||||
attachable(anchor,spin, two_d=true, path=path) {
|
attachable(anchor,spin, two_d=true, path=path) {
|
||||||
polygon(path);
|
polygon(path);
|
||||||
children();
|
children();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function mask2d_cove(r, inset=0, excess=0.01, d, anchor=CENTER,spin=0) =
|
function mask2d_cove(r, inset=0, mask_angle=90, excess=0.01, d, anchor=CENTER, spin=0) =
|
||||||
assert(is_finite(r)||is_finite(d))
|
assert(is_finite(r)||is_finite(d))
|
||||||
|
assert(is_finite(mask_angle) && mask_angle>0 && mask_angle<180)
|
||||||
assert(is_finite(excess))
|
assert(is_finite(excess))
|
||||||
assert(is_finite(inset)||(is_vector(inset)&&len(inset)==2))
|
assert(is_finite(inset)||(is_vector(inset)&&len(inset)==2))
|
||||||
let(
|
let(
|
||||||
inset = is_list(inset)? inset : [inset,inset],
|
inset = is_list(inset)? inset : [inset,inset],
|
||||||
r = get_radius(r=r,d=d,dflt=1),
|
r = get_radius(r=r,d=d,dflt=1),
|
||||||
steps = quantup(segs(r),4)/4,
|
avec = polar_to_xy(inset.x,mask_angle-90),
|
||||||
step = 90/steps,
|
line1 = [[0,inset.y], [100,inset.y]],
|
||||||
path = [
|
line2 = [avec, polar_to_xy(100,mask_angle)+avec],
|
||||||
[r+inset.x,-excess],
|
corner = line_intersection(line1,line2),
|
||||||
|
arcpts = arc(r=r, cp=corner, start=mask_angle, angle=-mask_angle),
|
||||||
|
ipath = [
|
||||||
|
arcpts[0] + polar_to_xy(inset.x+excess, mask_angle+90),
|
||||||
|
each arcpts,
|
||||||
|
last(arcpts) + polar_to_xy(inset.y+excess, -90),
|
||||||
|
[0,-excess],
|
||||||
[-excess,-excess],
|
[-excess,-excess],
|
||||||
[-excess, r+inset.y],
|
[-excess,0]
|
||||||
for (i=[0:1:steps]) inset + polar_to_xy(r,90-i*step)
|
],
|
||||||
]
|
path = deduplicate(ipath)
|
||||||
) reorient(anchor,spin, two_d=true, path=path, p=path);
|
) reorient(anchor,spin, two_d=true, path=path, p=path);
|
||||||
|
|
||||||
|
|
||||||
|
@ -230,16 +254,17 @@ function mask2d_chamfer(edge, angle=45, inset=0, excess=0.01, x, y, anchor=CENTE
|
||||||
// Topics: Shapes (2D), Paths (2D), Path Generators, Attachable, Masks (2D)
|
// Topics: Shapes (2D), Paths (2D), Path Generators, Attachable, Masks (2D)
|
||||||
// See Also: corner_profile(), edge_profile(), face_profile()
|
// See Also: corner_profile(), edge_profile(), face_profile()
|
||||||
// Usage: As Module
|
// Usage: As Module
|
||||||
// mask2d_rabbet(size, [excess]) [ATTACHMENTS];
|
// mask2d_rabbet(size, [mask_angle], [excess]) [ATTACHMENTS];
|
||||||
// Usage: As Function
|
// Usage: As Function
|
||||||
// path = mask2d_rabbet(size, [excess]);
|
// path = mask2d_rabbet(size, [mask_angle], [excess]);
|
||||||
// Description:
|
// Description:
|
||||||
// Creates a 2D rabbet mask shape that is useful for extruding into a 3D mask for a 90° edge.
|
// Creates a 2D rabbet mask shape that is useful for extruding into a 3D mask for an edge.
|
||||||
// Conversely, you can use that same extruded shape to make an interior shelf decoration between two walls at a 90º angle.
|
// Conversely, you can use that same extruded shape to make an interior shelf decoration between two walls.
|
||||||
// As a 2D mask, this is designed to be differenced away from the edge of a shape that is in the first (X+Y+) quadrant.
|
// As a 2D mask, this is designed to be differenced away from the edge of a shape that is in the first (X+Y+) quadrant.
|
||||||
// If called as a function, this just returns a 2D path of the outline of the mask shape.
|
// If called as a function, this just returns a 2D path of the outline of the mask shape.
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// size = The size of the rabbet, either as a scalar or an [X,Y] list.
|
// size = The size of the rabbet, either as a scalar or an [X,Y] list.
|
||||||
|
// mask_angle = Number of degrees in the corner angle to mask. Default: 90
|
||||||
// excess = Extra amount of mask shape to creates on the X- and Y- sides of the shape. Default: 0.01
|
// excess = Extra amount of mask shape to creates on the X- and Y- sides of the shape. Default: 0.01
|
||||||
// ---
|
// ---
|
||||||
// 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`
|
||||||
|
@ -248,6 +273,8 @@ function mask2d_chamfer(edge, angle=45, inset=0, excess=0.01, x, y, anchor=CENTE
|
||||||
// mask2d_rabbet(size=10);
|
// mask2d_rabbet(size=10);
|
||||||
// Example(2D): 2D Asymmetrical Rabbet Mask
|
// Example(2D): 2D Asymmetrical Rabbet Mask
|
||||||
// mask2d_rabbet(size=[5,10]);
|
// mask2d_rabbet(size=[5,10]);
|
||||||
|
// Example(2D): 2D Mask for a Non-Right Edge
|
||||||
|
// mask2d_rabbet(size=10,mask_angle=75);
|
||||||
// Example: Masking by Edge Attachment
|
// Example: Masking by Edge Attachment
|
||||||
// diff()
|
// diff()
|
||||||
// cube([50,60,70],center=true)
|
// cube([50,60,70],center=true)
|
||||||
|
@ -261,24 +288,31 @@ function mask2d_chamfer(edge, angle=45, inset=0, excess=0.01, x, y, anchor=CENTE
|
||||||
// xrot(90)
|
// xrot(90)
|
||||||
// linear_extrude(height=30, center=true)
|
// linear_extrude(height=30, center=true)
|
||||||
// mask2d_rabbet(size=[5,10]);
|
// mask2d_rabbet(size=[5,10]);
|
||||||
module mask2d_rabbet(size, excess=0.01, anchor=CENTER,spin=0) {
|
module mask2d_rabbet(size, mask_angle=90, excess=0.01, anchor=CTR, spin=0) {
|
||||||
path = mask2d_rabbet(size=size, excess=excess);
|
path = mask2d_rabbet(size=size, mask_angle=mask_angle, excess=excess);
|
||||||
attachable(anchor,spin, two_d=true, path=path, extent=false) {
|
attachable(anchor,spin, two_d=true, path=path, extent=false) {
|
||||||
polygon(path);
|
polygon(path);
|
||||||
children();
|
children();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function mask2d_rabbet(size, excess=0.01, anchor=CENTER,spin=0) =
|
function mask2d_rabbet(size, mask_angle=90, excess=0.01, anchor=CTR, spin=0) =
|
||||||
assert(is_finite(size)||(is_vector(size)&&len(size)==2))
|
assert(is_finite(size)||(is_vector(size)&&len(size)==2))
|
||||||
|
assert(is_finite(mask_angle) && mask_angle>0 && mask_angle<180)
|
||||||
assert(is_finite(excess))
|
assert(is_finite(excess))
|
||||||
let(
|
let(
|
||||||
size = is_list(size)? size : [size,size],
|
size = is_list(size)? size : [size,size],
|
||||||
|
avec = polar_to_xy(size.x,mask_angle-90),
|
||||||
|
line1 = [[0,size.y], [100,size.y]],
|
||||||
|
line2 = [avec, polar_to_xy(100,mask_angle)+avec],
|
||||||
|
cp = line_intersection(line1,line2),
|
||||||
path = [
|
path = [
|
||||||
[size.x, -excess],
|
cp + polar_to_xy(size.x+excess, mask_angle+90),
|
||||||
[-excess, -excess],
|
cp,
|
||||||
[-excess, size.y],
|
cp + polar_to_xy(size.y+excess, -90),
|
||||||
size
|
[0,-excess],
|
||||||
|
[-excess,-excess],
|
||||||
|
[-excess,0]
|
||||||
]
|
]
|
||||||
) reorient(anchor,spin, two_d=true, path=path, extent=false, p=path);
|
) reorient(anchor,spin, two_d=true, path=path, extent=false, p=path);
|
||||||
|
|
||||||
|
@ -368,18 +402,19 @@ function mask2d_dovetail(edge, angle=30, inset=0, shelf=0, excess=0.01, x, y, an
|
||||||
// Topics: Shapes (2D), Paths (2D), Path Generators, Attachable, Masks (2D), FDM Optimized
|
// Topics: Shapes (2D), Paths (2D), Path Generators, Attachable, Masks (2D), FDM Optimized
|
||||||
// See Also: corner_profile(), edge_profile(), face_profile()
|
// See Also: corner_profile(), edge_profile(), face_profile()
|
||||||
// Usage: As Module
|
// Usage: As Module
|
||||||
// mask2d_teardrop(r|d=, [angle], [excess]) [ATTACHMENTS];
|
// mask2d_teardrop(r|d=, [angle], [mask_angle], [excess]) [ATTACHMENTS];
|
||||||
// Usage: As Function
|
// Usage: As Function
|
||||||
// path = mask2d_teardrop(r|d=, [angle], [excess]);
|
// path = mask2d_teardrop(r|d=, [angle], [mask_angle], [excess]);
|
||||||
// Description:
|
// Description:
|
||||||
// Creates a 2D teardrop mask shape that is useful for extruding into a 3D mask for a 90° edge.
|
// Creates a 2D teardrop mask shape that is useful for extruding into a 3D mask for an edge.
|
||||||
// Conversely, you can use that same extruded shape to make an interior teardrop fillet between two walls at a 90º angle.
|
// Conversely, you can use that same extruded shape to make an interior teardrop fillet between two walls.
|
||||||
// As a 2D mask, this is designed to be differenced away from the edge of a shape that is in the first (X+Y+) quadrant.
|
// As a 2D mask, this is designed to be differenced away from the edge of a shape that is in the first (X+Y+) quadrant.
|
||||||
// If called as a function, this just returns a 2D path of the outline of the mask shape.
|
// If called as a function, this just returns a 2D path of the outline of the mask shape.
|
||||||
// This is particularly useful to make partially rounded bottoms, that don't need support to print.
|
// This is particularly useful to make partially rounded bottoms, that don't need support to print.
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// r = Radius of the rounding.
|
// r = Radius of the rounding.
|
||||||
// angle = The maximum angle from vertical.
|
// angle = The maximum angle from vertical.
|
||||||
|
// mask_angle = Number of degrees in the corner angle to mask. Default: 90
|
||||||
// excess = Extra amount of mask shape to creates on the X- and Y- sides of the shape. Default: 0.01
|
// excess = Extra amount of mask shape to creates on the X- and Y- sides of the shape. Default: 0.01
|
||||||
// ---
|
// ---
|
||||||
// d = Diameter of the rounding.
|
// d = Diameter of the rounding.
|
||||||
|
@ -387,6 +422,10 @@ function mask2d_dovetail(edge, angle=30, inset=0, shelf=0, excess=0.01, x, y, an
|
||||||
// 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`
|
||||||
// Example(2D): 2D Teardrop Mask
|
// Example(2D): 2D Teardrop Mask
|
||||||
// mask2d_teardrop(r=10);
|
// mask2d_teardrop(r=10);
|
||||||
|
// Example(2D): 2D Teardrop Mask for a Non-Right Edge
|
||||||
|
// mask2d_teardrop(r=10, mask_angle=75);
|
||||||
|
// Example(2D): Increasing Excess
|
||||||
|
// mask2d_teardrop(r=10, mask_angle=75, excess=2);
|
||||||
// Example(2D): Using a Custom Angle
|
// Example(2D): Using a Custom Angle
|
||||||
// mask2d_teardrop(r=10,angle=30);
|
// mask2d_teardrop(r=10,angle=30);
|
||||||
// Example: Masking by Edge Attachment
|
// Example: Masking by Edge Attachment
|
||||||
|
@ -402,25 +441,34 @@ function mask2d_dovetail(edge, angle=30, inset=0, shelf=0, excess=0.01, x, y, an
|
||||||
// xrot(90)
|
// xrot(90)
|
||||||
// linear_extrude(height=30, center=true)
|
// linear_extrude(height=30, center=true)
|
||||||
// mask2d_teardrop(r=10);
|
// mask2d_teardrop(r=10);
|
||||||
function mask2d_teardrop(r, angle=45, excess=0.01, d, anchor=CENTER, spin=0) =
|
function mask2d_teardrop(r, angle=45, mask_angle=90, excess=0.01, d, anchor=CENTER, spin=0) =
|
||||||
assert(is_finite(angle))
|
assert(is_finite(angle))
|
||||||
assert(angle>0 && angle<90)
|
assert(angle>0 && angle<90)
|
||||||
|
assert(is_finite(mask_angle) && mask_angle>0 && mask_angle<180)
|
||||||
assert(is_finite(excess))
|
assert(is_finite(excess))
|
||||||
let(
|
let(
|
||||||
r = get_radius(r=r, d=d, dflt=1),
|
r = get_radius(r=r, d=d, dflt=1),
|
||||||
n = ceil(segs(r) * angle/360),
|
avec = polar_to_xy(r,mask_angle-90),
|
||||||
cp = [r,r],
|
line1 = [[0,r], [100,r]],
|
||||||
|
line2 = [avec, polar_to_xy(100,mask_angle)+avec],
|
||||||
|
cp = line_intersection(line1,line2),
|
||||||
tp = cp + polar_to_xy(r,180+angle),
|
tp = cp + polar_to_xy(r,180+angle),
|
||||||
bp = [tp.x+adj_ang_to_opp(tp.y,angle), 0],
|
bp = [tp.x+adj_ang_to_opp(tp.y,angle), 0],
|
||||||
step = angle/n,
|
arcpts = arc(r=r, cp=cp, angle=[mask_angle+90,180+angle]),
|
||||||
path = [
|
ipath = [
|
||||||
bp, bp-[0,excess], [-excess,-excess], [-excess,r],
|
arcpts[0] + polar_to_xy(excess, mask_angle+90),
|
||||||
for (i=[0:1:n]) cp+polar_to_xy(r,180+i*step)
|
each arcpts,
|
||||||
]
|
bp,
|
||||||
|
bp + [0,-excess],
|
||||||
|
[0,-excess],
|
||||||
|
[-excess,-excess],
|
||||||
|
[-excess,0]
|
||||||
|
],
|
||||||
|
path = deduplicate(ipath)
|
||||||
) reorient(anchor,spin, two_d=true, path=path, p=path);
|
) reorient(anchor,spin, two_d=true, path=path, p=path);
|
||||||
|
|
||||||
module mask2d_teardrop(r, angle=45, excess=0.01, d, anchor=CENTER, spin=0) {
|
module mask2d_teardrop(r, angle=45, mask_angle=90, excess=0.01, d, anchor=CENTER, spin=0) {
|
||||||
path = mask2d_teardrop(r=r, d=d, angle=angle, excess=excess);
|
path = mask2d_teardrop(r=r, d=d, angle=angle, mask_angle=mask_angle, excess=excess);
|
||||||
attachable(anchor,spin, two_d=true, path=path) {
|
attachable(anchor,spin, two_d=true, path=path) {
|
||||||
polygon(path);
|
polygon(path);
|
||||||
children();
|
children();
|
||||||
|
|
|
@ -19,24 +19,24 @@ test_mask2d_chamfer();
|
||||||
|
|
||||||
module test_mask2d_cove() {
|
module test_mask2d_cove() {
|
||||||
$fn = 24;
|
$fn = 24;
|
||||||
assert_approx(mask2d_cove(r=10),[[10,-0.01],[-0.01,-0.01],[-0.01,10],[0,10],[2.58819045103,9.65925826289],[5,8.66025403784],[7.07106781187,7.07106781187],[8.66025403784,5],[9.65925826289,2.58819045103],[10,0]]);
|
assert_approx(mask2d_cove(r=10),[[-0.01,10],[0,10],[3.09016994375,9.51056516295],[5.87785252292,8.09016994375],[8.09016994375,5.87785252292],[9.51056516295,3.09016994375],[10,0],[10,-0.01],[0,-0.01],[-0.01,-0.01],[-0.01,0]]);
|
||||||
assert_approx(mask2d_cove(d=20),[[10,-0.01],[-0.01,-0.01],[-0.01,10],[0,10],[2.58819045103,9.65925826289],[5,8.66025403784],[7.07106781187,7.07106781187],[8.66025403784,5],[9.65925826289,2.58819045103],[10,0]]);
|
assert_approx(mask2d_cove(d=20),[[-0.01,10],[0,10],[3.09016994375,9.51056516295],[5.87785252292,8.09016994375],[8.09016994375,5.87785252292],[9.51056516295,3.09016994375],[10,0],[10,-0.01],[0,-0.01],[-0.01,-0.01],[-0.01,0]]);
|
||||||
assert_approx(mask2d_cove(r=10,inset=1),[[11,-0.01],[-0.01,-0.01],[-0.01,11],[1,11],[3.58819045103,10.6592582629],[6,9.66025403784],[8.07106781187,8.07106781187],[9.66025403784,6],[10.6592582629,3.58819045103],[11,1]]);
|
assert_approx(mask2d_cove(r=10,inset=1),[[-0.01,11],[1,11],[4.09016994375,10.510565163],[6.87785252292,9.09016994375],[9.09016994375,6.87785252292],[10.510565163,4.09016994375],[11,1],[11,-0.01],[0,-0.01],[-0.01,-0.01],[-0.01,0]]);
|
||||||
assert_approx(mask2d_cove(d=20,inset=1),[[11,-0.01],[-0.01,-0.01],[-0.01,11],[1,11],[3.58819045103,10.6592582629],[6,9.66025403784],[8.07106781187,8.07106781187],[9.66025403784,6],[10.6592582629,3.58819045103],[11,1]]);
|
assert_approx(mask2d_cove(d=20,inset=1),[[-0.01,11],[1,11],[4.09016994375,10.510565163],[6.87785252292,9.09016994375],[9.09016994375,6.87785252292],[10.510565163,4.09016994375],[11,1],[11,-0.01],[0,-0.01],[-0.01,-0.01],[-0.01,0]]);
|
||||||
assert_approx(mask2d_cove(r=10,inset=1,excess=1),[[11,-1],[-1,-1],[-1,11],[1,11],[3.58819045103,10.6592582629],[6,9.66025403784],[8.07106781187,8.07106781187],[9.66025403784,6],[10.6592582629,3.58819045103],[11,1]]);
|
assert_approx(mask2d_cove(r=10,inset=1,excess=1),[[-1,11],[1,11],[4.09016994375,10.510565163],[6.87785252292,9.09016994375],[9.09016994375,6.87785252292],[10.510565163,4.09016994375],[11,1],[11,-1],[0,-1],[-1,-1],[-1,0]]);
|
||||||
assert_approx(mask2d_cove(d=20,inset=1,excess=1),[[11,-1],[-1,-1],[-1,11],[1,11],[3.58819045103,10.6592582629],[6,9.66025403784],[8.07106781187,8.07106781187],[9.66025403784,6],[10.6592582629,3.58819045103],[11,1]]);
|
assert_approx(mask2d_cove(d=20,inset=1,excess=1),[[-1,11],[1,11],[4.09016994375,10.510565163],[6.87785252292,9.09016994375],[9.09016994375,6.87785252292],[10.510565163,4.09016994375],[11,1],[11,-1],[0,-1],[-1,-1],[-1,0]]);
|
||||||
}
|
}
|
||||||
test_mask2d_cove();
|
test_mask2d_cove();
|
||||||
|
|
||||||
|
|
||||||
module test_mask2d_roundover() {
|
module test_mask2d_roundover() {
|
||||||
$fn = 24;
|
$fn = 24;
|
||||||
assert_approx(mask2d_roundover(r=10),[[10,-0.01],[-0.01,-0.01],[-0.01,10],[0,10],[0.340741737109,7.41180954897],[1.33974596216,5],[2.92893218813,2.92893218813],[5,1.33974596216],[7.41180954897,0.340741737109],[10,0]]);
|
assert_approx(mask2d_roundover(r=10),[[-0.01,10],[-1.7763568394e-15,10],[0.489434837048,6.90983005625],[1.90983005625,4.12214747708],[4.12214747708,1.90983005625],[6.90983005625,0.489434837048],[10,-1.7763568394e-15],[10,-0.01],[0,-0.01],[-0.01,-0.01],[-0.01,0]]);
|
||||||
assert_approx(mask2d_roundover(d=20),[[10,-0.01],[-0.01,-0.01],[-0.01,10],[0,10],[0.340741737109,7.41180954897],[1.33974596216,5],[2.92893218813,2.92893218813],[5,1.33974596216],[7.41180954897,0.340741737109],[10,0]]);
|
assert_approx(mask2d_roundover(d=20),[[-0.01,10],[-1.7763568394e-15,10],[0.489434837048,6.90983005625],[1.90983005625,4.12214747708],[4.12214747708,1.90983005625],[6.90983005625,0.489434837048],[10,-1.7763568394e-15],[10,-0.01],[0,-0.01],[-0.01,-0.01],[-0.01,0]]);
|
||||||
assert_approx(mask2d_roundover(r=10,inset=1),[[11,-0.01],[-0.01,-0.01],[-0.01,11],[1,11],[1.34074173711,8.41180954897],[2.33974596216,6],[3.92893218813,3.92893218813],[6,2.33974596216],[8.41180954897,1.34074173711],[11,1]]);
|
assert_approx(mask2d_roundover(r=10,inset=1),[[-0.01,11],[1,11],[1.48943483705,7.90983005625],[2.90983005625,5.12214747708],[5.12214747708,2.90983005625],[7.90983005625,1.48943483705],[11,1],[11,-0.01],[0,-0.01],[-0.01,-0.01],[-0.01,0]]);
|
||||||
assert_approx(mask2d_roundover(d=20,inset=1),[[11,-0.01],[-0.01,-0.01],[-0.01,11],[1,11],[1.34074173711,8.41180954897],[2.33974596216,6],[3.92893218813,3.92893218813],[6,2.33974596216],[8.41180954897,1.34074173711],[11,1]]);
|
assert_approx(mask2d_roundover(d=20,inset=1),[[-0.01,11],[1,11],[1.48943483705,7.90983005625],[2.90983005625,5.12214747708],[5.12214747708,2.90983005625],[7.90983005625,1.48943483705],[11,1],[11,-0.01],[0,-0.01],[-0.01,-0.01],[-0.01,0]]);
|
||||||
assert_approx(mask2d_roundover(r=10,inset=1,excess=1),[[11,-1],[-1,-1],[-1,11],[1,11],[1.34074173711,8.41180954897],[2.33974596216,6],[3.92893218813,3.92893218813],[6,2.33974596216],[8.41180954897,1.34074173711],[11,1]]);
|
assert_approx(mask2d_roundover(r=10,inset=1,excess=1),[[-1,11],[1,11],[1.48943483705,7.90983005625],[2.90983005625,5.12214747708],[5.12214747708,2.90983005625],[7.90983005625,1.48943483705],[11,1],[11,-1],[0,-1],[-1,-1],[-1,0]]);
|
||||||
assert_approx(mask2d_roundover(d=20,inset=1,excess=1),[[11,-1],[-1,-1],[-1,11],[1,11],[1.34074173711,8.41180954897],[2.33974596216,6],[3.92893218813,3.92893218813],[6,2.33974596216],[8.41180954897,1.34074173711],[11,1]]);
|
assert_approx(mask2d_roundover(d=20,inset=1,excess=1),[[-1,11],[1,11],[1.48943483705,7.90983005625],[2.90983005625,5.12214747708],[5.12214747708,2.90983005625],[7.90983005625,1.48943483705],[11,1],[11,-1],[0,-1],[-1,-1],[-1,0]]);
|
||||||
}
|
}
|
||||||
test_mask2d_roundover();
|
test_mask2d_roundover();
|
||||||
|
|
||||||
|
@ -59,20 +59,20 @@ test_mask2d_dovetail();
|
||||||
|
|
||||||
|
|
||||||
module test_mask2d_rabbet() {
|
module test_mask2d_rabbet() {
|
||||||
assert_approx(mask2d_rabbet(10), [[10,-0.01],[-0.01,-0.01],[-0.01,10],[10,10]]);
|
assert_approx(mask2d_rabbet(10), [[-0.01,10],[10,10],[10,-0.01],[0,-0.01],[-0.01,-0.01],[-0.01,0]]);
|
||||||
assert_approx(mask2d_rabbet(size=10), [[10,-0.01],[-0.01,-0.01],[-0.01,10],[10,10]]);
|
assert_approx(mask2d_rabbet(size=10), [[-0.01,10],[10,10],[10,-0.01],[0,-0.01],[-0.01,-0.01],[-0.01,0]]);
|
||||||
assert_approx(mask2d_rabbet(size=[10,15]), [[10,-0.01],[-0.01,-0.01],[-0.01,15],[10,15]]);
|
assert_approx(mask2d_rabbet(size=[10,15]), [[-0.01,15],[10,15],[10,-0.01],[0,-0.01],[-0.01,-0.01],[-0.01,0]]);
|
||||||
assert_approx(mask2d_rabbet(size=[10,15],excess=1), [[10,-1],[-1,-1],[-1,15],[10,15]]);
|
assert_approx(mask2d_rabbet(size=[10,15],excess=1), [[-1,15],[10,15],[10,-1],[0,-1],[-1,-1],[-1,0]]);
|
||||||
}
|
}
|
||||||
test_mask2d_rabbet();
|
test_mask2d_rabbet();
|
||||||
|
|
||||||
|
|
||||||
module test_mask2d_teardrop() {
|
module test_mask2d_teardrop() {
|
||||||
$fn=24;
|
$fn=24;
|
||||||
assert_approx(mask2d_teardrop(r=10), [[5.85786437627,0],[5.85786437627,-0.01],[-0.01,-0.01],[-0.01,10],[0,10],[0.340741737109,7.41180954897],[1.33974596216,5],[2.92893218813,2.92893218813]]);
|
assert_approx(mask2d_teardrop(r=10), [[-0.01,10],[0,10],[0.761204674887,6.17316567635],[2.92893218813,2.92893218813],[5.85786437627,0],[5.85786437627,-0.01],[0,-0.01],[-0.01,-0.01],[-0.01,0]]);
|
||||||
assert_approx(mask2d_teardrop(d=20), [[5.85786437627,0],[5.85786437627,-0.01],[-0.01,-0.01],[-0.01,10],[0,10],[0.340741737109,7.41180954897],[1.33974596216,5],[2.92893218813,2.92893218813]]);
|
assert_approx(mask2d_teardrop(d=20), [[-0.01,10],[0,10],[0.761204674887,6.17316567635],[2.92893218813,2.92893218813],[5.85786437627,0],[5.85786437627,-0.01],[0,-0.01],[-0.01,-0.01],[-0.01,0]]);
|
||||||
assert_approx(mask2d_teardrop(r=10,angle=30), [[4.2264973081,0],[4.2264973081,-0.01],[-0.01,-0.01],[-0.01,10],[0,10],[0.340741737109,7.41180954897],[1.33974596216,5]]);
|
assert_approx(mask2d_teardrop(r=10,angle=30), [[-0.01,10],[0,10],[0.340741737109,7.41180954897],[1.33974596216,5],[4.2264973081,0],[4.2264973081,-0.01],[0,-0.01],[-0.01,-0.01],[-0.01,0]]);
|
||||||
assert_approx(mask2d_teardrop(r=10,angle=30,excess=1), [[4.2264973081,0],[4.2264973081,-1],[-1,-1],[-1,10],[0,10],[0.340741737109,7.41180954897],[1.33974596216,5]]);
|
assert_approx(mask2d_teardrop(r=10,angle=30,excess=1), [[-1,10],[0,10],[0.340741737109,7.41180954897],[1.33974596216,5],[4.2264973081,0],[4.2264973081,-1],[0,-1],[-1,-1],[-1,0]]);
|
||||||
}
|
}
|
||||||
test_mask2d_teardrop();
|
test_mask2d_teardrop();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue