mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2025-12-09 15:29:09 +00:00
add mask2d_smooth
This commit is contained in:
parent
c3dfb91f41
commit
4d097abcd8
1 changed files with 123 additions and 0 deletions
123
masks.scad
123
masks.scad
|
|
@ -236,6 +236,128 @@ function mask2d_roundover(r, inset=0, mask_angle=90, excess=0.01, clip_angle, fl
|
||||||
) reorient(anchor,spin, two_d=true, path=path, extent=false, p=path);
|
) reorient(anchor,spin, two_d=true, path=path, extent=false, p=path);
|
||||||
|
|
||||||
|
|
||||||
|
// Function&Module: mask2d_smooth()
|
||||||
|
// Synopsis: Creates a continuous curvature mask for rounding edges.
|
||||||
|
// SynTags: Geom, Path
|
||||||
|
// Topics: Shapes (2D), Paths (2D), Path Generators, Attachable, Masks (2D)
|
||||||
|
// See Also: corner_profile(), edge_profile(), face_profile()
|
||||||
|
// Usage: As module
|
||||||
|
// mask2d_smooth([mask_angle], [cut=], [joint=], [inset=], [excess=], [flat_top=], [anchor=], [spin=]) [ATTACHMENTS];
|
||||||
|
// Usage: As function
|
||||||
|
// path = mask2d_smooth([mask_angle], [cut=], [joint=], [inset=], [excess=], [flat_top=], [anchor=], [spin=]);
|
||||||
|
// Description:
|
||||||
|
// Creates a 2D continuous curvature rounding 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.
|
||||||
|
// As a 2D mask, this is designed to be differenced away from the edge of a shape that with its corner at the
|
||||||
|
// origin and one edge on the X+ axis and the other mask_angle degrees counterclockwise from the X+ axis.
|
||||||
|
// If called as a function, returns a 2D path of the outline of the mask shape.
|
||||||
|
// .
|
||||||
|
// The roundover can be specified by joint length or cut distance. (Radius is not meaningful for this type of mask.) You must also specify the
|
||||||
|
// continuous curvature smoothness parameter, `k`, which defaults to 0.5. This diagram shows a roundover for the default k value.
|
||||||
|
// 
|
||||||
|
// .
|
||||||
|
// With `k=0.75` the transition into the roundover is shorter and faster. The cut length is bigger for the same joint length.
|
||||||
|
// 
|
||||||
|
// .
|
||||||
|
// The diagrams above show symmetric roundovers, but you can also create asymmetric roundovers by giving a list of two values for `joint`. In this
|
||||||
|
// case the first one is the horizontal joint length and the second one is the joint length along the other side of the rounding.
|
||||||
|
// .
|
||||||
|
// If you need roundings to agree on edges of different mask_angle, e.g. to round the base of a prismoid, then you need all of the
|
||||||
|
// masks used to have the same height. (Note that it may appear that matching joint would also work, but it does not because the joint distances are measured
|
||||||
|
// in different directions.) You can get the same height by setting the joint parameter to a scalar to define the joint length in the horizontal direction and then setting
|
||||||
|
// the `height` parameter, which determines the length of the other joint so that it has the desired height.
|
||||||
|
// Arguments:
|
||||||
|
// mask_angle = Number of degrees in the corner angle to mask. Default: $edge_angle if set, 90 otherwise
|
||||||
|
// ---
|
||||||
|
// inset = Optional bead inset size, perpendicular to the two edges. Scalar or 2-vector. Default: 0
|
||||||
|
// excess = Extra amount of mask shape to creates on the X and quasi-Y sides of the shape. Default: 0.01
|
||||||
|
// cut = Cut distance. IE: How much of the corner to cut off. See [Types of Roundovers](rounding.scad#section-types-of-roundovers).
|
||||||
|
// joint = Joint distance. IE: How far from the edge the roundover should start. See [Types of Roundovers](rounding.scad#section-types-of-roundovers).
|
||||||
|
// h / height = Mask height excluding inset and excess. This determines the height of the mask when you want a consistent mask height, no matter what the mask angle. You must provide a scalar joint value to define the mask width, and you cannot give cut.
|
||||||
|
// flat_top = If true, the top inset of the mask will be horizontal instead of angled by the mask_angle. Default: false
|
||||||
|
// splinesteps = Numbers of segments to create on the roundover. Default: 16
|
||||||
|
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
|
||||||
|
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
|
||||||
|
// Example(2D): Mask defined by cut
|
||||||
|
// mask2d_smooth(cut=3);
|
||||||
|
// Example(2D): Mask defined by symmetric joint length
|
||||||
|
// mask2d_smooth(joint=10);
|
||||||
|
// Example(2D): Asymmetric mask by joint length with different lengths and a larger excess
|
||||||
|
// mask2d_smooth(joint=[10,7],excess=0.5);
|
||||||
|
// Example(2D): Acute angle mask by cut
|
||||||
|
// mask2d_smooth(mask_angle=66,cut=3,excess=0.5);
|
||||||
|
// Example(2D): Acute angle mask by cut, but large k value
|
||||||
|
// mask2d_smooth(mask_angle=66,cut=3,excess=0.5, k=.9);
|
||||||
|
// Example(2D): Acute angle mask by cut, but small k value
|
||||||
|
// mask2d_smooth(mask_angle=66,cut=3,excess=0.5, k=.2);
|
||||||
|
// Example(2D): Obtuse angle mask
|
||||||
|
// mask2d_smooth(mask_angle=116,joint=12,excess=0.5);
|
||||||
|
// Example(2D): Inset mask
|
||||||
|
// mask2d_smooth(mask_angle=75,joint=12,inset=2);
|
||||||
|
// Example(2D): Inset mask, flat top
|
||||||
|
// mask2d_smooth(mask_angle=75,joint=12,inset=2, flat_top=true);
|
||||||
|
// Example(3D): Masking by Edge Attachment
|
||||||
|
// diff()
|
||||||
|
// cube([50,60,70],center=true)
|
||||||
|
// edge_profile([TOP,"Z"],except=[BACK,TOP+LEFT])
|
||||||
|
// mask2d_smooth(cut=3);
|
||||||
|
// Example(3D): Masking a cylinder by edge attachment
|
||||||
|
// diff()
|
||||||
|
// cyl(h=25,d=15)
|
||||||
|
// edge_profile()
|
||||||
|
// mask2d_smooth(joint=5);
|
||||||
|
// Example(3D,Med,VPT=[25,30,12],VPR=[68,0,12],VPD=180): Rounding over top of an extreme prismoid using height option
|
||||||
|
// diff()
|
||||||
|
// prismoid([30,20], [50,60], h=20, shift=[40,50])
|
||||||
|
// edge_profile(TOP, excess=27)
|
||||||
|
// mask2d_smooth(height=5, joint=5);
|
||||||
|
|
||||||
|
function mask2d_smooth( mask_angle, cut, joint, height, h, k=0.5, excess=.01, inset=0,flat_top=false,splinesteps=16,anchor=CENTER,spin=0) =
|
||||||
|
let(
|
||||||
|
mask_angle=first_defined([mask_angle, $edge_angle, 90]),
|
||||||
|
inset = is_list(inset)? inset : [inset,inset],
|
||||||
|
height = one_defined([h,height], "h,height",dflt=undef)
|
||||||
|
)
|
||||||
|
assert(num_defined([cut,joint])==1, "Must define exactly one of cut and joint")
|
||||||
|
assert(num_defined([height,cut])<2, "With height cannot give a cut value")
|
||||||
|
assert(is_undef(cut) || all_positive([cut]), "cut must be a positive value")
|
||||||
|
assert(is_undef(joint) || (is_finite(joint) && joint>0) || (is_vector(joint) && all_positive(joint)),
|
||||||
|
"joint must be a positive value or list of two positive values")
|
||||||
|
assert(is_undef(height) || is_finite(joint), "With height must give a scalar joint value")
|
||||||
|
assert(all_nonnegative([excess]), "excess must be a nonnegative value")
|
||||||
|
assert(is_finite(mask_angle) && mask_angle>0 && mask_angle<180)
|
||||||
|
assert(is_finite(k) && k>=0 && k<=1, "k must be a number between 0 and 1")
|
||||||
|
assert(is_vector(inset,2) && all_nonnegative(inset), "inset must be a nonnegative value or a list of two such values")
|
||||||
|
let(
|
||||||
|
|
||||||
|
joint = is_def(cut)? 8*cut/cos(mask_angle/2)/(1+4*k)*[1,1]
|
||||||
|
: is_def(height) ? [joint, height/sin(mask_angle)]
|
||||||
|
: force_list(joint,2),
|
||||||
|
angle_path = [
|
||||||
|
zrot(mask_angle, [joint[1],0]),
|
||||||
|
[0,0],
|
||||||
|
[joint[0],0],
|
||||||
|
],
|
||||||
|
outside_corner = _inset_corner(angle_path, mask_angle, inset, excess, flat_top),
|
||||||
|
bez = _smooth_bez_fill(outside_corner[1],k),
|
||||||
|
path = deduplicate([
|
||||||
|
each outside_corner[0],
|
||||||
|
each bezier_curve(bez, splinesteps=splinesteps)
|
||||||
|
],
|
||||||
|
closed=true)
|
||||||
|
)
|
||||||
|
reorient(anchor,spin, two_d=true, path=path, extent=false, p=path);
|
||||||
|
|
||||||
|
module mask2d_smooth(mask_angle, cut, joint, height, h, k=0.5, excess=.01, inset=0, flat_top=false, splinesteps=16, anchor=CENTER, spin=0)
|
||||||
|
{
|
||||||
|
path = mask2d_smooth(mask_angle=mask_angle, cut=cut, joint=joint, height=height, h=h, k=k, excess=excess, inset=inset,
|
||||||
|
flat_top=flat_top, splinesteps=splinesteps,anchor=anchor, spin=spin);
|
||||||
|
attachable(anchor,spin, two_d=true, path=path) {
|
||||||
|
polygon(path);
|
||||||
|
children();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Function&Module: mask2d_teardrop()
|
// Function&Module: mask2d_teardrop()
|
||||||
// Synopsis: Creates a 2D teardrop shape with specified max angle from vertical.
|
// Synopsis: Creates a 2D teardrop shape with specified max angle from vertical.
|
||||||
|
|
@ -1794,6 +1916,7 @@ module chamfer_edge_mask(l, chamfer=1, excess=0.1, h, length, height, anchor=CEN
|
||||||
// attach(RIGHT+TOP,LEFT+FWD,inside=true,inset=-.1,align=FWD)
|
// attach(RIGHT+TOP,LEFT+FWD,inside=true,inset=-.1,align=FWD)
|
||||||
// rounding_edge_mask(r1=0,r2=10,length=10);
|
// rounding_edge_mask(r1=0,r2=10,length=10);
|
||||||
// Example(3D, NoScales): Here we blend a tapered mask applied with `rounding_edge_mask()` with {{cuboid()}} rounding and a 2d mask applied with {{edge_profile()}}.
|
// Example(3D, NoScales): Here we blend a tapered mask applied with `rounding_edge_mask()` with {{cuboid()}} rounding and a 2d mask applied with {{edge_profile()}}.
|
||||||
|
// $fa=5;$fs=0.5;
|
||||||
// diff()
|
// diff()
|
||||||
// cuboid(25,rounding=2,edges=[TOP+RIGHT,TOP+FRONT]){
|
// cuboid(25,rounding=2,edges=[TOP+RIGHT,TOP+FRONT]){
|
||||||
// attach(RIGHT+FRONT, LEFT+FWD, inside=true)
|
// attach(RIGHT+FRONT, LEFT+FWD, inside=true)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue