Tetrahedral Mesh

[1]:
from lapy import TetMesh

First, instead of loading, we define a small tetrahedral mesh representing a cube with a center vertex and twelve tetrahedra.

[2]:
# cube9 (cube with center node)
points = [
    [0, 0, 0],
    [1, 0, 0],
    [1, 1, 0],
    [0, 1, 0],
    [0, 0, 1],
    [1, 0, 1],
    [1, 1, 1],
    [0, 1, 1],
    [0.5, 0.5, 0.5],
]
tets = [
    [0, 5, 8, 1],
    [0, 4, 5, 8],
    [2, 5, 6, 8],
    [1, 5, 2, 8],
    [6, 7, 3, 8],
    [6, 3, 2, 8],
    [0, 3, 4, 8],
    [3, 7, 4, 8],
    [0, 1, 2, 8],
    [0, 2, 3, 8],
    [4, 6, 5, 8],
    [4, 7, 6, 8],
]
T = TetMesh(points, tets)

Note, that we flipped the first tetrahedron vertex order on purpose (it should be 0,5,1,8) to test and correct orientation below.

We can check if our tet mesh has free vertices (these are vertices that are not used in any tetrahedron).

[3]:
T.has_free_vertices()
[3]:
False

No free vertices are found, so we cannot remove any and the attempt will keep all 9.

[4]:
T.rm_free_vertices_()
[4]:
(array([0, 1, 2, 3, 4, 5, 6, 7, 8]), [])

Let’s see next, if we have consistent orientations (this should fail).

[5]:
T.is_oriented()
Orientations are not uniform
[5]:
False

Some functions don’t care about the orientation, for example the average edge length computation.

[6]:
T.avg_edge_length()
[6]:
1.0543647924813107

We can also get the boundary of the tet mesh as a triangle mesh.

[7]:
BT = T.boundary_tria()
Found 12 triangles on boundary.

But also the boundary is not oriented consistently (triangle normals of neighboring triangles point in opposite directions).

[8]:
BT.is_oriented()
[8]:
False

Let’s repeat those steps after correcting the orientation in the tet mesh.

[9]:
T.orient_()
T.is_oriented()
Flipped 1 tetrahedra
All tet orientations are correct
[9]:
True

When we extract the boundary surface now, we see it is also consistently oriented.

[10]:
BT = T.boundary_tria()
BT.is_oriented()
Found 12 triangles on boundary.
[10]:
True

Correct orientation is needed, e.g., to compute the volume of a surface mesh.

[11]:
BT.volume()
[11]:
1.0