mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2024-12-29 16:29:40 +00:00
Fixed interior_fillet(). Refactored circle_* functions.
This commit is contained in:
parent
65615dc07d
commit
d9691b3b4a
8 changed files with 145 additions and 139 deletions
|
@ -710,7 +710,7 @@ function arc(n, r, angle, d, cp, points, corner, width, thickness, start, wedge=
|
||||||
let( r = get_radius(r=r, d=d) )
|
let( r = get_radius(r=r, d=d) )
|
||||||
assert(is_finite(r) && r>0, "Must specify r= or d= when corner= is given.")
|
assert(is_finite(r) && r>0, "Must specify r= or d= when corner= is given.")
|
||||||
let(
|
let(
|
||||||
ci = circle_2tangents(corner[0], corner[1], corner[2], r=r, tangents=true),
|
ci = circle_2tangents(r, corner[0], corner[1], corner[2], tangents=true),
|
||||||
cp = ci[0], nrm = ci[1], tp1 = ci[2], tp2 = ci[3],
|
cp = ci[0], nrm = ci[1], tp1 = ci[2], tp2 = ci[3],
|
||||||
dir = det2([corner[1]-corner[0],corner[2]-corner[1]]) > 0,
|
dir = det2([corner[1]-corner[0],corner[2]-corner[1]]) > 0,
|
||||||
corner = dir? [tp1,tp2] : [tp2,tp1],
|
corner = dir? [tp1,tp2] : [tp2,tp1],
|
||||||
|
|
193
geometry.scad
193
geometry.scad
|
@ -861,14 +861,14 @@ function _is_point_above_plane(plane, point) =
|
||||||
|
|
||||||
// Function: circle_line_intersection()
|
// Function: circle_line_intersection()
|
||||||
// Usage:
|
// Usage:
|
||||||
// isect = circle_line_intersection(c, r|d=, line, [bounded], [eps=]);
|
// pts = circle_line_intersection(r|d=, cp, line, [bounded], [eps=]);
|
||||||
// Topics: Geometry, Circles, Lines, Intersection
|
// Topics: Geometry, Circles, Lines, Intersection
|
||||||
// Description:
|
// Description:
|
||||||
// Find intersection points between a 2d circle and a line, ray or segment specified by two points.
|
// Find intersection points between a 2D circle and a line, ray or segment specified by two points.
|
||||||
// By default the line is unbounded. Returns the list of zero or more intersection points.
|
// By default the line is unbounded. Returns the list of zero or more intersection points.
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// c = Center of circle
|
|
||||||
// r = Radius of circle
|
// r = Radius of circle
|
||||||
|
// cp = Center of circle
|
||||||
// line = Two points defining the line
|
// line = Two points defining the 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
|
// 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
|
||||||
// ---
|
// ---
|
||||||
|
@ -879,14 +879,14 @@ function _is_point_above_plane(plane, point) =
|
||||||
// cp = [1,2]; r = 10;
|
// cp = [1,2]; r = 10;
|
||||||
// translate(cp) circle(r=r);
|
// translate(cp) circle(r=r);
|
||||||
// color("black") stroke(line, endcaps="arrow2", width=0.5);
|
// color("black") stroke(line, endcaps="arrow2", width=0.5);
|
||||||
// isects = circle_line_intersection(c=cp, r=r, line=line);
|
// isects = circle_line_intersection(r=r, cp=cp, line=line);
|
||||||
// color("red") move_copies(isects) circle(d=1);
|
// color("red") move_copies(isects) circle(d=1);
|
||||||
// Example(2D): Tangent intersection returns one point.
|
// Example(2D): Tangent intersection returns one point.
|
||||||
// line = [[-10,12], [10,12]];
|
// line = [[-10,12], [10,12]];
|
||||||
// cp = [1,2]; r = 10;
|
// cp = [1,2]; r = 10;
|
||||||
// translate(cp) circle(r=r);
|
// translate(cp) circle(r=r);
|
||||||
// color("black") stroke(line, endcaps="arrow2", width=0.5);
|
// color("black") stroke(line, endcaps="arrow2", width=0.5);
|
||||||
// isects = circle_line_intersection(c=cp, r=r, line=line);
|
// isects = circle_line_intersection(r=r, cp=cp, line=line);
|
||||||
// color("#f44") move_copies(isects) circle(d=1);
|
// color("#f44") move_copies(isects) circle(d=1);
|
||||||
// Example(2D): A bounded ray might only intersect in one direction.
|
// Example(2D): A bounded ray might only intersect in one direction.
|
||||||
// line = [[-5,2], [5,7]];
|
// line = [[-5,2], [5,7]];
|
||||||
|
@ -895,30 +895,30 @@ function _is_point_above_plane(plane, point) =
|
||||||
// translate(cp) circle(r=r);
|
// translate(cp) circle(r=r);
|
||||||
// color("gray") dashed_stroke(extended, width=0.2);
|
// color("gray") dashed_stroke(extended, width=0.2);
|
||||||
// color("black") stroke(line, endcap2="arrow2", width=0.5);
|
// color("black") stroke(line, endcap2="arrow2", width=0.5);
|
||||||
// isects = circle_line_intersection(c=cp, r=r, line=line, bounded=[true,false]);
|
// isects = circle_line_intersection(r=r, cp=cp, line=line, bounded=[true,false]);
|
||||||
// color("#f44") move_copies(isects) circle(d=1);
|
// color("#f44") move_copies(isects) circle(d=1);
|
||||||
// Example(2D): If they don't intersect at all, then an empty list is returned.
|
// Example(2D): If they don't intersect at all, then an empty list is returned.
|
||||||
// line = [[-12,12], [12,8]];
|
// line = [[-12,12], [12,8]];
|
||||||
// cp = [-5,-2]; r = 10;
|
// cp = [-5,-2]; r = 10;
|
||||||
// translate(cp) circle(r=r);
|
// translate(cp) circle(r=r);
|
||||||
// color("black") stroke(line, endcaps="arrow2", width=0.5);
|
// color("black") stroke(line, endcaps="arrow2", width=0.5);
|
||||||
// isects = circle_line_intersection(c=cp, r=r, line=line);
|
// isects = circle_line_intersection(r=r, cp=cp, line=line);
|
||||||
// color("#f44") move_copies(isects) circle(d=1);
|
// color("#f44") move_copies(isects) circle(d=1);
|
||||||
function circle_line_intersection(c,r,line,bounded=false,d,eps=EPSILON) =
|
function circle_line_intersection(r, cp, line, bounded=false, d, eps=EPSILON) =
|
||||||
assert(_valid_line(line,2), "Invalid 2d line.")
|
assert(_valid_line(line,2), "Invalid 2d line.")
|
||||||
assert(is_vector(c,2), "Circle center must be a 2-vector")
|
assert(is_vector(cp,2), "Circle center must be a 2-vector")
|
||||||
_circle_or_sphere_line_intersection(c,r,line,bounded,d,eps);
|
_circle_or_sphere_line_intersection(r, cp, line, bounded, d, eps);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function _circle_or_sphere_line_intersection(c,r,line,bounded=false,d,eps=EPSILON) =
|
function _circle_or_sphere_line_intersection(r, cp, line, bounded=false, d, eps=EPSILON) =
|
||||||
let(r=get_radius(r=r,d=d,dflt=undef))
|
let(r=get_radius(r=r,d=d,dflt=undef))
|
||||||
assert(is_num(r) && r>0, "Radius must be positive")
|
assert(is_num(r) && r>0, "Radius must be positive")
|
||||||
assert(is_bool(bounded) || is_bool_list(bounded,2), "Invalid bound condition")
|
assert(is_bool(bounded) || is_bool_list(bounded,2), "Invalid bound condition")
|
||||||
let(
|
let(
|
||||||
bounded = force_list(bounded,2),
|
bounded = force_list(bounded,2),
|
||||||
closest = line_closest_point(line,c),
|
closest = line_closest_point(line,cp),
|
||||||
d = norm(closest-c)
|
d = norm(closest-cp)
|
||||||
)
|
)
|
||||||
d > r ? [] :
|
d > r ? [] :
|
||||||
let(
|
let(
|
||||||
|
@ -934,73 +934,74 @@ function _circle_or_sphere_line_intersection(c,r,line,bounded=false,d,eps=EPSILO
|
||||||
|
|
||||||
// Function: circle_circle_intersection()
|
// Function: circle_circle_intersection()
|
||||||
// Usage:
|
// Usage:
|
||||||
// pts = circle_circle_tangents(c1, r1|d1=, c2, r2|d2=, [eps]);
|
// pts = circle_circle_intersection(r1|d1=, cp1, r2|d2=, cp2, [eps]);
|
||||||
// Topics: Geometry, Circles
|
// Topics: Geometry, Circles
|
||||||
// Description:
|
// Description:
|
||||||
// Compute the intersection points of two circles. Returns a list of the intersection points, which
|
// Compute the intersection points of two circles. Returns a list of the intersection points, which
|
||||||
// will contain two points in the general case, one point for tangent circles, or will be empty
|
// will contain two points in the general case, one point for tangent circles, or will be empty
|
||||||
// if the circles do not intersect.
|
// if the circles do not intersect.
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// c1 = Center of the first circle.
|
|
||||||
// r1 = Radius of the first circle.
|
// r1 = Radius of the first circle.
|
||||||
// c2 = Center of the second circle.
|
// cp1 = Centerpoint of the first circle.
|
||||||
// r2 = Radius of the second circle.
|
// r2 = Radius of the second circle.
|
||||||
|
// cp2 = Centerpoint of the second circle.
|
||||||
// eps = Tolerance for detecting tangent circles. Default: EPSILON
|
// eps = Tolerance for detecting tangent circles. Default: EPSILON
|
||||||
// ---
|
// ---
|
||||||
// d1 = Diameter of the first circle.
|
// d1 = Diameter of the first circle.
|
||||||
// d2 = Diameter of the second circle.
|
// d2 = Diameter of the second circle.
|
||||||
// Example(2D,NoAxes): Circles intersect in two points.
|
// Example(2D,NoAxes): Circles intersect in two points.
|
||||||
// $fn=32;
|
// $fn=32;
|
||||||
// c1 = [4,4]; r1 = 3;
|
// cp1 = [4,4]; r1 = 3;
|
||||||
// c2 = [7,7]; r2 = 2;
|
// cp2 = [7,7]; r2 = 2;
|
||||||
// pts = circle_circle_intersection(c1,r1,c2,r2);
|
// pts = circle_circle_intersection(r1, cp1, r2, cp2);
|
||||||
// move(c1) stroke(circle(r=r1), width=0.2, closed=true);
|
// move(cp1) stroke(circle(r=r1), width=0.2, closed=true);
|
||||||
// move(c2) stroke(circle(r=r2), width=0.2, closed=true);
|
// move(cp2) stroke(circle(r=r2), width=0.2, closed=true);
|
||||||
// color("red")move_copies(pts) circle(r=.3);
|
// color("red") move_copies(pts) circle(r=.3);
|
||||||
// Example(2D,NoAxes): Circles are tangent, so one intersection point:
|
// Example(2D,NoAxes): Circles are tangent, so one intersection point:
|
||||||
// $fn=32;
|
// $fn=32;
|
||||||
// c1 = [4,4]; r1 = 4;
|
// cp1 = [4,4]; r1 = 4;
|
||||||
// c2 = [4,10]; r2 = 2;
|
// cp2 = [4,10]; r2 = 2;
|
||||||
// pts = circle_circle_intersection(c1,r1,c2,r2);
|
// pts = circle_circle_intersection(r1, cp1, r2, cp2);
|
||||||
// move(c1) stroke(circle(r=r1), width=0.2, closed=true);
|
// move(cp1) stroke(circle(r=r1), width=0.2, closed=true);
|
||||||
// move(c2) stroke(circle(r=r2), width=0.2, closed=true);
|
// move(cp2) stroke(circle(r=r2), width=0.2, closed=true);
|
||||||
// color("red")move_copies(pts) circle(r=.3);
|
// color("red") move_copies(pts) circle(r=.3);
|
||||||
// Example(2D,NoAxes): Another tangent example:
|
// Example(2D,NoAxes): Another tangent example:
|
||||||
// $fn=32;
|
// $fn=32;
|
||||||
// c1 = [4,4]; r1 = 4;
|
// cp1 = [4,4]; r1 = 4;
|
||||||
// c2 = [5,5]; r2 = 4-sqrt(2);
|
// cp2 = [5,5]; r2 = 4-sqrt(2);
|
||||||
// pts = circle_circle_intersection(c1,r1,c2,r2);
|
// pts = circle_circle_intersection(r1, cp1, r2, cp2);
|
||||||
// move(c1) stroke(circle(r=r1), width=0.2, closed=true);
|
// move(cp1) stroke(circle(r=r1), width=0.2, closed=true);
|
||||||
// move(c2) stroke(circle(r=r2), width=0.2, closed=true);
|
// move(cp2) stroke(circle(r=r2), width=0.2, closed=true);
|
||||||
// color("red")move_copies(pts) circle(r=.3);
|
// color("red") move_copies(pts) circle(r=.3);
|
||||||
// Example(2D,NoAxes): Circles do not intersect. Returns empty list.
|
// Example(2D,NoAxes): Circles do not intersect. Returns empty list.
|
||||||
// $fn=32;
|
// $fn=32;
|
||||||
// c1 = [3,4]; r1 = 2;
|
// cp1 = [3,4]; r1 = 2;
|
||||||
// c2 = [7,10]; r2 = 3;
|
// cp2 = [7,10]; r2 = 3;
|
||||||
// pts = circle_circle_intersection(c1,r1,c2,r2);
|
// pts = circle_circle_intersection(r1, cp1, r2, cp2);
|
||||||
// move(c1) stroke(circle(r=r1), width=0.2, closed=true);
|
// move(cp1) stroke(circle(r=r1), width=0.2, closed=true);
|
||||||
// move(c2) stroke(circle(r=r2), width=0.2, closed=true);
|
// move(cp2) stroke(circle(r=r2), width=0.2, closed=true);
|
||||||
// color("red")move_copies(pts) circle(r=.2); // pts is []
|
// color("red") move_copies(pts) circle(r=.3);
|
||||||
function circle_circle_intersection(c1,r1,c2,r2,eps=EPSILON,d1,d2) =
|
function circle_circle_intersection(r1, cp1, r2, cp2, eps=EPSILON, d1, d2) =
|
||||||
assert( is_path([c1,c2],dim=2), "Invalid center point(s)." )
|
assert( is_path([cp1,cp2],dim=2), "Invalid center point(s)." )
|
||||||
let(
|
let(
|
||||||
r1 = get_radius(r1=r1,d1=d1),
|
r1 = get_radius(r1=r1,d1=d1),
|
||||||
r2 = get_radius(r1=r2,d1=d2),
|
r2 = get_radius(r1=r2,d1=d2),
|
||||||
d = norm(c2-c1),
|
d = norm(cp2-cp1),
|
||||||
a = (c2-c1)/d,
|
a = (cp2-cp1)/d,
|
||||||
b = [-a.y,a.x],
|
b = [-a.y,a.x],
|
||||||
L = (r1^2-r2^2+d^2)/2/d,
|
L = (r1^2-r2^2+d^2)/2/d,
|
||||||
hsqr = r1^2-L^2
|
hsqr = r1^2-L^2
|
||||||
)
|
)
|
||||||
approx(hsqr,0,eps) ? [L*a+c1]
|
approx(hsqr,0,eps) ? [L*a+cp1]
|
||||||
: hsqr<0 ? []
|
: hsqr<0 ? []
|
||||||
: let(h=sqrt(hsqr))
|
: let(h=sqrt(hsqr))
|
||||||
[L*a+h*b+c1, L*a-h*b+c1];
|
[L*a+h*b+cp1, L*a-h*b+cp1];
|
||||||
|
|
||||||
|
|
||||||
// Function: circle_2tangents()
|
// Function: circle_2tangents()
|
||||||
// Usage:
|
// Usage:
|
||||||
// circ = circle_2tangents(pt1, pt2, pt3, r|d=, [tangents=]);
|
// circ = circle_2tangents(r|d=, pt1, pt2, pt3, [tangents=]);
|
||||||
|
// circ = circle_2tangents(r|d=, [PT1, PT2, PT3], [tangents=]);
|
||||||
// Topics: Geometry, Circles, Tangents
|
// Topics: Geometry, Circles, Tangents
|
||||||
// Description:
|
// Description:
|
||||||
// Given a pair of rays with a common origin, and a known circle radius/diameter, finds
|
// Given a pair of rays with a common origin, and a known circle radius/diameter, finds
|
||||||
|
@ -1017,7 +1018,7 @@ function circle_circle_intersection(c1,r1,c2,r2,eps=EPSILON,d1,d2) =
|
||||||
// Figure(3D,Med,NoAxes,VPD=130,VPT=[29,19,3],VPR=[55,0,25]):
|
// Figure(3D,Med,NoAxes,VPD=130,VPT=[29,19,3],VPR=[55,0,25]):
|
||||||
// pts = [[45,10,-5], [10,5,10], [15,40,5]];
|
// pts = [[45,10,-5], [10,5,10], [15,40,5]];
|
||||||
// rad = 15;
|
// rad = 15;
|
||||||
// circ = circle_2tangents(pt1=pts[0], pt2=pts[1], pt3=pts[2], r=rad, tangents=true);
|
// circ = circle_2tangents(r=rad, pt1=pts[0], pt2=pts[1], pt3=pts[2], tangents=true);
|
||||||
// cp = circ[0]; n = circ[1]; tp1 = circ[2]; tp2 = circ[3];
|
// cp = circ[0]; n = circ[1]; tp1 = circ[2]; tp2 = circ[3];
|
||||||
// color("yellow") stroke(pts, endcaps="arrow2");
|
// color("yellow") stroke(pts, endcaps="arrow2");
|
||||||
// color("purple") move_copies([cp,tp1,tp2]) sphere(d=2, $fn=12);
|
// color("purple") move_copies([cp,tp1,tp2]) sphere(d=2, $fn=12);
|
||||||
|
@ -1034,32 +1035,32 @@ function circle_circle_intersection(c1,r1,c2,r2,eps=EPSILON,d1,d2) =
|
||||||
// ["TanPt2", "brown", 2.0, [-5, 0, 2], tp2],
|
// ["TanPt2", "brown", 2.0, [-5, 0, 2], tp2],
|
||||||
// ];
|
// ];
|
||||||
// for(l=labels)
|
// for(l=labels)
|
||||||
// color(l[1]) move(l[4]+l[3]) rot($vpr)
|
// color(l[1]) move(l[4]+l[3]) rot([55,0,25])
|
||||||
// linear_extrude(height=0.1)
|
// linear_extrude(height=0.1)
|
||||||
// text(text=l[0], size=l[2], halign="center", valign="center");
|
// text(text=l[0], size=l[2], halign="center", valign="center");
|
||||||
// color("green",0.5) move(cp) cyl(h=0.1, r=rad, orient=n, $fn=36);
|
// color("green",0.5) move(cp) cyl(h=0.1, r=rad, orient=n, $fn=36);
|
||||||
// Arguments:
|
// Arguments:
|
||||||
|
// r = The radius of the circle to find.
|
||||||
// pt1 = A point that the first ray passes though.
|
// pt1 = A point that the first ray passes though.
|
||||||
// pt2 = The starting point of both rays.
|
// pt2 = The starting point of both rays.
|
||||||
// pt3 = A point that the second ray passes though.
|
// pt3 = A point that the second ray passes though.
|
||||||
// r = The radius of the circle to find.
|
|
||||||
// ---
|
// ---
|
||||||
// d = The diameter of the circle to find.
|
// d = The diameter of the circle to find.
|
||||||
// tangents = If true, extended information about the tangent points is calculated and returned. Default: false
|
// tangents = If true, extended information about the tangent points is calculated and returned. Default: false
|
||||||
// Example(2D):
|
// Example(2D):
|
||||||
// pts = [[40,40], [10,10], [55,5]]; rad = 10;
|
// pts = [[40,40], [10,10], [55,5]]; rad = 10;
|
||||||
// circ = circle_2tangents(pt1=pts[0], pt2=pts[1], pt3=pts[2], r=rad);
|
// circ = circle_2tangents(r=rad, pt1=pts[0], pt2=pts[1], pt3=pts[2]);
|
||||||
// stroke(pts, endcaps="arrow2");
|
// stroke(pts, endcaps="arrow2");
|
||||||
// color("red") move(circ[0]) circle(r=rad);
|
// color("red") move(circ[0]) circle(r=rad);
|
||||||
// Example(2D):
|
// Example(2D):
|
||||||
// pts = [[20,40], [10,10], [55,20]]; rad = 10;
|
// pts = [[20,40], [10,10], [55,20]]; rad = 10;
|
||||||
// circ = circle_2tangents(pt1=pts[0], pt2=pts[1], pt3=pts[2], r=rad, tangents=true);
|
// circ = circle_2tangents(r=rad, pt1=pts[0], pt2=pts[1], pt3=pts[2], tangents=true);
|
||||||
// stroke(pts, endcaps="arrow2");
|
// stroke(pts, endcaps="arrow2");
|
||||||
// color("red") move(circ[0]) circle(r=rad);
|
// color("red") move(circ[0]) circle(r=rad);
|
||||||
// color("blue") move_copies(select(circ,2,3)) circle(d=2);
|
// color("blue") move_copies(select(circ,2,3)) circle(d=2);
|
||||||
// Example(3D): Fit into 3D path corner.
|
// Example(3D): Fit into 3D path corner.
|
||||||
// pts = [[45,5,10], [10,10,15], [30,40,30]]; rad = 10;
|
// pts = [[45,5,10], [10,10,15], [30,40,30]]; rad = 10;
|
||||||
// circ = circle_2tangents(pt1=pts[0], pt2=pts[1], pt3=pts[2], r=rad);
|
// circ = circle_2tangents(r=rad, pt1=pts[0], pt2=pts[1], pt3=pts[2]);
|
||||||
// stroke(pts, endcaps="arrow2");
|
// stroke(pts, endcaps="arrow2");
|
||||||
// color("red") move(circ[0]) cyl(h=10, r=rad, orient=circ[1]);
|
// color("red") move(circ[0]) cyl(h=10, r=rad, orient=circ[1]);
|
||||||
// Example(3D):
|
// Example(3D):
|
||||||
|
@ -1067,17 +1068,17 @@ function circle_circle_intersection(c1,r1,c2,r2,eps=EPSILON,d1,d2) =
|
||||||
// stroke(path, closed=true);
|
// stroke(path, closed=true);
|
||||||
// for (i = [0:1:5]) {
|
// for (i = [0:1:5]) {
|
||||||
// crn = select(path, i*2-1, i*2+1);
|
// crn = select(path, i*2-1, i*2+1);
|
||||||
// ci = circle_2tangents(crn[0], crn[1], crn[2], r=5);
|
// ci = circle_2tangents(r=5, crn[0], crn[1], crn[2]);
|
||||||
// move(ci[0]) cyl(h=10,r=5,,orient=ci[1]);
|
// move(ci[0]) cyl(h=10,r=5,,orient=ci[1]);
|
||||||
// }
|
// }
|
||||||
function circle_2tangents(pt1, pt2, pt3, r, d, tangents=false) =
|
function circle_2tangents(r, pt1, pt2, pt3, tangents=false, d) =
|
||||||
let(r = get_radius(r=r, d=d, dflt=undef))
|
let(r = get_radius(r=r, d=d, dflt=undef))
|
||||||
assert(r!=undef, "Must specify either r or d.")
|
assert(r!=undef, "Must specify either r or d.")
|
||||||
assert( ( is_path(pt1) && len(pt1)==3 && is_undef(pt2) && is_undef(pt3))
|
assert( ( is_path(pt1) && len(pt1)==3 && is_undef(pt2) && is_undef(pt3))
|
||||||
|| (is_matrix([pt1,pt2,pt3]) && (len(pt1)==2 || len(pt1)==3) ),
|
|| (is_matrix([pt1,pt2,pt3]) && (len(pt1)==2 || len(pt1)==3) ),
|
||||||
"Invalid input points." )
|
"Invalid input points." )
|
||||||
is_undef(pt2)
|
is_undef(pt2)
|
||||||
? circle_2tangents(pt1[0], pt1[1], pt1[2], r=r, tangents=tangents)
|
? circle_2tangents(r, pt1[0], pt1[1], pt1[2], tangents=tangents)
|
||||||
: is_collinear(pt1, pt2, pt3)? undef :
|
: is_collinear(pt1, pt2, pt3)? undef :
|
||||||
let(
|
let(
|
||||||
v1 = unit(pt1 - pt2),
|
v1 = unit(pt1 - pt2),
|
||||||
|
@ -1100,7 +1101,7 @@ function circle_2tangents(pt1, pt2, pt3, r, d, tangents=false) =
|
||||||
// Function: circle_3points()
|
// Function: circle_3points()
|
||||||
// Usage:
|
// Usage:
|
||||||
// circ = circle_3points(pt1, pt2, pt3);
|
// circ = circle_3points(pt1, pt2, pt3);
|
||||||
// circ = circle_3points([pt1, pt2, pt3]);
|
// circ = circle_3points([PT1, PT2, PT3]);
|
||||||
// Topics: Geometry, Circles
|
// Topics: Geometry, Circles
|
||||||
// Description:
|
// Description:
|
||||||
// Returns the [CENTERPOINT, RADIUS, NORMAL] of the circle that passes through three non-collinear
|
// Returns the [CENTERPOINT, RADIUS, NORMAL] of the circle that passes through three non-collinear
|
||||||
|
@ -1109,8 +1110,8 @@ function circle_2tangents(pt1, pt2, pt3, r, d, tangents=false) =
|
||||||
// points are 2D, then the resulting centerpoint will be 2D, and the normal will be UP ([0,0,1]).
|
// points are 2D, then the resulting centerpoint will be 2D, and the normal will be UP ([0,0,1]).
|
||||||
// If any of the points are 3D, then the resulting centerpoint will be 3D. If the three points are
|
// If any of the points are 3D, then the resulting centerpoint will be 3D. If the three points are
|
||||||
// collinear, then `[undef,undef,undef]` will be returned. The normal will be a normalized 3D
|
// collinear, then `[undef,undef,undef]` will be returned. The normal will be a normalized 3D
|
||||||
// vector with a non-negative Z axis.
|
// vector with a non-negative Z axis. Instead of 3 arguments, it is acceptable to input the 3 points
|
||||||
// Instead of 3 arguments, it is acceptable to input the 3 points in a list `pt1`, leaving `pt2`and `pt3` as undef.
|
// as a list given in `pt1`, leaving `pt2`and `pt3` as undef.
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// pt1 = The first point.
|
// pt1 = The first point.
|
||||||
// pt2 = The second point.
|
// pt2 = The second point.
|
||||||
|
@ -1186,7 +1187,7 @@ function circle_point_tangents(r, cp, pt, d) =
|
||||||
|
|
||||||
// Function: circle_circle_tangents()
|
// Function: circle_circle_tangents()
|
||||||
// Usage:
|
// Usage:
|
||||||
// segs = circle_circle_tangents(c1, r1|d1=, c2, r2|d2=);
|
// segs = circle_circle_tangents(r1|d1=, cp1, r2|d2=, cp2);
|
||||||
// Topics: Geometry, Circles, Tangents
|
// Topics: Geometry, Circles, Tangents
|
||||||
// Description:
|
// Description:
|
||||||
// Computes 2d lines tangents to a pair of circles in 2d. Returns a list of line endpoints [p1,p2] where
|
// Computes 2d lines tangents to a pair of circles in 2d. Returns a list of line endpoints [p1,p2] where
|
||||||
|
@ -1200,54 +1201,54 @@ function circle_point_tangents(r, cp, pt, d) =
|
||||||
// so the function returns the empty set. When the circles are tangent a degenerate tangent line
|
// so the function returns the empty set. When the circles are tangent a degenerate tangent line
|
||||||
// passes through the point of tangency of the two circles: this degenerate line is NOT returned.
|
// passes through the point of tangency of the two circles: this degenerate line is NOT returned.
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// c1 = Center of the first circle.
|
|
||||||
// r1 = Radius of the first circle.
|
// r1 = Radius of the first circle.
|
||||||
// c2 = Center of the second circle.
|
// cp1 = Centerpoint of the first circle.
|
||||||
// r2 = Radius of the second circle.
|
// r2 = Radius of the second circle.
|
||||||
|
// cp2 = Centerpoint of the second circle.
|
||||||
// ---
|
// ---
|
||||||
// d1 = Diameter of the first circle.
|
// d1 = Diameter of the first circle.
|
||||||
// d2 = Diameter of the second circle.
|
// d2 = Diameter of the second circle.
|
||||||
// Example(2D,NoAxes): Four tangents, first in green, second in black, third in blue, last in red.
|
// Example(2D,NoAxes): Four tangents, first in green, second in black, third in blue, last in red.
|
||||||
// $fn=32;
|
// $fn=32;
|
||||||
// c1 = [3,4]; r1 = 2;
|
// cp1 = [3,4]; r1 = 2;
|
||||||
// c2 = [7,10]; r2 = 3;
|
// cp2 = [7,10]; r2 = 3;
|
||||||
// pts = circle_circle_tangents(c1,r1,c2,r2);
|
// pts = circle_circle_tangents(r1, cp1, r2, cp2);
|
||||||
// move(c1) stroke(circle(r=r1), width=0.2, closed=true);
|
// move(cp1) stroke(circle(r=r1), width=0.2, closed=true);
|
||||||
// move(c2) stroke(circle(r=r2), width=0.2, closed=true);
|
// move(cp2) stroke(circle(r=r2), width=0.2, closed=true);
|
||||||
// colors = ["green","black","blue","red"];
|
// colors = ["green","black","blue","red"];
|
||||||
// for(i=[0:len(pts)-1]) color(colors[i]) stroke(pts[i],width=0.2);
|
// for(i=[0:len(pts)-1]) color(colors[i]) stroke(pts[i],width=0.2);
|
||||||
// Example(2D,NoAxes): Circles overlap so only exterior tangents exist.
|
// Example(2D,NoAxes): Circles overlap so only exterior tangents exist.
|
||||||
// $fn=32;
|
// $fn=32;
|
||||||
// c1 = [4,4]; r1 = 3;
|
// cp1 = [4,4]; r1 = 3;
|
||||||
// c2 = [7,7]; r2 = 2;
|
// cp2 = [7,7]; r2 = 2;
|
||||||
// pts = circle_circle_tangents(c1,r1,c2,r2);
|
// pts = circle_circle_tangents(r1, cp1, r2, cp2);
|
||||||
// move(c1) stroke(circle(r=r1), width=0.2, closed=true);
|
// move(cp1) stroke(circle(r=r1), width=0.2, closed=true);
|
||||||
// move(c2) stroke(circle(r=r2), width=0.2, closed=true);
|
// move(cp2) stroke(circle(r=r2), width=0.2, closed=true);
|
||||||
// colors = ["green","black","blue","red"];
|
// colors = ["green","black","blue","red"];
|
||||||
// for(i=[0:len(pts)-1]) color(colors[i]) stroke(pts[i],width=0.2);
|
// for(i=[0:len(pts)-1]) color(colors[i]) stroke(pts[i],width=0.2);
|
||||||
// Example(2D,NoAxes): Circles are tangent. Only exterior tangents are returned. The degenerate internal tangent is not returned.
|
// Example(2D,NoAxes): Circles are tangent. Only exterior tangents are returned. The degenerate internal tangent is not returned.
|
||||||
// $fn=32;
|
// $fn=32;
|
||||||
// c1 = [4,4]; r1 = 4;
|
// cp1 = [4,4]; r1 = 4;
|
||||||
// c2 = [4,10]; r2 = 2;
|
// cp2 = [4,10]; r2 = 2;
|
||||||
// pts = circle_circle_tangents(c1,r1,c2,r2);
|
// pts = circle_circle_tangents(r1, cp1, r2, cp2);
|
||||||
// move(c1) stroke(circle(r=r1), width=0.2, closed=true);
|
// move(cp1) stroke(circle(r=r1), width=0.2, closed=true);
|
||||||
// move(c2) stroke(circle(r=r2), width=0.2, closed=true);
|
// move(cp2) stroke(circle(r=r2), width=0.2, closed=true);
|
||||||
// colors = ["green","black","blue","red"];
|
// colors = ["green","black","blue","red"];
|
||||||
// for(i=[0:1:len(pts)-1]) color(colors[i]) stroke(pts[i],width=0.2);
|
// for(i=[0:1:len(pts)-1]) color(colors[i]) stroke(pts[i],width=0.2);
|
||||||
// Example(2D,NoAxes): One circle is inside the other: no tangents exist. If the interior circle is tangent the single degenerate tangent will not be returned.
|
// Example(2D,NoAxes): One circle is inside the other: no tangents exist. If the interior circle is tangent the single degenerate tangent will not be returned.
|
||||||
// $fn=32;
|
// $fn=32;
|
||||||
// c1 = [4,4]; r1 = 4;
|
// cp1 = [4,4]; r1 = 4;
|
||||||
// c2 = [5,5]; r2 = 2;
|
// cp2 = [5,5]; r2 = 2;
|
||||||
// pts = circle_circle_tangents(c1,r1,c2,r2);
|
// pts = circle_circle_tangents(r1, cp1, r2, cp2);
|
||||||
// move(c1) stroke(circle(r=r1), width=0.2, closed=true);
|
// move(cp1) stroke(circle(r=r1), width=0.2, closed=true);
|
||||||
// move(c2) stroke(circle(r=r2), width=0.2, closed=true);
|
// move(cp2) stroke(circle(r=r2), width=0.2, closed=true);
|
||||||
// echo(pts); // Returns []
|
// echo(pts); // Returns []
|
||||||
function circle_circle_tangents(c1,r1,c2,r2,d1,d2) =
|
function circle_circle_tangents(r1, cp1, r2, cp2, d1, d2) =
|
||||||
assert( is_path([c1,c2],dim=2), "Invalid center point(s)." )
|
assert( is_path([cp1,cp2],dim=2), "Invalid center point(s)." )
|
||||||
let(
|
let(
|
||||||
r1 = get_radius(r1=r1,d1=d1),
|
r1 = get_radius(r1=r1,d1=d1),
|
||||||
r2 = get_radius(r1=r2,d1=d2),
|
r2 = get_radius(r1=r2,d1=d2),
|
||||||
Rvals = [r2-r1, r2-r1, -r2-r1, -r2-r1]/norm(c1-c2),
|
Rvals = [r2-r1, r2-r1, -r2-r1, -r2-r1]/norm(cp1-cp2),
|
||||||
kvals = [-1,1,-1,1],
|
kvals = [-1,1,-1,1],
|
||||||
ext = [1,1,-1,-1],
|
ext = [1,1,-1,-1],
|
||||||
N = 1-sqr(Rvals[2])>=0 ? 4 :
|
N = 1-sqr(Rvals[2])>=0 ? 4 :
|
||||||
|
@ -1256,13 +1257,13 @@ function circle_circle_tangents(c1,r1,c2,r2,d1,d2) =
|
||||||
for(i=[0:1:N-1]) [
|
for(i=[0:1:N-1]) [
|
||||||
[Rvals[i], -kvals[i]*sqrt(1-sqr(Rvals[i]))],
|
[Rvals[i], -kvals[i]*sqrt(1-sqr(Rvals[i]))],
|
||||||
[kvals[i]*sqrt(1-sqr(Rvals[i])), Rvals[i]]
|
[kvals[i]*sqrt(1-sqr(Rvals[i])), Rvals[i]]
|
||||||
] * unit(c2-c1)
|
] * unit(cp2-cp1)
|
||||||
]
|
]
|
||||||
) [
|
) [
|
||||||
for(i=[0:1:N-1]) let(
|
for(i=[0:1:N-1]) let(
|
||||||
pt = [
|
pt = [
|
||||||
c1-r1*coef[i],
|
cp1-r1*coef[i],
|
||||||
c2-ext[i]*r2*coef[i]
|
cp2-ext[i]*r2*coef[i]
|
||||||
]
|
]
|
||||||
) if (pt[0]!=pt[1]) pt
|
) if (pt[0]!=pt[1]) pt
|
||||||
];
|
];
|
||||||
|
@ -1311,15 +1312,15 @@ function _noncollinear_triple(points,error=true,eps=EPSILON) =
|
||||||
|
|
||||||
// Function: sphere_line_intersection()
|
// Function: sphere_line_intersection()
|
||||||
// Usage:
|
// Usage:
|
||||||
// isect = sphere_line_intersection(c,r|d=,line,[bounded],[eps=]);
|
// isect = sphere_line_intersection(r|d=, cp, line, [bounded], [eps=]);
|
||||||
// Topics: Geometry, Spheres, Lines, Intersection
|
// Topics: Geometry, Spheres, Lines, Intersection
|
||||||
// Description:
|
// Description:
|
||||||
// Find intersection points between a sphere and a line, ray or segment specified by two points.
|
// Find intersection points between a sphere and a line, ray or segment specified by two points.
|
||||||
// By default the line is unbounded.
|
// By default the line is unbounded.
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// c = center of sphere
|
// r = Radius of sphere
|
||||||
// r = radius of sphere
|
// cp = Centerpoint of sphere
|
||||||
// line = two points defining the line
|
// line = Two points defining the 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
|
// 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
|
||||||
// ---
|
// ---
|
||||||
// d = diameter of sphere
|
// d = diameter of sphere
|
||||||
|
@ -1327,14 +1328,14 @@ function _noncollinear_triple(points,error=true,eps=EPSILON) =
|
||||||
// Example(3D):
|
// Example(3D):
|
||||||
// cp = [10,20,5]; r = 40;
|
// cp = [10,20,5]; r = 40;
|
||||||
// line = [[-50,-10,25], [70,0,40]];
|
// line = [[-50,-10,25], [70,0,40]];
|
||||||
// isects = sphere_line_intersection(c=cp, r=r, line=line);
|
// isects = sphere_line_intersection(r=r, cp=cp, line=line);
|
||||||
// color("cyan") stroke(line);
|
// color("cyan") stroke(line);
|
||||||
// move(cp) sphere(r=r, $fn=72);
|
// move(cp) sphere(r=r, $fn=72);
|
||||||
// color("red") move_copies(isects) sphere(d=3, $fn=12);
|
// color("red") move_copies(isects) sphere(d=3, $fn=12);
|
||||||
function sphere_line_intersection(c,r,line,bounded=false,d,eps=EPSILON) =
|
function sphere_line_intersection(r, cp, line, bounded=false, d, eps=EPSILON) =
|
||||||
assert(_valid_line(line,3), "Invalid 3d line.")
|
assert(_valid_line(line,3), "Invalid 3d line.")
|
||||||
assert(is_vector(c,3), "Sphere center must be a 3-vector")
|
assert(is_vector(cp,3), "Sphere center must be a 3-vector")
|
||||||
_circle_or_sphere_line_intersection(c,r,line,bounded,d,eps);
|
_circle_or_sphere_line_intersection(r, cp, line, bounded, d, eps);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -963,7 +963,7 @@ module rabbit_clip(type, length, width, snap, thickness, depth, compression=0.1
|
||||||
scaled_len = length - 0.5 * (earwidth * snap + point_length * length) / sqrt(sqr(snap)+sqr(length/2));
|
scaled_len = length - 0.5 * (earwidth * snap + point_length * length) / sqrt(sqr(snap)+sqr(length/2));
|
||||||
bottom_pt = [0,max(scaled_len*0.15+thickness, 2*thickness)];
|
bottom_pt = [0,max(scaled_len*0.15+thickness, 2*thickness)];
|
||||||
ctr = [width/2,scaled_len] + line_normal([width/2-snap, scaled_len/2], [width/2, scaled_len]) * earwidth/2;
|
ctr = [width/2,scaled_len] + line_normal([width/2-snap, scaled_len/2], [width/2, scaled_len]) * earwidth/2;
|
||||||
inside_pt = circle_circle_tangents(bottom_pt, 0, ctr, earwidth/2)[0][1];
|
inside_pt = circle_circle_tangents(0, bottom_pt, earwidth/2, ctr)[0][1];
|
||||||
sidepath =[
|
sidepath =[
|
||||||
[width/2,0],
|
[width/2,0],
|
||||||
[width/2-snap,scaled_len/2],
|
[width/2-snap,scaled_len/2],
|
||||||
|
|
|
@ -3281,7 +3281,7 @@ function _fix_angle_list(list,ind=0, result=[]) =
|
||||||
function _cyl_line_intersection(R, line, ref) =
|
function _cyl_line_intersection(R, line, ref) =
|
||||||
let(
|
let(
|
||||||
line2d = path2d(line),
|
line2d = path2d(line),
|
||||||
cisect = circle_line_intersection([0,0], r=R, line= line2d)
|
cisect = circle_line_intersection(r=R, cp=[0,0], line=line2d)
|
||||||
)
|
)
|
||||||
len(cisect)<2 ? [] :
|
len(cisect)<2 ? [] :
|
||||||
let(
|
let(
|
||||||
|
@ -3300,7 +3300,7 @@ function _cyl_line_intersection(R, line, ref) =
|
||||||
|
|
||||||
function _sphere_line_isect_best(R, line, ref) =
|
function _sphere_line_isect_best(R, line, ref) =
|
||||||
let(
|
let(
|
||||||
pts = sphere_line_intersection([0,0,0],abs(R), line=line)
|
pts = sphere_line_intersection(abs(R), [0,0,0], line=line)
|
||||||
)
|
)
|
||||||
len(pts)<2 ? [] :
|
len(pts)<2 ? [] :
|
||||||
let(
|
let(
|
||||||
|
|
|
@ -254,7 +254,7 @@ function circle(r, d, points, corner, anchor=CENTER, spin=0) =
|
||||||
assert(is_undef(points), "Cannot specify points= when corner= is given.")
|
assert(is_undef(points), "Cannot specify points= when corner= is given.")
|
||||||
let(
|
let(
|
||||||
r = get_radius(r=r, d=d, dflt=1),
|
r = get_radius(r=r, d=d, dflt=1),
|
||||||
c = circle_2tangents(pt1=corner[0], pt2=corner[1], pt3=corner[2], r=r)
|
c = circle_2tangents(r=r, pt1=corner[0], pt2=corner[1], pt3=corner[2])
|
||||||
)
|
)
|
||||||
assert(c!=undef, "Corner path cannot be collinear.")
|
assert(c!=undef, "Corner path cannot be collinear.")
|
||||||
let( cp = c[0] )
|
let( cp = c[0] )
|
||||||
|
@ -283,7 +283,7 @@ module circle(r, d, points, corner, anchor=CENTER, spin=0) {
|
||||||
}
|
}
|
||||||
} else if (is_path(corner)) {
|
} else if (is_path(corner)) {
|
||||||
r = get_radius(r=r, d=d, dflt=1);
|
r = get_radius(r=r, d=d, dflt=1);
|
||||||
c = circle_2tangents(pt1=corner[0], pt2=corner[1], pt3=corner[2], r=r);
|
c = circle_2tangents(r=r, pt1=corner[0], pt2=corner[1], pt3=corner[2]);
|
||||||
check = assert(c != undef && c[0] != undef, "Points must not be collinear.");
|
check = assert(c != undef && c[0] != undef, "Points must not be collinear.");
|
||||||
cp = c[0];
|
cp = c[0];
|
||||||
translate(cp) {
|
translate(cp) {
|
||||||
|
@ -1298,7 +1298,7 @@ function egg(length, r1, r2, R, d1, d2, D, anchor=CENTER, spin=0) =
|
||||||
c1 = [-length/2+r1,0],
|
c1 = [-length/2+r1,0],
|
||||||
c2 = [length/2-r2,0],
|
c2 = [length/2-r2,0],
|
||||||
Rmin = (r1+r2+norm(c1-c2))/2,
|
Rmin = (r1+r2+norm(c1-c2))/2,
|
||||||
Mlist = circle_circle_intersection(c1,R-r1,c2,R-r2),
|
Mlist = circle_circle_intersection(R-r1, c1, R-r2, c2),
|
||||||
arcparms = reverse([for(M=Mlist) [M, c1+r1*unit(c1-M), c2+r2*unit(c2-M)]]),
|
arcparms = reverse([for(M=Mlist) [M, c1+r1*unit(c1-M), c2+r2*unit(c2-M)]]),
|
||||||
path = concat(
|
path = concat(
|
||||||
arc(r=r2, cp=c2, points=[[length/2,0],arcparms[0][2]],endpoint=false),
|
arc(r=r2, cp=c2, points=[[length/2,0],arcparms[0][2]],endpoint=false),
|
||||||
|
|
|
@ -1223,7 +1223,7 @@ module cyl(
|
||||||
) [p1,p2]
|
) [p1,p2]
|
||||||
) : !is_undef(fil2)? (
|
) : !is_undef(fil2)? (
|
||||||
let(
|
let(
|
||||||
cn = circle_2tangents([r2-fil2,l/2], [r2,l/2], [r1,-l/2], r=abs(fil2)),
|
cn = circle_2tangents(r=abs(fil2), [r2-fil2,l/2], [r2,l/2], [r1,-l/2]),
|
||||||
ang = fil2<0? phi : phi-180,
|
ang = fil2<0? phi : phi-180,
|
||||||
steps = ceil(abs(ang)/360*segs(abs(fil2))),
|
steps = ceil(abs(ang)/360*segs(abs(fil2))),
|
||||||
step = ang/steps,
|
step = ang/steps,
|
||||||
|
@ -1238,7 +1238,7 @@ module cyl(
|
||||||
) [p1,p2]
|
) [p1,p2]
|
||||||
) : !is_undef(fil1)? (
|
) : !is_undef(fil1)? (
|
||||||
let(
|
let(
|
||||||
cn = circle_2tangents([r1-fil1,-l/2], [r1,-l/2], [r2,l/2], r=abs(fil1)),
|
cn = circle_2tangents(r=abs(fil1), [r1-fil1,-l/2], [r1,-l/2], [r2,l/2]),
|
||||||
ang = fil1<0? 180-phi : -phi,
|
ang = fil1<0? 180-phi : -phi,
|
||||||
steps = ceil(abs(ang)/360*segs(abs(fil1))),
|
steps = ceil(abs(ang)/360*segs(abs(fil1))),
|
||||||
step = ang/steps,
|
step = ang/steps,
|
||||||
|
@ -2706,19 +2706,21 @@ module path_text(path, text, font, size, thickness, lettersize, offset=0, revers
|
||||||
//
|
//
|
||||||
// Example:
|
// Example:
|
||||||
// union() {
|
// union() {
|
||||||
// translate([0,2,-4])
|
// translate([0,2,-4])
|
||||||
// cube([20, 4, 24], anchor=BOTTOM);
|
// cube([20, 4, 24], anchor=BOTTOM);
|
||||||
// translate([0,-10,-4])
|
// translate([0,-10,-4])
|
||||||
// cube([20, 20, 4], anchor=BOTTOM);
|
// cube([20, 20, 4], anchor=BOTTOM);
|
||||||
// color("green")
|
// color("green")
|
||||||
// interior_fillet(
|
// interior_fillet(
|
||||||
// l=20, r=10,
|
// l=20, r=10,
|
||||||
// spin=180, orient=RIGHT
|
// spin=180, orient=RIGHT
|
||||||
// );
|
// );
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// Example:
|
// Examples:
|
||||||
// interior_fillet(l=40, r=10, spin=-90);
|
// interior_fillet(l=10, r=20, ang=60);
|
||||||
|
// interior_fillet(l=10, r=20, ang=90);
|
||||||
|
// interior_fillet(l=10, r=20, ang=120);
|
||||||
//
|
//
|
||||||
// Example: Using with Attachments
|
// Example: Using with Attachments
|
||||||
// cube(50,center=true) {
|
// cube(50,center=true) {
|
||||||
|
@ -2727,19 +2729,22 @@ module path_text(path, text, font, size, thickness, lettersize, offset=0, revers
|
||||||
// position(BOT+FRONT)
|
// position(BOT+FRONT)
|
||||||
// interior_fillet(l=50, r=10, spin=180, orient=RIGHT);
|
// interior_fillet(l=50, r=10, spin=180, orient=RIGHT);
|
||||||
// }
|
// }
|
||||||
module interior_fillet(l=1.0, r, ang=90, overlap=0.01, d, anchor=FRONT+LEFT, spin=0, orient=UP) {
|
module interior_fillet(l=1.0, r, ang=90, overlap=0.01, d, anchor=CENTER, spin=0, orient=UP) {
|
||||||
r = get_radius(r=r, d=d, dflt=1);
|
r = get_radius(r=r, d=d, dflt=1);
|
||||||
dy = r/tan(ang/2);
|
steps = ceil(segs(r)*(180-ang)/360);
|
||||||
steps = ceil(segs(r)*ang/360);
|
arc = arc(n=steps+1, r=r, corner=[polar_to_xy(r,ang),[0,0],[r,0]]);
|
||||||
step = ang/steps;
|
maxx = last(arc).x;
|
||||||
attachable(anchor,spin,orient, size=[r,r,l]) {
|
maxy = arc[0].y;
|
||||||
|
path = [
|
||||||
|
[maxx, -overlap],
|
||||||
|
polar_to_xy(overlap, 180+ang/2),
|
||||||
|
arc[0] + polar_to_xy(overlap, 90+ang),
|
||||||
|
each arc
|
||||||
|
];
|
||||||
|
attachable(anchor,spin,orient, size=[2*maxx,2*maxy,l]) {
|
||||||
if (l > 0) {
|
if (l > 0) {
|
||||||
linear_extrude(height=l, convexity=4, center=true) {
|
linear_extrude(height=l, convexity=4, center=true) {
|
||||||
path = concat(
|
polygon(path);
|
||||||
[[0,0]],
|
|
||||||
[for (i=[0:1:steps]) let(a=270-i*step) r*[cos(a),sin(a)]+[dy,r]]
|
|
||||||
);
|
|
||||||
translate(-[r,r]/2) polygon(path);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
children();
|
children();
|
||||||
|
|
|
@ -424,15 +424,15 @@ module test_line_closest_point() {
|
||||||
|
|
||||||
module test_circle_2tangents() {
|
module test_circle_2tangents() {
|
||||||
//** missing tests with arg tangent=true
|
//** missing tests with arg tangent=true
|
||||||
assert(approx(circle_2tangents([10,10],[0,0],[10,-10],r=10/sqrt(2))[0],[10,0]));
|
assert(approx(circle_2tangents(r=10/sqrt(2),[10,10],[0,0],[10,-10])[0], [10,0]));
|
||||||
assert(approx(circle_2tangents([-10,10],[0,0],[-10,-10],r=10/sqrt(2))[0],[-10,0]));
|
assert(approx(circle_2tangents(r=10/sqrt(2),[-10,10],[0,0],[-10,-10])[0], [-10,0]));
|
||||||
assert(approx(circle_2tangents([-10,10],[0,0],[10,10],r=10/sqrt(2))[0],[0,10]));
|
assert(approx(circle_2tangents(r=10/sqrt(2),[-10,10],[0,0],[10,10])[0], [0,10]));
|
||||||
assert(approx(circle_2tangents([-10,-10],[0,0],[10,-10],r=10/sqrt(2))[0],[0,-10]));
|
assert(approx(circle_2tangents(r=10/sqrt(2),[-10,-10],[0,0],[10,-10])[0], [0,-10]));
|
||||||
assert(approx(circle_2tangents([0,10],[0,0],[10,0],r=10)[0],[10,10]));
|
assert(approx(circle_2tangents(r=10,[0,10],[0,0],[10,0])[0], [10,10]));
|
||||||
assert(approx(circle_2tangents([10,0],[0,0],[0,-10],r=10)[0],[10,-10]));
|
assert(approx(circle_2tangents(r=10,[10,0],[0,0],[0,-10])[0], [10,-10]));
|
||||||
assert(approx(circle_2tangents([0,-10],[0,0],[-10,0],r=10)[0],[-10,-10]));
|
assert(approx(circle_2tangents(r=10,[0,-10],[0,0],[-10,0])[0], [-10,-10]));
|
||||||
assert(approx(circle_2tangents([-10,0],[0,0],[0,10],r=10)[0],[-10,10]));
|
assert(approx(circle_2tangents(r=10,[-10,0],[0,0],[0,10])[0], [-10,10]));
|
||||||
assert_approx(circle_2tangents(polar_to_xy(10,60),[0,0],[10,0],r=10)[0],polar_to_xy(20,30));
|
assert_approx(circle_2tangents(r=10,polar_to_xy(10,60),[0,0],[10,0])[0], polar_to_xy(20,30));
|
||||||
}
|
}
|
||||||
*test_circle_2tangents();
|
*test_circle_2tangents();
|
||||||
|
|
||||||
|
|
|
@ -183,10 +183,10 @@ module thinning_wall(h=50, l=100, thick=5, ang=30, braces=false, strut, wall, an
|
||||||
wall = is_num(wall)? wall : thick/2;
|
wall = is_num(wall)? wall : thick/2;
|
||||||
|
|
||||||
bevel_h = strut + (thick-wall)/2/tan(ang);
|
bevel_h = strut + (thick-wall)/2/tan(ang);
|
||||||
cp1 = circle_2tangents([0,0,+h/2], [l2/2,0,+h/2], [l1/2,0,-h/2], r=strut)[0];
|
cp1 = circle_2tangents(r=strut, [0,0,+h/2], [l2/2,0,+h/2], [l1/2,0,-h/2])[0];
|
||||||
cp2 = circle_2tangents([0,0,+h/2], [l2/2,0,+h/2], [l1/2,0,-h/2], r=bevel_h)[0];
|
cp2 = circle_2tangents(r=bevel_h, [0,0,+h/2], [l2/2,0,+h/2], [l1/2,0,-h/2])[0];
|
||||||
cp3 = circle_2tangents([0,0,-h/2], [l1/2,0,-h/2], [l2/2,0,+h/2], r=bevel_h)[0];
|
cp3 = circle_2tangents(r=bevel_h, [0,0,-h/2], [l1/2,0,-h/2], [l2/2,0,+h/2])[0];
|
||||||
cp4 = circle_2tangents([0,0,-h/2], [l1/2,0,-h/2], [l2/2,0,+h/2], r=strut)[0];
|
cp4 = circle_2tangents(r=strut, [0,0,-h/2], [l1/2,0,-h/2], [l2/2,0,+h/2])[0];
|
||||||
|
|
||||||
z1 = h/2;
|
z1 = h/2;
|
||||||
z2 = cp1.z;
|
z2 = cp1.z;
|
||||||
|
|
Loading…
Reference in a new issue