Merge pull request #1 from revarbat/master

Updating my repository
This commit is contained in:
RonaldoCMP 2020-08-27 11:50:20 +01:00 committed by GitHub
commit 75a7dabfd2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 399 additions and 131 deletions

View file

@ -1235,17 +1235,20 @@ module show(tags="")
// }
module diff(neg, pos=undef, keep=undef)
{
difference() {
if (pos != undef) {
show(pos) children();
} else {
if (keep == undef) {
hide(neg) children();
// Don't perform the operation if the current tags are hidden
if (attachment_is_shown($tags)) {
difference() {
if (pos != undef) {
show(pos) children();
} else {
hide(str(neg," ",keep)) children();
if (keep == undef) {
hide(neg) children();
} else {
hide(str(neg," ",keep)) children();
}
}
show(neg) children();
}
show(neg) children();
}
if (keep!=undef) {
show(keep) children();
@ -1280,17 +1283,20 @@ module diff(neg, pos=undef, keep=undef)
// }
module intersect(a, b=undef, keep=undef)
{
intersection() {
if (b != undef) {
show(b) children();
} else {
if (keep == undef) {
hide(a) children();
// Don't perform the operation if the current tags are hidden
if (attachment_is_shown($tags)) {
intersection() {
if (b != undef) {
show(b) children();
} else {
hide(str(a," ",keep)) children();
if (keep == undef) {
hide(a) children();
} else {
hide(str(a," ",keep)) children();
}
}
show(a) children();
}
show(a) children();
}
if (keep!=undef) {
show(keep) children();

View file

@ -356,7 +356,7 @@ function bezier_segment_length(curve, start_u=0, end_u=1, max_deflect=0.01) =
// Function: fillet3pts()
// Usage:
// fillet3pts(p0, p1, p2, r);
// fillet3pts(p0, p1, p2, r|d);
// Description:
// Takes three points, defining two line segments, and works out the
// cubic (degree 3) bezier segment (and surrounding control points)
@ -368,7 +368,8 @@ function bezier_segment_length(curve, start_u=0, end_u=1, max_deflect=0.01) =
// p1 = The middle point.
// p2 = The ending point.
// r = The radius of the fillet/rounding.
// maxerr = Max amount bezier curve should diverge from actual radius curve. Default: 0.1
// d = The diameter of the fillet/rounding.
// maxerr = Max amount bezier curve should diverge from actual curve. Default: 0.1
// Example(2D):
// p0 = [40, 0];
// p1 = [0, 0];
@ -376,7 +377,8 @@ function bezier_segment_length(curve, start_u=0, end_u=1, max_deflect=0.01) =
// trace_polyline([p0,p1,p2], showpts=true, size=0.5, color="green");
// fbez = fillet3pts(p0,p1,p2, 10);
// trace_bezier(slice(fbez, 1, -2), size=1);
function fillet3pts(p0, p1, p2, r, maxerr=0.1, w=0.5, dw=0.25) = let(
function fillet3pts(p0, p1, p2, r, d, maxerr=0.1, w=0.5, dw=0.25) = let(
r = get_radius(r=r,d=d),
v0 = unit(p0-p1),
v1 = unit(p2-p1),
midv = unit((v0+v1)/2),
@ -391,8 +393,8 @@ function fillet3pts(p0, p1, p2, r, maxerr=0.1, w=0.5, dw=0.25) = let(
bp = bezier_points([tp0, cp0, cp1, tp1], 0.5),
tdist = norm(cp-bp)
) (abs(tdist-cpr) <= maxerr)? [tp0, tp0, cp0, cp1, tp1, tp1] :
(tdist<cpr)? fillet3pts(p0, p1, p2, r, maxerr=maxerr, w=w+dw, dw=dw/2) :
fillet3pts(p0, p1, p2, r, maxerr=maxerr, w=w-dw, dw=dw/2);
(tdist<cpr)? fillet3pts(p0, p1, p2, r=r, maxerr=maxerr, w=w+dw, dw=dw/2) :
fillet3pts(p0, p1, p2, r=r, maxerr=maxerr, w=w-dw, dw=dw/2);
@ -613,7 +615,7 @@ function fillet_path(pts, fillet, maxerr=0.1) = concat(
p1 = pts[p],
p0 = (pts[p-1]+p1)/2,
p2 = (pts[p+1]+p1)/2
) for (pt = fillet3pts(p0, p1, p2, fillet, maxerr=maxerr)) pt
) for (pt = fillet3pts(p0, p1, p2, r=fillet, maxerr=maxerr)) pt
],
[pts[len(pts)-1], pts[len(pts)-1]]
);

View file

@ -686,7 +686,7 @@ module rot_copies(rots=[], v=undef, cp=[0,0,0], n=undef, sa=0, offset=0, delta=[
// cp = Centerpoint to rotate around.
// n = Optional number of evenly distributed copies to be rotated around the ring.
// sa = Starting angle, in degrees. For use with `n`. Angle is in degrees counter-clockwise from Y+, when facing the origin from X+. First unrotated copy is placed at that angle.
// r = Radius to move children back, away from cp, before rotating. Makes rings of copies.
// r = Radius to move children back (Y+), away from cp, before rotating. Makes rings of copies.
// subrot = If false, don't sub-rotate children as they are copied around the ring.
//
// Side Effects:
@ -743,7 +743,7 @@ module xrot_copies(rots=[], cp=[0,0,0], n=undef, sa=0, r=0, subrot=true)
// cp = Centerpoint to rotate around.
// n = Optional number of evenly distributed copies to be rotated around the ring.
// sa = Starting angle, in degrees. For use with `n`. Angle is in degrees counter-clockwise from X-, when facing the origin from Y+.
// r = Radius to move children left, away from cp, before rotating. Makes rings of copies.
// r = Radius to move children left (X-), away from cp, before rotating. Makes rings of copies.
// subrot = If false, don't sub-rotate children as they are copied around the ring.
//
// Side Effects:
@ -800,7 +800,7 @@ module yrot_copies(rots=[], cp=[0,0,0], n=undef, sa=0, r=0, subrot=true)
// cp = Centerpoint to rotate around. Default: [0,0,0]
// n = Optional number of evenly distributed copies to be rotated around the ring.
// sa = Starting angle, in degrees. For use with `n`. Angle is in degrees counter-clockwise from X+, when facing the origin from Z+. Default: 0
// r = Radius to move children right, away from cp, before rotating. Makes rings of copies. Default: 0
// r = Radius to move children right (X+), away from cp, before rotating. Makes rings of copies. Default: 0
// subrot = If false, don't sub-rotate children as they are copied around the ring. Default: true
//
// Side Effects:

View file

@ -12,8 +12,8 @@
// Module: angle_pie_mask()
// Usage:
// angle_pie_mask(r|d, l, ang);
// angle_pie_mask(r1|d1, r2|d2, l, ang);
// angle_pie_mask(r|d, l, ang, [excess]);
// angle_pie_mask(r1|d1, r2|d2, l, ang, [excess]);
// Description:
// Creates a pie wedge shape that can be used to mask other shapes.
// Arguments:
@ -25,6 +25,7 @@
// d = Diameter of circle wedge is created from. (optional)
// d1 = Bottom diameter of cone that wedge is created from. (optional)
// d2 = Upper diameter of cone that wedge is created from. (optional)
// excess = The extra thickness of the mask. Default: `0.1`.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
@ -34,14 +35,14 @@ module angle_pie_mask(
ang=45, l=undef,
r=undef, r1=undef, r2=undef,
d=undef, d1=undef, d2=undef,
h=undef,
h=undef, excess=0.1,
anchor=CENTER, spin=0, orient=UP
) {
l = first_defined([l, h, 1]);
r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=10);
r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=10);
attachable(anchor,spin,orient, r1=r1, r2=r2, l=l) {
pie_slice(ang=ang, l=l+0.1, r1=r1, r2=r2, anchor=CENTER);
pie_slice(ang=ang, l=l+excess, r1=r1, r2=r2, anchor=CENTER);
children();
}
}
@ -49,13 +50,13 @@ module angle_pie_mask(
// Module: cylinder_mask()
// Usage: Mask objects
// cylinder_mask(l, r|d, chamfer, [chamfang], [from_end], [circum], [overage], [ends_only]);
// cylinder_mask(l, r|d, rounding, [circum], [overage], [ends_only]);
// cylinder_mask(l, r|d, [chamfer1|rounding1], [chamfer2|rounding2], [chamfang1], [chamfang2], [from_end], [circum], [overage], [ends_only]);
// cylinder_mask(l, r|d, chamfer, [chamfang], [from_end], [circum], [excess], [ends_only]);
// cylinder_mask(l, r|d, rounding, [circum], [excess], [ends_only]);
// cylinder_mask(l, r|d, [chamfer1|rounding1], [chamfer2|rounding2], [chamfang1], [chamfang2], [from_end], [circum], [excess], [ends_only]);
// Usage: Masking operators
// cylinder_mask(l, r|d, chamfer, [chamfang], [from_end], [circum], [overage], [ends_only]) ...
// cylinder_mask(l, r|d, rounding, [circum], [overage], [ends_only]) ...
// cylinder_mask(l, r|d, [chamfer1|rounding1], [chamfer2|rounding2], [chamfang1], [chamfang2], [from_end], [circum], [overage], [ends_only]) ...
// cylinder_mask(l, r|d, chamfer, [chamfang], [from_end], [circum], [excess], [ends_only]) ...
// cylinder_mask(l, r|d, rounding, [circum], [excess], [ends_only]) ...
// cylinder_mask(l, r|d, [chamfer1|rounding1], [chamfer2|rounding2], [chamfang1], [chamfang2], [from_end], [circum], [excess], [ends_only]) ...
// Description:
// If passed children, bevels/chamfers and/or rounds one or both
// ends of the origin-centered cylindrical region specified. If
@ -83,7 +84,7 @@ module angle_pie_mask(
// rounding2 = The radius of the rounding on the axis-positive end of the region.
// circum = If true, region will circumscribe the circle of the given radius/diameter.
// from_end = If true, chamfer/bevel size is measured from end of region. If false, chamfer/bevel is measured outset from the radius of the region. (Default: false)
// overage = The extra thickness of the mask. Default: `10`.
// excess = The extra thickness of the mask. Default: `10`.
// ends_only = If true, only mask the ends and not around the middle of the cylinder.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
@ -105,7 +106,7 @@ module cylinder_mask(
chamfang=undef, chamfang1=undef, chamfang2=undef,
rounding=undef, rounding1=undef, rounding2=undef,
circum=false, from_end=false,
overage=10, ends_only=false,
excess=10, ends_only=false,
anchor=CENTER, spin=0, orient=UP
) {
r1 = get_radius(r=r, d=d, r1=r1, d1=d1, dflt=1);
@ -132,12 +133,12 @@ module cylinder_mask(
chlen1 = cham1 / (from_end? 1 : tan(ang1));
chlen2 = cham2 / (from_end? 1 : tan(ang2));
if (!ends_only) {
cylinder(r=maxd+overage, h=l+2*overage, center=true);
cylinder(r=maxd+excess, h=l+2*excess, center=true);
} else {
if (cham2>0) up(l/2-chlen2) cylinder(r=maxd+overage, h=chlen2+overage, center=false);
if (cham1>0) down(l/2+overage) cylinder(r=maxd+overage, h=chlen1+overage, center=false);
if (fil2>0) up(l/2-fil2) cylinder(r=maxd+overage, h=fil2+overage, center=false);
if (fil1>0) down(l/2+overage) cylinder(r=maxd+overage, h=fil1+overage, center=false);
if (cham2>0) up(l/2-chlen2) cylinder(r=maxd+excess, h=chlen2+excess, center=false);
if (cham1>0) down(l/2+excess) cylinder(r=maxd+excess, h=chlen1+excess, center=false);
if (fil2>0) up(l/2-fil2) cylinder(r=maxd+excess, h=fil2+excess, center=false);
if (fil1>0) down(l/2+excess) cylinder(r=maxd+excess, h=fil1+excess, center=false);
}
}
cyl(r1=sc*r1, r2=sc*r2, l=l, chamfer1=cham1, chamfer2=cham2, chamfang1=ang1, chamfang2=ang2, from_end=from_end, rounding1=fil1, rounding2=fil2);
@ -154,14 +155,15 @@ module cylinder_mask(
// Module: chamfer_mask()
// Usage:
// chamfer_mask(l, chamfer);
// chamfer_mask(l, chamfer, [excess]);
// Description:
// Creates a shape that can be used to chamfer a 90 degree edge.
// Difference it from the object to be chamfered. The center of
// the mask object should align exactly with the edge to be chamfered.
// Arguments:
// l = Length of mask.
// chamfer = Size of chamfer
// chamfer = Size of chamfer.
// excess = The extra amount to add to the length of the mask so that it differences away from other shapes cleanly. Default: `0.1`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
@ -170,9 +172,9 @@ module cylinder_mask(
// cube(50, anchor=BOTTOM+FRONT);
// #chamfer_mask(l=50, chamfer=10, orient=RIGHT);
// }
module chamfer_mask(l=1, chamfer=1, anchor=CENTER, spin=0, orient=UP) {
module chamfer_mask(l=1, chamfer=1, excess=0.1, anchor=CENTER, spin=0, orient=UP) {
attachable(anchor,spin,orient, size=[chamfer*2, chamfer*2, l]) {
cylinder(r=chamfer, h=l+0.1, center=true, $fn=4);
cylinder(r=chamfer, h=l+excess, center=true, $fn=4);
children();
}
}
@ -180,14 +182,15 @@ module chamfer_mask(l=1, chamfer=1, anchor=CENTER, spin=0, orient=UP) {
// Module: chamfer_mask_x()
// Usage:
// chamfer_mask_x(l, chamfer, [anchor]);
// chamfer_mask_x(l, chamfer, [excess]);
// Description:
// Creates a shape that can be used to chamfer a 90 degree edge along the X axis.
// Difference it from the object to be chamfered. The center of the mask
// object should align exactly with the edge to be chamfered.
// Arguments:
// l = Height of mask
// chamfer = size of chamfer
// l = Length of mask.
// chamfer = Size of chamfer.
// excess = The extra amount to add to the length of the mask so that it differences away from other shapes cleanly. Default: `0.1`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the X axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// Example:
@ -195,21 +198,22 @@ module chamfer_mask(l=1, chamfer=1, anchor=CENTER, spin=0, orient=UP) {
// cube(50, anchor=BOTTOM+FRONT);
// #chamfer_mask_x(l=50, chamfer=10);
// }
module chamfer_mask_x(l=1.0, chamfer=1.0, anchor=CENTER, spin=0) {
chamfer_mask(l=l, chamfer=chamfer, anchor=anchor, spin=spin, orient=RIGHT) children();
module chamfer_mask_x(l=1.0, chamfer=1.0, excess=0.1, anchor=CENTER, spin=0) {
chamfer_mask(l=l, chamfer=chamfer, excess=excess, anchor=anchor, spin=spin, orient=RIGHT) children();
}
// Module: chamfer_mask_y()
// Usage:
// chamfer_mask_y(l, chamfer, [anchor]);
// chamfer_mask_y(l, chamfer, [excess]);
// Description:
// Creates a shape that can be used to chamfer a 90 degree edge along the Y axis.
// Difference it from the object to be chamfered. The center of the mask
// object should align exactly with the edge to be chamfered.
// Arguments:
// l = Height of mask
// chamfer = size of chamfer
// l = Length of mask.
// chamfer = Size of chamfer.
// excess = The extra amount to add to the length of the mask so that it differences away from other shapes cleanly. Default: `0.1`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Y axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// Example:
@ -217,21 +221,22 @@ module chamfer_mask_x(l=1.0, chamfer=1.0, anchor=CENTER, spin=0) {
// cube(50, anchor=BOTTOM+RIGHT);
// #chamfer_mask_y(l=50, chamfer=10);
// }
module chamfer_mask_y(l=1.0, chamfer=1.0, anchor=CENTER, spin=0) {
chamfer_mask(l=l, chamfer=chamfer, anchor=anchor, spin=spin, orient=BACK) children();
module chamfer_mask_y(l=1.0, chamfer=1.0, excess=0.1, anchor=CENTER, spin=0) {
chamfer_mask(l=l, chamfer=chamfer, excess=excess, anchor=anchor, spin=spin, orient=BACK) children();
}
// Module: chamfer_mask_z()
// Usage:
// chamfer_mask_z(l, chamfer, [anchor]);
// chamfer_mask_z(l, chamfer, [excess]);
// Description:
// Creates a shape that can be used to chamfer a 90 degree edge along the Z axis.
// Difference it from the object to be chamfered. The center of the mask
// object should align exactly with the edge to be chamfered.
// Arguments:
// l = Height of mask
// chamfer = size of chamfer
// l = Length of mask.
// chamfer = Size of chamfer.
// excess = The extra amount to add to the length of the mask so that it differences away from other shapes cleanly. Default: `0.1`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// Example:
@ -239,8 +244,8 @@ module chamfer_mask_y(l=1.0, chamfer=1.0, anchor=CENTER, spin=0) {
// cube(50, anchor=FRONT+RIGHT);
// #chamfer_mask_z(l=50, chamfer=10);
// }
module chamfer_mask_z(l=1.0, chamfer=1.0, anchor=CENTER, spin=0) {
chamfer_mask(l=l, chamfer=chamfer, anchor=anchor, spin=spin, orient=UP) children();
module chamfer_mask_z(l=1.0, chamfer=1.0, excess=0.1, anchor=CENTER, spin=0) {
chamfer_mask(l=l, chamfer=chamfer, excess=excess, anchor=anchor, spin=spin, orient=UP) children();
}
@ -313,7 +318,7 @@ module chamfer_cylinder_mask(r=undef, d=undef, chamfer=0.25, ang=45, from_end=fa
// Module: chamfer_hole_mask()
// Usage:
// chamfer_hole_mask(r|d, chamfer, [ang], [from_end]);
// chamfer_hole_mask(r|d, chamfer, [ang], [from_end], [excess]);
// Description:
// Create a mask that can be used to bevel/chamfer the end of a cylindrical hole.
// Difference it from the hole to be chamfered. The center of the mask object
@ -324,7 +329,7 @@ module chamfer_cylinder_mask(r=undef, d=undef, chamfer=0.25, ang=45, from_end=fa
// chamfer = Size of the chamfer. (Default: 0.25)
// ang = Angle of chamfer in degrees from vertical. (Default: 45)
// from_end = If true, chamfer size is measured from end of hole. If false, chamfer is measured outset from the radius of the hole. (Default: false)
// overage = The extra thickness of the mask. Default: `0.1`.
// excess = The extra thickness of the mask. Default: `0.1`.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
@ -341,8 +346,8 @@ module chamfer_cylinder_mask(r=undef, d=undef, chamfer=0.25, ang=45, from_end=fa
// up(50) chamfer_hole_mask(d=50, chamfer=10);
// }
// Example:
// chamfer_hole_mask(d=100, chamfer=25, ang=30, overage=10);
module chamfer_hole_mask(r=undef, d=undef, chamfer=0.25, ang=45, from_end=false, overage=0.1, anchor=CENTER, spin=0, orient=UP)
// chamfer_hole_mask(d=100, chamfer=25, ang=30, excess=10);
module chamfer_hole_mask(r=undef, d=undef, chamfer=0.25, ang=45, from_end=false, excess=0.1, anchor=CENTER, spin=0, orient=UP)
{
r = get_radius(r=r, d=d, dflt=1);
h = chamfer * (from_end? 1 : tan(90-ang));
@ -350,7 +355,7 @@ module chamfer_hole_mask(r=undef, d=undef, chamfer=0.25, ang=45, from_end=false,
$fn = segs(r);
attachable(anchor,spin,orient, r1=r, r2=r2, l=h*2) {
union() {
cylinder(r=r2, h=overage, center=false);
cylinder(r=r2, h=excess, center=false);
down(h) cylinder(r1=r, r2=r2, h=h, center=false);
}
children();
@ -363,8 +368,8 @@ module chamfer_hole_mask(r=undef, d=undef, chamfer=0.25, ang=45, from_end=false,
// Module: rounding_mask()
// Usage:
// rounding_mask(l|h, r)
// rounding_mask(l|h, r1, r2)
// rounding_mask(l|h, r|d)
// rounding_mask(l|h, r1|d1, r2|d2)
// Description:
// Creates a shape that can be used to round a vertical 90 degree edge.
// Difference it from the object to be rounded. The center of the mask
@ -374,6 +379,9 @@ module chamfer_hole_mask(r=undef, d=undef, chamfer=0.25, ang=45, from_end=false,
// r = Radius of the rounding.
// r1 = Bottom radius of rounding.
// r2 = Top radius of rounding.
// d = Diameter of the rounding.
// d1 = Bottom diameter of rounding.
// d2 = Top diameter of rounding.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
@ -404,11 +412,11 @@ module chamfer_hole_mask(r=undef, d=undef, chamfer=0.25, ang=45, from_end=false,
// rounding_mask(l=p.x, r=25, spin=45, orient=RIGHT);
// }
// }
module rounding_mask(l=undef, r=undef, r1=undef, r2=undef, anchor=CENTER, spin=0, orient=UP, h=undef)
module rounding_mask(l, r, r1, r2, d, d1, d2, anchor=CENTER, spin=0, orient=UP, h=undef)
{
l = first_defined([l, h, 1]);
r1 = get_radius(r1=r1, r=r, dflt=1);
r2 = get_radius(r1=r2, r=r, dflt=1);
r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=1);
r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=1);
sides = quantup(segs(max(r1,r2)),4);
attachable(anchor,spin,orient, size=[2*r1,2*r1,l], size2=[2*r2,2*r2]) {
if (r1<r2) {
@ -435,8 +443,8 @@ module rounding_mask(l=undef, r=undef, r1=undef, r2=undef, anchor=CENTER, spin=0
// Module: rounding_mask_x()
// Usage:
// rounding_mask_x(l, r, [anchor])
// rounding_mask_x(l, r1, r2, [anchor])
// rounding_mask_x(l, r|d, [anchor])
// rounding_mask_x(l, r1|d1, r2|d2, [anchor])
// Description:
// Creates a shape that can be used to round a 90 degree edge oriented
// along the X axis. Difference it from the object to be rounded.
@ -447,6 +455,9 @@ module rounding_mask(l=undef, r=undef, r1=undef, r2=undef, anchor=CENTER, spin=0
// r = Radius of the rounding.
// r1 = Left end radius of rounding.
// r2 = Right end radius of rounding.
// d = Diameter of the rounding.
// d1 = Left end diameter of rounding.
// d2 = Right end diameter of rounding.
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// Example:
// difference() {
@ -458,10 +469,10 @@ module rounding_mask(l=undef, r=undef, r1=undef, r2=undef, anchor=CENTER, spin=0
// cube(size=100, center=false);
// #rounding_mask_x(l=100, r1=10, r2=30, anchor=LEFT);
// }
module rounding_mask_x(l=1.0, r=undef, r1=undef, r2=undef, anchor=CENTER, spin=0)
module rounding_mask_x(l=1.0, r, r1, r2, d, d1, d2, anchor=CENTER, spin=0)
{
anchor = rot(p=anchor, from=RIGHT, to=TOP);
rounding_mask(l=l, r=r, r1=r1, r2=r2, anchor=anchor, spin=spin, orient=RIGHT) {
rounding_mask(l=l, r=r, r1=r1, r2=r2, d=d, d1=d1, d2=d2, anchor=anchor, spin=spin, orient=RIGHT) {
for (i=[0:1:$children-2]) children(i);
if ($children) children($children-1);
}
@ -470,8 +481,8 @@ module rounding_mask_x(l=1.0, r=undef, r1=undef, r2=undef, anchor=CENTER, spin=0
// Module: rounding_mask_y()
// Usage:
// rounding_mask_y(l, r, [anchor])
// rounding_mask_y(l, r1, r2, [anchor])
// rounding_mask_y(l, r|d, [anchor])
// rounding_mask_y(l, r1|d1, r2|d2, [anchor])
// Description:
// Creates a shape that can be used to round a 90 degree edge oriented
// along the Y axis. Difference it from the object to be rounded.
@ -482,6 +493,9 @@ module rounding_mask_x(l=1.0, r=undef, r1=undef, r2=undef, anchor=CENTER, spin=0
// r = Radius of the rounding.
// r1 = Front end radius of rounding.
// r2 = Back end radius of rounding.
// d = Diameter of the rounding.
// d1 = Front end diameter of rounding.
// d2 = Back end diameter of rounding.
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// Example:
// difference() {
@ -493,10 +507,10 @@ module rounding_mask_x(l=1.0, r=undef, r1=undef, r2=undef, anchor=CENTER, spin=0
// cube(size=100, center=false);
// right(100) #rounding_mask_y(l=100, r1=10, r2=30, anchor=FRONT);
// }
module rounding_mask_y(l=1.0, r=undef, r1=undef, r2=undef, anchor=CENTER, spin=0)
module rounding_mask_y(l=1.0, r, r1, r2, d, d1, d2, anchor=CENTER, spin=0)
{
anchor = rot(p=anchor, from=BACK, to=TOP);
rounding_mask(l=l, r=r, r1=r1, r2=r2, anchor=anchor, spin=spin, orient=BACK) {
rounding_mask(l=l, r=r, r1=r1, r2=r2, d=d, d1=d1, d2=d2, anchor=anchor, spin=spin, orient=BACK) {
for (i=[0:1:$children-2]) children(i);
if ($children) children($children-1);
}
@ -505,8 +519,8 @@ module rounding_mask_y(l=1.0, r=undef, r1=undef, r2=undef, anchor=CENTER, spin=0
// Module: rounding_mask_z()
// Usage:
// rounding_mask_z(l, r, [anchor])
// rounding_mask_z(l, r1, r2, [anchor])
// rounding_mask_z(l, r|d, [anchor])
// rounding_mask_z(l, r1|d1, r2|d2, [anchor])
// Description:
// Creates a shape that can be used to round a 90 degree edge oriented
// along the Z axis. Difference it from the object to be rounded.
@ -517,6 +531,9 @@ module rounding_mask_y(l=1.0, r=undef, r1=undef, r2=undef, anchor=CENTER, spin=0
// r = Radius of the rounding.
// r1 = Bottom radius of rounding.
// r2 = Top radius of rounding.
// d = Diameter of the rounding.
// d1 = Bottom diameter of rounding.
// d2 = Top diameter of rounding.
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// Example:
// difference() {
@ -528,9 +545,9 @@ module rounding_mask_y(l=1.0, r=undef, r1=undef, r2=undef, anchor=CENTER, spin=0
// cube(size=100, center=false);
// #rounding_mask_z(l=100, r1=10, r2=30, anchor=BOTTOM);
// }
module rounding_mask_z(l=1.0, r=undef, r1=undef, r2=undef, anchor=CENTER, spin=0)
module rounding_mask_z(l=1.0, r, r1, r2, d, d1, d2, anchor=CENTER, spin=0)
{
rounding_mask(l=l, r=r, r1=r1, r2=r2, anchor=anchor, spin=spin, orient=UP) {
rounding_mask(l=l, r=r, r1=r1, r2=r2, d=d, d1=d1, d2=d2, anchor=anchor, spin=spin, orient=UP) {
for (i=[0:1:$children-2]) children(i);
if ($children) children($children-1);
}
@ -539,11 +556,12 @@ module rounding_mask_z(l=1.0, r=undef, r1=undef, r2=undef, anchor=CENTER, spin=0
// Module: rounding()
// Usage:
// rounding(r, size, [edges]) ...
// rounding(r|d, size, [edges]) ...
// Description:
// Rounds the edges of a cuboid region containing the given children.
// Arguments:
// r = Radius of the rounding. (Default: 1)
// d = Diameter of the rounding. (Default: 1)
// size = The size of the rectangular cuboid we want to chamfer.
// edges = Edges to round. See the docs for [`edges()`](edges.scad#edges) to see acceptable values. Default: All edges.
// except_edges = Edges to explicitly NOT round. See the docs for [`edges()`](edges.scad#edges) to see acceptable values. Default: No edges.
@ -555,8 +573,9 @@ module rounding_mask_z(l=1.0, r=undef, r1=undef, r2=undef, anchor=CENTER, spin=0
// rounding(r=10, size=[50,50,75], edges=[TOP,FRONT+RIGHT], except_edges=TOP+LEFT, $fn=24) {
// cube(size=[50,50,75], center=true);
// }
module rounding(r=1, size=[1,1,1], edges=EDGES_ALL, except_edges=[])
module rounding(r, size=[1,1,1], d, edges=EDGES_ALL, except_edges=[])
{
r = get_radius(r=r, d=d, dflt=1);
difference() {
children();
difference() {
@ -569,8 +588,8 @@ module rounding(r=1, size=[1,1,1], edges=EDGES_ALL, except_edges=[])
// Module: rounding_angled_edge_mask()
// Usage:
// rounding_angled_edge_mask(h, r, [ang]);
// rounding_angled_edge_mask(h, r1, r2, [ang]);
// rounding_angled_edge_mask(h, r|d, [ang]);
// rounding_angled_edge_mask(h, r1|d1, r2|d2, [ang]);
// Description:
// Creates a vertical mask that can be used to round the edge where two face meet, at any arbitrary
// angle. Difference it from the object to be rounded. The center of the mask should align exactly
@ -580,6 +599,9 @@ module rounding(r=1, size=[1,1,1], edges=EDGES_ALL, except_edges=[])
// r = Radius of the rounding.
// r1 = Bottom radius of rounding.
// r2 = Top radius of rounding.
// d = Diameter of the rounding.
// d1 = Bottom diameter of rounding.
// d2 = Top diameter of rounding.
// ang = Angle that the planes meet at.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
@ -594,7 +616,7 @@ module rounding(r=1, size=[1,1,1], edges=EDGES_ALL, except_edges=[])
// angle_pie_mask(ang=70, h=50, d=100);
// #rounding_angled_edge_mask(h=51, r1=10, r2=25, ang=70, $fn=32);
// }
module rounding_angled_edge_mask(h=1.0, r=undef, r1=undef, r2=undef, ang=90, anchor=CENTER, spin=0, orient=UP)
module rounding_angled_edge_mask(h=1.0, r, r1, r2, d, d1, d2, ang=90, anchor=CENTER, spin=0, orient=UP)
{
function _mask_shape(r) = [
for (i = [0:1:n]) let (a=90+ang+i*sweep/n) [r*cos(a)+x, r*sin(a)+r],
@ -604,8 +626,8 @@ module rounding_angled_edge_mask(h=1.0, r=undef, r1=undef, r2=undef, ang=90, anc
];
sweep = 180-ang;
r1 = get_radius(r1=r1, r=r, dflt=1);
r2 = get_radius(r1=r2, r=r, dflt=1);
r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=1);
r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=1);
n = ceil(segs(max(r1,r2))*sweep/360);
x = sin(90-(ang/2))/sin(ang/2) * (r1<r2? r2 : r1);
if(r1<r2) {
@ -630,13 +652,14 @@ module rounding_angled_edge_mask(h=1.0, r=undef, r1=undef, r2=undef, ang=90, anc
// Module: rounding_angled_corner_mask()
// Usage:
// rounding_angled_corner_mask(r, ang);
// rounding_angled_corner_mask(r|d, ang);
// Description:
// Creates a shape that can be used to round the corner of an angle.
// Difference it from the object to be rounded. The center of the mask
// object should align exactly with the point of the corner to be rounded.
// Arguments:
// r = Radius of the rounding.
// d = Diameter of the rounding.
// ang = Angle between planes that you need to round the corner of.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
@ -651,8 +674,9 @@ module rounding_angled_edge_mask(h=1.0, r=undef, r1=undef, r2=undef, ang=90, anc
// }
// rounding_angled_edge_mask(h=51, r=20, ang=ang);
// }
module rounding_angled_corner_mask(r=1.0, ang=90, anchor=CENTER, spin=0, orient=UP)
module rounding_angled_corner_mask(r, ang=90, d, anchor=CENTER, spin=0, orient=UP)
{
r = get_radius(r=r, d=d, dflt=1);
dx = r / tan(ang/2);
dx2 = dx / cos(ang/2) + 1;
fn = quantup(segs(r), 4);
@ -678,13 +702,14 @@ module rounding_angled_corner_mask(r=1.0, ang=90, anchor=CENTER, spin=0, orient=
// Module: rounding_corner_mask()
// Usage:
// rounding_corner_mask(r, [anchor]);
// rounding_corner_mask(r|d, [anchor]);
// Description:
// Creates a shape that you can use to round 90 degree corners.
// Difference it from the object to be rounded. The center of the mask
// object should align exactly with the corner to be rounded.
// Arguments:
// r = Radius of corner rounding.
// d = Diameter of corner rounding.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
@ -698,8 +723,9 @@ module rounding_angled_corner_mask(r=1.0, ang=90, anchor=CENTER, spin=0, orient=
// translate([15, 25, 0]) rounding_mask_z(l=81, r=15);
// translate([15, 25, 40]) #rounding_corner_mask(r=15);
// }
module rounding_corner_mask(r=1.0, anchor=CENTER, spin=0, orient=UP)
module rounding_corner_mask(r, d, anchor=CENTER, spin=0, orient=UP)
{
r = get_radius(r=r, d=d, dflt=1);
attachable(anchor,spin,orient, size=[2,2,2]*r) {
difference() {
cube(size=r*2, center=true);
@ -714,7 +740,7 @@ module rounding_corner_mask(r=1.0, anchor=CENTER, spin=0, orient=UP)
// Module: rounding_cylinder_mask()
// Usage:
// rounding_cylinder_mask(r, rounding);
// rounding_cylinder_mask(r|d, rounding);
// Description:
// Create a mask that can be used to round the end of a cylinder.
// Difference it from the cylinder to be rounded. The center of the
@ -722,6 +748,7 @@ module rounding_corner_mask(r=1.0, anchor=CENTER, spin=0, orient=UP)
// cylinder to be rounded.
// Arguments:
// r = Radius of cylinder. (Default: 1.0)
// d = Diameter of cylinder. (Default: 1.0)
// rounding = Radius of the edge rounding. (Default: 0.25)
// Example:
// difference() {
@ -733,16 +760,17 @@ module rounding_corner_mask(r=1.0, anchor=CENTER, spin=0, orient=UP)
// cylinder(r=50, h=50, center=false);
// up(50) rounding_cylinder_mask(r=50, rounding=10);
// }
module rounding_cylinder_mask(r=1.0, rounding=0.25)
module rounding_cylinder_mask(r, rounding=0.25, d)
{
cylinder_mask(l=rounding*3, r=r, rounding2=rounding, overage=rounding, ends_only=true, anchor=TOP);
r = get_radius(r=r, d=d, dflt=1);
cylinder_mask(l=rounding*3, r=r, rounding2=rounding, excess=rounding, ends_only=true, anchor=TOP);
}
// Module: rounding_hole_mask()
// Usage:
// rounding_hole_mask(r|d, rounding);
// rounding_hole_mask(r|d, rounding, [excess]);
// Description:
// Create a mask that can be used to round the edge of a circular hole.
// Difference it from the hole to be rounded. The center of the
@ -752,7 +780,7 @@ module rounding_cylinder_mask(r=1.0, rounding=0.25)
// r = Radius of hole.
// d = Diameter of hole to rounding.
// rounding = Radius of the rounding. (Default: 0.25)
// overage = The extra thickness of the mask. Default: `0.1`.
// excess = The extra thickness of the mask. Default: `0.1`.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
@ -770,13 +798,13 @@ module rounding_cylinder_mask(r=1.0, rounding=0.25)
// }
// Example:
// rounding_hole_mask(r=40, rounding=20, $fa=2, $fs=2);
module rounding_hole_mask(r=undef, d=undef, rounding=0.25, overage=0.1, anchor=CENTER, spin=0, orient=UP)
module rounding_hole_mask(r, rounding=0.25, excess=0.1, d, anchor=CENTER, spin=0, orient=UP)
{
r = get_radius(r=r, d=d, dflt=1);
attachable(anchor,spin,orient, r=r+rounding, l=2*rounding) {
rotate_extrude(convexity=4) {
difference() {
right(r-overage) fwd(rounding) square(rounding+overage, center=false);
right(r-excess) fwd(rounding) square(rounding+excess, center=false);
right(r+rounding) fwd(rounding) circle(r=rounding);
}
}
@ -808,7 +836,7 @@ module rounding_hole_mask(r=undef, d=undef, rounding=0.25, overage=0.1, anchor=C
// corner_profile(BOT,r=10)
// mask2d_teardrop(r=10, angle=40);
// }
module teardrop_corner_mask(r, d, angle, excess=0.1, anchor=CENTER, spin=0, orient=UP) {
module teardrop_corner_mask(r, angle, excess=0.1, d, anchor=CENTER, spin=0, orient=UP) {
assert(is_num(angle));
assert(is_num(excess));
assert(angle>0 && angle<90);

119
math.scad
View file

@ -864,6 +864,123 @@ function is_matrix(A,m,n,square=false) =
// Section: Comparisons and Logic
// Function: is_zero()
// Usage:
// is_zero(x);
// Description:
// Returns true if the number passed to it is approximately zero, to within `eps`.
// If passed a list, recursively checks if all items in the list are approximately zero.
// Otherwise, returns false.
// Arguments:
// x = The value to check.
// eps = The maximum allowed variance. Default: `EPSILON` (1e-9)
// Example:
// is_zero(0); // Returns: true.
// is_zero(1e-3); // Returns: false.
// is_zero([0,0,0]); // Returns: true.
// is_zero([0,0,1e-3]); // Returns: false.
function is_zero(x, eps=EPSILON) =
is_list(x)? (x != [] && [for (xx=x) if(!is_zero(xx,eps=eps)) 1] == []) :
is_num(x)? approx(x,eps) :
false;
// Function: is_positive()
// Usage:
// is_positive(x);
// Description:
// Returns true if the number passed to it is greater than zero.
// If passed a list, recursively checks if all items in the list are positive.
// Otherwise, returns false.
// Arguments:
// x = The value to check.
// Example:
// is_positive(-2); // Returns: false.
// is_positive(0); // Returns: false.
// is_positive(2); // Returns: true.
// is_positive([0,0,0]); // Returns: false.
// is_positive([0,1,2]); // Returns: false.
// is_positive([3,1,2]); // Returns: true.
// is_positive([3,-1,2]); // Returns: false.
function is_positive(x) =
is_list(x)? (x != [] && [for (xx=x) if(!is_positive(xx)) 1] == []) :
is_num(x)? x>0 :
false;
// Function: is_negative()
// Usage:
// is_negative(x);
// Description:
// Returns true if the number passed to it is less than zero.
// If passed a list, recursively checks if all items in the list are negative.
// Otherwise, returns false.
// Arguments:
// x = The value to check.
// Example:
// is_negative(-2); // Returns: true.
// is_negative(0); // Returns: false.
// is_negative(2); // Returns: false.
// is_negative([0,0,0]); // Returns: false.
// is_negative([0,1,2]); // Returns: false.
// is_negative([3,1,2]); // Returns: false.
// is_negative([3,-1,2]); // Returns: false.
// is_negative([-3,-1,-2]); // Returns: true.
function is_negative(x) =
is_list(x)? (x != [] && [for (xx=x) if(!is_negative(xx)) 1] == []) :
is_num(x)? x<0 :
false;
// Function: is_nonpositive()
// Usage:
// is_nonpositive(x);
// Description:
// Returns true if the number passed to it is less than or equal to zero.
// If passed a list, recursively checks if all items in the list are nonpositive.
// Otherwise, returns false.
// Arguments:
// x = The value to check.
// Example:
// is_nonpositive(-2); // Returns: true.
// is_nonpositive(0); // Returns: true.
// is_nonpositive(2); // Returns: false.
// is_nonpositive([0,0,0]); // Returns: true.
// is_nonpositive([0,1,2]); // Returns: false.
// is_nonpositive([3,1,2]); // Returns: false.
// is_nonpositive([3,-1,2]); // Returns: false.
// is_nonpositive([-3,-1,-2]); // Returns: true.
function is_nonpositive(x) =
is_list(x)? (x != [] && [for (xx=x) if(!is_nonpositive(xx)) 1] == []) :
is_num(x)? x<=0 :
false;
// Function: is_nonnegative()
// Usage:
// is_nonnegative(x);
// Description:
// Returns true if the number passed to it is greater than or equal to zero.
// If passed a list, recursively checks if all items in the list are nonnegative.
// Otherwise, returns false.
// Arguments:
// x = The value to check.
// Example:
// is_nonnegative(-2); // Returns: false.
// is_nonnegative(0); // Returns: true.
// is_nonnegative(2); // Returns: true.
// is_nonnegative([0,0,0]); // Returns: true.
// is_nonnegative([0,1,2]); // Returns: true.
// is_nonnegative([0,-1,-2]); // Returns: false.
// is_nonnegative([3,1,2]); // Returns: true.
// is_nonnegative([3,-1,2]); // Returns: false.
// is_nonnegative([-3,-1,-2]); // Returns: false.
function is_nonnegative(x) =
is_list(x)? (x != [] && [for (xx=x) if(!is_nonnegative(xx)) 1] == []) :
is_num(x)? x>=0 :
false;
// Function: approx()
// Usage:
// approx(a,b,[eps])
@ -1382,4 +1499,4 @@ function real_roots(p,eps=undef,tol=1e-14) =
? [for(z=roots) if (abs(z.y)/(1+norm(z))<eps) z.x]
: [for(i=idx(roots)) if (abs(roots[i].y)<=err[i]) roots[i].x];
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap

View file

@ -321,7 +321,7 @@ module chain_hull()
// Usage:
// cylindrical_extrude(size, ir|id, or|od, [convexity]) ...
// Description:
// Cylindrically extrudes all 2D children, curved around a cylidrical shape.
// Extrudes all 2D children outwards, curved around a cylindrical shape.
// Arguments:
// or = The outer radius to extrude to.
// od = The outer diameter to extrude to.

View file

@ -418,7 +418,7 @@ function path_torsion(path, closed=false) =
// scale = [X,Y] scaling factors for each axis. Default: `[1,1]`
// Example(3D):
// trace_polyline(path3d_spiral(turns=2.5, h=100, n=24, r=50), N=1, showpts=true);
function path3d_spiral(turns=3, h=100, n=12, r=undef, d=undef, cp=[0,0], scale=[1,1]) = let(
function path3d_spiral(turns=3, h=100, n=12, r, d, cp=[0,0], scale=[1,1]) = let(
rr=get_radius(r=r, d=d, dflt=100),
cnt=floor(turns*n),
dz=h/cnt
@ -774,15 +774,19 @@ function assemble_path_fragments(fragments, eps=EPSILON, _finished=[]) =
// Module: modulated_circle()
// Usage:
// modulated_circle(r|d, sines);
// Description:
// Creates a 2D polygon circle, modulated by one or more superimposed sine waves.
// Arguments:
// r = radius of the base circle.
// r = Radius of the base circle. Default: 40
// d = Diameter of the base circle.
// sines = array of [amplitude, frequency] pairs, where the frequency is the number of times the cycle repeats around the circle.
// Example(2D):
// modulated_circle(r=40, sines=[[3, 11], [1, 31]], $fn=6);
module modulated_circle(r=40, sines=[10])
module modulated_circle(r, sines=[10], d)
{
r = get_radius(r=r, d=d, dflt=40);
freqs = len(sines)>0? [for (i=sines) i[1]] : [5];
points = [
for (a = [0 : (360/segs(r)/max(freqs)) : 360])
@ -829,7 +833,8 @@ module extrude_from_to(pt1, pt2, convexity=undef, twist=undef, scale=undef, slic
// Arguments:
// polyline = Array of points of a polyline path, to be extruded.
// h = height of the spiral to extrude along.
// r = radius of the spiral to extrude along.
// r = Radius of the spiral to extrude along. Default: 50
// d = Diameter of the spiral to extrude along.
// twist = number of degrees of rotation to spiral up along height.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
@ -838,7 +843,8 @@ module extrude_from_to(pt1, pt2, convexity=undef, twist=undef, scale=undef, slic
// Example:
// poly = [[-10,0], [-3,-5], [3,-5], [10,0], [0,-30]];
// spiral_sweep(poly, h=200, r=50, twist=1080, $fn=36);
module spiral_sweep(polyline, h, r, twist=360, center, anchor, spin=0, orient=UP) {
module spiral_sweep(polyline, h, r, twist=360, center, d, anchor, spin=0, orient=UP) {
r = get_radius(r=r, d=d, dflt=50);
polyline = path3d(polyline);
pline_count = len(polyline);
steps = ceil(segs(r)*(twist/360));

View file

@ -730,9 +730,10 @@ function stellate_faces(scalefactor,stellate,vertices,faces_normals) =
) [newfaces, normals, allpts];
function trapezohedron(faces, r, side, longside, h) =
function trapezohedron(faces, r, side, longside, h, d) =
assert(faces%2==0, "Number of faces must be even")
let(
r = get_radius(r=r, d=d, dflt=1),
N = faces/2,
parmcount = num_defined([r,side,longside,h])
)

View file

@ -1498,13 +1498,14 @@ module pie_slice(
// Center this part along the concave edge to be chamfered and union it in.
//
// Usage:
// interior_fillet(l, r, [ang], [overlap]);
// interior_fillet(l, r|d, [ang], [overlap]);
//
// Arguments:
// l = length of edge to fillet.
// r = radius of fillet.
// ang = angle between faces to fillet.
// overlap = overlap size for unioning with faces.
// l = Length of edge to fillet.
// r = Radius of fillet.
// d = Diameter of fillet.
// ang = Angle between faces to fillet.
// overlap = Overlap size for unioning with faces.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `FRONT+LEFT`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
@ -1526,7 +1527,8 @@ module pie_slice(
// position(BOT+FRONT)
// interior_fillet(l=50, r=10, spin=180, orient=RIGHT);
// }
module interior_fillet(l=1.0, r=1.0, ang=90, overlap=0.01, anchor=FRONT+LEFT, spin=0, orient=UP) {
module interior_fillet(l=1.0, r, ang=90, overlap=0.01, d, anchor=FRONT+LEFT, spin=0, orient=UP) {
r = get_radius(r=r, d=d, dflt=1);
dy = r/tan(ang/2);
steps = ceil(segs(r)*ang/360);
step = ang/steps;

View file

@ -29,6 +29,7 @@ test_point3d();
module test_path3d() {
assert(path3d([[1,2], [3,4], [5,6], [7,8]])==[[1,2,0],[3,4,0],[5,6,0],[7,8,0]]);
assert(path3d([[1,2], [3,4], [5,6], [7,8]],9)==[[1,2,9],[3,4,9],[5,6,9],[7,8,9]]);
assert(path3d([[1,2,3], [2,3,4], [3,4,5], [4,5,6]])==[[1,2,3],[2,3,4],[3,4,5],[4,5,6]]);
assert(path3d([[1,2,3,4], [2,3,4,5], [3,4,5,6], [4,5,6,7]])==[[1,2,3],[2,3,4],[3,4,5],[4,5,6]]);
}
@ -41,6 +42,9 @@ module test_point4d() {
assert(point4d([1,2,3])==[1,2,3,0]);
assert(point4d([2,3])==[2,3,0,0]);
assert(point4d([1])==[1,0,0,0]);
assert(point4d([1,2,3],9)==[1,2,3,9]);
assert(point4d([2,3],9)==[2,3,9,9]);
assert(point4d([1],9)==[1,9,9,9]);
}
test_point4d();

View file

@ -100,6 +100,106 @@ module test_is_matrix() {
test_is_matrix();
module test_is_zero() {
assert(is_zero(0));
assert(is_zero([0,0,0]));
assert(is_zero([[0,0,0],[0,0]]));
assert(is_zero([EPSILON/2,EPSILON/2,EPSILON/2]));
assert(!is_zero(1e-3));
assert(!is_zero([0,0,1e-3]));
assert(!is_zero([EPSILON*10,0,0]));
assert(!is_zero([0,EPSILON*10,0]));
assert(!is_zero([0,0,EPSILON*10]));
assert(!is_zero(true));
assert(!is_zero(false));
assert(!is_zero(INF));
assert(!is_zero(-INF));
assert(!is_zero(NAN));
assert(!is_zero("foo"));
assert(!is_zero([]));
assert(!is_zero([0:1:2]));
}
test_is_zero();
module test_is_positive() {
assert(!is_positive(-2));
assert(!is_positive(0));
assert(is_positive(2));
assert(!is_positive([0,0,0]));
assert(!is_positive([0,1,2]));
assert(is_positive([3,1,2]));
assert(!is_positive([3,-1,2]));
assert(!is_positive([]));
assert(!is_positive(true));
assert(!is_positive(false));
assert(!is_positive("foo"));
assert(!is_positive([0:1:2]));
}
test_is_positive();
module test_is_negative() {
assert(is_negative(-2));
assert(!is_negative(0));
assert(!is_negative(2));
assert(!is_negative([0,0,0]));
assert(!is_negative([0,1,2]));
assert(!is_negative([3,1,2]));
assert(!is_negative([3,-1,2]));
assert(is_negative([-3,-1,-2]));
assert(!is_negative([-3,1,-2]));
assert(is_negative([[-5,-7],[-3,-1,-2]]));
assert(!is_negative([[-5,-7],[-3,1,-2]]));
assert(!is_negative([]));
assert(!is_negative(true));
assert(!is_negative(false));
assert(!is_negative("foo"));
assert(!is_negative([0:1:2]));
}
test_is_negative();
module test_is_nonpositive() {
assert(is_nonpositive(-2));
assert(is_nonpositive(0));
assert(!is_nonpositive(2));
assert(is_nonpositive([0,0,0]));
assert(!is_nonpositive([0,1,2]));
assert(is_nonpositive([0,-1,-2]));
assert(!is_nonpositive([3,1,2]));
assert(!is_nonpositive([3,-1,2]));
assert(!is_nonpositive([]));
assert(!is_nonpositive(true));
assert(!is_nonpositive(false));
assert(!is_nonpositive("foo"));
assert(!is_nonpositive([0:1:2]));
}
test_is_nonpositive();
module test_is_nonnegative() {
assert(!is_nonnegative(-2));
assert(is_nonnegative(0));
assert(is_nonnegative(2));
assert(is_nonnegative([0,0,0]));
assert(is_nonnegative([0,1,2]));
assert(is_nonnegative([3,1,2]));
assert(!is_nonnegative([3,-1,2]));
assert(!is_nonnegative([-3,-1,-2]));
assert(!is_nonnegative([[-5,-7],[-3,-1,-2]]));
assert(!is_nonnegative([[-5,-7],[-3,1,-2]]));
assert(!is_nonnegative([[5,7],[3,-1,2]]));
assert(is_nonnegative([[5,7],[3,1,2]]));
assert(!is_nonnegative([]));
assert(!is_nonnegative(true));
assert(!is_nonnegative(false));
assert(!is_nonnegative("foo"));
assert(!is_nonnegative([0:1:2]));
}
test_is_nonnegative();
module test_approx() {
assert_equal(approx(PI, 3.141592653589793236), true);
assert_equal(approx(PI, 3.1415926), false);
@ -924,4 +1024,4 @@ module test_poly_add(){
}
test_poly_add();
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap

View file

@ -306,11 +306,11 @@ function up(z=0,p=undef) = move([0,0,z],p=p);
// * Called as a function with a `p` argument containing a list of points, returns the list of rotated points.
// * Called as a function with a [bezier patch](beziers.scad) in the `p` argument, returns the rotated patch.
// * Called as a function with a [VNF structure](vnf.scad) in the `p` argument, returns the rotated VNF.
// * Called as a function without a `p` argument, and `planar` is true, returns the affine2d rotational matrix.
// * Called as a function without a `p` argument, and `planar` is true, returns the affine2d rotational matrix. Requires that `a` is a finite scalar.
// * Called as a function without a `p` argument, and `planar` is false, returns the affine3d rotational matrix.
//
// Arguments:
// a = Scalar angle or vector of XYZ rotation angles to rotate by, in degrees.
// a = Scalar angle or vector of XYZ rotation angles to rotate by, in degrees. If `planar` is true and `p` is not given, then `a` must be a finite scalar. Default: `0`
// v = vector for the axis of rotation. Default: [0,0,1] or UP
// cp = centerpoint to rotate around. Default: [0,0,0]
// from = Starting vector for vector-based rotations.
@ -343,16 +343,21 @@ module rot(a=0, v=undef, cp=undef, from=undef, to=undef, reverse=false)
function rot(a=0, v, cp, from, to, reverse=false, planar=false, p, _m) =
assert(is_undef(from)==is_undef(to), "from and to must be specified together.")
assert(is_undef(from) || is_vector(from, zero=false), "'from' must be a non-zero vector.")
assert(is_undef(to) || is_vector(to, zero=false), "'to' must be a non-zero vector.")
assert(is_undef(v) || is_vector(v, zero=false), "'v' must be a non-zero vector.")
assert(is_undef(cp) || is_vector(cp), "'cp' must be a vector.")
assert(is_finite(a) || is_vector(a), "'a' must be a finite scalar or a vector.")
assert(is_bool(reverse))
assert(is_bool(planar))
is_undef(p)? (
planar? let(
check = assert(is_num(a)),
cp = is_undef(cp)? cp : point2d(cp),
m1 = is_undef(from)? affine2d_zrot(a) :
assert(is_vector(from))
assert(!approx(norm(from),0))
assert(approx(point3d(from).z, 0))
assert(is_vector(to))
assert(!approx(norm(to),0))
assert(approx(point3d(to).z, 0))
assert(a==0, "'from' and 'to' cannot be used with 'a' when 'planar' is true.")
assert(approx(point3d(from).z, 0), "'from' must be a 2D vector when 'planar' is true.")
assert(approx(point3d(to).z, 0), "'to' must be a 2D vector when 'planar' is true.")
affine2d_zrot(
vang(point2d(to)) -
vang(point2d(from))
@ -364,13 +369,10 @@ function rot(a=0, v, cp, from, to, reverse=false, planar=false, p, _m) =
to = is_undef(to)? undef : point3d(to),
cp = is_undef(cp)? undef : point3d(cp),
m1 = !is_undef(from)? (
assert(is_vector(from))
assert(!approx(norm(from),0))
assert(is_vector(to))
assert(!approx(norm(to),0))
assert(is_num(a))
affine3d_rot_from_to(from,to) * affine3d_zrot(a)
) :
!is_undef(v)? affine3d_rot_by_axis(v,a) :
!is_undef(v)? assert(is_num(a)) affine3d_rot_by_axis(v,a) :
is_num(a)? affine3d_zrot(a) :
affine3d_zrot(a.z) * affine3d_yrot(a.y) * affine3d_xrot(a.x),
m2 = is_undef(cp)? m1 : (move(cp) * m1 * move(-cp)),

View file

@ -8,7 +8,7 @@
//////////////////////////////////////////////////////////////////////
BOSL_VERSION = [2,0,405];
BOSL_VERSION = [2,0,410];
// Section: BOSL Library Version Functions