mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2025-12-09 15:29:09 +00:00
Merge pull request #1832 from adrianVmariano/master
Add masks2d_smooth, change prism_connector named anchor names
This commit is contained in:
commit
ad3a376c4b
2 changed files with 135 additions and 4 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)
|
||||||
|
|
|
||||||
|
|
@ -4171,7 +4171,13 @@ function _prism_fillet_prism(name, basepoly, bot, top, d, k, N, overlap, uniform
|
||||||
// Adjsting the points on your prism profile so that a point falls close to the corner will achieve the best result, and make sure
|
// Adjsting the points on your prism profile so that a point falls close to the corner will achieve the best result, and make sure
|
||||||
// that `smooth_normals` is disabled (the default for edges) because it results in a completely incorrect fillet in this case.
|
// that `smooth_normals` is disabled (the default for edges) because it results in a completely incorrect fillet in this case.
|
||||||
// If you connect to an extrusion object, the default value for `smooth_normals` is true, which generally works better when
|
// If you connect to an extrusion object, the default value for `smooth_normals` is true, which generally works better when
|
||||||
// for a uniformly sampled smooth object, but if your object has corners you may get better results by setting `smooth_normals=false`.
|
// for a uniformly sampled smooth object, but if your object has corners you may get better results by setting `smooth_normals=false`.
|
||||||
|
// .
|
||||||
|
// You can use two named anchors, "end1" and "end2", that provide anchors at the connecting points on the end faces of the connector prism. These anchors
|
||||||
|
// point **along the prism axis**, which means they are not necessarily perpendicular to the end face of the prism. If you need
|
||||||
|
// an anchor perpendicular to the end face of the prism you can use the anchor from the description at that end that you used
|
||||||
|
// to construct the prism by using {{restore()}}. If you have shifted the connector point you will need to apply a similar transformation
|
||||||
|
// to the anchor point based on the description.
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// profile = path giving cross section to extrude to create the connecting prism
|
// profile = path giving cross section to extrude to create the connecting prism
|
||||||
// desc1 = description of first object to connect
|
// desc1 = description of first object to connect
|
||||||
|
|
@ -4205,8 +4211,8 @@ function _prism_fillet_prism(name, basepoly, bot, top, d, k, N, overlap, uniform
|
||||||
// debug = pass-through to the {{join_prism()}} debug parameter. If true then various cases where the fillet self intersects will be displayed instead of creating an error. Default: false
|
// debug = pass-through to the {{join_prism()}} debug parameter. If true then various cases where the fillet self intersects will be displayed instead of creating an error. Default: false
|
||||||
// debug_pos = if set to true display an unfilleted prism instead of invoking {{join_prism()}} so that you can diagnose errors about the prism not intersecting the object. Default: false
|
// debug_pos = if set to true display an unfilleted prism instead of invoking {{join_prism()}} so that you can diagnose errors about the prism not intersecting the object. Default: false
|
||||||
// Named Anchors:
|
// Named Anchors:
|
||||||
// "root" = Root point of the connector prism at the desc1 end, pointing out in the direction of the prism axis (anchor inherited from {{join_prism()}}
|
// "end1" = Root point of the connector prism at the desc1 end, pointing out in the direction of the prism axis (not necessarily perpendicular to the end of the prism connector!)
|
||||||
// "end" = Root point of the connector prism at the desc2 end, pointing out in the direction of the prism axis (anchor inherited from {{join_prism()}}
|
// "end2" = Root point of the connector prism at the desc2 end, pointing out in the direction of the prism axis (not necessarily perpendicular to the end of the prism connector!)
|
||||||
// Example(3D,NoAxes,VPT=[11.5254,0.539284,6.44131],VPR=[71.8,0,29.2],VPD=113.4): A circular prism connects a prismoid to a sphere. Note different fillet sizes at each length.
|
// Example(3D,NoAxes,VPT=[11.5254,0.539284,6.44131],VPR=[71.8,0,29.2],VPD=113.4): A circular prism connects a prismoid to a sphere. Note different fillet sizes at each length.
|
||||||
// circ = circle(r=3, $fn=48);
|
// circ = circle(r=3, $fn=48);
|
||||||
// prismoid(20,13,shift=[-2,1],h=15) let(prism=parent())
|
// prismoid(20,13,shift=[-2,1],h=15) let(prism=parent())
|
||||||
|
|
@ -4819,7 +4825,9 @@ module prism_connector(profile, desc1, anchor1, desc2, anchor2, shift1, shift2,
|
||||||
base_n=base_n, aux_n=aux_n, base_fillet=base_fillet, aux_fillet=aux_fillet,
|
base_n=base_n, aux_n=aux_n, base_fillet=base_fillet, aux_fillet=aux_fillet,
|
||||||
base_smooth_normals = base_smooth_normals, aux_smooth_normals=aux_smooth_normals,
|
base_smooth_normals = base_smooth_normals, aux_smooth_normals=aux_smooth_normals,
|
||||||
debug=debug,
|
debug=debug,
|
||||||
_name1="desc1", _name2="desc2") children();
|
_name1="desc1", _name2="desc2")
|
||||||
|
change_anchors(alias=[["end1","root"],["end2","end"]], remove=["root","end"])
|
||||||
|
children();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue