From c7950a74754c2a8bf6c13147ea3a37efe56762e2 Mon Sep 17 00:00:00 2001 From: Adrian Mariano Date: Tue, 21 May 2024 19:36:22 -0400 Subject: [PATCH] fix vnf_validate isect bug, plus doc tweaks --- geometry.scad | 2 +- vnf.scad | 86 ++++++++++++++++++++++++++++----------------------- walls.scad | 15 ++++++--- 3 files changed, 58 insertions(+), 45 deletions(-) diff --git a/geometry.scad b/geometry.scad index 8134407..c8c29e5 100644 --- a/geometry.scad +++ b/geometry.scad @@ -1711,7 +1711,7 @@ function point_in_polygon(point, poly, nonzero=false, eps=EPSILON) = // Description: // Takes a possibly bounded line, and a 2D or 3D planar polygon, and finds their intersection. Note the polygon is // treated as its boundary and interior, so the intersection may include both points and line segments. -// If the line does not intersect the polygon returns `undef`. +// If the line does not intersect the polygon then returns `undef`. // In 3D if the line is not on the plane of the polygon but intersects it then you get a single intersection point. // Otherwise the polygon and line are in the same plane, or when your input is 2D, you will get a list of segments and // single point lists. Use `is_vector` to distinguish these two cases. diff --git a/vnf.scad b/vnf.scad index 3ef2290..8a2e7c0 100644 --- a/vnf.scad +++ b/vnf.scad @@ -1772,8 +1772,8 @@ module debug_vnf(vnf, faces=true, vertices=true, opacity=0.5, size=1, convexity= // vnf_validate(vnf); // Example(3D,Edges): FACE_ISECT Errors; Faces Intersect // vnf = vnf_join([ -// vnf_triangulate(linear_sweep(square(100,center=true), height=100)), -// move([75,35,30],p=vnf_triangulate(linear_sweep(square(100,center=true), height=100))) +// linear_sweep(square(100,center=true), height=100), +// move([75,35,30],p=linear_sweep(square(100,center=true), height=100)) // ]); // vnf_validate(vnf,size=2,check_isects=true); // Example(3D,Edges): HOLE_EDGE Errors; Edges Adjacent to Holes. @@ -1893,43 +1893,51 @@ function _vnf_validate(vnf, show_warns=true, check_isects=false) = ) t_juncts? issues : let( isect_faces = !check_isects? [] : unique([ - for (i = [0:1:len(faces)-2]) let( - f1 = faces[i], - poly1 = select(varr, faces[i]), - plane1 = plane3pt(poly1[0], poly1[1], poly1[2]), - normal1 = [plane1[0], plane1[1], plane1[2]] - ) - for (j = [i+1:1:len(faces)-1]) let( - f2 = faces[j], - poly2 = select(varr, f2), - val = poly2 * normal1 - ) - if( min(val)<=plane1[3] && max(val)>=plane1[3] ) let( - plane2 = plane_from_polygon(poly2), - normal2 = [plane2[0], plane2[1], plane2[2]], - val = poly1 * normal2 - ) - if( min(val)<=plane2[3] && max(val)>=plane2[3] ) let( - shared_edges = [ - for (edge1 = pair(f1, true), edge2 = pair(f2, true)) - if (edge1 == [edge2[1], edge2[0]]) 1 - ] - ) - if (!shared_edges) let( - line = plane_intersection(plane1, plane2) - ) - if (!is_undef(line)) let( - isects = polygon_line_intersection(poly1, line) - ) - if (!is_undef(isects)) - for (isect = isects) - if (len(isect) > 1) let( - isects2 = polygon_line_intersection(poly2, isect, bounded=true) - ) - if (!is_undef(isects2)) - for (seg = isects2) - if (seg[0] != seg[1]) - _vnf_validate_err("FACE_ISECT", seg) + for (i = [0:1:len(faces)-2]) + let( + f1 = faces[i], + poly1 = select(varr, faces[i]), + plane1 = plane3pt(poly1[0], poly1[1], poly1[2]), + normal1 = [plane1[0], plane1[1], plane1[2]] + ) + for (j = [i+1:1:len(faces)-1]) + let( + f2 = faces[j], + poly2 = select(varr, f2), + val = poly2 * normal1 + ) + // The next test skips f2 if it lies entirely on one side of the plane of poly1 + if( min(val)<=plane1[3] && max(val)>=plane1[3] ) + let( + plane2 = plane_from_polygon(poly2), + normal2 = [plane2[0], plane2[1], plane2[2]], + val = poly1 * normal2 + ) + // Skip if f1 lies entirely on one side of the plane defined by poly2 + if( min(val)<=plane2[3] && max(val)>=plane2[3] ) + let( + shared_edges = [ + for (edge1 = pair(f1, true), edge2 = pair(f2, true)) + if (edge1 == [edge2[1], edge2[0]]) 1 + ] + ) + if (shared_edges==[]) + let( + line = plane_intersection(plane1, plane2) + ) + if (is_def(line)) + let( + isects = polygon_line_intersection(poly1, line) + ) + if (is_def(isects)) + for (isect = isects) + if (len(isect) > 1) + let( + isects2 = polygon_line_intersection(poly2, isect, bounded=true) + ) + if (is_def(isects2)) + for (seg = isects2) + if (len(seg)>1 && seg[0] != seg[1]) _vnf_validate_err("FACE_ISECT", seg) ]), issues = concat(issues, isect_faces) ) isect_faces? issues : diff --git a/walls.scad b/walls.scad index c1748fe..8657c3b 100644 --- a/walls.scad +++ b/walls.scad @@ -18,7 +18,7 @@ include // Synopsis: Makes an open cross-braced rectangular wall. // SynTags: Geom // Topics: FDM Optimized, Walls -// See Also: corrugated_wall(), thinning_wall(), thinning_triangle(), narrowing_strut() +// See Also: hex_panel(), corrugated_wall(), thinning_wall(), thinning_triangle(), narrowing_strut() // // Usage: // sparse_wall(h, l, thick, [maxang=], [strut=], [max_bridge=]) [ATTACHMENTS]; @@ -81,7 +81,7 @@ module sparse_wall(h=50, l=100, thick=4, maxang=30, strut=5, max_bridge=20, anch // Synopsis: Makes an open cross-braced rectangular wall. // SynTags: Geom // Topics: FDM Optimized, Walls -// See Also: sparse_wall(), corrugated_wall(), thinning_wall(), thinning_triangle(), narrowing_strut() +// See Also: sparse_wall(), hex_panel(), corrugated_wall(), thinning_wall(), thinning_triangle(), narrowing_strut() // // Usage: // sparse_wall2d(size, [maxang=], [strut=], [max_bridge=]) [ATTACHMENTS]; @@ -153,7 +153,7 @@ module sparse_wall2d(size=[50,100], maxang=30, strut=5, max_bridge=20, anchor=CE // Synopsis: Makes an open cross-braced cuboid // SynTags: Geom // Topics: FDM Optimized, Walls -// See Also: sparse_wall(), corrugated_wall(), thinning_wall(), thinning_triangle(), narrowing_strut(), cuboid() +// See Also: sparse_wall(), hex_panel(), corrugated_wall(), thinning_wall(), thinning_triangle(), narrowing_strut(), cuboid() // Usage: // sparse_cuboid(size, [dir], [maxang=], [struct=] // Description: @@ -220,10 +220,15 @@ module sparse_cuboid(size, dir=RIGHT, strut=5, maxang=30, max_bridge=20, // Module: hex_panel() +// Synopsis: Create a hexagon braced panel of any shape +// SynTags: Geom +// Topics: FDM Optimized, Walls +// See Also: sparse_wall(), hex_panel(), corrugated_wall(), thinning_wall(), thinning_triangle(), narrowing_strut() // Usage: // hex_panel(shape, wall, spacing, [frame=], [bevel=], [bevel_frame=], [h=|height=|l=|length=], [anchor=], [orient=], [spin=]) // Description: -// Produces a panel with a honeycomb interior. The panel consists of a frame containing +// Produces a panel with a honeycomb interior that can be rectangular with optional beveling, or +// an arbitrary polygon shape without beveling. The panel consists of a frame containing // a honeycob interior. The frame is laid out in the XY plane with the honeycob interior // and then extruded to the height h. The shape argument defines the outer bounderies of // the frame. @@ -246,7 +251,7 @@ module sparse_cuboid(size, dir=RIGHT, strut=5, maxang=30, max_bridge=20, // shape = 3D size vector or a 2D path // strut = thickness of hexagonal bracing // spacing = center-to-center spacing of hex cells in the honeycomb. -// -- +// --- // frame = width of the frame around the honeycomb. Default: same as strut // bevel = list of edges to bevel on rectangular case when shape is a size vector; allowed options are RIGHT, LEFT, BACK, or FRONT, or those directions with BOTTOM added. Default: [] // bevel_frame = width of the frame applied at bevels. Default: same as frame