Methods

All methods infer float precision based on the input (32bit or 64bit).

pysplashsurf.check_mesh_consistency(grid, mesh, *, check_closed: bool, check_manifold: bool, debug: bool)

Checks the consistency of the mesh (currently checks for holes, non-manifold edges and vertices) and returns a string with debug information in case of problems

Parameters:
grid: UniformGridF32 | UniformGridF64

Uniform grid object

mesh: TriMesh3dF32 | TriMesh3dF64 | TriMeshWithDataF32 | TriMeshWithDataF64

Triangular mesh object

check_closed: bool

Flag to check for closed mesh

check_manifold: bool

Flag to check for manifold mesh

debug: bool

Flag to enable debug output

pysplashsurf.convert_tris_to_quads(mesh, *, non_squareness_limit: float, normal_angle_limit_rad: float, max_interior_angle: float)

Merges triangles sharing an edge to quads if they fulfill the given criteria

Parameters:
mesh: TriMesh3dF32 | TriMesh3dF64 | TriMeshWithDataF32 | TriMeshWithDataF64

Triangular mesh object

When called with a MeshWithData Object, the resulting MixedTriQuadMeshWithData won’t inherit the cell attributes from the input.

non_squareness_limit: float

Non-squareness limit

normal_angle_limit_rad: float

Normal angle limit in radians

max_interior_angle: float

Maximum interior angle in radians

Returns:
MixedTriQuadMesh3dF32 | MixedTriQuadMesh3dF64 | MixedTriQuadMeshWithDataF32 | MixedTriQuadMeshWithDataF64

Mixed triangular and quadrilateral mesh object

pysplashsurf.create_aabb_object(aabb_min, aabb_max)

Create the corresponding AABB object to a set of min and max values

Parameters:
aabb_min: np.ndarray

Smallest corner of the axis-aligned bounding box

aabb_max: np.ndarray

Largest corner of the axis-aligned bounding box

Returns:
Aabb3dF32 | Aabb3dF64

Aabb object

pysplashsurf.create_aabb_object_from_points(points)

Create the corresponding AABB object to a set of points

Parameters:
points: np.ndarray

2-dimensional array containing all point positions [[ax, ay, az], [bx, by, bz], …]

Returns:
Aabb3dF32 | Aabb3dF64

Aabb object

pysplashsurf.create_mesh_with_data_object(mesh)

Create the corresponding mesh with data object to a mesh object

Parameters:
mesh: TriMesh3dF64 | TriMesh3dF32 | MixedTriQuadMesh3dF64 | MixedTriQuadMesh3dF32

Mesh object to convert

Returns:
TriMeshWithDataF64 | TriMeshWithDataF32 | MixedTriQuadMeshWithDataF64 | MixedTriQuadMeshWithDataF32

Mesh with data object

pysplashsurf.create_sph_interpolator_object(particle_positions, particle_densities, particle_rest_mass, compact_support_radius)

Create the corresponding SPH interpolator object to a set of particle data

Parameters:
particle_positions: np.ndarray

2-dimensional array containing all particle positions [[ax, ay, az], [bx, by, bz], …]

particle_densities: np.ndarray

1-dimensional array containing all particle densities

particle_rest_mass: float

Rest mass of the particles

compact_support_radius: float

Compact support radius of the SPH kernel

Returns:
SphInterpolatorF32 | SphInterpolatorF64

SphInterpolator object

pysplashsurf.decimation(mesh, keep_vertices: bool = False)

Barnacle decimation

For details see “Weighted Laplacian Smoothing for Surface Reconstruction of Particle-based Fluids” (Löschner, Böttcher, Jeske, Bender; 2023).

Parameters:
mesh: TriMesh3dF32 | TriMesh3dF64 | TriMeshWithDataF32 | TriMeshWithDataF64

Mesh object to simplify

keep_vertices: bool

Flag to keep vertices

Returns:
list

vertex connectivity list of the simplified mesh

pysplashsurf.marching_cubes_cleanup(mesh, grid, max_iter: int = 5, keep_vertices: bool = False)

Mesh simplification designed for marching cubes surfaces meshes inspired by the “Compact Contouring”/”Mesh displacement” approach by Doug Moore and Joe Warren

See Moore and Warren: “Mesh Displacement: An Improved Contouring Method for Trivariate Data” (1991) or Moore and Warren: “Compact Isocontours from Sampled Data” in “Graphics Gems III” (1992).

Parameters:
mesh: TriMesh3dF32 | TriMesh3dF64 | TriMeshWithDataF32 | TriMeshWithDataF64

Mesh object to simplify

grid: UniformGridF32 | UniformGridF64

Uniform grid object that was used to construct the mesh

max_iter: int

Maximum number of iterations

keep_vertices: bool

Flag to keep vertices

Returns:
list

vertex connectivity list of the simplified mesh

pysplashsurf.neighborhood_search_spatial_hashing_parallel(domain, particle_positions: ndarray, search_radius: float)

Performs a neighborhood search (multi-threaded implementation)

Returns the indices of all neighboring particles in the given search radius per particle as a list[list[int]].

Parameters:
domain: Aabb3dF32 | Aabb3dF64

Axis-aligned bounding box of the domain

particle_positions: np.ndarray

2D-Array of particle positions

search_radius: float

Search radius

pysplashsurf.par_laplacian_smoothing_inplace(mesh, vertex_connectivity: list[list[int]], iterations: int, beta: float, weights: list[float])

Laplacian Smoothing with feature weights

Move each vertex towards the mean position of its neighbors.

Factor beta in [0;1] proportional to amount of smoothing (for beta=1 each vertex is placed at the mean position).

Additionally, feature weights can be specified to apply a varying amount of smoothing over the mesh.

Parameters:
mesh: TriMesh3dF32 | TriMesh3dF64 | TriMeshWithDataF32 | TriMeshWithDataF64

Mesh object to smooth

vertex_connectivity: list[list[int]]

Vertex connectivity list

iterations: int

Number of iterations

beta: float

Smoothing factor

weights: list[float]

Feature weights for the vertices

pysplashsurf.par_laplacian_smoothing_normals_inplace(normals: ndarray, vertex_connectivity: list[list[int]], iterations: int)

Laplacian smoothing of a normal field

Parameters:
normals: np.ndarray

2D-Array of vertex normals to smooth

vertex_connectivity: list[list[int]]

Vertex connectivity list

iterations: int

Number of iterations

pysplashsurf.reconstruct_surface(particles, *, particle_radius: float = 0.025, rest_density: float = 1000.0, smoothing_length: float = 2.0, cube_size: float = 0.5, iso_surface_threshold: float = 0.6, enable_multi_threading: bool = False, global_neighborhood_list: bool = False, subdomain_grid: bool = False, subdomain_num_cubes_per_dim: int = 64, aabb_min=None, aabb_max=None)

Reconstruct the surface from only particle positions

Performs a marching cubes surface construction of the fluid represented by the given particle positions

Parameters:
particles: np.ndarray

2-dimensional array containing all particle positions [[ax, ay, az], [bx, by, bz], …]

particle_radius: float, optional (default=0.025)

Particle radius

rest_density: float

Rest density of the fluid

smoothing_length: float

Smoothing length of the fluid

cube_size: float

Size of the cubes used in the uniform grid

iso_surface_threshold: float

Threshold for the iso surface

enable_multi_threading: bool

Multi-threading flag

global_neighborhood_list: bool

Global neighborhood list flag

subdomain_grid: bool

Enable spatial decomposition using a regular grid-based approach

subdomain_num_cubes_per_dim: int

Each subdomain will be a cube consisting of this number of MC cube cells along each coordinate axis

aabb_min: np.ndarray

Smallest corner of the axis-aligned bounding box

aabb_max: np.ndarray

Largest corner of the axis-aligned bounding box

Returns:
SurfaceReconstructionF32 | SurfaceReconstructionF64

SurfaceReconstruction object containing the reconstructed mesh and used grid

pysplashsurf.reconstruction_pipeline(particles, *, attributes_to_interpolate={}, particle_radius, rest_density=1000.0, smoothing_length=2.0, cube_size, iso_surface_threshold=0.6, enable_multi_threading=True, check_mesh_closed=False, check_mesh_manifold=False, check_mesh_orientation=False, check_mesh_debug=False, mesh_smoothing_weights=False, sph_normals=False, mesh_smoothing_weights_normalization=13.0, mesh_smoothing_iters=None, normals_smoothing_iters=None, mesh_cleanup=False, mesh_cleanup_snap_dist=None, decimate_barnacles=False, keep_vertices=False, compute_normals=False, output_raw_normals=False, output_raw_mesh=False, output_mesh_smoothing_weights=False, mesh_aabb_clamp_vertices=False, subdomain_grid=True, subdomain_num_cubes_per_dim=64, aabb_min=None, aabb_max=None, mesh_aabb_min=None, mesh_aabb_max=None, generate_quads=False, quad_max_edge_diag_ratio=1.75, quad_max_normal_angle=10.0, quad_max_interior_angle=135.0)

Surface reconstruction based on particle positions with subsequent post-processing

Parameters:
particles: np.ndarray

2-dimensional array containing all particle positions [[ax, ay, az], [bx, by, bz], …]

attributes_to_interpolate: dict

Dictionary containing all attributes to interpolate. The keys are the attribute names and the values are the corresponding 1D/2D arrays.

The arrays must have the same length as the number of particles.

Supported array types are 2D float32/float64 arrays for vector attributes and 1D uint64/float32/float64 arrays for scalar attributes.

particle_radius: float

Particle radius

rest_density: float

Rest density of the fluid

smoothing_length: float

Smoothing length of the fluid in multiples of the particle radius (compact support radius of SPH kernel will be twice the smoothing length)

cube_size: float

Size of the cubes used for the marching cubes grid in multiples of the particle radius

iso_surface_threshold: float

Threshold for the iso surface

enable_multi_threading: bool

Multi-threading flag

check_mesh_closed: bool

Enable checking the final mesh for holes

check_mesh_manifold: bool

Enable checking the final mesh for non-manifold edges and vertices

check_mesh_orientation: bool

Enable checking the final mesh for inverted triangles (compares angle between vertex normals and adjacent face normals)

check_mesh_debug: bool

Enable additional debug output for the check-mesh operations (has no effect if no other check-mesh option is enabled)

sph_normals: bool

Flag to compute normals using SPH interpolation instead of geometry-based normals.

mesh_smoothing_weights: bool

Flag to compute mesh smoothing weights

This implements the method from “Weighted Laplacian Smoothing for Surface Reconstruction of Particle-based Fluids” (Löschner, Böttcher, Jeske, Bender; 2023).

mesh_smoothing_weights_normalization: float

Normalization factor for the mesh smoothing weights

mesh_smoothing_iters: int

Number of iterations for the mesh smoothing

normals_smoothing_iters: int

Number of iterations for the normal smoothing

mesh_cleanup: bool

Flag to perform mesh cleanup

This implements the method from “Compact isocontours from sampled data” (Moore, Warren; 1992)

mesh_cleanup_snap_dist: float

If MC mesh cleanup is enabled, vertex snapping can be limited to this distance relative to the MC edge length (should be in range of [0.0,0.5])

decimate_barnacles: bool

Flag to perform barnacle decimation

For details see “Weighted Laplacian Smoothing for Surface Reconstruction of Particle-based Fluids” (Löschner, Böttcher, Jeske, Bender; 2023).

keep_vertices: bool

Flag to keep any vertices without connectivity resulting from mesh cleanup or decimation step

compute_normals: bool

Flag to compute normals

If set to True, the normals will be computed and stored in the mesh.

output_mesh_smoothing_weights: bool

Flag to store the mesh smoothing weights if smoothing weights are computed.

output_raw_normals: bool

Flag to output the raw normals in addition to smoothed normals if smoothing of normals is enabled

output_raw_mesh: bool

When true, also return the SurfaceReconstruction object with no post-processing applied

mesh_aabb_clamp_vertices: bool

Flag to clamp the vertices of the mesh to the AABB

subdomain_grid: bool

Enables spatial decomposition using a regular grid-based approach

subdomain_num_cubes_per_dim: int

Each subdomain will be a cube consisting of this number of MC cube cells along each coordinate axis

aabb_min: np.ndarray

Smallest corner of the axis-aligned bounding box

aabb_max: np.ndarray

Largest corner of the axis-aligned bounding box

mesh_aabb_min: np.ndarray

Smallest corner of the axis-aligned bounding box for the mesh

mesh_aabb_max: np.ndarray

Largest corner of the axis-aligned bounding box for the mesh

generate_quads: bool

Enable trying to convert triangles to quads if they meet quality criteria

quad_max_edge_diag_ratio: float

Maximum allowed ratio of quad edge lengths to its diagonals to merge two triangles to a quad (inverse is used for minimum)

quad_max_normal_angle: float

Maximum allowed angle (in degrees) between triangle normals to merge them to a quad

quad_max_interior_angle: float

Maximum allowed vertex interior angle (in degrees) inside a quad to merge two triangles to a quad

Returns:
tuple[TriMeshWithDataF32 | TriMeshWithDataF64 | MixedTriQuadMeshWithDataF32 | MixedTriQuadMeshWithDataF64, Optional[SurfaceReconstructionF32] | Optional[SurfaceReconstructionF64]]

Mesh with data object and SurfaceReconstruction object containing the reconstructed mesh and used grid

pysplashsurf.write_to_file(mesh_with_data, filename, file_format=None, consume_object=False)

Write the mesh and its attributes to a file using meshio

Parameters:
mesh: TriMeshWithDataF64 | TriMeshWithDataF32 | MixedTriQuadMeshWithDataF64 | MixedTriQuadMeshWithDataF32

Mesh with data object to write

filename: Any

File path for the output file

file_format: str | None

File format for the output file, generally also derived from filename

consume_object: bool

Flag for specifying whether the MeshWithData object should be consumed for a faster execution. Only consumes the mesh field.