Mesh Classes#

Base Classes#

Define the base Mesh class on which the other classes are based.

class sphedron.mesh.base.Mesh(nodes: ndarray[tuple[Any, ...], dtype[_ScalarT]], faces: ndarray[tuple[Any, ...], dtype[_ScalarT]])[source]#

Flexible base class for spherical meshes.

Provides core functionality for node/face storage, node masking, and cached property computation.

Use from_base() to start from a class-defined base graph, or from_graph() to start from provided nodes/faces. Both optionally rotate and refine before constructing the Mesh.

Subclasses must implement base() and refine().

Parameters:
  • nodes – Cartesian coordinates of mesh nodes, shape (N, 3).

  • faces – Face definitions as indices into nodes, shape (F, K) where K is 3 for triangles or 4 for rectangles.

Attributes

property edges#

Get the edges of the mesh

property edges_symmetric: ndarray[tuple[Any, ...], dtype[int64]]#

Get the edges of the undirected mesh

property edges_unique#

Get directed edges of the graph, from lower to higher index nodes

property faces: ndarray[tuple[Any, ...], dtype[int64]]#

Get faces of the mesh, can be rectangles or triangles or more

property faces_partial: ndarray[tuple[Any, ...], dtype[_ScalarT]]#

Get faces of the mesh including those with partially masked nodes

property nodes#

Returns the nodes of mesh in cartesian coordinates

property nodes_latlong#

Returns the nodes of mesh in latitude/longitude format (degree)

property num_edges#

Number of edges

property num_faces: int#

Number of faces

property num_nodes#

Number of nodes

property triangles#

Return triangles of the mesh, useful for trimesh construction

Methods

from_base([refine_factor, rotate, ...])

Create an instance starting from the class base graph.

from_graph(nodes, faces[, refine_factor, ...])

Create mesh from nodes and faces and optionally rotate/refine.

refine(nodes, faces, factor[, use_angle])

Refine the mesh.

base()

Return the base (nodes, faces) geometry.

reset()

Reset the node mask so all nodes are visible again.

mask_nodes(nodes_mask)

Mask the nodes associated with nodes_mask[i] == True.

faces2triangles(faces)

Convert face to their corresponding triangles

triangle2face_index(triangle_idx)

Convert triangle index to face index

face2triangle_index(face_idx)

Convert face index to triangle index

build_trimesh()

return Trimesh instance from the current nodes and faces

query_edges_from_faces(receiver_mesh)

Get edges connecting nodes of the nearest face to receiver nodes.

query_edges_from_radius(receiver_mesh, radius)

Get edges connecting nearest neighboring nodes to receiver nodes.

query_edges_from_neighbors(receiver_mesh, ...)

Return edges connecting nearest neighboring nodes to receiver nodes.

classmethod from_base(refine_factor: int = 1, rotate: bool = True, refine_by_angle: bool = False)[source]#

Create an instance starting from the class base graph.

Pipeline:

base -> optional rotate -> optional refine -> construct

Parameters:
  • refine_factor – The factor by which to refine the mesh.

  • rotate – Whether to rotate base nodes using rotation_axis/angle.

  • refine_by_angle – Whether to refine by angle (strategy-specific).

Returns:

An instance of the class created from the generated nodes and faces.

classmethod from_graph(nodes: ndarray[tuple[Any, ...], dtype[_ScalarT]], faces: ndarray[tuple[Any, ...], dtype[_ScalarT]], refine_factor: int = 1, refine_by_angle: bool = False, rotate: bool = False)[source]#

Create mesh from nodes and faces and optionally rotate/refine.

Pipeline:

provided graph -> optional rotate -> optional refine -> construct

Parameters:
  • nodes (numpy.ndarray[M, ...]) – Coordinates of the nodes.

  • faces (numpy.ndarray[N, K]) – Faces defined by indices into nodes.

  • refine_factor (int) – Factor by which to refine the mesh. Higher values yield a more finely subdivided mesh.

  • refine_by_angle (bool) – If True, refinement considers edge angles.

  • rotate (bool) – If True, rotate the provided nodes using the class rotation parameters before refinement.

Returns:

A new instance containing the (optionally) refined graph.

Return type:

Mesh

Example

>>> from sphedron.mesh import Icosphere
>>> base_nodes, base_faces = Icosphere.base()
>>> refined = Icosphere.from_graph(
...     base_nodes, base_faces, refine_factor=2
... )
>>> print(refined.num_nodes, refined.num_faces)
static refine(nodes, faces, factor, use_angle=False, **kwargs) Tuple[ndarray[tuple[Any, ...], dtype[_ScalarT]], ndarray[tuple[Any, ...], dtype[_ScalarT]]][source]#

Refine the mesh. Subclasses must override this method.

static base() Tuple[ndarray[tuple[Any, ...], dtype[_ScalarT]], ndarray[tuple[Any, ...], dtype[_ScalarT]]][source]#

Return the base (nodes, faces) geometry. Subclasses must override.

reset()[source]#

Reset the node mask so all nodes are visible again.

mask_nodes(nodes_mask: ndarray[tuple[Any, ...], dtype[bool]])[source]#

Mask the nodes associated with nodes_mask[i] == True.

This method expects a boolean mask of size (num_nodes,). It will mask the specified nodes but will not unmask any nodes that have previously been masked.

Parameters:

nodes_mask – A boolean array indicating which nodes to mask. The array should have a size equal to the number of nodes in the graph.

faces2triangles(faces)[source]#

Convert face to their corresponding triangles

triangle2face_index(triangle_idx)[source]#

Convert triangle index to face index

face2triangle_index(face_idx)[source]#

Convert face index to triangle index

build_trimesh()[source]#

return Trimesh instance from the current nodes and faces

query_edges_from_faces(receiver_mesh: Mesh) ndarray[tuple[Any, ...], dtype[_ScalarT]][source]#

Get edges connecting nodes of the nearest face to receiver nodes.

This method retrieves the edges that connect the nodes of the nearest face in the current mesh to the nodes in the provided receiver mesh.

Parameters:

receiver_mesh – The mesh object that contains the receiver nodes.

Returns:

An NDArray containing the edges that connect the nodes of the nearest face to the receiver nodes, shape (N,2)

query_edges_from_radius(receiver_mesh: Mesh, radius: float) ndarray[tuple[Any, ...], dtype[_ScalarT]][source]#

Get edges connecting nearest neighboring nodes to receiver nodes.

Parameters:
  • receiver_mesh – The mesh object to query edges from.

  • radius – The radius within which to find neighboring nodes.

Returns:

Array of edges connecting nearest neighboring nodes to receiver

nodes, shaped (N,2)

query_edges_from_neighbors(receiver_mesh, n_neighbors)[source]#

Return edges connecting nearest neighboring nodes to receiver nodes.

Parameters:
  • receiver_mesh – The mesh object to receive edges from.

  • n_neighbors – The number of nearest neighbors to consider.

Returns:

Array of edges connecting nearest neighboring nodes to receiver

nodes, shaped (N,2)

class sphedron.mesh.base.NodesOnlyMesh(nodes_latlong)[source]#

Bases: Mesh

A mesh defined only by a set of nodes, with no real face connectivity.

This class does not support the refinement creation pattern (from_base/from_graph). Use it when you only need node positions on the sphere.

Parameters:

nodes_latlong – Array of (latitude, longitude) pairs in degrees, shape (N, 2).

class sphedron.mesh.base.TriangularMesh(nodes: ndarray[tuple[Any, ...], dtype[_ScalarT]], faces: ndarray[tuple[Any, ...], dtype[_ScalarT]])[source]#

Bases: Mesh

Base class for meshes with triangular faces.

Provides triangle-based refinement via sphedron.refine.refine_triangles().

Methods

refine(nodes, faces, factor[, use_angle])

Refine a triangular mesh by subdividing each face.

faces2triangles(faces)

Triangles are the faces themselves for triangular meshes.

triangle2face_index(triangle_idx)

Triangle-to-face index (identity for triangular).

face2triangle_index(face_idx)

Face-to-triangle index (identity for triangular).

static refine(nodes, faces, factor, use_angle=False, **kwargs)[source]#

Refine a triangular mesh by subdividing each face.

Parameters:
  • nodes – Node coordinates, shape (N, 3).

  • faces – Triangular face indices, shape (F, 3).

  • factor – Subdivision factor per edge.

  • use_angle – Use angle-based (geodesic) interpolation.

Returns:

Tuple of (refined_nodes, refined_faces).

faces2triangles(faces: ndarray[tuple[Any, ...], dtype[_ScalarT]]) ndarray[tuple[Any, ...], dtype[_ScalarT]][source]#

Triangles are the faces themselves for triangular meshes.

triangle2face_index(triangle_idx)[source]#

Triangle-to-face index (identity for triangular).

face2triangle_index(face_idx)[source]#

Face-to-triangle index (identity for triangular).

class sphedron.mesh.base.RectangularMesh(nodes: ndarray[tuple[Any, ...], dtype[_ScalarT]], faces: ndarray[tuple[Any, ...], dtype[_ScalarT]])[source]#

Bases: Mesh

Base class for meshes with rectangular (quad) faces.

Provides rectangle-based refinement via sphedron.refine.refine_rectrangles().

Methods

refine(nodes, faces, factor[, use_angle])

Refine a rectangular mesh by subdividing each face.

faces2triangles(faces)

Split each rectangle into two triangles.

triangle2face_index(triangle_idx)

Convert triangle index to face index.

face2triangle_index(face_idx)

Convert face index to its first triangle index.

static refine(nodes, faces, factor, use_angle=False, **kwargs)[source]#

Refine a rectangular mesh by subdividing each face.

Parameters:
  • nodes – Node coordinates, shape (N, 3).

  • faces – Rectangular face indices, shape (F, 4).

  • factor – Subdivision factor per edge.

  • use_angle – Use angle-based (geodesic) interpolation.

Returns:

Tuple of (refined_nodes, refined_faces).

faces2triangles(faces: ndarray[tuple[Any, ...], dtype[_ScalarT]]) ndarray[tuple[Any, ...], dtype[_ScalarT]][source]#

Split each rectangle into two triangles.

triangle2face_index(triangle_idx)[source]#

Convert triangle index to face index.

faces2triangles stacks faces[:, [0,1,2]] then faces[:, [2,3,0]], so triangle i maps to face i % num_faces.

face2triangle_index(face_idx)[source]#

Convert face index to its first triangle index.

Refinable Meshes#

Refinable mesh classes: icosphere, octasphere, cubesphere, uniform.

class sphedron.mesh.refinables.Icosphere(nodes: ndarray[tuple[Any, ...], dtype[_ScalarT]], faces: ndarray[tuple[Any, ...], dtype[_ScalarT]])[source]#

Bases: TriangularMesh

A triangular mesh generated from a refined icosahedron. Rotation angle is chosen to match Graphcast paper.

static base() Tuple[ndarray[tuple[Any, ...], dtype[_ScalarT]], ndarray[tuple[Any, ...], dtype[_ScalarT]]][source]#

Provides the base 12-node, 20-face icosahedron geometry.

class sphedron.mesh.refinables.Octasphere(nodes: ndarray[tuple[Any, ...], dtype[_ScalarT]], faces: ndarray[tuple[Any, ...], dtype[_ScalarT]])[source]#

Bases: TriangularMesh

A triangular mesh generated from a refined octahedron.

static base() Tuple[ndarray[tuple[Any, ...], dtype[_ScalarT]], ndarray[tuple[Any, ...], dtype[_ScalarT]]][source]#

Provides the base 6-node, 8-face octahedron geometry.

class sphedron.mesh.refinables.Cubesphere(nodes: ndarray[tuple[Any, ...], dtype[_ScalarT]], faces: ndarray[tuple[Any, ...], dtype[_ScalarT]])[source]#

Bases: RectangularMesh

Represents an cubesphere mesh, square-based.

rotation_angle#

The angle used for rotating the icosphere.

rotation_axis#

The axis around which the icosphere is rotated.

static base() Tuple[ndarray[tuple[Any, ...], dtype[_ScalarT]], ndarray[tuple[Any, ...], dtype[_ScalarT]]][source]#

Create the base cube geometry.

Returns:

Tuple (nodes, faces) of shapes (8, 3) and (6, 4).

The cube layout:

    (-1,-1,1) 4------------5 (-1,1,1)
             /|           /|
            / |          / |
           /  |         /  |
 (1,-1,1) 0---|--------1 (1,1,1)
   (-1,-1,-1) 7--------|---6 (-1,1,-1)
          |  /         |  /
          | /          | /
          |/           |/
(1,-1,-1) 3------------2 (1,1,-1)
class sphedron.mesh.refinables.UniformMesh(resolution=1.0, uniform_lats: ndarray[tuple[Any, ...], dtype[_ScalarT]] | None = None, uniform_longs: ndarray[tuple[Any, ...], dtype[_ScalarT]] | None = None)[source]#

Bases: RectangularMesh

A rectangular mesh of uniformly distributed latitude and longitude.

The lat/lon grid is connected with quad faces where each cell connects four neighboring grid points. Longitude wraps around so the last column connects back to the first.

Parameters:
  • resolution – Grid spacing in degrees (default 1.0). Ignored if uniform_lats and uniform_longs are provided.

  • uniform_lats – Custom latitude values in degrees. Must be provided together with uniform_longs.

  • uniform_longs – Custom longitude values in degrees. Must be provided together with uniform_lats.

Methods

reshape(values)

Reshape flat node values back to the (lat, lon) grid layout.

reshape(values)[source]#

Reshape flat node values back to the (lat, lon) grid layout.

Parameters:

values – Flat array of shape (num_nodes,) or (num_nodes, d).

Returns:

Array of shape (n_lats, n_lons) or (n_lats, n_lons, d).

Nested Meshes#

Hierarchical nested mesh structures at multiple refinement levels.

class sphedron.mesh.nested.NestedMeshes(factors: List[int], refine_by_angle: bool = False, rotate: bool = True)[source]#

A manager for a hierarchy of meshes at increasing refinement levels.

Composes multiple Mesh objects. Individual levels are accessible via indexing (nested[i]), and convenience properties aggregate nodes, edges, and faces across the hierarchy.

Parameters:
  • factors – List of refinement factors. Each entry refines the previous level by that factor. The cumulative product gives the effective depth at each level.

  • refine_by_angle – Use angle-based (geodesic) interpolation during refinement.

  • rotate – Rotate the base mesh using the class rotation parameters.

Attributes

property finest_mesh: Mesh#

Returns the mesh at the highest refinement level.

property nodes#

Nodes of the finest (most refined) mesh.

property nodes_latlong#

Nodes of the finest mesh in latitude/longitude format (degrees).

property num_edges#

Total number of edges across all refinement levels.

property num_faces#

Total number of faces across all refinement levels.

property num_nodes#

Number of nodes in the finest mesh.

property edges: ndarray[tuple[Any, ...], dtype[int64]]#

All edges from every refinement level, concatenated.

property faces: ndarray[tuple[Any, ...], dtype[int64]]#

All faces from every refinement level, concatenated.

Methods

__getitem__(level)

Get the mesh at a specific refinement level.

__len__()

Return the number of refinement levels.

reset()

Resets the node masks on all meshes in the hierarchy.

mask_nodes(nodes_mask)

Apply a mask to nodes, propagating to all refinement levels.

build_trimesh()

Build a Trimesh from the finest mesh.

query_edges_from_faces(receiver_mesh)

Delegate face-based edge query to the finest mesh.

query_edges_from_radius(receiver_mesh, radius)

Delegate radius-based edge query to the finest mesh.

query_edges_from_neighbors(receiver_mesh, ...)

Delegate neighbor-based edge query to the finest mesh.

__getitem__(level: int) Mesh[source]#

Get the mesh at a specific refinement level.

__len__() int[source]#

Return the number of refinement levels.

reset()[source]#

Resets the node masks on all meshes in the hierarchy.

mask_nodes(nodes_mask: ndarray[tuple[Any, ...], dtype[bool]])[source]#

Apply a mask to nodes, propagating to all refinement levels.

Applies the mask to the finest mesh and propagates the masking effect to coarser meshes where applicable.

build_trimesh()[source]#

Build a Trimesh from the finest mesh.

query_edges_from_faces(receiver_mesh) ndarray[tuple[Any, ...], dtype[_ScalarT]][source]#

Delegate face-based edge query to the finest mesh.

query_edges_from_radius(receiver_mesh, radius: float) ndarray[tuple[Any, ...], dtype[_ScalarT]][source]#

Delegate radius-based edge query to the finest mesh.

query_edges_from_neighbors(receiver_mesh, n_neighbors) ndarray[tuple[Any, ...], dtype[_ScalarT]][source]#

Delegate neighbor-based edge query to the finest mesh.

class sphedron.mesh.nested.NestedIcospheres(factors: List[int], refine_by_angle: bool = False, rotate: bool = True)[source]#

Bases: NestedMeshes

Nested icospheres, refined version of the previous.

class sphedron.mesh.nested.NestedOctaspheres(factors: List[int], refine_by_angle: bool = False, rotate: bool = True)[source]#

Bases: NestedMeshes

Nested octaspheres, where self.mesh[i+1] is a refined self.meshes[i].

class sphedron.mesh.nested.NestedCubespheres(factors: List[int], refine_by_angle: bool = False, rotate: bool = True)[source]#

Bases: NestedMeshes

Nested cubespheres, where self.mesh[i+1] is a refined self.meshes[i].