face_adjacency doesn't find all adjacent faces
tomas16 opened this issue · comments
trimesh version 4.1.4
# Face 2866 contains vertices 1795, 387 and 1792.
face = 2866
vertices_in_face = mesh.faces[face, :]
# TrackedArray([1795, 387, 1792])
mask = np.any(mesh.face_adjacency == face, axis=1)
face_pairs = mesh.face_adjacency[mask, :]
# array([[2744, 2866],
# [2865, 2866]])
all_adjacent_faces = np.setdiff1d(face_pairs, face)
# array([2744, 2865])
mesh.faces[all_adjacent_faces, :]
# TrackedArray([[1792, 387, 465],
# [1795, 384, 387]])
# => The only vertex shared by faces 2866, 2744 and 2865 is vertex 387
# => The shared edge between face 2866 and 2744 is the edge containing vertices 387 and 1792
# => The shared edge between face 2866 and 2865 is the edge containing vertices 387 and 1795
# => According to mesh.face_adjacency, there's no adjacent face on the edge containing vertices 1792 and 1795
# Let's double-check this...
faces_with_vertices = np.nonzero(np.any(mesh.faces == 1792, axis=1) & np.any(mesh.faces == 1795, axis=1))[0]
# array([2866, 8222, 8961])
assert face in faces_with_vertices
mesh.faces[faces_with_vertices, :]
# TrackedArray([[1795, 387, 1792],
# [1795, 1792, 3914],
# [1795, 4423, 1792]])
# => Our original face 2866 does in fact have 2 additional adjacent faces not found by mesh.face_adjacency !
Before opening this issue, I found #1545
Not sure I follow that one entirely, but does it mean for face_adjacency
to detect adjacent faces, the shared edge must have a certain orientation? If that's the case, the "bug" here would be a documentation bug, as it isn't mentioned here.
Yeah perhaps the docstring should be clearer, is the situation here is "there are N faces sharing an edge where N > 2"? I.e. the mesh is not watertight/manifold/etc? Maybe a more exact definition of what face_adjacency
is doing is:
"If an edge occurs exactly twice, mesh.face_adjacency
returns the indexes of the two faces that contain that edge."
Thanks, that explains the difference. Not what I expected from "face_adjacency" 😉