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.