Skip to content

Subdivision

Due to the connectivity data attached to the meshes data structures, subdividing meshes by hand is unsafe and can lead to faulty results. To correctly apply subdivisions, one needs to first convert back the mesh to a RawMeshData, apply the combinatorial functions, and rebuild a correct mesh. This is handled by the SurfaceSubdivision and the VolumeSubdivision classes, which are designed to be used in a with block:

import mouette as M

surface = M.mesh.load("/path/to/my/mesh.obj")

# At the start of the with block, the mesh is transformed into a RawMeshData and its connectivity is disabled
with M.mesh.SurfaceSubdivision(surface) as editor:
    # Call here the subdivision functions
    editor.subdivide_triangles_3quads()
    editor.triangulate()
# When exiting the 'with' block, the mesh is transformed back into a SurfaceMesh
# and its connectivity is regenerated
M.mesh.save(surface, "path/to/my/new/mesh.obj")

PointCloud(data=None)

Bases: Mesh

A data structure for representing point clouds

Attributes:

Name Type Description
vertices DataContainer

the container for all vertices

__str__ str

Representation of the object and its elements as a string.

id_vertices property

Shortcut for range(len(self.vertices))

append(x)

Shortcut for self.vertices.append(x), since we can only append elements in the 'vertices' container

PolyLine(data=None)

Bases: Mesh

A data structure for representing polylines.

Attributes:

Name Type Description
vertices DataContainer

the container for all vertices

edges DataContainer

the container for all edges

__str__

Representation of the object and its elements as a string.

id_edges property

Shortcut for range(len(self.edges))

id_vertices property

Shortcut for range(len(self.vertices))

SurfaceMesh(data=None)

Bases: Mesh

A data structure for representing polygonal surfaces.

Attributes:

Name Type Description
vertices DataContainer

the container for all vertices

edges DataContainer

the container for all edges

faces DataContainer

the container for all faces

face_corners DataContainer

the container for all corner of faces

boundary_edges list

list of all edge indices on the boundary

interior_edges list

list of all interior edge indices (all edges \ boundary_edges)

boundary_vertices list

list of all vertex indices on the boundary

interior_vertices list

list of all interior verticex indices (all vertices \ boundary_vertices)

connectivity _SurfaceConnectivity

the connectivity utility class

id_corners property

Shortcut for range(len(self.face_corners))

id_edges property

Shortcut for range(len(self.edges))

id_faces property

Shortcut for range(len(self.faces))

id_vertices property

Shortcut for range(len(self.vertices))

clear_boundary_data()

Clear all boundary data. Next call to a boundary/interior container or method will recompute everything

is_edge_on_border(u, v)

whether edge (u,v) is a boundary edge or not

Parameters:

Name Type Description Default
u int

vertex id

required
v int

vertex id

required

Returns:

Name Type Description
bool bool

whether edge (u,v) is a boundary edge or not. Returns False if (u,v) is not a valid edge.

is_quad()

Returns:

Name Type Description
bool bool

True if the mesh is quadrangular (all faces are quad)

is_triangular()

Returns:

Name Type Description
bool bool

True if the mesh is triangular (all faces are triangles)

is_vertex_on_border(u)

whether vertex u is a boundary vertex or not.

Parameters:

Name Type Description Default
u int

vertex id

required

Returns:

Name Type Description
bool bool

whether vertex u is a boundary vertex or not.

ith_vertex_of_face(fid, i)

helper function to get the i-th vertex of a face, i.e. self.faces[fid][i]

Parameters:

Name Type Description Default
fid int

face id

required
i int

vertex id in face. Should be 0 <= vid < len(face)

required

Returns:

Name Type Description
int int

the id of the i-th vertex in face fid (self.faces[fid][i])

pt_of_face(fid)

point coordinates of vertices of face fid

Parameters:

Name Type Description Default
fid int

face id

required

Returns:

Name Type Description
Iterable

iterator of Vec objects representing point coordinates of vertices

SurfaceSubdivision(mesh, verbose=False)

Bases: Logger

split_face_as_fan(face_id)

Adds a vertex at the barycenter of face 'face_id' and create a fan of triangles that replaces the face

Parameters:

Name Type Description Default
face_id int

the face to split

required

subdivide_triangles(n=1)

Subdivides triangles of a mesh in 4 triangles by splitting along middle of edges. If the mesh is not triangulated, will triangulate the mesh first.

Parameters:

Name Type Description Default
n int

Number of times the subdivision is applied. Defaults to 1.

1

subdivide_triangles_3quads()

Subdivides triangles of a mesh in 3 quads by adding a point at the barycenter and three middles of edges. If the mesh is not triangulated, will triangulate the mesh first.

subdivide_triangles_6(repeat=1)

Subdivides triangles of a mesh in 6 triangles by adding a point at the barycenter and three middles of edges. If the mesh is not triangulated, will triangulate the mesh first.

Parameters:

Name Type Description Default
repeat int

number of successive subdivisions. Eventual first triangulation does not count. Defaults to 1.

1

triangulate()

Triangulates all faces of a mesh. Calls triangulate_face on every faces.

triangulate_face(face_id)

Triangulates the face "face_id"

Parameters:

Name Type Description Default
face_id int

the face to triangulate

required

VolumeMesh(data=None)

Bases: Mesh

id_cells property

Shortcut for range(len(self.cells))

id_corners property

Shortcut for range(len(self.face_corners))

id_edges property

Shortcut for range(len(self.edges))

id_faces property

Shortcut for range(len(self.faces))

id_vertices property

Shortcut for range(len(self.vertices))

is_edge_on_border(*args)

Simple test to determine if a given edge is on the boundary of the mesh.

Returns:

Name Type Description
bool bool

Returns True if the given edge is on the boundary of the mesh.

is_face_on_border(*args)

Simple test to determine if a given face is on the boundary of the mesh.

Returns:

Name Type Description
bool bool

Returns True is the given face exists and is on the boundary of the mesh

is_tetrahedral()

Returns:

Name Type Description
bool bool

True if the mesh is tetrahedral (all cells are tetrahedra)

VolumeSubdivision(mesh, verbose=False)

Bases: Logger

split_cell_as_fan(cell_id)

Adds a vertex at the barycenter of cell 'cell_id' and create a fan of tetrahedra that replaces the cell. If the cell 'cell_id' is not a tetrahedron, does nothing.

Parameters:

Name Type Description Default
mesh VolumeMesh

the input mesh

required
cell_id int

the (tetrahedral) cell to split

required

Returns:

Type Description
VolumeMesh

the modified input mesh

split_tet_from_face_center(face_id)

Split the triangle face_id into three triangles by adding a point at its barycenter, and split adjacent tetrahedra accordingly.

Parameters:

Name Type Description Default
face_id int

index of the face to split

required