Fixed broken line-plane intersections. Attachment enhanced vnf_polyhedron().

This commit is contained in:
Garth Minette 2020-08-28 19:07:10 -07:00
parent 7051f8ef19
commit e1b0985afc
5 changed files with 49 additions and 19 deletions

View file

@ -461,13 +461,16 @@ function find_anchor(anchor, geom) =
rpts = apply(rot(from=anchor, to=RIGHT) * move(point3d(-cp)), points), rpts = apply(rot(from=anchor, to=RIGHT) * move(point3d(-cp)), points),
hits = [ hits = [
for (face = faces) let( for (face = faces) let(
verts = select(rpts, face) verts = select(rpts, face),
xs = subindex(verts,0),
ys = subindex(verts,1),
zs = subindex(verts,2)
) if ( ) if (
max(subindex(verts,0)) >= -eps && max(xs) >= -eps &&
max(subindex(verts,1)) >= -eps && max(ys) >= -eps &&
max(subindex(verts,2)) >= -eps && max(zs) >= -eps &&
min(subindex(verts,1)) <= eps && min(ys) <= eps &&
min(subindex(verts,2)) <= eps min(zs) <= eps
) let( ) let(
poly = select(points, face), poly = select(points, face),
pt = polygon_line_intersection(poly, [cp,cp+anchor], bounded=[true,false], eps=eps) pt = polygon_line_intersection(poly, [cp,cp+anchor], bounded=[true,false], eps=eps)

View file

@ -1007,11 +1007,20 @@ function closest_point_on_plane(plane, point) =
// Returns [LINE, undef] if the line is on the plane. // Returns [LINE, undef] if the line is on the plane.
// Returns undef if line is parallel to, but not on the given plane. // Returns undef if line is parallel to, but not on the given plane.
function _general_plane_line_intersection(plane, line, eps=EPSILON) = function _general_plane_line_intersection(plane, line, eps=EPSILON) =
let( a = plane*[each line[0],-1], let(
b = plane*[each(line[1]-line[0]),-1] ) l0 = line[0], // Ray start point
approx(b,0,eps) u = line[1] - l0, // Ray direction vector
? points_on_plane(line[0],plane,eps)? [line,undef]: undef n = plane_normal(plane),
: [ line[0]+a/b*(line[1]-line[0]), a/b ]; p0 = n * plane[3], // A point on the plane
w = l0 - p0 // Vector from plane point to ray start
) approx(n*u, 0, eps=eps) ? (
// Line is parallel to plane.
approx(n*w, 0, eps=eps)
? [line, undef] // Line is on the plane.
: undef // Line never intersects the plane.
) : let(
t = (-n * w) / (n * u) // Distance ratio along ray
) [ l0 + u*t, t ];
// Function: plane_line_angle() // Function: plane_line_angle()
@ -1098,8 +1107,8 @@ function polygon_line_intersection(poly, line, bounded=false, eps=EPSILON) =
linevec = unit(line[1] - line[0]), linevec = unit(line[1] - line[0]),
lp1 = line[0] + (bounded[0]? 0 : -1000000) * linevec, lp1 = line[0] + (bounded[0]? 0 : -1000000) * linevec,
lp2 = line[1] + (bounded[1]? 0 : 1000000) * linevec, lp2 = line[1] + (bounded[1]? 0 : 1000000) * linevec,
poly2d = clockwise_polygon(project_plane(poly, p1, p2, p3)), poly2d = clockwise_polygon(project_plane(poly, plane)),
line2d = project_plane([lp1,lp2], p1, p2, p3), line2d = project_plane([lp1,lp2], plane),
parts = split_path_at_region_crossings(line2d, [poly2d], closed=false), parts = split_path_at_region_crossings(line2d, [poly2d], closed=false),
inside = [for (part = parts) inside = [for (part = parts)
if (point_in_polygon(mean(part), poly2d)>0) part if (point_in_polygon(mean(part), poly2d)>0) part
@ -1107,7 +1116,7 @@ function polygon_line_intersection(poly, line, bounded=false, eps=EPSILON) =
) )
!inside? undef : !inside? undef :
let( let(
isegs = [for (seg = inside) lift_plane(seg, p1, p2, p3) ] isegs = [for (seg = inside) lift_plane(seg, plane) ]
) )
isegs isegs
) )
@ -1264,7 +1273,6 @@ function find_circle_2tangents(pt1, pt2, pt3, r, d, tangents=false) =
x = hyp * cos(a/2), x = hyp * cos(a/2),
tp1 = pt2 + x * v1, tp1 = pt2 + x * v1,
tp2 = pt2 + x * v2, tp2 = pt2 + x * v2,
// fff=echo(tp1=tp1,cp=cp,pt2=pt2),
dang1 = vector_angle(tp1-cp,pt2-cp), dang1 = vector_angle(tp1-cp,pt2-cp),
dang2 = vector_angle(tp2-cp,pt2-cp) dang2 = vector_angle(tp2-cp,pt2-cp)
) )

View file

@ -53,7 +53,7 @@ test_tri_functions();
//test__general_plane_line_intersection(); //test__general_plane_line_intersection();
//test_plane_line_angle(); //test_plane_line_angle();
//test_plane_line_intersection(); //test_plane_line_intersection();
//test_polygon_line_intersection(); test_polygon_line_intersection();
//test_plane_intersection(); //test_plane_intersection();
test_coplanar(); test_coplanar();
test_points_on_plane(); test_points_on_plane();
@ -542,6 +542,17 @@ module test_distance_from_plane() {
*test_distance_from_plane(); *test_distance_from_plane();
module test_polygon_line_intersection() {
poly1 = [[50,50,50], [50,-50,50], [-50,-50,50]];
assert_approx(polygon_line_intersection(poly1, [CENTER, UP]), [0,0,50]);
assert_approx(polygon_line_intersection(poly1, [CENTER, UP+RIGHT]), [50,0,50]);
assert_approx(polygon_line_intersection(poly1, [CENTER, UP+BACK+RIGHT]), [50,50,50]);
assert_approx(polygon_line_intersection(poly1, [[0,0,50], [1,0,50]]), [[[0,0,50], [50,0,50]]]);
assert_approx(polygon_line_intersection(poly1, [[0,0,0], [1,0,0]]), undef);
}
*test_polygon_line_intersection();
module test_coplanar() { module test_coplanar() {
assert(coplanar([ [5,5,1],[0,0,1],[-1,-1,1] ]) == false); assert(coplanar([ [5,5,1],[0,0,1],[-1,-1,1] ]) == false);
assert(coplanar([ [5,5,1],[0,0,0],[-1,-1,1] ]) == true); assert(coplanar([ [5,5,1],[0,0,0],[-1,-1,1] ]) == true);

View file

@ -8,7 +8,7 @@
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
BOSL_VERSION = [2,0,413]; BOSL_VERSION = [2,0,414];
// Section: BOSL Library Version Functions // Section: BOSL Library Version Functions

View file

@ -341,9 +341,17 @@ function vnf_vertex_array(
// Arguments: // Arguments:
// vnf = A VNF structure, or list of VNF structures. // vnf = A VNF structure, or list of VNF structures.
// convexity = Max number of times a line could intersect a wall of the shape. // convexity = Max number of times a line could intersect a wall of the shape.
module vnf_polyhedron(vnf, convexity=2) { // extent = If true, calculate anchors by extents, rather than intersection. Default: true.
// cp = Centerpoint of VNF to use for anchoring when `extent` is false. Default: `[0, 0, 0]`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `"origin"`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
module vnf_polyhedron(vnf, convexity=2, extent=true, cp=[0,0,0], anchor="origin", spin=0, orient=UP) {
vnf = is_vnf_list(vnf)? vnf_merge(vnf) : vnf; vnf = is_vnf_list(vnf)? vnf_merge(vnf) : vnf;
polyhedron(vnf[0], vnf[1], convexity=convexity); attachable(anchor,spin,orient, vnf=vnf, cp=cp, extent=extent) {
polyhedron(vnf[0], vnf[1], convexity=convexity);
children();
}
} }