API Reference

Functions

isoext.marching_cubes(grid: isoext.isoext_ext.Grid, level: float = 0.0, method: str = 'nagae') tuple

Extract an iso-surface from a grid using the Marching Cubes algorithm.

Parameters:
  • grid – The input grid (UniformGrid or SparseGrid) containing scalar values.

  • level – The iso-value at which to extract the surface. Default is 0.0.

  • method – The marching cubes variant to use. Options are ‘nagae’ (default) or ‘lorensen’.

Returns:

A tuple (vertices, faces) where vertices is an (N, 3) float32 tensor of vertex positions and faces is an (M, 3) uint32 tensor of triangle indices.

isoext.dual_contouring(grid: isoext.isoext_ext.Grid, level: float = 0.0, intersection: isoext.isoext_ext.Intersection | None = None, reg: float = 0.009999999776482582, svd_tol: float = 9.999999974752427e-07) tuple

Extract an iso-surface using the Dual Contouring algorithm.

Dual Contouring produces meshes with better-placed vertices than Marching Cubes, especially for sharp features. It solves a QEF (Quadric Error Function) per cell to find optimal vertex positions.

Parameters:
  • grid – The input grid containing scalar values.

  • level – The iso-value. Default is 0.0.

  • intersection – Optional Intersection data from get_intersection(). If not provided, intersections are computed automatically. If provided but normals not set, normals are computed automatically.

  • reg – Regularization weight for the QEF solver. Default is 0.01.

  • svd_tol – SVD tolerance for the QEF solver. Default is 1e-6.

Returns:

A tuple (vertices, faces) where vertices is an (N, 3) float32 tensor and faces is an (M, 3) int32 tensor of triangle indices.

isoext.get_intersection(grid: isoext.isoext_ext.Grid, level: float = 0.0, compute_normals: bool = False) isoext.isoext_ext.Intersection

Compute edge-surface intersections for dual contouring.

Finds where grid edges cross the iso-surface and computes intersection points using linear interpolation.

Parameters:
  • grid – The input grid containing scalar values.

  • level – The iso-value. Default is 0.0.

  • compute_normals – If True, compute normals from grid values. Default is False.

Returns:

An Intersection object containing points (and normals if compute_normals=True).

isoext.make_grid(aabb, res, device='cuda')

Create a uniform grid from an axis-aligned bounding box.

Parameters:
  • aabb (list[float]) – Axis-aligned bounding box as [x_min, y_min, z_min, x_max, y_max, z_max]

  • res (int | list[int]) – Resolution, either a single int or list of 3 ints for [x_res, y_res, z_res]

  • device (str) – Device to create the grid on (default: “cuda”)

Returns:

Grid tensor with shape (x_res, y_res, z_res, 3)

Return type:

Tensor

isoext.write_obj(obj_path, v, f)

Write vertices and faces to an OBJ file.

Parameters:
  • obj_path (str) – Path to the output OBJ file

  • v (Tensor) – Tensor of vertices with shape (N, 3)

  • f (Tensor) – Tensor of face indices with shape (M, 3)

Return type:

None

Classes

UniformGrid

class isoext.UniformGrid(shape, aabb_min=[-1, -1, -1], aabb_max=[1, 1, 1], default_value=float_max)

A dense uniform grid for storing scalar values.

The grid divides a 3D axis-aligned bounding box into a regular lattice of cells. Each cell has 8 corner points where scalar values are stored.

Parameters:
  • shape (Sequence[int]) – The number of cells in each dimension (x, y, z).

  • aabb_min (Sequence[float]) – The minimum corner of the bounding box.

  • aabb_max (Sequence[float]) – The maximum corner of the bounding box.

  • default_value (float) – Initial scalar value for all points.

UniformGrid.get_points(self) torch.Tensor[dtype=float32, order='C', device='cuda']

Return the 3D coordinates of all grid points as a (X, Y, Z, 3) float32 tensor.

UniformGrid.get_values(self) torch.Tensor[dtype=float32, order='C', device='cuda']

Return the scalar values as a (X, Y, Z) float32 tensor.

UniformGrid.set_values(self, new_values: torch.Tensor[dtype=float32, shape=(*, *, *), order='C', device='cuda']) None

Set the scalar values from a (X, Y, Z) float32 tensor.

SparseGrid

class isoext.SparseGrid(shape, aabb_min=[-1, -1, -1], aabb_max=[1, 1, 1], default_value=float_max)

A sparse adaptive grid for storing scalar values.

Unlike UniformGrid, SparseGrid only allocates memory for cells that are explicitly added. This is useful for large domains where only a small region contains the iso-surface.

Parameters:
  • shape (Sequence[int]) – The maximum number of cells in each dimension (x, y, z).

  • aabb_min (Sequence[float]) – The minimum corner of the bounding box.

  • aabb_max (Sequence[float]) – The maximum corner of the bounding box.

  • default_value (float) – Default scalar value for unset points.

SparseGrid.get_num_cells(self) int

Return the number of active cells in the grid.

SparseGrid.get_num_points(self) int

Return the number of points in active cells (num_cells * 8).

SparseGrid.get_points(self) torch.Tensor[dtype=float32, order='C', device='cuda']

Return the 3D coordinates of points in active cells as an (N, 8, 3) float32 tensor.

SparseGrid.get_values(self) torch.Tensor[dtype=float32, order='C', device='cuda']

Return the scalar values at active cell corners as an (N, 8) float32 tensor.

SparseGrid.set_values(self, new_values: torch.Tensor[dtype=float32, shape=(*, 8), order='C', device='cuda']) None

Set the scalar values from an (N, 8) float32 tensor.

SparseGrid.get_cells(self) torch.Tensor[dtype=uint32, order='C', device='cuda']

Return the cell connectivity as point indices.

SparseGrid.add_cells(self, new_cell_indices: torch.Tensor[dtype=int32, shape=(*), order='C', device='cuda']) None

Add cells to the grid by their linear indices.

Parameters:

new_cell_indices – 1D int32 tensor of cell indices to add.

SparseGrid.remove_cells(self, new_cell_indices: torch.Tensor[dtype=int32, shape=(*), order='C', device='cuda']) None

Remove cells from the grid by their linear indices.

Parameters:

new_cell_indices – 1D int32 tensor of cell indices to remove.

SparseGrid.get_cell_indices(self) torch.Tensor[dtype=int32, order='C', device='cuda']

Return the linear indices of all active cells as a 1D int32 tensor.

SparseGrid.get_potential_cell_indices(self, arg: int, /) list[torch.Tensor[dtype=int32, order='C', device='cuda']]

Get potential cell indices in chunks for memory-efficient processing.

Parameters:

chunk_size – Maximum number of cells per chunk.

Returns:

A list of 1D int32 tensors, each containing cell indices for a chunk.

SparseGrid.get_points_by_cell_indices(self, cell_indices: torch.Tensor[dtype=int32, shape=(*), order='C', device='cuda']) torch.Tensor[dtype=float32, order='C', device='cuda']

Get the corner points of specified cells.

Parameters:

cell_indices – 1D int32 tensor of cell indices.

Returns:

An (N, 8, 3) float32 tensor of corner coordinates.

SparseGrid.filter_cell_indices(self, cell_indices: torch.Tensor[dtype=int32, shape=(*), order='C', device='cuda'], values: torch.Tensor[dtype=float32, shape=(*, 8), order='C', device='cuda'], level: float = 0.0) torch.Tensor[dtype=int32, order='C', device='cuda']

Filter cells to keep only those that cross the iso-surface.

Parameters:
  • cell_indices – 1D int32 tensor of cell indices to filter.

  • values – (N, 8) float32 tensor of scalar values at cell corners.

  • level – The iso-value to check against. Default is 0.0.

Returns:

A 1D int32 tensor of cell indices that cross the iso-surface.

Intersection

class isoext.Intersection

Stores edge-surface intersection points and normals for dual contouring.

Created by get_intersection() and used as input to dual_contouring(). You can modify the normals to control the surface reconstruction.

get_normals

Return the surface normals at intersection points as an (N, 3) float32 tensor.

get_points

Return the intersection points as an (N, 3) float32 tensor.

has_normals

Return True if normals have been set or computed.

set_normals

Set custom normals for the intersection points.

Parameters:

new_normals – (N, 3) float32 tensor of normal vectors.