@@ -828,14 +828,29 @@ def projected(
828828 vertices_2D = transform_points (mesh .vertices , to_2D )[:, :2 ]
829829
830830 if precise :
831+ # precise mode just unions triangles as one shapely
832+ # polygon per triangle which historically has been very slow
833+ # but it is more defensible intellectually
831834 faces = mesh .faces [side ]
832- # Cleanup vertices
833- vertices_2D_rounded = np .round (vertices_2D , int (np .abs (np .round (np .log10 (precise_eps ))) + 1 ))
834- triangles = vertices_2D_rounded [np .column_stack ((faces , faces [:, :1 ]))]
835- valid = ~ (triangles [:,[0 ,0 ,2 ]] == triangles [:,[1 ,2 ,1 ]]).all (axis = 2 ).any (axis = 1 )
836- triangles = triangles [valid ]
837- # Union all the polygons
838- return ops .unary_union ([Polygon (f ) for f in triangles ]).buffer (precise_eps ).buffer (- precise_eps )
835+ # round the 2D vertices with slightly more precision
836+ # than our final dilate-erode cleanup
837+ digits = int (np .abs (np .log10 (precise_eps )) + 2 )
838+ rounded = np .round (vertices_2D , digits )
839+ # get the triangles as closed 4-vertex polygons
840+ triangles = rounded [np .column_stack ((faces , faces [:, :1 ]))]
841+ # do a check for exactly-degenerate triangles where any two
842+ # vertices are exactly identical which means the triangle has
843+ # zero area
844+ valid = ~ (triangles [:, [0 , 0 , 2 ]] == triangles [:, [1 , 2 , 1 ]]).all (axis = 2 ).any (
845+ axis = 1
846+ )
847+ # union the valid triangles and then dilate-erode to clean up
848+ # any holes or defects smaller than precise_eps
849+ return (
850+ ops .unary_union ([Polygon (f ) for f in triangles [valid ]])
851+ .buffer (precise_eps )
852+ .buffer (- precise_eps )
853+ )
839854
840855 # a sequence of face indexes that are connected
841856 face_groups = graph .connected_components (adjacency , nodes = np .nonzero (side )[0 ])
0 commit comments