Merge pull request #959 from adrianVmariano/master

attachable offset_stroke, screw doc fixes
This commit is contained in:
Revar Desmera 2022-09-25 16:44:04 -07:00 committed by GitHub
commit ea7bb49fa7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 124 additions and 65 deletions

View file

@ -537,7 +537,7 @@ module attach(from, to, overlap, norot=false)
}
}
// Section: Attachment Modifiers
// Section: Tagging
// Module: tag()
// Usage:
@ -715,6 +715,8 @@ module tag_scope(scope){
}
// Section: Attachment Modifiers
// Module: diff()
// Usage:
// diff([remove], [keep]) CHILDREN;
@ -1129,7 +1131,7 @@ module conv_hull(keep="keep")
// Module: tag_conv_hull()
// Usage:
// tag,conv_hull(tag, [keep]) CHILDREN;
// tag_conv_hull(tag, [keep]) CHILDREN;
// Topics: Attachments
// See Also: tag(), recolor(), show_only(), hide(), diff(), intersect()
// Description:
@ -1765,6 +1767,39 @@ module corner_profile(corners=CORNERS_ALL, except=[], r, d, convexity=10) {
// polygon(path);
// children();
// }
//
// Example: An object can be designed to attach as negative space using {{diff()}}, but if you want an object to include both positive and negative space then you need to call attachable() twice, because tags inside the attachable() call don't work as expected. This example shows how you can call attachable twice to create an object with positive and negative space. Note, however, that children in the negative space are differenced away: the highlighted little cube does not survive into the final model.
// module thing(anchor,spin,orient) {
// tag("remove") attachable(size=[15,15,15],anchor=anchor,spin=spin,orient=orient){
// cuboid([10,10,16]);
// union(){} // dummy children
// }
// attachable(size=[15,15,15], anchor=anchor, spin=spin, orient=orient){
// cuboid([15,15,15]);
// children();
// }
// }
// diff()
// cube([19,10,19])
// attach([FRONT],overlap=-4)
// thing(anchor=TOP)
// # attach(TOP) cuboid(2,anchor=TOP);
// Example: Here is an example where the "keep" tag allows children to appear in the negative space. That tag is also needed for this module to produce the desired output. As above, the tag must be applied outside the attachable() call.
// module thing(anchor = CENTER, spin = 0, orient = UP) {
// tag("remove") attachable(anchor, spin, orient, d1=0,d2=95,h=33) {
// cylinder(h = 33.1, d1 = 0, d2 = 95, anchor=CENTER);
// union(){} // dummy children
// }
// tag("keep") attachable(anchor, spin, orient,d1=0,d2=95,h=33) {
// cylinder(h = 33, d = 10,anchor=CENTER);
// children();
// }
// }
// diff()
// cube(100)
// attach([FRONT,TOP],overlap=-4)
// thing(anchor=TOP)
// tube(ir=12,h=10);
module attachable(
anchor, spin, orient,
size, size2, shift,
@ -2659,14 +2694,14 @@ function _standard_anchors(two_d=false) = [
// Module: show_anchors()
// Usage:
// ... show_anchors([s], [std=], [custom=]);
// PARENT() show_anchors([s], [std=], [custom=]);
// Description:
// Show all standard anchors for the parent object.
// Arguments:
// s = Length of anchor arrows.
// ---
// std = If true (default), show standard anchors.
// custom = If true (default), show custom anchors.
// std = If true show standard anchors. Default: true
// custom = If true show named anchors. Default: true
// Example(FlatSpin,VPD=333):
// cube(50, center=true) show_anchors();
module show_anchors(s=10, std=true, custom=true) {

View file

@ -876,10 +876,10 @@ function _path_join(paths,joint,k=0.5,i=0,result=[],relocate=true,closed=false)
// Function&Module: offset_stroke()
// Usage: as module
// offset_stroke(path, [width], [rounded=], [chamfer=], [start=], [end=], [check_valid=], [quality=], [closed=]);
// offset_stroke(path, [width], [rounded=], [chamfer=], [start=], [end=], [check_valid=], [quality=], [closed=],...) [ATTACHMENTS];
// Usage: as function
// path = offset_stroke(path, [width], closed=false, [rounded=], [chamfer=], [start=], [end=], [check_valid=], [quality=]);
// region = offset_stroke(path, [width], closed=true, [rounded=], [chamfer=], [start=], [end=], [check_valid=], [quality=]);
// path = offset_stroke(path, [width], closed=false, [rounded=], [chamfer=], [start=], [end=], [check_valid=], [quality=],...);
// region = offset_stroke(path, [width], closed=true, [rounded=], [chamfer=], [start=], [end=], [check_valid=], [quality=],...);
// Description:
// Uses `offset()` to compute a stroke for the input path. Unlike `stroke`, the result does not need to be
// centered on the input path. The corners can be rounded, pointed, or chamfered, and you can make the ends
@ -927,12 +927,15 @@ function _path_join(paths,joint,k=0.5,i=0,result=[],relocate=true,closed=false)
// ---
// rounded = set to true to use rounded offsets, false to use sharp (delta) offsets. Default: true
// chamfer = set to true to use chamfers when `rounded=false`. Default: false
// start = end treatment for the start of the stroke. See above for details. Default: "flat"
// end = end treatment for the end of the stroke. See above for details. Default: "flat"
// start = end treatment for the start of the stroke when closed=false. See above for details. Default: "flat"
// end = end treatment for the end of the stroke when closed=false. See above for details. Default: "flat"
// check_valid = passed to offset(). Default: true
// quality = passed to offset(). Default: 1
// closed = true if the curve is closed, false otherwise. Default: false
//
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `"origin"`
// spin = Rotate this many degrees after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// cp = Centerpoint for determining intersection anchors or centering the shape. Determintes the base of the anchor vector. Can be "centroid", "mean", "box" or a 2D point. Default: "centroid"
// atype = Set to "hull" or "intersect" to select anchor type. Default: "hull"
// Example(2D): Basic examples illustrating flat, round, and pointed ends, on a finely sampled arc and a path made from 3 segments.
// arc = arc(points=[[1,1],[3,4],[6,3]],n=50);
// path = [[0,0],[6,2],[9,7],[8,10]];
@ -1028,44 +1031,53 @@ function _path_join(paths,joint,k=0.5,i=0,result=[],relocate=true,closed=false)
// stroke(path, closed=true);
// right(12)
// offset_stroke(path, width=1, closed=true);
function offset_stroke(path, width=1, rounded=true, start="flat", end="flat", check_valid=true, quality=1, chamfer=false, closed=false) =
function offset_stroke(path, width=1, rounded=true, start, end, check_valid=true, quality=1, chamfer=false, closed=false,
atype="hull", anchor, spin, cp="centroid") =
let(path = force_path(path))
assert(is_path(path,2),"path is not a 2d path")
let(closedok = !closed || (is_undef(start) && is_undef(end)))
let(
closedok = !closed || (is_undef(start) && is_undef(end)),
start = default(start,"flat"),
end = default(end,"flat")
)
assert(closedok, "Parameters `start` and `end` not allowed with closed path")
let(
start = closed? [] : _parse_stroke_end(default(start,"flat"),"start"),
end = closed? [] : _parse_stroke_end(default(end,"flat"),"end"),
width = is_list(width)? reverse(sort(width)) : [1,-1]*width/2,
left_r = !rounded? undef : width[0],
left_delta = rounded? undef : width[0],
right_r = !rounded? undef : width[1],
right_delta = rounded? undef : width[1],
left_path = offset(
path, delta=left_delta, r=left_r, closed=closed,
check_valid=check_valid, quality=quality,
chamfer=chamfer
),
right_path = offset(
path, delta=right_delta, r=right_r, closed=closed,
check_valid=check_valid, quality=quality,
chamfer=chamfer
)
)
closed? [left_path, right_path] :
let(
startpath = _stroke_end(width,left_path, right_path, start),
endpath = _stroke_end(reverse(width),reverse(right_path), reverse(left_path),end),
clipping_ok = startpath[1]+endpath[2]<=len(left_path) && startpath[2]+endpath[1]<=len(right_path)
)
assert(clipping_ok, "End treatment removed the whole stroke")
concat(
slice(left_path,startpath[1],-1-endpath[2]),
endpath[0],
reverse(slice(right_path,startpath[2],-1-endpath[1])),
startpath[0]
);
start = closed? [] : _parse_stroke_end(default(start,"flat"),"start"),
end = closed? [] : _parse_stroke_end(default(end,"flat"),"end"),
width = is_list(width)? reverse(sort(width)) : [1,-1]*width/2,
left_r = !rounded? undef : width[0],
left_delta = rounded? undef : width[0],
right_r = !rounded? undef : width[1],
right_delta = rounded? undef : width[1],
left_path = offset(
path, delta=left_delta, r=left_r, closed=closed,
check_valid=check_valid, quality=quality,
chamfer=chamfer
),
right_path = offset(
path, delta=right_delta, r=right_r, closed=closed,
check_valid=check_valid, quality=quality,
chamfer=chamfer
)
)
closed? let(pts = [left_path, right_path])
reorient(anchor=anchor, spin=spin, two_d=true, region=pts, extent=atype=="hull", cp=cp, p=pts)
:
let(
startpath = _stroke_end(width,left_path, right_path, start),
endpath = _stroke_end(reverse(width),reverse(right_path), reverse(left_path),end),
clipping_ok = startpath[1]+endpath[2]<=len(left_path) && startpath[2]+endpath[1]<=len(right_path)
)
assert(clipping_ok, "End treatment removed the whole stroke")
let(
pts = concat(
slice(left_path,startpath[1],-1-endpath[2]),
endpath[0],
reverse(slice(right_path,startpath[2],-1-endpath[1])),
startpath[0]
)
)
reorient(anchor=anchor, spin=spin, two_d=true, path=pts, extent=atype=="hull", cp=cp, p=pts);
function os_pointed(dist,loc=0) =
assert(is_def(dist), "Must specify `dist`")
@ -1222,9 +1234,9 @@ function _path_line_intersection(path, line, ind=0) =
[intersect, ind+1] :
_path_line_intersection(path, line, ind+1);
module offset_stroke(path, width=1, rounded=true, start, end, check_valid=true, quality=1, chamfer=false, closed=false)
module offset_stroke(path, width=1, rounded=true, start, end, check_valid=true, quality=1, chamfer=false, closed=false,
atype="hull", anchor, spin, cp="centroid")
{
no_children($children);
result = offset_stroke(
path, width=width, rounded=rounded,
start=start, end=end,
@ -1232,11 +1244,7 @@ module offset_stroke(path, width=1, rounded=true, start, end, check_valid=true,
chamfer=chamfer,
closed=closed
);
if (closed) {
region(result);
} else {
polygon(result);
}
region(result,atype=atype, anchor=anchor, spin=spin, cp=cp) children();
}
@ -2459,7 +2467,8 @@ module bent_cutout_mask(r, thickness, path, radius, convexity=10)
zmean = mean(column(fixpath,1));
innerzero = repeat([0,0,zmean], len(fixpath));
outerpt = repeat( [1.5*mindist*cos((maxangle+minangle)/2),1.5*mindist*sin((maxangle+minangle)/2),zmean], len(fixpath));
vnf_polyhedron(vnf_vertex_array([innerzero, each profiles, outerpt],col_wrap=true),convexity=convexity);
default_tag("remove")
vnf_polyhedron(vnf_vertex_array([innerzero, each profiles, outerpt],col_wrap=true),convexity=convexity);
}

View file

@ -212,6 +212,8 @@ Torx values: https://www.stanleyengineeredfastening.com/-/media/web/sef/resourc
// anchor = Translate so anchor point on the shaft is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `BOTTOM`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Side Effects:
// `$screw_spec` is set to the spec specification structure.
// Anchor Types:
// screw = the entire screw (default)
// head = screw head (invalid for headless screws)
@ -429,6 +431,7 @@ module screw(spec, head, drive, thread, drive_size,
is_struct(spec) ? spec
: screw_info(spec, default(head,"none"), drive, thread=thread, drive_size=drive_size,
threads_oversize=-shaft_undersize, head_oversize=-head_undersize) );
$screw_spec = spec;
head = struct_val(spec,"head");
pitch = thread==0 || thread=="none" ? 0 : struct_val(spec, "pitch") ;
nominal_diam = struct_val(spec, "diameter");
@ -593,6 +596,8 @@ module screw(spec, head, drive, thread, drive_size,
// anchor = Translate so anchor point on the shaft is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `BOTTOM`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Side Effects:
// `$screw_spec` is set to the spec specification structure.
// Anchor Types:
// screw = the entire screw (default)
// head = screw head (invalid for headless screws)
@ -636,7 +641,6 @@ module screw_hole(spec, head, thread=false, oversize, hole_oversize, head_oversi
atype="screw",anchor=BOTTOM,spin=0, orient=UP)
{
// Force flatheads to sharp for proper countersink shape
head = is_def(head) && starts_with(head,"flat") ? str(head," sharp")
: head;
if ((thread && thread!="none") || is_def(oversize) || is_def(hole_oversize) || tolerance==0 || tolerance=="none") {
@ -753,7 +757,7 @@ module screw_hole(spec, head, thread=false, oversize, hole_oversize, head_oversi
: in_list(downcase(tolerance), ["normal", "medium"]) ? 1
: in_list(downcase(tolerance), ["loose", "coarse"]) ? 2
: in_list(tolerance, ["H12","H13","H14"]) ?
assert(struct_val(spec,"systerm")=="ISO", str("Hole tolerance ", tolerance, " only allowed with ISO screws"))
assert(struct_val(spec,"system")=="ISO", str("Hole tolerance ", tolerance, " only allowed with ISO screws"))
parse_int(substr(tolerance,1))
: assert(false,str("Unknown tolerance ",tolerance, " for clearance hole"));
tol_table = struct_val(spec,"system")=="UTS" ? UTS_clearance[tol_ind] : ISO_clearance[tol_ind];
@ -805,8 +809,9 @@ module screw_hole(spec, head, thread=false, oversize, hole_oversize, head_oversi
// drive_size = size of the drive recess
// thread = thread type or specification. See [screw pitch](#subsection-standard-screw-pitch). Default: "coarse"
// spec = screw specification to define the thread size
// head_height = scalar or vector to give width,height, if no height computed according to formula for UTS sockets
// for flathead second value is the sharp size, and if not given it will be 12% more than given size
// head_size = scalar or vector to give width or [width, height]. If you only give width, height is computed using a formula for socket heads. For flat head screws the second value in the vector is the sharp size; if you don't give it then the sharp size will be 12% more than the given size
// Side Effects:
// `$screw_spec` is set to the spec specification structure.
// Anchor Types:
// screw = the entire screw (default)
// head = screw head (invalid for headless screws)
@ -1359,7 +1364,7 @@ echo(polygon=([[0,-flat_height],[r2,-flat_height],[r1,-flat_height+slopeheight],
// Note that flat head screws are defined by two different diameters, the theoretical maximum diameter, "head_size_sharp"
// and the actual diameter, "head_size". The screw form is defined using the theoretical maximum, which gives
// sharp circular edge at the top of the screw. Real screws have a flat chamfer around the edge.
// Figure(2D,Med): Flat head screw geometry
// Figure(2D,Med,NoAxes,VPD=39,VPT=[0,-4]): Flat head screw geometry
// polysharp = [[0, -5.07407], [4.92593, -5.07407], [10, 0], [10, 0.01], [0, 0.01]];
// color("blue"){
// xflip_copy()polygon(polysharp);
@ -1418,7 +1423,8 @@ function screw_info(spec, head="none", drive, thread="coarse", drive_size=undef,
over_ride = concat(
len(drive_info)>=3 ? ["drive_depth", drive_info[2]] : [],
is_def(type[3]) ? ["length",type[3]] : [],
is_def(drive_info[1]) ? ["drive_size", drive_info[1]] : []
is_def(drive_info[1]) ? ["drive_size", drive_info[1]] : [],
"name",spec
)
)
_oversize_screw(struct_set(screwdata, over_ride), threads_oversize=threads_oversize, head_oversize=head_oversize);
@ -1828,8 +1834,14 @@ function _screw_info_english(diam, threadcount, head, thread, drive) =
]
: []
)
concat([["system","UTS"],["diameter",INCH*diameter],["pitch", pitch],["drive",drive]],
head_data
concat([
["type","screw_info"],
["system","UTS"],
["diameter",INCH*diameter],
["pitch", pitch],
["drive",drive]
],
head_data
);
@ -2144,13 +2156,16 @@ function _screw_info_metric(diam, pitch, head, thread, drive) =
: []
)
concat(
[["system","ISO"],["diameter",diam],["pitch", pitch],["drive",drive]],
[
["type","screw_info"],
["system","ISO"],
["diameter",diam],
["pitch", pitch],
["drive",drive]
],
head_data
);
function _is_positive(x) = is_num(x) && x>0;
function _validate_screw_spec(spec) = let(