MeshBuilder¶
The MeshBuilder classes are helper tools to manage meshes buildup by
vertices and faces.
The vertices are stored in a vertices list as Vec3 instances.
The faces are stored as a sequence of vertex indices which is the location of
the vertex in the vertex list. A single MeshBuilder class can contain
multiple separated meshes at the same time.
The method MeshBuilder.render_mesh() renders the content as a single DXF
Mesh entity, which supports ngons, ngons are polygons
with more than 4 vertices. This entity requires at least DXF R2000.
The method MeshBuilder.render_polyface() renders the content as a single
DXF Polyface entity, which supports only triangles and
quadrilaterals. This entity is supported by DXF R12.
The method MeshBuilder.render_3dfaces() renders each face of the mesh as
a single DXF Face3d entity, which supports only
triangles and quadrilaterals. This entity is supported by DXF R12.
The MeshTransformer class is often used as an interface object to
transfer mesh data between functions and moduls, like for the mesh exchange
add-on meshex.
The basic MeshBuilder class does not support transformations.
- class ezdxf.render.MeshBuilder¶
-
- faces¶
List of faces as list of vertex indices, where a vertex index is the index of the vertex in the
verticeslist. A face requires at least three vertices,Meshsupports ngons, so the count of vertices is not limited.
- add_face(vertices: Iterable[UVec]) None¶
Add a face as vertices list to the mesh. A face requires at least 3 vertices, each vertex is a
(x, y, z)tuple orVec3object. The new vertex indices are stored as face in thefaceslist.- Parameters:
vertices – list of at least 3 vertices
[(x1, y1, z1), (x2, y2, z2), (x3, y3, y3), ...]
- add_mesh(vertices: list[Vec3] | None = None, faces: list[Sequence[int]] | None = None, mesh=None) None¶
Add another mesh to this mesh.
A mesh can be a
MeshBuilder,MeshVertexMergerorMeshobject or requires the attributesverticesandfaces.- Parameters:
vertices – list of vertices, a vertex is a
(x, y, z)tuple orVec3objectfaces – list of faces, a face is a list of vertex indices
mesh – another mesh entity
- add_vertices(vertices: Iterable[UVec]) Sequence[int]¶
Add new vertices to the mesh, each vertex is a
(x, y, z)tuple or aVec3object, returns the indices of the vertices added to theverticeslist.e.g. adding 4 vertices to an empty mesh, returns the indices
(0, 1, 2, 3), adding additional 4 vertices returns the indices(4, 5, 6, 7).
- bbox() BoundingBox¶
Returns the
BoundingBoxof the mesh.
- copy()¶
Returns a copy of mesh.
- diagnose() MeshDiagnose¶
Returns the
MeshDiagnoseobject for this mesh.
- face_normals() Iterator[Vec3]¶
Yields all face normals, yields the
NULLVECinstance for degenerated faces.
- face_orientation_detector(reference: int = 0) FaceOrientationDetector¶
Returns a
FaceOrientationDetectoror short fod instance. The forward orientation is defined by the reference face which is 0 by default.The fod can check if all faces are reachable from the reference face and if all faces have the same orientation. The fod can be reused to unify the face orientation of the mesh.
- flip_normals() None¶
Flips the normals of all faces by reversing the vertex order inplace.
- classmethod from_builder(other: MeshBuilder)¶
Create new mesh from other mesh builder, faster than
from_mesh()but supports onlyMeshBuilderand inherited classes.
- classmethod from_mesh(other: MeshBuilder | Mesh) T¶
Create new mesh from other mesh as class method.
- Parameters:
other – mesh of type
MeshBuilderand inherited or DXFMeshentity or any object providing attributesvertices,edgesandfaces.
- get_face_normal(index: int) Vec3¶
Returns the normal vector of the face index as
Vec3, returns theNULLVECinstance for degenerated faces.
- merge_coplanar_faces(passes: int = 1) MeshTransformer¶
Returns a new
MeshBuilderobject with merged adjacent coplanar faces.The faces have to share at least two vertices and have to have the same clockwise or counter-clockwise vertex order.
The current implementation is not very capable!
- mesh_tessellation(max_vertex_count: int = 4) MeshTransformer¶
Returns a new
MeshTransformerinstance, where each face has no more vertices than the given max_vertex_count.The fast mode uses a shortcut for faces with less than 6 vertices which may not work for concave faces!
- normalize_faces() None¶
Removes duplicated vertex indices from faces and stores all faces as open faces, where the last vertex is not coincident with the first vertex.
- open_faces() Iterator[Sequence[int]]¶
Yields all faces as sequence of integers where the first vertex is not coincident with the last vertex.
- optimize_vertices(precision: int = 6) MeshTransformer¶
Returns a new mesh with optimized vertices. Coincident vertices are merged together and all faces are open faces (first vertex != last vertex). Uses internally the
MeshVertexMergerclass to merge vertices.
- render_3dfaces(layout: GenericLayoutType, dxfattribs=None, matrix: Matrix44 | None = None, ucs: UCS | None = None)¶
Render mesh as
Face3dentities into layout.- Parameters:
layout –
BaseLayoutobjectdxfattribs – dict of DXF attributes e.g.
{'layer': 'mesh', 'color': 7}matrix – transformation matrix of type
Matrix44
- render_mesh(layout: GenericLayoutType, dxfattribs=None, matrix: Matrix44 | None = None, ucs: UCS | None = None)¶
Render mesh as
Meshentity into layout.- Parameters:
layout –
BaseLayoutobjectdxfattribs – dict of DXF attributes e.g.
{'layer': 'mesh', 'color': 7}matrix – transformation matrix of type
Matrix44
- render_normals(layout: GenericLayoutType, length: float = 1, relative=True, dxfattribs=None)¶
Render face normals as
Lineentities into layout, useful to check orientation of mesh faces.- Parameters:
layout –
BaseLayoutobjectlength – visual length of normal, use length < 0 to point normals in opposite direction
relative – scale length relative to face size if
Truedxfattribs – dict of DXF attributes e.g.
{'layer': 'normals', 'color': 6}
- render_polyface(layout: GenericLayoutType, dxfattribs=None, matrix: Matrix44 | None = None, ucs: UCS | None = None)¶
Render mesh as
Polyfaceentity into layout.- Parameters:
layout –
BaseLayoutobjectdxfattribs – dict of DXF attributes e.g.
{'layer': 'mesh', 'color': 7}matrix – transformation matrix of type
Matrix44
- separate_meshes() list[MeshTransformer]¶
A single
MeshBuilderinstance can store multiple separated meshes. This function returns this separated meshes as multipleMeshTransformerinstances.
- subdivide(level: int = 1, quads=True) MeshTransformer¶
Returns a new
MeshTransformerobject with all faces subdivided.- Parameters:
level – subdivide levels from 1 to max of 5
quads – create quad faces if
Trueelse create triangles
- subdivide_ngons(max_vertex_count=4) Iterator[Sequence[Vec3]]¶
Yields all faces as sequence of
Vec3instances, where all ngons which have more than max_vertex_count vertices gets subdivided. In contrast to thetessellation()method, creates this method a new vertex in the centroid of the face. This can create a more regular tessellation but only works reliable for convex faces!
- tessellation(max_vertex_count: int = 4) Iterator[Sequence[Vec3]]¶
Yields all faces as sequence of
Vec3instances, each face has no more vertices than the given max_vertex_count. This method uses the “ear clipping” algorithm which works with concave faces too and does not create any additional vertices.
- unify_face_normals(*, fod: FaceOrientationDetector | None = None) MeshTransformer¶
Returns a new
MeshTransformerobject with unified face normal vectors of all faces. The forward direction (not necessarily outwards) is defined by the face-normals of the majority of the faces. This function can not process non-manifold meshes (more than two faces are connected by a single edge) or multiple disconnected meshes in a singleMeshBuilderobject.It is possible to pass in an existing
FaceOrientationDetectorinstance as argument fod.- Raises:
NonManifoldError – non-manifold mesh
MultipleMeshesError – the
MeshBuilderobject contains multiple disconnected meshes
- unify_face_normals_by_reference(reference: int = 0, *, force_outwards=False, fod: FaceOrientationDetector | None = None) MeshTransformer¶
Returns a new
MeshTransformerobject with unified face normal vectors of all faces. The forward direction (not necessarily outwards) is defined by the reference face, which is the first face of the mesh by default. This function can not process non-manifold meshes (more than two faces are connected by a single edge) or multiple disconnected meshes in a singleMeshBuilderobject.The outward direction of all face normals can be forced by stetting the argument force_outwards to
Truebut this works only for closed surfaces, and it’s time-consuming!It is not possible to check for a closed surface as long the face normal vectors are not unified. But it can be done afterward by the attribute
MeshDiagnose.is_closed_surface()to see if the result is trustworthy.It is possible to pass in an existing
FaceOrientationDetectorinstance as argument fod.- Parameters:
reference – index of the reference face
force_outwards – forces face-normals to point outwards, this works only for closed surfaces, and it’s time-consuming!
fod –
FaceOrientationDetectorinstance
- Raises:
ValueError – non-manifold mesh or the
MeshBuilderobject contains multiple disconnected meshes
MeshTransformer¶
Same functionality as MeshBuilder but supports inplace transformation.
- class ezdxf.render.MeshTransformer¶
Subclass of
MeshBuilder- transform(matrix: Matrix44)¶
Transform mesh inplace by applying the transformation matrix.
- Parameters:
matrix – 4x4 transformation matrix as
Matrix44object
- translate(dx: float | UVec = 0, dy: float = 0, dz: float = 0)¶
Translate mesh inplace.
- Parameters:
dx – translation in x-axis or translation vector
dy – translation in y-axis
dz – translation in z-axis
- scale(sx: float = 1, sy: float = 1, sz: float = 1)¶
Scale mesh inplace.
- Parameters:
sx – scale factor for x-axis
sy – scale factor for y-axis
sz – scale factor for z-axis
- scale_uniform(s: float)¶
Scale mesh uniform inplace.
- Parameters:
s – scale factor for x-, y- and z-axis
- rotate_x(angle: float)¶
Rotate mesh around x-axis about angle inplace.
- Parameters:
angle – rotation angle in radians
- rotate_y(angle: float)¶
Rotate mesh around y-axis about angle inplace.
- Parameters:
angle – rotation angle in radians
- rotate_z(angle: float)¶
Rotate mesh around z-axis about angle inplace.
- Parameters:
angle – rotation angle in radians
MeshVertexMerger¶
Same functionality as MeshBuilder, but created meshes with unique
vertices and no doublets, but MeshVertexMerger needs extra memory for
bookkeeping and also does not support transformations.
The location of the merged vertices is the location of the first vertex with the
same key.
This class is intended as intermediate object to create compact meshes and
convert them to MeshTransformer objects to apply transformations:
mesh = MeshVertexMerger()
# create your mesh
mesh.add_face(...)
# convert mesh to MeshTransformer object
return MeshTransformer.from_builder(mesh)
- class ezdxf.render.MeshVertexMerger(precision: int = 6)¶
Subclass of
MeshBuilderMesh with unique vertices and no doublets, but needs extra memory for bookkeeping.
MeshVertexMergercreates a key for every vertex by rounding its components by the Pythonround()function and a given precision value. Each vertex with the same key gets the same vertex index, which is the index of first vertex with this key, so all vertices with the same key will be located at the location of this first vertex. If you want an average location of all vertices with the same key use theMeshAverageVertexMergerclass.- Parameters:
precision – floating point precision for vertex rounding
MeshAverageVertexMerger¶
This is an extended version of MeshVertexMerger.
The location of the merged vertices is the average location of all vertices with
the same key, this needs extra memory and runtime in comparison to
MeshVertexMerger and this class also does not support
transformations.
- class ezdxf.render.MeshAverageVertexMerger(precision: int = 6)¶
Subclass of
MeshBuilderMesh with unique vertices and no doublets, but needs extra memory for bookkeeping and runtime for calculation of average vertex location.
MeshAverageVertexMergercreates a key for every vertex by rounding its components by the Pythonround()function and a given precision value. Each vertex with the same key gets the same vertex index, which is the index of first vertex with this key, the difference to theMeshVertexMergerclass is the calculation of the average location for all vertices with the same key, this needs extra memory to keep track of the count of vertices for each key and extra runtime for updating the vertex location each time a vertex with an existing key is added.- Parameters:
precision – floating point precision for vertex rounding
- class ezdxf.render.mesh.EdgeStat(count: int, balance: int)¶
Named tuple of edge statistics.
- count¶
how often the edge (a, b) is used in faces as (a, b) or (b, a)
- balance¶
count of edges (a, b) - count of edges (b, a) and should be 0 in “healthy” closed surfaces, if the balance is not 0, maybe doubled coincident faces exist or faces may have mixed clockwise and counter-clockwise vertex orders
MeshBuilder Helper Classes¶
- class ezdxf.render.MeshDiagnose¶
Diagnose tool which can be used to analyze and detect errors of
MeshBuilderobjects like topology errors for closed surfaces. The object contains cached values, which do not get updated if the source mesh will be changed!Note
There exist no tools in ezdxf to repair broken surfaces, but you can use the
ezdxf.addons.meshexaddon to exchange meshes with the open source tool MeshLab.Create an instance of this tool by the
MeshBuilder.diagnose()method.- property bbox: BoundingBox¶
Returns the
BoundingBoxof the mesh. (cached data)
- property edge_stats: Dict[Tuple[int, int], EdgeStat]¶
Returns the edge statistics as a
dict. The dict-key is the edge as tuple of two vertex indices (a, b) where a is always smaller than b. The dict-value is anEdgeStattuple of edge count and edge balance, seeEdgeStatfor the definition of edge count and edge balance. (cached data)
- property euler_characteristic: int¶
Returns the Euler characteristic: https://en.wikipedia.org/wiki/Euler_characteristic
This number is always 2 for convex polyhedra.
- property face_normals: Sequence[Vec3]¶
Returns all face normal vectors as sequence. The
NULLVECinstance is used as normal vector for degenerated faces. (cached data)
- property faces: Sequence[Sequence[int]]¶
Sequence of faces as
Sequence[int]
- property is_closed_surface: bool¶
Returns
Trueif the mesh has a closed surface. This method does not require a unified face orientation. If multiple separated meshes are present the state is onlyTrueif all meshes have a closed surface. (cached data)Returns
Falsefor non-manifold meshes.
- property is_edge_balance_broken: bool¶
Returns
Trueif the edge balance is broken, this indicates a topology error for closed surfaces. A non-broken edge balance reflects that each edge connects two faces, where the edge is clockwise oriented in the first face and counter-clockwise oriented in the second face. A broken edge balance indicates possible topology errors like mixed face vertex orientations or a non-manifold mesh where an edge connects more than two faces. (cached data)
- property is_manifold: bool¶
Returns
Trueif all edges have an edge count < 3. (cached data)A non-manifold mesh has edges with 3 or more connected faces.
- property n_edges: int¶
Returns the unique edge count. (cached data)
- property n_faces: int¶
Returns the face count.
- property n_vertices: int¶
Returns the vertex count.
- estimate_face_normals_direction() float¶
Returns the estimated face-normals direction as
floatvalue in the range [-1.0, 1.0] for a closed surface.This heuristic works well for simple convex hulls but struggles with more complex structures like a torus (doughnut).
A counter-clockwise (ccw) vertex arrangement for outward pointing faces is assumed but a clockwise (cw) arrangement works too but the return values are reversed.
The closer the value to 1.0 (-1.0 for cw) the more likely all normals pointing outwards from the surface.
The closer the value to -1.0 (1.0 for cw) the more likely all normals pointing inwards from the surface.
There are no exact confidence values if all faces pointing outwards, here some examples for surfaces created by
ezdxf.render.formsfunctions:cube()returns 1.0cylinder()returns 0.9992sphere()returns 0.9994cone()returns 0.9162cylinder()with all hull faces pointing outwards but caps pointing inwards returns 0.7785 but the propertyis_edge_balance_brokenreturnsTruewhich indicates the mixed vertex orientationand the estimation of 0.0469 for a
torus()is barely usable
- has_non_planar_faces() bool¶
Returns
Trueif any face is non-planar.
- surface_area() float¶
Returns the surface area.
- total_edge_count() int¶
Returns the total edge count of all faces, shared edges are counted separately for each face. In closed surfaces this count should be 2x the unique edge count
n_edges. (cached data)
- unique_edges() Iterable[Tuple[int, int]]¶
Yields the unique edges of the mesh as int 2-tuples. (cached data)
- volume() float¶
Returns the volume of a closed surface or 0 otherwise.
Warning
The face vertices have to be in counter-clockwise order, this requirement is not checked by this method.
The result is not correct for multiple separated meshes in a single MeshBuilder object!!!
- class ezdxf.render.FaceOrientationDetector(mesh: MeshBuilder, reference: int = 0)¶
Helper class for face orientation and face normal vector detection. Use the method
MeshBuilder.face_orientation_detector()to create an instance.The face orientation detector classifies the faces of a mesh by their forward or backward orientation. The forward orientation is defined by a reference face, which is the first face of the mesh by default and this orientation is not necessarily outwards.
This class has some overlapping features with
MeshDiagnosebut it has a longer setup time and needs more memory thanMeshDiagnose.- Parameters:
mesh – source mesh as
MeshBuilderobjectreference – index of the reference face
- is_manifold¶
Trueif all edges have an edge count < 3. A non-manifold mesh has edges with 3 or more connected faces.
- property all_reachable: bool¶
Returns
Trueif all faces are reachable from the reference face same as propertyis_single_mesh.
- property count: tuple[int, int]¶
Returns the count of forward and backward oriented faces.
- property backward_faces: Iterator[Sequence[int]]¶
Yields all backward oriented faces.
- property forward_faces: Iterator[Sequence[int]]¶
Yields all forward oriented faces.
- property has_uniform_face_normals: bool¶
Returns
Trueif all reachable faces are forward oriented according to the reference face.
- property is_closed_surface: bool¶
Returns
Trueif the mesh has a closed surface. This method does not require a unified face orientation. If multiple separated meshes are present the state is onlyTrueif all meshes have a closed surface.Returns
Falsefor non-manifold meshes.
- property is_single_mesh: bool¶
Returns
Trueif only a single mesh is present same as propertyall_reachable.
- classify_faces(reference: int = 0) None¶
Detect the forward and backward oriented faces.
The forward and backward orientation has to be defined by a reference face.
- is_reference_face_pointing_outwards() bool¶
Returns
Trueif the normal vector of the reference face is pointing outwards. This works only for meshes with unified faces which represent a closed surfaces, and it’s a time-consuming calculation!