@@ -203,6 +203,57 @@ def test_fan():
203203 assert repair .is_winding_consistent
204204
205205
206+ def test_fix_normals_mixed_multibox ():
207+ from trimesh .creation import box
208+ # a test for multibody meshes with some watertight, some not
209+
210+ # create a multibody mesh with two cubes, one of which is inverted
211+ a = box ()
212+ b = box ().apply_translation ([4 , 0 , 0 ]).invert ()
213+ c = a + b
214+
215+ # inverted should sum to zero volume
216+ assert g .np .isclose (c .volume , 0.0 )
217+ # area isn't signed so should be correct
218+ assert g .np .isclose (c .area , 12.0 )
219+
220+ # fix_normals should repair the disconnected meshes
221+ r = c .copy ().fix_normals ()
222+ assert g .np .allclose (r .volume , 2.0 )
223+
224+ # create a non-watertight cube
225+ frag = box ().apply_translation ([8 , 0 , 0 ])
226+ frag .faces = frag .faces [:- 1 ]
227+ assert not frag .is_watertight
228+
229+ # append on the non-watertight cube
230+ c += frag
231+
232+ # exactly half of one 1x1 square face is missing
233+ assert g .np .isclose (c .area , 17.5 ), c .area
234+
235+ # run the fix_normals call with:
236+ # - 1 good cube
237+ # - 1 inverted cube
238+ # - 1 cube missing a face
239+ # this should fix the inverted and ignore the one with holes in it
240+ c .fix_normals ()
241+
242+ # split without repairing the hole, but culling the non-watertight result
243+ split = c .split (only_watertight = True , repair = False )
244+ assert len (split ) == 2 , len (split )
245+ assert all (s .is_volume for s in split )
246+ assert all (g .np .isclose (s .volume , 1.0 ) for s in split )
247+
248+ # split WITH repairing the hole and culling anything non-watertight
249+ split = c .split (only_watertight = True , repair = True )
250+ assert len (split ) == 3 , len (split )
251+
252+ # the non-watertight mesh should have been repaired but not inverted?
253+ assert sum (s .is_volume for s in split ) == 2
254+
255+
206256if __name__ == "__main__" :
207257 g .trimesh .util .attach_to_log ()
208258 g .unittest .main ()
259+ test_fix_normals_mixed_multibox ()
0 commit comments