mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2025-12-07 19:32:06 +00:00
Compare commits
8 commits
a239254739
...
cf729e563e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cf729e563e | ||
|
|
0fc47cf3c0 | ||
|
|
0637b8731b | ||
|
|
ad1437f8af | ||
|
|
4a04048dd4 | ||
|
|
ded2c11456 | ||
|
|
c0981763e7 | ||
|
|
b8b4dba594 |
4 changed files with 203 additions and 59 deletions
|
|
@ -779,22 +779,20 @@ function _make_anchor_legal(anchor,geom) =
|
|||
// do `attach(RIGHT,BOT)` this puts the bottom of the child onto the right anchor of the parent.
|
||||
// When an object is attached to the top or bottom, its BACK direction remains pointing BACK.
|
||||
// When an object is attached to one of the other anchors its FRONT is pointed DOWN and its
|
||||
// BACK pointed UP. You can change this using the `spin=` argument to attach(). Note that this spin
|
||||
// BACK pointed UP. You can change this using the `spin=` argument to attach(). This spin
|
||||
// rotates around the attachment vector and is not the same as the spin argument to the child, which
|
||||
// will usually rotate around some other direction that may be hard to predict. For 2D objects you cannot
|
||||
// give spin because it is not possible to spin around the attachment vector; spinning the object around the Z axis
|
||||
// would change the child orientation so that the anchors are no longer parallel. Furthermore, any spin
|
||||
// will usually rotate around some other direction that may be hard to predict. Any spin
|
||||
// parameter you give to the child is ignored so that the attachment condition of parallel anchors is preserved.
|
||||
// For 2D objects you cannot give spin because it is not possible to spin around the attachment vector;
|
||||
// spinning the object around the Z axis would change the child orientation so that the anchors are no longer parallel.
|
||||
// .
|
||||
// As with {{align()}} you can use the `align=` parameter to align the child to an edge or corner of the
|
||||
// face where that child is attached. For example, `attach(TOP,BOT,align=RIGHT)` would stand the child
|
||||
// up on the top while aligning it with the right edge of the top face, and `attach(RIGHT,BOT,align=TOP)`, which
|
||||
// stand the object on the right face while aligning with the top edge. If you apply spin using the
|
||||
// argument to `attach()`, then it is taken into account for the alignment. However, if you apply spin with
|
||||
// argument to `attach()`, then it is taken into account for the alignment. However, if you apply spin as
|
||||
// a parameter to the child, it is **not** taken into account. The special spin value "align"
|
||||
// spins the child so that the child's BACK direction is pointed toward the aligned edge on the parent.
|
||||
// Note that spin is not permitted for
|
||||
// 2D objects because it would change the child orientation so that the anchors are no longer parallel.
|
||||
// When you use `align=` you can also adjust the position using `inset=`, which shifts the child
|
||||
// away from the edge or corner it is aligned to.
|
||||
// .
|
||||
|
|
@ -845,7 +843,7 @@ function _make_anchor_legal(anchor,geom) =
|
|||
// overlap = Amount to sink child into the parent. Equivalent to `down(X)` after the attach. This defaults to the value in `$overlap`, which is `0` by default.
|
||||
// inside = If `child` is given you can set `inside=true` to attach the child to the inside of the parent for diff() operations. Default: false
|
||||
// shiftout = Shift an inside object outward so that it overlaps all the aligned faces. Default: 0
|
||||
// spin = Amount to rotate the parent around the axis of the parent anchor. Can set to "align" to align the child's BACK with the parent aligned edge. (Permitted only in 3D.)
|
||||
// spin = Angle to rotate the child around the axis of the parent anchor. Can set to "align" to align the child's BACK with the parent aligned edge. (Permitted only in 3D.)
|
||||
// Side Effects:
|
||||
// `$anchor` set to the parent anchor value used for the child.
|
||||
// `$align` set to the align value used for the child.
|
||||
|
|
|
|||
106
joiners.scad
106
joiners.scad
|
|
@ -1439,4 +1439,110 @@ module hirth(n, ir, or, id, od, tooth_angle=60, cone_angle=0, chamfer, rounding,
|
|||
}
|
||||
}
|
||||
|
||||
// Asserts a solution exists when called
|
||||
function _dist2inner_for_cylindrical_clamp(angle_from_tangent, or, ir) =
|
||||
is_undef(angle_from_tangent)?sqrt(pow(or,2)-pow(ir,2)):
|
||||
assert(angle_from_tangent<90)
|
||||
assert(angle_from_tangent>=0)
|
||||
let(
|
||||
// The line leaving the circumference is the tangent line of some concentric circle with radius:
|
||||
tangent_circle_radius = or * sin(angle_from_tangent),
|
||||
length_from_starting_point_to_tangent_circle = or * cos(angle_from_tangent)
|
||||
)
|
||||
assert(tangent_circle_radius<=ir, "The angle given for cylindrical clamp fins does not allow it to intersect with the inner circle radius")
|
||||
let(
|
||||
length_from_tangent_circle_tangent_to_intersection_of_inner_circle = sqrt(pow(ir,2)-pow(tangent_circle_radius,2)),
|
||||
fin_length=length_from_starting_point_to_tangent_circle-length_from_tangent_circle_tangent_to_intersection_of_inner_circle
|
||||
)
|
||||
echo(tangent_circle_radius=tangent_circle_radius,length_from_starting_point_to_tangent_circle=length_from_starting_point_to_tangent_circle,length_from_tangent_circle_tangent_to_intersection_of_inner_circle=length_from_tangent_circle_tangent_to_intersection_of_inner_circle,fin_length=fin_length)
|
||||
fin_length;
|
||||
|
||||
assert(_dist2inner_for_cylindrical_clamp(0,8,5)==3);
|
||||
|
||||
// Module: cylindrical_clamp()
|
||||
// Synopsis: Builds a finned clamp for circular objects.
|
||||
// SynTags: Geom
|
||||
// Topics: Joiners, Parts
|
||||
// Usage:
|
||||
// cylindrical_clamp(h, od, id, [fin_thick=0.4], [num=3], [fin_angle=30]);
|
||||
// cylindrical_clamp(h, od1=, od2=, id1=, id2=, ...);
|
||||
// cylindrical_clamp(h, od, id, [shift=[dx,dy]], ...);
|
||||
// Description:
|
||||
// Generate a clamp designed to hold a cylindrical or slightly-conical object.
|
||||
// It uses an arrangement of fins which deform to apply pressure when the cylindrical object is inserted; thus the inner diameter must be less than the diameter of the intended object, but how much less is dependent on many factors.
|
||||
// This is intended to be placed within a cylindrical opening.
|
||||
// Only works when printed within overhang tolerance of vertical. Horizontally-printed should use a series of conical washer shapes.
|
||||
// Arguments:
|
||||
// h = Length of fins along oriented axis. Default: 1
|
||||
// od = Diameter fins will attach to on their outer length. Should be at least the inserted object's OD + 2*fin_thick or the fins will have nowhere to bend. Default: 10
|
||||
// id = Diameter fins will leave open in the middle. Default: 6
|
||||
// ---
|
||||
// ir1,id1,or1,od1 = Set the inner or outer radius or diameter for the bottom fin circle. Follows same rules as `cyl`.
|
||||
// ir2,id2,or2,od2 = Set the inner or outer radius or diameter for the top fin circle. Follows same rules as `cyl`.
|
||||
// ir,or = Alternatives to id and od. Follows same rules as `cyl`.
|
||||
// fin_angle = Degrees away from the radius line (0 is straight in to center, 90 is tangent). If left unset, will pick the largest possible angle (which yields the longest possible fin). Default: undef
|
||||
// $slop = Increase the inner radius by $slop.
|
||||
// fin_thick = How thick the fin will be. Must be at least the minimum line width of your printer, but that often results in a single unstable wall. Better is to be at least 2xline width (for classic wall) or 1.75xline width (for Arachne). Default: 0.4
|
||||
// TODO: document the rest
|
||||
// TODO: implement orient and anchor and attachables
|
||||
// TODO: allow other fin direction by expanding fin angle past 90
|
||||
module cylindrical_clamp(h=1,od=undef,id=undef,od1=undef,od2=undef,id1=undef,id2=undef,or=undef,ir=undef,or1=undef,or2=undef,ir1=undef,ir2=undef,num=3,fin_thick=0.4,fin_angle=undef,shift=[0,0]) {
|
||||
//
|
||||
if(!is_undef(fin_angle)) {
|
||||
assert(fin_angle>0);
|
||||
assert(fin_angle<=90);
|
||||
}
|
||||
or1 = get_radius(r1=or1, r=or, d1=od1, d=od, dflt=5);
|
||||
or2 = get_radius(r1=or2, r=or, d1=od2, d=od, dflt=5);
|
||||
ir1 = get_radius(r1=ir1, r=ir, d1=id1, d=id, dflt=3)+get_slop();
|
||||
ir2 = get_radius(r1=ir2, r=ir, d1=id2, d=id, dflt=3)+get_slop();
|
||||
dist1 = _dist2inner_for_cylindrical_clamp(fin_angle, or1, ir1);
|
||||
dist2 = _dist2inner_for_cylindrical_clamp(fin_angle, or2, ir2);
|
||||
fin_length1 = dist1; //sqrt(pow(dist1,2)-pow(fin_thick/2,2));
|
||||
fin_length2 = dist2; //sqrt(pow(dist2,2)-pow(fin_thick/2,2));
|
||||
// fin_length1 = dist1;
|
||||
// fin_length2 = _dist2inner_for_cylindrical_clamp(fin_angle, or2, ir2);
|
||||
actual_angle = (is_undef(fin_angle)?asin(ir1/or1):fin_angle)/*-asin(fin_thick/2/dist1)*/;
|
||||
echo(fin_length1=fin_length1,actual_angle=actual_angle);
|
||||
/*down(h/2)*/ skew(sxz=shift.x/h, syz=shift.y/h) /*up(h/2)*/
|
||||
// If sharing, this tag should probably be a uuid per invocation
|
||||
// diff("circ_clamp") cylinder(h,r1=or1,r2=or2) {
|
||||
// tag("circ_clamp") position(BOT) cylinder(h,r1=or1,r2=or2);
|
||||
zrot_copies(n=num)
|
||||
fwd(or1) zrot(-actual_angle) prismoid([fin_thick,fin_length1],[fin_thick,fin_length2],h,[0,(fin_length2-fin_length1)/2],rounding=[fin_thick/2,fin_thick/2,0,0], anchor=BOT+LEFT+FRONT);
|
||||
// }
|
||||
}
|
||||
|
||||
xdistribute(10) {
|
||||
union() {
|
||||
cylindrical_clamp(h=5,od=2,id=1.5,fin_thick=0.4,shift=[2,-1],$fn=10);
|
||||
#cyl(h=5,d=1.5,shift=[2,-1],$fn=30, anchor=BOT);
|
||||
}
|
||||
|
||||
union() {
|
||||
cylindrical_clamp(h=5,od=4.5,id=3.8,fin_thick=0.4,num=10,shift=[2,-1],$fn=10);
|
||||
#cyl(h=5,d=3.8,shift=[2,-1],$fn=30, anchor=BOT);
|
||||
}
|
||||
|
||||
union() {
|
||||
cylindrical_clamp(h=5,od=4.5,id=3.8,fin_thick=0.2,num=10,$fn=10);
|
||||
#tube(h=5,od=4.5,id=3.8,$fn=48, anchor=BOT);
|
||||
}
|
||||
|
||||
union() {
|
||||
cylindrical_clamp(h=5,od=4.5,id=3.8,fin_thick=0.2,num=10,fin_angle=20,$fn=10);
|
||||
#tube(h=5,od=4.5,id=3.8,$fn=48, anchor=BOT);
|
||||
}
|
||||
|
||||
union() {
|
||||
cylindrical_clamp(h=5,od=4.5,id=3,fin_thick=0.2,num=10,$fn=10);
|
||||
#tube(h=5,od=4.5,id=3,$fn=48, anchor=BOT);
|
||||
}
|
||||
|
||||
// union() {
|
||||
// grip_fins(h=5,od=4.5,id=3.8,fin_thick=0.2,num=10,fin_angle=20,$fn=32);
|
||||
// #tube(h=5,od=4.5,id=3.8,$fn=48, anchor=BOT);
|
||||
// }
|
||||
}
|
||||
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ function _inset_corner(corner, mask_angle, inset, excess, flat_top) =
|
|||
// If called as a function, returns a 2D path of the outline of the mask shape.
|
||||
// .
|
||||
// The roundover can be specified by radius, diameter, height, cut, or joint length.
|
||||
// .
|
||||
// 
|
||||
// .
|
||||
// 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
|
||||
|
|
@ -253,10 +254,12 @@ function mask2d_roundover(r, inset=0, mask_angle=90, excess=0.01, clip_angle, fl
|
|||
// 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.
|
||||
// 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
|
||||
|
|
@ -375,6 +378,7 @@ module mask2d_smooth(mask_angle, cut, joint, height, h, k=0.5, excess=.01, inset
|
|||
// If called as a function, returns a 2D path of the outline of the mask shape.
|
||||
// This is particularly useful to make partially rounded bottoms, that don't need support to print.
|
||||
// The roundover can be specified by radius, diameter, height, cut, or joint length.
|
||||
// .
|
||||
// 
|
||||
// Arguments:
|
||||
// r = Radius of the rounding.
|
||||
|
|
|
|||
136
rounding.scad
136
rounding.scad
|
|
@ -2226,7 +2226,7 @@ function _rp_compute_patches(top, bot, rtop, rsides, ktop, ksides, concave) =
|
|||
// value and the rounding is symmetric around each edge. However, you can specify a 2-vector for the joint distance to produce asymmetric
|
||||
// rounding which is different on the two sides of the edge. This may be useful when one one edge in your polygon is much larger than another.
|
||||
// For the top and bottom you can specify negative joint distances. If you give a scalar negative value, then the roundover flares
|
||||
// outward. If you give a vector value then a negative value, then if `joint_top[0]` is negative the shape flares outward, but if
|
||||
// outward. If you give a vector value then if `joint_top[0]` is negative the shape flares outward, but if
|
||||
// `joint_top[1]` is negative, the shape flares upward. At least one value must be non-negative. The same rules apply for joint_bot.
|
||||
// The joint_sides parameter must be entirely nonnegative.
|
||||
// .
|
||||
|
|
@ -2243,7 +2243,7 @@ function _rp_compute_patches(top, bot, rtop, rsides, ktop, ksides, concave) =
|
|||
// can also use "intersect" to get the intersection anchors to the unrounded object. If you prefer anchors that respect the rounding
|
||||
// then use "surf_hull" or "intersect_hull". Lastly, in the special case of a prism with four sides, you can use "prismoid" anchoring
|
||||
// which attempts to assign standard prismoid anchors to the shape by assigning as RIGHT the face that is closest to the RIGHT direction,
|
||||
// and defining the other anchors around the shape baesd on that choice.
|
||||
// and defining the other anchors around the shape based on that choice.
|
||||
// .
|
||||
// Note that rounded_prism() is not well suited to rounding shapes that have already been rounded, or that have many points.
|
||||
// It works best when the top and bottom are polygons with well-defined corners. When the polygons have been rounded already,
|
||||
|
|
@ -4465,7 +4465,7 @@ function _prism_fillet_prism(name, basepoly, bot, top, d, k, N, overlap, uniform
|
|||
// Get the object type from the specified geometry and anchor point
|
||||
|
||||
// Note that profile is needed just to find its dimensions for making a big enough edge profile
|
||||
function _get_obj_type(ind,geom,anchor,prof,edger=0) =
|
||||
function _get_obj_type(ind,geom,anchor,prof,edge_r,edge_joint,edge_k) =
|
||||
geom[0]=="spheroid" ? "sphere"
|
||||
: geom[0]=="conoid" ? let(
|
||||
axis = geom[5],
|
||||
|
|
@ -4491,8 +4491,9 @@ function _get_obj_type(ind,geom,anchor,prof,edger=0) =
|
|||
x = y/tan(edge_angle/2),
|
||||
corner=[[x,-y],[0,0], [x,y]]
|
||||
)
|
||||
round_corners(corner, r=edger, closed=false)
|
||||
|
||||
is_def(edge_r)? round_corners(corner, r=edge_r, closed=false)
|
||||
: is_def(edge_joint) ? echo(jk=edge_joint,edge_k)round_corners(corner, method="smooth",joint=edge_joint, k=edge_k, closed=false)
|
||||
: corner
|
||||
: starts_with(geom[0], "extrusion") ?
|
||||
anchor==UP || anchor==DOWN || starts_with(anchor,"face") ? "plane"
|
||||
:
|
||||
|
|
@ -4858,7 +4859,7 @@ module prism_connector(profile, desc1, anchor1, desc2, anchor2, shift1, shift2,
|
|||
// Topics: Rounding, Extrusion, Sweep
|
||||
// See Also: join_prism(), prism_connector()
|
||||
// Usage:
|
||||
// PARENT() attach_prism(profile, anchor, [fillet], [rounding], [l=/h=/length=/height=], [endpoint=], [T=], [shift=], [scale=], [inside=], [n=], [n_base=], [n_end=], [k=], [k_base=], [k_end=], [overlap=], [uniform=], [smooth_normals=], [debug=] ) CHILDREN;
|
||||
// PARENT() attach_prism(profile, anchor, [fillet], [rounding], [l=/h=/length=/height=], [endpoint=], [T=], [shift=], [scale=], [inside=], [n=], [n_base=], [n_end=], [k=], [k_base=], [k_end=], [overlap=], [uniform=], [smooth_normals=], [edge_r=], [edge_joint=], [edge_k=], [debug=] ) CHILDREN;
|
||||
// Description:
|
||||
// Constructs a filleted prism that attaches to the specified anchor point of the parent object, with an optional rounded free end.
|
||||
// This is an alternative interface to {{join_prism()}}. The `profile` parameter gives the cross section of the prism the module constructions.
|
||||
|
|
@ -4878,7 +4879,7 @@ module prism_connector(profile, desc1, anchor1, desc2, anchor2, shift1, shift2,
|
|||
// when the anchor point is not on the surface.
|
||||
// .
|
||||
// If you specify a length or height then he prism normally appears in the anchor direction, perpendicular to the parent object. You can
|
||||
// adjust its angle by setting the transoformation. For example, `T=xrot(20)` will rotate the prism so it is a 20 deg angle. It will shift
|
||||
// adjust its angle by setting the transformation. For example, `T=xrot(20)` will rotate the prism so it is a 20 deg angle. It will shift
|
||||
// to the right as seen from above. The transformation applies in the anchored coordinate system where Z is perpendicular to the parent
|
||||
// and Y points in the spin direction. When `T` is a rotation the face of the prism will be perpendicular to the prism axis.
|
||||
// You can also specify the prism endpoint as a point in space, again in the anchored coordinate system. In this case you cannot give
|
||||
|
|
@ -4900,17 +4901,28 @@ module prism_connector(profile, desc1, anchor1, desc2, anchor2, shift1, shift2,
|
|||
// Normally {{join_prism()}} will issue an error in this situation. The `debug` parameter is passed through to {{join_prism()}} and
|
||||
// tells that module to display invalid self-intersecting geometry to help you understand the problem.
|
||||
// .
|
||||
// When connecting to an edge, artifacts may occur at the corners where the prism doesn't meet the object in the ideal fashion.
|
||||
// The `overlap` parameter creates an extension of the prism into the parent object. Unlike `overlap` for {{attach()}} it actually extends
|
||||
// the prism rather than shifting it by the overlap. When connecting to curved parent objects, be sure the overlap is sufficient or you may
|
||||
// create a hole in between the prism and its parent. When subtracting a prism to create a hole, insufficient overlap will leave parts of
|
||||
// the parent object behind, blocking the hole.
|
||||
// .
|
||||
// When connecting to an unrounded edge, artifacts may occur at the corners where the prism doesn't meet the object in the ideal fashion.
|
||||
// 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.
|
||||
// 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 this reason, the default is false when connecting to an edge that is not rounded.
|
||||
// .
|
||||
// When connecting to a rounded edge, the edge geometry must be circular or a smooth bezier rounding. In the circular case
|
||||
// you must provide the `edge_r` parameter to specify the radius of the circular rounding. In the latter case you
|
||||
// must give `edge_joint` to specify the size of the rounding, and you may optionally provide `edge_k` as required. The default
|
||||
// of `edge_k=0.5` matches the default for {{rounded_prism()}}.
|
||||
// .
|
||||
// The "end" named anchor is located at the end face of the prism and (unlike {{join_prism()}}) provides a normal anchor
|
||||
// that is perpendicular to the end face of the prism.
|
||||
// Arguments:
|
||||
// profile = path giving cross section to extrude to create the connecting prism
|
||||
// anchor = parent anchor where prism will be attached
|
||||
// anchor = parent anchor where prism will be attached or a list of anchors
|
||||
// fillet = fillet size. Default: 0
|
||||
// rounding = end rounding of prism. Default: 0
|
||||
// ---
|
||||
|
|
@ -4920,7 +4932,10 @@ module prism_connector(profile, desc1, anchor1, desc2, anchor2, shift1, shift2,
|
|||
// inside = if true attach the prism on the inside of the parent for diff() operations. Default: false
|
||||
// shift = shift anchor point, a scalar for cylinders, extrusions, or edges, a 2-vector for faces, not permitted for spheres
|
||||
// scale = scale the profile by this factor at the end. Default: 1
|
||||
// spin = angle to rotate the prism around its axis before attaching it. Default: 0
|
||||
// edge_r = when attaching to an edge, assume it has a circular rounding with this radius
|
||||
// edge_joint = when attaching to an edge, assume it has a smooth bezier rounding with this joint length
|
||||
// edge_k = when attaching to an edge with a bezier rounding, use this k parameter value. Default: 0.5 (matches rounded_prism)
|
||||
// n = number of facets to use for fillets and roundings
|
||||
// n_base = number of facets to use for fillets at the base
|
||||
// n_end = number of facets to use for roundings at the end
|
||||
|
|
@ -4929,7 +4944,7 @@ module prism_connector(profile, desc1, anchor1, desc2, anchor2, shift1, shift2,
|
|||
// k_end = rounding curvature parameter for end. Default: 0.7
|
||||
// uniform = set to false to get non-uniform filleting. Default: true
|
||||
// overlap = the amount of overlap of the prism fillet into the parent object. Default: 1
|
||||
// smooth_normals = controls whether normals are smoothed when the parent is a prism or edge; no effect otherwise. Default: false if object is an edge, true otherwise
|
||||
// smooth_normals = controls whether normals are smoothed when the parent is a prism or edge; no effect otherwise. Default: false if object is an unrounded edge, true otherwise
|
||||
// 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
|
||||
// Named Anchors:
|
||||
// "end" = End of the attached prism. (A normal anchor that is perpendicular to the end face of the prism.)
|
||||
|
|
@ -4947,6 +4962,9 @@ module prism_connector(profile, desc1, anchor1, desc2, anchor2, shift1, shift2,
|
|||
// Example(3D): Attaching to sphere with scaling of the prism
|
||||
// sphere(d=20)
|
||||
// attach_prism(circle(r=4,$fn=64), RIGHT+TOP+FWD, fillet=2, rounding=1.5, l=7, scale=.5);
|
||||
// Example(3D): Here we've attached a rectangular prism to a cylinder. It makes a nice joint at the sides but the top doesn't look right. This is because {{rect()}} only provides four points, which is not sufficient to match the curvature of the cylinder. You need to resample with {{subdivide_path()}} or some other reampling method as shown in the next example.
|
||||
// cyl(d=10,h=8)
|
||||
// attach_prism(rect(4), FWD+RIGHT, 1/2, rounding=1/2, l=4, edge_r=2);
|
||||
// Example(3D): Attaching to an extrusion. Here we used a rounded rectangle and resample it to ensure enough points to match the curve of the ellipse.
|
||||
// $fn=128;
|
||||
// rr = subdivide_path(rect(7,rounding=2), maxlen=.5);
|
||||
|
|
@ -4968,14 +4986,28 @@ module prism_connector(profile, desc1, anchor1, desc2, anchor2, shift1, shift2,
|
|||
// Example(3D): Adjusting prism angle with a transformation. The prism end is perpendicular to the prism axis.
|
||||
// cuboid(20)
|
||||
// attach_prism(circle(r=4,$fn=32), FWD, fillet=1, rounding=1.5, l=10, T=xrot(-20));
|
||||
// Example(3D): Creating a hole
|
||||
// Example(3D): Creating a hole. The default overlap is too small to fully clear out the hole.
|
||||
// diff()
|
||||
// cyl(d=20,h=22,$fn=128*2)
|
||||
// attach_prism(circle(r=6,$fn=64), RIGHT+FWD, inside=true,
|
||||
// fillet=2, rounding=3, l=8, overlap=2);
|
||||
// Example(3D): Attaching with multiple anchor points
|
||||
// cuboid(12)
|
||||
// attach_prism(circle(r=3,$fn=32), [TOP, RIGHT+FWD],length=4,fillet=2);
|
||||
// Example(3D): Attaching to a rounded cuboid edge (circular rounding)
|
||||
// cuboid([12,12,15],rounding=2, $fn=32)
|
||||
// attach_prism(circle(r=3,$fn=128),RIGHT+FWD, length=4, fillet=2, edge_r=2);
|
||||
// Example(3D): Attaching the the edge on a {{rounded_prism()}}. The `$fn` value given to `attach_prism()` controls the number of facets used to model the curved edge that the prism mates to.
|
||||
// joint = 3;
|
||||
// rounded_prism(rect(12), rect(8), h=15, joint_sides=joint,atype="prismoid")
|
||||
// attach_prism(circle(r=3,$fn=128),RIGHT+FWD, length=4, fillet=2, edge_joint=joint, $fn=32);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
module attach_prism(profile, anchor, fillet=0, rounding=0, inside=false, l, length, h, height, endpoint, T=IDENT, shift=0, overlap=1,
|
||||
n,n_base, n_end, k, k_base, k_end, uniform=true, smooth_normals, edge_r, debug=false, scale=1)
|
||||
n,n_base, n_end, k, k_base, k_end, uniform=true, smooth_normals, edge_r, edge_joint, edge_k=0.5, debug=false, scale=1, spin=0)
|
||||
{
|
||||
length = one_defined([l, h, length, height],"l,h,length,height",dflt=undef);
|
||||
profile = force_path(profile,"profile");
|
||||
|
|
@ -4987,51 +5019,55 @@ module attach_prism(profile, anchor, fillet=0, rounding=0, inside=false, l, leng
|
|||
assert(is_matrix(T,4,4), "T must be a 4x4 transformation matrix")
|
||||
assert(is_undef(length) || all_positive([length]), "length/height must be a positive value")
|
||||
assert(point3d(anchor)!=CTR, "CENTER anchor is not permitted")
|
||||
;
|
||||
edge_r=default(edge_r,0);
|
||||
assert(num_defined([edge_r,edge_joint])<=1, "Cannot give both edge_r and edge_joint")
|
||||
;
|
||||
n_base = first_defined([n_base,n,15]);
|
||||
n_end = first_defined([n_end,n,15]);
|
||||
k_base = first_defined([k_base, k, 0.7]);
|
||||
k_end = first_defined([k_end,k,0.7]);
|
||||
|
||||
anchor = is_string(anchor) ? anchor : point3d(anchor);
|
||||
anchor_list = is_string(anchor) || is_vector(anchor) ? [anchor] : anchor;
|
||||
|
||||
type = _get_obj_type(undef,$parent_geom,anchor,profile,edge_r);
|
||||
offset = in_list(type,["cyl","sphere"]) ? (inside?-1:1)*$parent_geom[1] : 0;
|
||||
base_r = (inside?-1:1)*(in_list(type,["cyl","sphere"]) ? $parent_geom[1] : 1);
|
||||
spin = -90;
|
||||
base_edge = _is_geom_an_edge($parent_geom,anchor);
|
||||
smooth_normals = default(smooth_normals, !base_edge);
|
||||
|
||||
shift = type=="sphere" ? assert(shift==0, "Cannot give a (nonzero) shift for attaching to a spherical object") [0,0]
|
||||
: type=="cyl" ? assert(is_finite(shift), "Value shift for a cylindrical object must be a scalar") [0,shift]
|
||||
: is_list(type) ? assert(is_finite(shift), "Value shift for an edge must be a scalar") [0,shift]
|
||||
: assert(is_finite(shift) || is_vector(shift,2), "Value for shift for a planar face must be a scalar or 2-vector")
|
||||
force_list(shift,2,0);
|
||||
T = is_def(endpoint) ? move([endpoint.y-shift.y,-endpoint.x-shift.x])
|
||||
: zrot(spin)*T;
|
||||
mod_type = is_list(type) && inside ? zrot(180,type) : type;
|
||||
anchors = [named_anchor("end", is_def(endpoint) ? yrot(inside?180:0,endpoint) : point3d(shift)+apply(yrot(inside?180:0)*zrot(-spin)*T,[0,0,(inside?1:1)*length]),
|
||||
is_def(endpoint) ? (inside?-1:1)*UP : unit( apply(yrot(inside?180:0)*zrot(-spin)*T,[0,0,length])-apply(zrot(-spin)*T,CTR)),
|
||||
inside && is_undef(endpoint) ? 180 : 0)
|
||||
];
|
||||
vnf= join_prism(zrot(spin,profile), mod_type, base_r=base_r,
|
||||
l=is_def(endpoint)?endpoint.z:length,
|
||||
prism_end_T=T,
|
||||
base_fillet=fillet,
|
||||
end_round=rounding,
|
||||
base_overlap=overlap, uniform=uniform, smooth_normals=smooth_normals,
|
||||
base_n=n_base, aux_n=n_end, base_k=k_base, aux_k=k_end,debug=debug,scale=scale);
|
||||
attach(anchor)
|
||||
default_tag("remove", inside)
|
||||
attachable(vnf=vnf, anchors=anchors) {
|
||||
translate(shift)
|
||||
yrot(inside?180:0)
|
||||
down(offset)
|
||||
zrot(-spin)
|
||||
vnf_polyhedron(vnf);
|
||||
children();
|
||||
}
|
||||
for(anchor=anchor_list){
|
||||
anchor = is_string(anchor) ? anchor : point3d(anchor);
|
||||
type = _get_obj_type(undef,$parent_geom,anchor,profile,edge_r,edge_joint,edge_k);
|
||||
offset = in_list(type,["cyl","sphere"]) ? (inside?-1:1)*$parent_geom[1] : 0;
|
||||
base_r = (inside?-1:1)*(in_list(type,["cyl","sphere"]) ? $parent_geom[1] : 1);
|
||||
spinfix = -90;
|
||||
base_edge = _is_geom_an_edge($parent_geom,anchor);
|
||||
smooth_normals = default(smooth_normals, !base_edge || default(edge_r,0)>0 || default(edge_joint,0)>0);
|
||||
|
||||
shift = type=="sphere" ? assert(shift==0, "Cannot give a (nonzero) shift for attaching to a spherical object") [0,0]
|
||||
: type=="cyl" ? assert(is_finite(shift), "Value shift for a cylindrical object must be a scalar") [0,shift]
|
||||
: is_list(type) ? assert(is_finite(shift), "Value shift for an edge must be a scalar") [0,shift]
|
||||
: assert(is_finite(shift) || is_vector(shift,2), "Value for shift for a planar face must be a scalar or 2-vector")
|
||||
force_list(shift,2,0);
|
||||
T = is_def(endpoint) ? move([endpoint.y-shift.y,-endpoint.x-shift.x])
|
||||
: zrot(spinfix)*T;
|
||||
mod_type = is_list(type) && inside ? zrot(180,type) : type;
|
||||
anchors = [named_anchor("end", is_def(endpoint) ? yrot(inside?180:0,endpoint) : point3d(shift)+apply(yrot(inside?180:0)*zrot(-spinfix)*T,[0,0,(inside?1:1)*length]),
|
||||
is_def(endpoint) ? (inside?-1:1)*UP : unit( apply(yrot(inside?180:0)*zrot(-spinfix)*T,[0,0,length])-apply(zrot(-spinfix)*T,CTR)),
|
||||
inside && is_undef(endpoint) ? 180 : 0)
|
||||
];
|
||||
vnf= join_prism(zrot(spin+spinfix,profile), mod_type, base_r=base_r,
|
||||
l=is_def(endpoint)?endpoint.z:length,
|
||||
prism_end_T=T,
|
||||
base_fillet=fillet,
|
||||
end_round=rounding,
|
||||
base_overlap=overlap, uniform=uniform, smooth_normals=smooth_normals,
|
||||
base_n=n_base, aux_n=n_end, base_k=k_base, aux_k=k_end,debug=debug,scale=scale);
|
||||
attach(anchor)
|
||||
default_tag("remove", inside)
|
||||
attachable(vnf=vnf, anchors=anchors) {
|
||||
translate(shift)
|
||||
yrot(inside?180:0)
|
||||
down(offset)
|
||||
zrot(-spinfix)
|
||||
vnf_polyhedron(vnf);
|
||||
children();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue