Procedural Mesh Generation

Box generation

pymesh.generate_box_mesh(box_min, box_max, num_samples=1, keep_symmetry=False, subdiv_order=0, using_simplex=True)

Generate axis-aligned box mesh.

Each box is made of a number of cells (a square in 2D and cube in 3D), and each cell is made of triangles (2D) or tetrahedra (3D).

  • box_min (numpy.ndarray) – min corner of the box.
  • box_max (numpy.ndarray) – max corner of the box.
  • num_samples (int) – (optional) Number of segments on each edge of the box. Default is 1.
  • keep_symmetry (bool) – (optional) If true, ensure mesh connectivity respect all reflective symmetries of the box. Default is true.
  • subdiv_order (int) – (optional) The subdivision order. Default is 0.
  • using_simplex (bool) – If true, build box using simplex elements (i.e. triangle or tets), otherwise, use quad or hex element.

A box Mesh. The following attributes are defined.

  • cell_index: An numpy.ndarray of size \(N_e\) that maps each element to the index of the cell it belongs to. \(N_e\) is the number of elements.

Sphere generation

pymesh.generate_icosphere(radius, center, refinement_order=0)

Generate icosphere (subdivision surface of a regular icosahedron).

  • radius (float) – Radius of icosphere.
  • center (numpy.ndarray) – Sphere center.
  • refinement_order (int) – (optional) Number of refinement.

The (possibly refined) icosphere Mesh.

Cylinder generation

pymesh.generate_cylinder(p0, p1, r0, r1, num_segments=16)

Generate cylinder (or conical frustum to be precise).

  • p0 (np.ndarray) – Bottom center.
  • p1 (np.ndarray) – Top center.
  • r0 (float) – Bottom radius.
  • r1 (float) – Top radius.
  • num_segments (int) – Number of segments to a discrete circle consists.

The cylinder Mesh.

Tube generation

pymesh.generate_tube(p0, p1, r0_out, r1_out, r0_in, r1_in, num_segments=16, with_quad=False)

Generate generalized tube (i.e. cylinder with an axial hole).

  • p0 (np.ndarray) – Bottom center.
  • p1 (np.ndarray) – Top center.
  • r0_out (float) – Bottom outer radius.
  • r1_out (float) – Top outer radius.
  • r0_in (float) – Bottom inner radius.
  • r1_in (float) – Top inner radius.
  • num_segments (int) – Number of segments to a discrete circle consists.
  • with_quad (bool) – Output a quad mesh instead.

A generalized tube Mesh.

Other Platonic solids

pymesh.generate_regular_tetrahedron(edge_length=1.0, center=[0.0, 0.0, 0.0])

Generate a regular tetrahedron with the specified edge length and center.

  • edge_length (float) – edge length of the regular tet.
  • center (numpy.ndarray) – center of the tet.

A Mesh object containing a regular tetrahedron.

pymesh.generate_dodecahedron(radius, center)

Generate a regular dodecahedron.

  • radius (float) – Radius of the shape.
  • center (numpy.ndarray) – shape center.

The dodecahedron Mesh object.

Wire mesh generation

class pymesh.wires.WireNetwork

Data structure for wire network.

A wire network consists of a list of vertices and a list of edges. Thus, it is very similar to a graph except all vertices have their positions specified. Optionally, each vertex and edge could be associated with one or more attributes.


int – The dimension of the embedding space of this wire network. Must be 2 or 3.


numpy.ndarray – A V by dim vertex matrix. One vertex per row.


numpy.ndarray – A E by 2 edge matrix. One edge per row.


int – The number of vertices (i.e. V).


int – The number of edges (i.e. E).


numpy.ndarray – A 2 by dim matrix with first and second rows being the minimum and maximum corners of the bounding box respectively.


numpy.ndarray – Center of the bbox.


numpy.ndarray – Average of all vertices.


numpy.ndarray – An array of lengths of all edges.


float – Sum of wire_lengths.


list of str – The names of all defined attributes.

classmethod create_empty()

Handy factory method to create an empty wire network.

classmethod create_from_file(wire_file)

Handy factory method to load data from a file.

classmethod create_from_data(vertices, edges)

Handy factory method to create wire network from vertices and edges.


>>> vertices = np.array([
...     [0.0, 0.0, 0.0],
...     [1.0, 0.0, 0.0],
...     [1.0, 1.0, 0.0],
...     ]);
>>> edges = np.array([
...     [0, 1],
...     [0, 2],
...     [1, 2],
...     ]);
>>> wires = WireNetwork.create_from_data(vertices, edges);
load(vertices, edges)

Load vertices and edges from data.

  • vertices (numpy.ndarray) – num_vertices by dim array of vertex coordinates.
  • faces (numpy.ndarray) – num_edges by 2 array of vertex indices.

Load vertices and edges from a file.

Parameters:wire_file (str) – Input wire file name.

The file should have the following format:

# This is a comment
v x y z
v x y z
l i j # where i and j are vertex indices (starting from 1)
l i j

Load vertex and edges from raw C++ wire data structure.


Save the current wire network into a file.


Scale the wire network by factors

Parameters:factors – scaling factors. Scale uniformly if factors is a scalar. If factors is an array, scale each dimension separately (dimension i is scaled by factors[i]).

Offset vertices by per-vertex offset_vector.

Parameters:offset_vector (numpy.ndarray) – A \(N imes dim\) matrix representing per-vertex offset vectors.

Translate the wire networks to have its center at the origin.


Remove all hanging edges. e.g. edge with at least one vertex of valance <= 1


Remove all vertices other than the ones marked with to_keep. Edges are updated accordingly.


Remove all edges unless marked with to keep. Vertices are left unchanged.


Compute the following symmetry orbits:

  • vertex_symmetry_orbit: all vertices belonging to the same orbit can be mapped to each other by reflection with respect to planes orthogonal to axis.
  • vertex_cubic_symmetry_orbit: all vertices belonging to the same orbit can be mapped to each other by reflection with respect to any symmetry planes of a perfect cube.
  • edge_symmetry_orbit: all edges belonging to the same orbit can be mapped to each other by reflection with respect to planes orthogonal to axis.
  • edge_cubic_symmetry_orbit: all edges belonging to the same orbit can be mapped to each other by reflection with respect to any symmetry planes of a perfect cube.

All orbits are stored as attributes.


Get the names of all defined attributes.


Check if an attribute exists.

add_attribute(name, value=None, vertex_wise=True)

Add a new attirbute.

  • name (str) – Attribute name.
  • value (numpy.ndarray) – N by d matrix of attribute values (one row per vertex or per edge). Default is None to represent uninitialized attribute value.
  • vertex_wise (bool) – Whether this attribute is assigned to vertices or edges.

Get the value of an attribute.


Returns true if name is a per-vertex attribute.

set_attribute(name, value)

Set the value of the attribute name to be value.


Returns a list of vertex indices which are connected to vertex i via an edge.

class pymesh.wires.Parameters(wire_network, default_thickness=0.5)

This class is a thin wrapper around PyMesh.ParameterManager class.

class pymesh.wires.Tiler(base_pattern=None)
class pymesh.wires.Inflator(wire_network)

Set the cross section shape of each wire to N-gon.

set_refinement(order=1, method='loop')

Refine the output mesh using subdivision.

  • order – how many times to subdivide.
  • mehtod – which subdivision scheme to use. Options are loop and simple.