Doc tweak for modular hose. Add is_bool_list to common.scad. Add

line circle intersection and line bezier intersection.
This commit is contained in:
Adrian Mariano 2021-02-02 17:49:44 -05:00
parent d6f49714fa
commit 592fd34986
4 changed files with 80 additions and 5 deletions

View file

@ -324,8 +324,6 @@ function bezier_segment_closest_point(curve, pt, max_err=0.01, u=0, end_u=1) =
bezier_segment_closest_point(curve, pt, max_err=max_err, u=minima[0], end_u=minima[1]);
// Function: bezier_segment_length()
// Usage:
// pathlen = bezier_segment_length(curve, <start_u>, <end_u>, <max_deflect>);
@ -361,6 +359,28 @@ function bezier_segment_length(curve, start_u=0, end_u=1, max_deflect=0.01) =
// Function: bezier_line_intersection()
// Usages:
// u = bezier_line_intersection(curve, line);
// Description:
// Finds the parameter(s) of the 2d curve whose Bezier control points are `curve`
// corresponding to its intersection points with the line through
// the pair of distinct 2d points in `line`.
// Arguments:
// curve = List of 2d control points for the Bezier curve
// line = a list of two distinct 2d points defining a line
function bezier_line_intersection(curve, line) =
assert(is_path(curve,2), "The input ´curve´ must be a 2d bezier")
assert(_valid_line(line,2), "The input `line` is not a valid 2d line")
let(
a = _bezier_matrix(len(curve)-1)*curve, // curve algebraic coeffs.
n = [-line[1].y+line[0].y, line[1].x-line[0].x], // line normal
q = [for(i=[len(a)-1:-1:1]) a[i]*n, (a[0]-line[0])*n] // curve SDF to line
)
[for(u=real_roots(q)) if (u>=0 && u<=1) u];
// Function: fillet3pts()
// Usage:
// bez_path_pts = fillet3pts(p0, p1, p2, r);

View file

@ -222,6 +222,18 @@ function _list_pattern(list) =
function same_shape(a,b) = _list_pattern(a) == b*0;
// Function: is_bool_list()
// Usage:
// check = is_bool_list(list,<length>)
// Description:
// Tests whether input is a list containing only booleans, and optionally checks its length.
// Arguments:
// list = list to test
// length = if given, list must be this length
function is_bool_list(list, length) =
is_list(list) && (is_undef(length) || len(list)==length) && []==[for(entry=list) if (!is_bool(entry)) 1];
// Section: Handling `undef`s.

View file

@ -1139,7 +1139,7 @@ function plane_line_angle(plane, line) =
function plane_line_intersection(plane, line, bounded=false, eps=EPSILON) =
assert( is_finite(eps) && eps>=0, "The tolerance should be a positive number." )
assert(_valid_plane(plane,eps=eps) && _valid_line(line,dim=3,eps=eps), "Invalid plane and/or line.")
assert(is_bool(bounded) || (is_list(bounded) && len(bounded)==2), "Invalid bound condition(s).")
assert(is_bool(bounded) || is_bool_list(bounded,2), "Invalid bound condition.")
let(
bounded = is_list(bounded)? bounded : [bounded, bounded],
res = _general_plane_line_intersection(plane, line, eps=eps)
@ -1591,6 +1591,47 @@ function circle_circle_tangents(c1,r1,c2,r2,d1,d2) =
// Function: circle_line_intersection()
// Usage:
// isect = circle_line_intersection(c,r,line,<bounded>,<eps>);
// isect = circle_line_intersection(c,d,line,<bounded>,<eps>);
// Description:
// Find intersection points between a 2d circle and a line, ray or segment specified by two points.
// By default the line is unbounded.
// Arguments:
// c = center of circle
// r = radius of circle
// line = two points defining the unbounded line
// bounded = false for unbounded line, true for a segment, or a vector [false,true] or [true,false] to specify a ray with the first or second end unbounded. Default: false
// eps = epsilon used for identifying the case with one solution. Default: 1e-9
// --
// d = diameter of circle
function circle_line_intersection(c,r,line,d,bounded=false,eps=EPSILON) =
let(r=get_radius(r=r,d=d,dflt=undef))
assert(_valid_line(line,2), "Input 'line' is not a valid 2d line.")
assert(is_vector(c,2), "Circle center must be a 2-vector")
assert(is_num(r) && r>0, "Radius must be positive")
assert(is_bool(bounded) || is_bool_list(bounded,2), "Invalid bound condition")
let(
bounded = force_list(bounded,2),
closest = line_closest_point(line,c),
d = norm(closest-c)
)
d > r ? [] :
let(
isect = approx(d,r,eps) ? [closest] :
let( offset = sqrt(r*r-d*d),
uvec=unit(line[1]-line[0])
) [closest-offset*uvec, closest+offset*uvec]
)
[for(p=isect)
if ((!bounded[0] || (p-line[0])*(line[1]-line[0])>=0)
&& (!bounded[1] || (p-line[1])*(line[0]-line[1])>=0)) p];
// Section: Pointlists

View file

@ -126,7 +126,9 @@ _hose_waist = [1.7698, 1.8251, 3.95998];
// or you can make modular hose segments. To make assembly possible with printed
// parts you can add clearances that make the ball end smaller and the socket end
// larger. These work by simply increasing the radius of the whole end by the specified
// amount. On a Prusa printer with PETG clearance values around .1 work, but you
// amount. On a Prusa printer with PETG, a clearance of 0.05 allows the 3/4" hose parts to mate
// with standard modular hose or itself. A clearance of 0.1 allows the 3/4" parts to mate with
// standard hoseclearance values around .1 work, but you
// will have to experiment with your machine and materials. And note clearance values
// are different for the different sizes.
// Arguments:
@ -174,7 +176,7 @@ module modular_hose(size, type, clearance=0, waist_len, anchor=BOTTOM, spin=0,or
center = mean(bounds);
attachable(anchor,spin,orient,l=bounds[1].y-bounds[0].y, r=bounds[1].x)
{
rotate_extrude()
rotate_extrude(convexity=4)
polygon(fwd(center.y,p=shape));
children();
}