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 |
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 |
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 |