Constructor
Domain(*args, **kwargs)
Parameters
Parameter | Type | Description |
---|---|---|
*args |
variable |
Can be:
|
**kwargs |
dict | Additional keyword arguments passed to data processing methods |
Attributes
Attribute | Type | Description |
---|---|---|
points |
np.ndarray | Point cloud defining the domain (n×d array) |
normals |
np.ndarray | Normal vectors at each point (n×d array) |
boundary |
pv.PolyData | Boundary mesh of the domain |
mesh |
pv.UnstructuredGrid | Interior tetrahedral/triangular mesh |
patches |
list | List of Patch objects for implicit function |
functions |
list | List of implicit functions |
n |
int | Number of points |
d |
int | Spatial dimension (2 or 3) |
characteristic_length |
float | Characteristic length scale of the domain |
area |
float | Surface area (3D) or perimeter (2D) |
volume |
float | Volume (3D) or area (2D) |
convexity |
float | Ratio of domain volume to convex hull volume |
Methods
Core Methods
set_data(*args, **kwargs)
Set the data for the domain from point-wise data or a PyVista object.
Parameters
*args
: Points array, points and normals arrays, or PyVista object**kwargs
: Additional processing parameters
create(**kwargs)
Create patches for the domain. This is the first step in building the implicit function.
Parameters
**kwargs
: Parameters passed to the allocation algorithm
solve(**kwargs)
Solve the individual patch interpolation problems prior to blending.
build(**kwargs)
Build the implicit function describing the domain.
Parameters
resolution
(int, default=25): Grid resolution for boundary extractionskip_boundary
(bool, default=False): Skip boundary generation
Evaluation Methods
__call__(points, **kwargs)
Evaluate the implicit function at given points.
Parameters
points
(np.ndarray): Points to evaluate (m×d array)k
(int, default=1): Number of nearest patches to considernormalize
(bool, default=True): Normalize output valuestolerance
(float): Tolerance for patch selection
Returns
values
(np.ndarray): Implicit function values (m×1 array)
within(points, level=0, **kwargs)
Determine if points are within the domain.
Returns
inside
(np.ndarray): Boolean array indicating if points are inside
Mesh Generation
get_boundary(resolution, **kwargs)
Extract the boundary surface of the domain.
Parameters
resolution
(int): Grid resolution for marching cubes/squaresget_largest
(bool, default=True): Reserved (current implementation always returns the largest connected component)
Returns
boundary
(pv.PolyData): Boundary meshgrid
(pv.ImageData): Volumetric grid used for extraction
get_interior(verbose=False, **kwargs)
Generate tetrahedral (3D) or triangular (2D) mesh of the interior.
Parameters
verbose
(bool): Print mesh generation progress**kwargs
: Parameters passed to TetGen/Triangle
Returns
mesh
(pv.UnstructuredGrid): Interior mesh
Point Sampling
get_interior_points(n, tree=None, volume_threshold=None, threshold=None, method=None, implicit_range=(-1.0, 0.0), **kwargs)
Sample random points from the domain interior.
Parameters
n
(int): Number of points to sampletree
(KDTree, optional): Existing tree structure for collision detectionvolume_threshold
(float, optional): Maximum distance from treethreshold
(float, optional): Minimum distance from treemethod
(str, optional): Sampling method ('implicit_only', 'preallocate', or default)implicit_range
(tuple): Range of implicit function values to accept
Returns
points
(np.ndarray): Sampled points (n×d array)cells
(np.ndarray): Cell indices for each point
get_boundary_points(n, method=None, **kwargs)
Sample random points from the domain boundary.
Parameters
n
(int): Number of points to samplemethod
(str, optional): Sampling method
Returns
points
(np.ndarray): Sampled boundary points (n×d array)
Utility Methods
set_random_seed(seed)
Set the random seed for reproducible sampling.
set_random_generator()
Initialize the random number generator with the set seed.
Operators
domain1 + domain2
Union of two domains (set union operation).
# Create union of two domains
combined_domain = domain1 + domain2
domain1 - domain2
Difference of two domains (set difference operation).
# Subtract domain2 from domain1
difference_domain = domain1 - domain2
Examples
Creating a Domain from STL File
import pyvista as pv
from svv.domain import Domain
# Load STL file
mesh = pv.read('vessel.stl')
# Create domain
domain = Domain(mesh)
# Build implicit function with custom resolution
domain.create()
domain.solve()
domain.build(resolution=30)
# Get mesh statistics
print(f"Domain volume: {domain.volume:.2f}")
print(f"Domain surface area: {domain.area:.2f}")
print(f"Convexity: {domain.convexity:.3f}")
Boolean Operations on Domains
# Create two domains
sphere1 = pv.Sphere(center=(0, 0, 0), radius=1.0)
domain1 = Domain(sphere1)
domain1.create()
domain1.solve()
domain1.build()
sphere2 = pv.Sphere(center=(0.5, 0, 0), radius=0.8)
domain2 = Domain(sphere2)
domain2.create()
domain2.solve()
domain2.build()
# Create union (merged domains)
union_domain = domain1 + domain2
# Create difference (domain1 with hole from domain2)
diff_domain = domain1 - domain2
# Evaluate at test points
test_points = np.random.randn(100, 3)
union_values = union_domain(test_points)
diff_values = diff_domain(test_points)
Sampling Points with Collision Avoidance
from scipy.spatial import cKDTree
# Create domain
domain = Domain(mesh)
domain.create()
domain.solve()
domain.build()
# Create existing tree structure (e.g., from vessel centerlines)
existing_points = np.array([[0, 0, 0], [1, 0, 0], [0, 1, 0]])
tree = cKDTree(existing_points)
# Sample points avoiding existing structure
new_points, cells = domain.get_interior_points(
n=1000,
tree=tree,
threshold=0.5, # Minimum distance from existing points
volume_threshold=5.0 # Maximum distance from existing points
)
# Sample boundary points
boundary_points = domain.get_boundary_points(n=500)
Notes
Implicit Function: The domain uses radial basis function (RBF) interpolation to create a smooth implicit function representation. Points inside the domain have negative values, points outside have positive values, and the boundary is at the zero level set.
Memory Usage: For large point clouds or high-resolution meshes, the implicit function construction can be memory-intensive. Consider using lower resolution for initial testing.
Performance: The domain uses optimized Cython routines for point sampling (c_sample.pyx
) and allocation (c_allocate.pyx
). These provide significant speedups for large-scale operations.
create()
→ solve()
→ build()
to properly construct the implicit function before using evaluation or sampling methods.
See Also
svv.domain.Patch
- Individual patch for RBF interpolationsvv.tree.Tree
- Vascular tree generation using domainssvv.forest.Forest
- Collection of trees within a domain