From 592fd349867e60dd6ecd4cac06c85a6025b19682 Mon Sep 17 00:00:00 2001 From: Adrian Mariano Date: Tue, 2 Feb 2021 17:49:44 -0500 Subject: [PATCH 1/4] Doc tweak for modular hose. Add is_bool_list to common.scad. Add line circle intersection and line bezier intersection. --- beziers.scad | 24 ++++++++++++++++++++++-- common.scad | 12 ++++++++++++ geometry.scad | 43 ++++++++++++++++++++++++++++++++++++++++++- modular_hose.scad | 6 ++++-- 4 files changed, 80 insertions(+), 5 deletions(-) diff --git a/beziers.scad b/beziers.scad index 4162a17..0a09d95 100644 --- a/beziers.scad +++ b/beziers.scad @@ -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, , , ); @@ -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); diff --git a/common.scad b/common.scad index 2a51a3b..bf7b79c 100644 --- a/common.scad +++ b/common.scad @@ -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,) +// 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. diff --git a/geometry.scad b/geometry.scad index 52f03c2..b11fa0f 100644 --- a/geometry.scad +++ b/geometry.scad @@ -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,,); +// isect = circle_line_intersection(c,d,line,,); +// 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 diff --git a/modular_hose.scad b/modular_hose.scad index fdf2861..e7275be 100644 --- a/modular_hose.scad +++ b/modular_hose.scad @@ -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(); } From 483c8cf79c3c649dfa5366cda35642b04b442864 Mon Sep 17 00:00:00 2001 From: Adrian Mariano Date: Tue, 2 Feb 2021 17:52:26 -0500 Subject: [PATCH 2/4] doc tweak --- modular_hose.scad | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modular_hose.scad b/modular_hose.scad index e7275be..e7e71d1 100644 --- a/modular_hose.scad +++ b/modular_hose.scad @@ -128,9 +128,9 @@ _hose_waist = [1.7698, 1.8251, 3.95998]; // larger. These work by simply increasing the radius of the whole end by the specified // 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. +// standard hose, and with clearance 0 the 1/4" parts will mate with standard hose. And note clearance values +// are different for the different sizes. You will have to experiment with your machine and materials. Small +// adjustments will change the stiffness of the connection. // Arguments: // size = size of modular hose part, must be 1/4, 1/2 or 3/4. // type = type of part to make, either "segment", "socket" (or "big"), or "ball" (or "small") From fbcf8b02b7c44aad34bc78dab88740684f92ca10 Mon Sep 17 00:00:00 2001 From: Adrian Mariano Date: Tue, 2 Feb 2021 18:00:07 -0500 Subject: [PATCH 3/4] doc fix --- geometry.scad | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geometry.scad b/geometry.scad index b11fa0f..6e7f6c4 100644 --- a/geometry.scad +++ b/geometry.scad @@ -1604,7 +1604,7 @@ function circle_circle_tangents(c1,r1,c2,r2,d1,d2) = // 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)) From ffd80c29f234c57d05fc69ca5db1a2dcf60c825a Mon Sep 17 00:00:00 2001 From: Adrian Mariano Date: Tue, 2 Feb 2021 18:04:47 -0500 Subject: [PATCH 4/4] doc fix --- beziers.scad | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beziers.scad b/beziers.scad index 0a09d95..9b02948 100644 --- a/beziers.scad +++ b/beziers.scad @@ -360,7 +360,7 @@ function bezier_segment_length(curve, start_u=0, end_u=1, max_deflect=0.01) = // Function: bezier_line_intersection() -// Usages: +// Usage: // u = bezier_line_intersection(curve, line); // Description: // Finds the parameter(s) of the 2d curve whose Bezier control points are `curve`