1//////////////////////////////////////////////////////////////////////
2// LibFile: masks3d.scad
3// This file defines 3D masks for applying chamfers, roundovers, and teardrop roundovers to straight edges and circular
4// edges in three dimensions.
5// Includes:
6// include <BOSL2/std.scad>
7// FileGroup: Basic Modeling
8// FileSummary: 3D masks for rounding or chamfering edges and corners.
9// FileFootnotes: STD=Included in std.scad
10//////////////////////////////////////////////////////////////////////
11
12
13// Section: Chamfer Masks
14
15
16// Module: chamfer_edge_mask()
17// Usage:
18// chamfer_edge_mask(l, chamfer, [excess]) [ATTACHMENTS];
19// Description:
20// Creates a shape that can be used to chamfer a 90 degree edge.
21// Difference it from the object to be chamfered. The center of
22// the mask object should align exactly with the edge to be chamfered.
23// Arguments:
24// l = Length of mask.
25// chamfer = Size of chamfer.
26// excess = The extra amount to add to the length of the mask so that it differences away from other shapes cleanly. Default: `0.1`
27// ---
28// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
29// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
30// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
31// Example:
32// chamfer_edge_mask(l=50, chamfer=10);
33// Example:
34// difference() {
35// cube(50, anchor=BOTTOM+FRONT);
36// #chamfer_edge_mask(l=50, chamfer=10, orient=RIGHT);
37// }
38// Example: Masking by Attachment
39// diff()
40// cube(50, center=true) {
41// edge_mask(TOP+RIGHT)
42// #chamfer_edge_mask(l=50, chamfer=10);
43// }
44function chamfer_edge_mask(l=1, chamfer=1, excess=0.1, anchor=CENTER, spin=0, orient=UP) = no_function("chamfer_edge_mask");
45module chamfer_edge_mask(l=1, chamfer=1, excess=0.1, anchor=CENTER, spin=0, orient=UP) {
46 attachable(anchor,spin,orient, size=[chamfer*2, chamfer*2, l]) {
47 cylinder(r=chamfer, h=l+excess, center=true, $fn=4);
48 children();
49 }
50}
51
52
53// Module: chamfer_corner_mask()
54// Usage:
55// chamfer_corner_mask(chamfer) [ATTACHMENTS];
56// Description:
57// Creates a shape that can be used to chamfer a 90 degree corner.
58// Difference it from the object to be chamfered. The center of
59// the mask object should align exactly with the corner to be chamfered.
60// Arguments:
61// chamfer = Size of chamfer.
62// ---
63// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
64// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
65// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
66// Example:
67// chamfer_corner_mask(chamfer=10);
68// Example:
69// difference() {
70// cuboid(50, chamfer=10, trimcorners=false);
71// move(25*[1,-1,1]) #chamfer_corner_mask(chamfer=10);
72// }
73// Example: Masking by Attachment
74// diff()
75// cuboid(100, chamfer=20, trimcorners=false) {
76// corner_mask(TOP+FWD+RIGHT)
77// chamfer_corner_mask(chamfer=20);
78// }
79// Example: Anchors
80// chamfer_corner_mask(chamfer=20)
81// show_anchors();
82function chamfer_corner_mask(chamfer=1, anchor=CENTER, spin=0, orient=UP) = no_function("chamfer_corner_mask");
83module chamfer_corner_mask(chamfer=1, anchor=CENTER, spin=0, orient=UP) {
84 octahedron(chamfer*4, anchor=anchor, spin=spin, orient=orient) children();
85}
86
87
88// Module: chamfer_cylinder_mask()
89// Usage:
90// chamfer_cylinder_mask(r|d=, chamfer, [ang], [from_end]) [ATTACHMENTS];
91// Description:
92// Create a mask that can be used to bevel/chamfer the end of a cylindrical region.
93// Difference it from the end of the region to be chamfered. The center of the mask
94// object should align exactly with the center of the end of the cylindrical region
95// to be chamfered.
96// Arguments:
97// r = Radius of cylinder to chamfer.
98// chamfer = Size of the edge chamfered, inset from edge.
99// ---
100// d = Diameter of cylinder to chamfer. Use instead of r.
101// ang = Angle of chamfer in degrees from the horizontal. (Default: 45)
102// from_end = If true, chamfer size is measured from end of cylinder. If false, chamfer is measured outset from the radius of the cylinder. (Default: false)
103// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
104// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
105// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
106// Example:
107// difference() {
108// cylinder(r=50, h=100, center=true);
109// up(50) #chamfer_cylinder_mask(r=50, chamfer=10);
110// }
111// Example:
112// difference() {
113// cylinder(r=50, h=100, center=true);
114// up(50) chamfer_cylinder_mask(r=50, chamfer=10);
115// }
116// Example: Changing the chamfer angle
117// difference() {
118// cylinder(r=50, h=100, center=true);
119// up(50) #chamfer_cylinder_mask(r=50, chamfer=10, ang=70);
120// }
121// Example:
122// difference() {
123// cylinder(r=50, h=100, center=true);
124// up(50) chamfer_cylinder_mask(r=50, chamfer=10, ang=70);
125// }
126// Example: Masking by Attachment
127// diff()
128// cyl(d=100,h=40)
129// attach([TOP,BOT])
130// tag("remove")chamfer_cylinder_mask(d=100, chamfer=10);
131function chamfer_cylinder_mask(r, chamfer, d, ang=45, from_end=false, anchor=CENTER, spin=0, orient=UP) = no_function("chamfer_cylinder_mask");
132module chamfer_cylinder_mask(r, chamfer, d, ang=45, from_end=false, anchor=CENTER, spin=0, orient=UP)
133{
134 r = get_radius(r=r, d=d, dflt=1);
135 dummy = assert(all_nonnegative([chamfer]), "Chamfer must be a nonnegative number");
136 ch = from_end? chamfer : opp_ang_to_adj(chamfer,90-ang);
137 attachable(anchor,spin,orient, r=r, l=ch*2) {
138 difference() {
139 cyl(r=r+chamfer, l=ch*2, anchor=CENTER);
140 cyl(r=r, l=ch*3, chamfer=chamfer, chamfang=ang, from_end=from_end, anchor=TOP);
141 }
142 children();
143 }
144}
145
146
147
148// Section: Rounding Masks
149
150// Module: rounding_edge_mask()
151// Usage:
152// rounding_edge_mask(l|h, r|d, [excess=]) [ATTACHMENTS];
153// rounding_edge_mask(l|h, r1=|d1=, r2=|d2=, [excess=]) [ATTACHMENTS];
154// Description:
155// Creates a shape that can be used to round a vertical 90 degree edge.
156// Difference it from the object to be rounded. The center of the mask
157// object should align exactly with the edge to be rounded.
158// Arguments:
159// l/h = Length of mask.
160// r = Radius of the rounding.
161// ---
162// r1 = Bottom radius of rounding.
163// r2 = Top radius of rounding.
164// d = Diameter of the rounding.
165// d1 = Bottom diameter of rounding.
166// d2 = Top diameter of rounding.
167// excess = Extra size for the mask. Defaults: 0.1
168// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
169// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
170// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
171// Example(VPD=200,VPR=[55,0,120]):
172// rounding_edge_mask(l=50, r1=10, r2=25);
173// Example:
174// difference() {
175// cube(size=100, center=false);
176// #rounding_edge_mask(l=100, r=25, orient=UP, anchor=BOTTOM);
177// }
178// Example: Varying Rounding Radius
179// difference() {
180// cube(size=50, center=false);
181// #rounding_edge_mask(l=50, r1=25, r2=10, orient=UP, anchor=BOTTOM);
182// }
183// Example: Masking by Attachment
184// diff()
185// cube(100, center=true)
186// edge_mask(FRONT+RIGHT)
187// #rounding_edge_mask(l=$parent_size.z+0.01, r=25);
188// Example: Multiple Masking by Attachment
189// diff()
190// cube([80,90,100], center=true) {
191// let(p = $parent_size*1.01) {
192// edge_mask(TOP)
193// rounding_edge_mask(l=p.z, r=25);
194// }
195// }
196function rounding_edge_mask(l, r, r1, r2, d, d1, d2, excess=0.1, anchor=CENTER, spin=0, orient=UP, h=undef) = no_function("rounding_edge_mask");
197module rounding_edge_mask(l, r, r1, r2, d, d1, d2, excess=0.1, anchor=CENTER, spin=0, orient=UP, h=undef)
198{
199 l = first_defined([l, h, 1]);
200 r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=1);
201 r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=1);
202 sides = quantup(segs(max(r1,r2)),4);
203 attachable(anchor,spin,orient, size=[2*r1,2*r1,l], size2=[2*r2,2*r2]) {
204 if (r1<r2) {
205 zflip() {
206 linear_extrude(height=l, convexity=4, center=true, scale=r1/r2) {
207 difference() {
208 translate(-excess*[1,1]) square(r2+excess);
209 translate([r2,r2]) circle(r=r2, $fn=sides);
210 }
211 }
212 }
213 } else {
214 linear_extrude(height=l, convexity=4, center=true, scale=r2/r1) {
215 difference() {
216 translate(-excess*[1,1]) square(r1+excess);
217 translate([r1,r1]) circle(r=r1, $fn=sides);
218 }
219 }
220 }
221 children();
222 }
223}
224
225
226// Module: rounding_corner_mask()
227// Usage:
228// rounding_corner_mask(r|d, [excess=], [style=]) [ATTACHMENTS];
229// Description:
230// Creates a shape that you can use to round 90 degree corners.
231// Difference it from the object to be rounded. The center of the mask
232// object should align exactly with the corner to be rounded.
233// Arguments:
234// r = Radius of corner rounding.
235// ---
236// d = Diameter of corner rounding.
237// excess = Extra size for the mask. Defaults: 0.1
238// style = The style of the sphere cutout's construction. One of "orig", "aligned", "stagger", "octa", or "icosa". Default: "octa"
239// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
240// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
241// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
242// Example:
243// rounding_corner_mask(r=20.0);
244// Example:
245// difference() {
246// cube(size=[50, 60, 70], center=true);
247// translate([-25, -30, 35])
248// #rounding_corner_mask(r=20, spin=90, orient=DOWN);
249// translate([25, -30, 35])
250// #rounding_corner_mask(r=20, orient=DOWN);
251// translate([25, -30, -35])
252// #rounding_corner_mask(r=20, spin=90);
253// }
254// Example: Masking by Attachment
255// diff()
256// cube(size=[50, 60, 70]) {
257// corner_mask(TOP)
258// #rounding_corner_mask(r=20);
259// }
260function rounding_corner_mask(r, d, style="octa", excess=0.1, anchor=CENTER, spin=0, orient=UP) = no_function("rounding_corner_mask");
261module rounding_corner_mask(r, d, style="octa", excess=0.1, anchor=CENTER, spin=0, orient=UP)
262{
263 r = get_radius(r=r, d=d, dflt=1);
264 attachable(anchor,spin,orient, size=[2,2,2]*r) {
265 difference() {
266 translate(-excess*[1,1,1])
267 cube(size=r+excess, center=false);
268 translate([r,r,r])
269 sphere(r=r, style=style);
270 }
271 children();
272 }
273}
274
275
276// Module: rounding_angled_edge_mask()
277// Usage:
278// rounding_angled_edge_mask(h, r|d=, [ang=]) [ATTACHMENTS];
279// rounding_angled_edge_mask(h, r1=|d1=, r2=|d2=, [ang=]) [ATTACHMENTS];
280// Description:
281// Creates a vertical mask that can be used to round the edge where two face meet, at any arbitrary
282// angle. Difference it from the object to be rounded. The center of the mask should align exactly
283// with the edge to be rounded.
284// Arguments:
285// h = Height of vertical mask.
286// r = Radius of the rounding.
287// ---
288// r1 = Bottom radius of rounding.
289// r2 = Top radius of rounding.
290// d = Diameter of the rounding.
291// d1 = Bottom diameter of rounding.
292// d2 = Top diameter of rounding.
293// ang = Angle that the planes meet at. Default: 90
294// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
295// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
296// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
297// Example:
298// difference() {
299// pie_slice(ang=70, h=50, d=100, center=true);
300// #rounding_angled_edge_mask(h=51, r=20.0, ang=70, $fn=32);
301// }
302// Example: Varying Rounding Radius
303// difference() {
304// pie_slice(ang=70, h=50, d=100, center=true);
305// #rounding_angled_edge_mask(h=51, r1=10, r2=25, ang=70, $fn=32);
306// }
307function rounding_angled_edge_mask(h, r, r1, r2, d, d1, d2, ang=90, anchor=CENTER, spin=0, orient=UP) = no_function("rounding_angled_edge_mask");
308module rounding_angled_edge_mask(h, r, r1, r2, d, d1, d2, ang=90, anchor=CENTER, spin=0, orient=UP)
309{
310 function _mask_shape(r) = [
311 for (i = [0:1:n]) let (a=90+ang+i*sweep/n) [r*cos(a)+x, r*sin(a)+r],
312 for (i = [0:1:n]) let (a=90+i*sweep/n) [r*cos(a)+x, r*sin(a)-r],
313 [min(-1, r*cos(270-ang)+x-1), r*sin(270-ang)-r],
314 [min(-1, r*cos(90+ang)+x-1), r*sin(90+ang)+r],
315 ];
316
317 sweep = 180-ang;
318 r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=1);
319 r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=1);
320 n = ceil(segs(max(r1,r2))*sweep/360);
321 x = sin(90-(ang/2))/sin(ang/2) * (r1<r2? r2 : r1);
322 if(r1<r2) {
323 attachable(anchor,spin,orient, size=[2*x*r1/r2,2*r1,h], size2=[2*x,2*r2]) {
324 zflip() {
325 linear_extrude(height=h, convexity=4, center=true, scale=r1/r2) {
326 polygon(_mask_shape(r2));
327 }
328 }
329 children();
330 }
331 } else {
332 attachable(anchor,spin,orient, size=[2*x,2*r1,h], size2=[2*x*r2/r1,2*r2]) {
333 linear_extrude(height=h, convexity=4, center=true, scale=r2/r1) {
334 polygon(_mask_shape(r1));
335 }
336 children();
337 }
338 }
339}
340
341
342// Module: rounding_angled_corner_mask()
343// Usage:
344// rounding_angled_corner_mask(r|d=, [ang]) [ATTACHMENTS];
345// Description:
346// Creates a shape that can be used to round the corner of an angle.
347// Difference it from the object to be rounded. The center of the mask
348// object should align exactly with the point of the corner to be rounded.
349// Arguments:
350// r = Radius of the rounding.
351// ---
352// d = Diameter of the rounding.
353// ang = Angle between planes that you need to round the corner of. Default: 90
354// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
355// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
356// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
357// Example(Med):
358// ang=60;
359// difference() {
360// pie_slice(ang=ang, h=50, r=200, center=true);
361// up(50/2) #rounding_angled_corner_mask(r=20, ang=ang);
362// }
363function rounding_angled_corner_mask(r, ang=90, d, anchor=CENTER, spin=0, orient=UP) = no_function("rounding_angled_corner_mask");
364module rounding_angled_corner_mask(r, ang=90, d, anchor=CENTER, spin=0, orient=UP)
365{
366 r = get_radius(r=r, d=d, dflt=1);
367 dx = r / tan(ang/2);
368 dx2 = dx / cos(ang/2) + 1;
369 fn = quantup(segs(r), 4);
370 attachable(anchor,spin,orient, d=dx2, l=2*r) {
371 difference() {
372 down(r) cylinder(r=dx2, h=r+1, center=false);
373 yflip_copy() {
374 translate([dx, r, -r]) {
375 hull() {
376 sphere(r=r, $fn=fn);
377 down(r*3) sphere(r=r, $fn=fn);
378 zrot_copies([0,ang]) {
379 right(r*3) sphere(r=r, $fn=fn);
380 }
381 }
382 }
383 }
384 }
385 children();
386 }
387}
388
389
390// Module: rounding_cylinder_mask()
391// Usage:
392// rounding_cylinder_mask(r|d=, rounding);
393// Description:
394// Create a mask that can be used to round the end of a cylinder.
395// Difference it from the cylinder to be rounded. The center of the
396// mask object should align exactly with the center of the end of the
397// cylinder to be rounded.
398// Arguments:
399// r = Radius of cylinder.
400// rounding = Radius of the edge rounding.
401// ---
402// d = Diameter of cylinder.
403// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
404// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
405// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
406// Example:
407// difference() {
408// cylinder(r=50, h=50, center=false);
409// up(50) #rounding_cylinder_mask(r=50, rounding=10);
410// }
411// Example:
412// difference() {
413// cylinder(r=50, h=50, center=false);
414// up(50) rounding_cylinder_mask(r=50, rounding=10);
415// }
416// Example: Masking by Attachment
417// diff()
418// cyl(h=30, d=30) {
419// attach(TOP)
420// #tag("remove")
421// rounding_cylinder_mask(d=30, rounding=5);
422// }
423function rounding_cylinder_mask(r, rounding, d, anchor, spin, orient) = no_function("rounding_cylinder_mask");
424module rounding_cylinder_mask(r, rounding, d, anchor=CENTER, spin=0, orient=UP)
425{
426 r = get_radius(r=r, d=d, dflt=1);
427 attachable(anchor,spin,orient, r=r+rounding, l=rounding*2) {
428 difference() {
429 cyl(r=r+rounding, l=rounding*2, anchor=CENTER);
430 cyl(r=r, l=rounding*3, rounding=rounding, anchor=TOP);
431 }
432 children();
433 }
434}
435
436
437
438// Module: rounding_hole_mask()
439// Usage:
440// rounding_hole_mask(r|d, rounding, [excess]) [ATTACHMENTS];
441// Description:
442// Create a mask that can be used to round the edge of a circular hole.
443// Difference it from the hole to be rounded. The center of the
444// mask object should align exactly with the center of the end of the
445// hole to be rounded.
446// Arguments:
447// r = Radius of hole.
448// d = Diameter of hole to rounding.
449// rounding = Radius of the rounding.
450// excess = The extra thickness of the mask. Default: `0.1`.
451// ---
452// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
453// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
454// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
455// Example:
456// rounding_hole_mask(r=40, rounding=20, $fa=2, $fs=2);
457// Example(Med):
458// difference() {
459// cube([150,150,100], center=true);
460// cylinder(r=50, h=100.1, center=true);
461// up(50) #rounding_hole_mask(r=50, rounding=10);
462// }
463// Example(Med):
464// difference() {
465// cube([150,150,100], center=true);
466// cylinder(r=50, h=100.1, center=true);
467// up(50) rounding_hole_mask(r=50, rounding=10);
468// }
469function rounding_hole_mask(r, rounding, excess=0.1, d, anchor=CENTER, spin=0, orient=UP) = no_function("rounding_hole_mask");
470module rounding_hole_mask(r, rounding, excess=0.1, d, anchor=CENTER, spin=0, orient=UP)
471{
472 r = get_radius(r=r, d=d, dflt=1);
473 attachable(anchor,spin,orient, r=r+rounding, l=2*rounding) {
474 rotate_extrude(convexity=4) {
475 difference() {
476 right(r-excess) fwd(rounding) square(rounding+excess, center=false);
477 right(r+rounding) fwd(rounding) circle(r=rounding);
478 }
479 }
480 children();
481 }
482}
483
484
485// Section: Teardrop Masking
486
487// Module: teardrop_edge_mask()
488// Usage:
489// teardrop_edge_mask(l, r|d=, [angle], [excess], [anchor], [spin], [orient]) [ATTACHMENTS];
490// Description:
491// Makes an apropriate 3D corner rounding mask that keeps within `angle` degrees of vertical.
492// Arguments:
493// l = length of mask
494// r = Radius of the mask rounding.
495// angle = Maximum angle from vertical. Default: 45
496// excess = Excess mask size. Default: 0.1
497// ---
498// d = Diameter of the mask rounding.
499// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
500// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
501// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
502// Example(VPD=50,VPR=[55,0,120]):
503// teardrop_edge_mask(l=20, r=10, angle=40);
504// Example(VPD=300,VPR=[75,0,25]):
505// diff()
506// cuboid([50,60,70],rounding=10,edges="Z",anchor=CENTER) {
507// edge_mask(BOT)
508// teardrop_edge_mask(l=max($parent_size)+1, r=10, angle=40);
509// corner_mask(BOT)
510// teardrop_corner_mask(r=10, angle=40);
511// }
512function teardrop_edge_mask(l, r, angle, excess=0.1, d, anchor, spin, orient) = no_function("teardrop_edge_mask");
513module teardrop_edge_mask(l, r, angle, excess=0.1, d, anchor=CTR, spin=0, orient=UP)
514{
515 check =
516 assert(is_num(l) && l>0, "Length of mask must be positive")
517 assert(is_num(angle) && angle>0 && angle<90, "Angle must be a number between 0 and 90")
518 assert(is_num(excess));
519 r = get_radius(r=r, d=d, dflt=1);
520 path = mask2d_teardrop(r=r, angle=angle, excess=excess);
521 linear_sweep(path, height=l, center=true, atype="bbox", anchor=anchor, spin=spin, orient=orient) children();
522}
523
524
525// Module: teardrop_corner_mask()
526// Usage:
527// teardrop_corner_mask(r|d=, [angle], [excess], [anchor], [spin], [orient]) [ATTACHMENTS];
528// Description:
529// Makes an apropriate 3D corner rounding mask that keeps within `angle` degrees of vertical.
530// Arguments:
531// r = Radius of the mask rounding.
532// angle = Maximum angle from vertical. Default: 45
533// excess = Excess mask size. Default: 0.1
534// ---
535// d = Diameter of the mask rounding.
536// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
537// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
538// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
539// Example:
540// teardrop_corner_mask(r=20, angle=40);
541// Example:
542// diff()
543// cuboid([50,60,70],rounding=10,edges="Z",anchor=CENTER) {
544// edge_profile(BOT)
545// mask2d_teardrop(r=10, angle=40);
546// corner_mask(BOT)
547// teardrop_corner_mask(r=10, angle=40);
548// }
549function teardrop_corner_mask(r, angle, excess=0.1, d, anchor, spin, orient) = no_function("teardrop_corner_mask");
550module teardrop_corner_mask(r, angle, excess=0.1, d, anchor=CTR, spin=0, orient=UP)
551{
552 assert(is_num(angle));
553 assert(is_num(excess));
554 assert(angle>0 && angle<90);
555 r = get_radius(r=r, d=d, dflt=1);
556 size = (r+excess) * [1,1,1];
557 midpt = (r-excess)/2 * [1,1,1];
558 attachable(anchor,spin,orient, size=size, offset=midpt) {
559 difference() {
560 translate(-[1,1,1]*excess) cube(r+excess, center=false);
561 translate([1,1,1]*r) onion(r=r, ang=angle, orient=DOWN);
562 }
563 children();
564 }
565}
566
567
568
569// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap