Merge pull request #1762 from amatulic/general_dev

Fix for #1759 - move nonplanar polygon check earlier in `_slice_3dpolygons()`
This commit is contained in:
adrianVmariano
2025-07-29 19:45:38 -04:00
committed by GitHub

View File

@@ -1370,28 +1370,31 @@ function _slice_3dpolygons(polys, dir, cuts) =
) )
flatten([ flatten([
for (poly = polys) for (poly = polys)
if (polygon_area(poly)>EPSILON) // Discard zero area polygons
let(
plane = plane_from_polygon(poly,1e-4))
assert(plane,"\nFound non-coplanar face.")
let( let(
normal = point3d(plane), polyarea = polygon_area(poly),
pnormal = normal - (normal*I[dir_ind])*I[dir_ind] err = assert(!is_undef(polyarea), "\nFound non-coplanar face.")
) )
approx(pnormal,[0,0,0]) ? [poly] // Polygons parallel to cut plane just pass through if (polyarea > EPSILON) // Discard zero area polygons
: let( let(
pind = max_index(v_abs(pnormal)), // project along this direction plane = plane_from_polygon(poly,1e-4),
otherind = 3-pind-dir_ind, // keep dir_ind and this direction err2 = assert(plane,"\nFound non-coplanar face."), // possibly redundant
keep = [I[dir_ind], I[otherind]], // dir ind becomes the x dir normal = point3d(plane),
poly2d = poly*transpose(keep), // project to 2d, putting selected direction in the X position pnormal = normal - (normal*I[dir_ind])*I[dir_ind]
poly_list = [for(p=_split_2dpolygons_at_each_x([poly2d], cuts)) )
let( approx(pnormal,[0,0,0]) ? [poly] // Polygons parallel to cut plane just pass through
a = p*keep, // unproject, but pind dimension data is missing : let(
ofs = outer_product((repeat(plane[3], len(a))-a*normal)/plane[pind],I[pind]) pind = max_index(v_abs(pnormal)), // project along this direction
) otherind = 3-pind-dir_ind, // keep dir_ind and this direction
a+ofs] // ofs computes the missing pind dimension data and adds it back in keep = [I[dir_ind], I[otherind]], // dir ind becomes the x dir
) poly2d = poly*transpose(keep), // project to 2d, putting selected direction in the X position
poly_list poly_list = [
for(p=_split_2dpolygons_at_each_x([poly2d], cuts))
let(
a = p*keep, // unproject, but pind dimension data is missing
ofs = outer_product((repeat(plane[3], len(a))-a*normal)/plane[pind],I[pind])
) a+ofs
] // ofs computes the missing pind dimension data and adds it back in
) poly_list
]); ]);
@@ -2403,12 +2406,13 @@ module debug_vnf(vnf, faces=true, vertices=true, opacity=0.5, size=1, convexity=
// ------- | -------- | ------------ | --------------------------------- // ------- | -------- | ------------ | ---------------------------------
// WARNING | Yellow | BIG_FACE | Face has more than 3 vertices, and may confuse CGAL. // WARNING | Yellow | BIG_FACE | Face has more than 3 vertices, and may confuse CGAL.
// WARNING | Blue | NULL_FACE | Face has zero area. // WARNING | Blue | NULL_FACE | Face has zero area.
// ERROR | Green | BAD_INDEX | Invalid face vertex index.
// ERROR | Cyan | NONPLANAR | Face vertices are not coplanar. // ERROR | Cyan | NONPLANAR | Face vertices are not coplanar.
// ERROR | Brown | DUP_FACE | Multiple instances of the same face. // ERROR | Brown | DUP_FACE | Multiple instances of the same face.
// ERROR | Orange | MULTCONN | Multiply Connected Geometry. Too many faces attached at Edge. // ERROR | Orange | MULTCONN | Multiply Connected Geometry. Too many faces attached at Edge.
// ERROR | Violet | REVERSAL | Faces reverse across edge. // ERROR | Violet | REVERSAL | Faces reverse across edge.
// ERROR | Red | T_JUNCTION | Vertex is mid-edge on another Face. // ERROR | Red | T_JUNCTION | Vertex is mid-edge on another Face.
// ERROR | Brown | FACE_ISECT | Faces intersect. // ERROR | Pink | FACE_ISECT | Faces intersect.
// ERROR | Magenta | HOLE_EDGE | Edge bounds Hole. // ERROR | Magenta | HOLE_EDGE | Edge bounds Hole.
// . // .
// Still to implement: // Still to implement:
@@ -2660,16 +2664,16 @@ function _vnf_validate(vnf, show_warns=true, check_isects=false) =
_vnf_validate_errs = [ _vnf_validate_errs = [
["BIG_FACE", "WARNING", "cyan", "Face has more than 3 vertices, and may confuse CGAL"], ["BIG_FACE", "WARNING", "yellow", "Face has more than 3 vertices, and may confuse CGAL"],
["NULL_FACE", "WARNING", "blue", "Face has zero area."], ["NULL_FACE", "WARNING", "blue", "Face has zero area."],
["BAD_INDEX", "ERROR", "cyan", "Invalid face vertex index."], ["BAD_INDEX", "ERROR", "green", "Invalid face vertex index."],
["NONPLANAR", "ERROR", "yellow", "Face vertices are not coplanar"], ["NONPLANAR", "ERROR", "cyan", "Face vertices are not coplanar"],
["DUP_FACE", "ERROR", "brown", "Multiple instances of the same face."], ["DUP_FACE", "ERROR", "brown", "Multiple instances of the same face."],
["MULTCONN", "ERROR", "orange", "Multiply Connected Geometry. Too many faces attached at Edge"], ["MULTCONN", "ERROR", "orange", "Multiply Connected Geometry. Too many faces attached at Edge"],
["REVERSAL", "ERROR", "violet", "Faces Reverse Across Edge"], ["REVERSAL", "ERROR", "violet", "Faces Reverse Across Edge"],
["T_JUNCTION", "ERROR", "magenta", "Vertex is mid-edge on another Face"], ["T_JUNCTION", "ERROR", "red", "Vertex is mid-edge on another Face"],
["FACE_ISECT", "ERROR", "brown", "Faces intersect"], ["FACE_ISECT", "ERROR", "pink", "Faces intersect"],
["HOLE_EDGE", "ERROR", "red", "Edge bounds Hole"] ["HOLE_EDGE", "ERROR", "magenta", "Edge bounds Hole"]
]; ];