Spatial Module¶
spatial ¶
DEPRECATED!!!! This module provides a kD-tree implementation but specialized to 3D. The reason why it is deprecated is that scipy.spatial contains a very flexible KDTree class that is much more generic and obviates the need for GEL's KDTree. Going forward, the KDTree may be removed from PyGEL but not from the C++ GEL API.
I3DTree ¶
kD tree specialized for 3D keys and integer values. This tree data structure is useful for storing 3D points and associated integer values - typically indices. There is also a more general kd tree in scipy.spatial if this one does not suit your needs.
Source code in pygel3d/spatial.py
insert ¶
Insert v at 3D point given by p. Insert should be called before calling build.
build ¶
Build the tree. This function call makes the tree searchable. It is assumed that all calls to insert come before calling this function.
closest_point ¶
Search for point closest to p within a max radius r. This function should only be called after build.
Source code in pygel3d/spatial.py
in_sphere ¶
Retrieve all points within a radius r of p. This function should only be called after build.
Source code in pygel3d/spatial.py
The spatial module provides spatial data structures for efficient geometric queries.
I3DTree Class¶
The I3DTree class is a kD-tree specialized for mapping 3D points to integers (typically array indices).
Creating a Tree¶
from pygel3d import I3DTree
import numpy as np
# Create tree
tree = I3DTree()
# Insert points with associated indices
points = np.random.rand(1000, 3)
for i, point in enumerate(points):
tree.insert(point, i)
Tree Operations¶
Insertion¶
tree.insert(point, value)- Insert a point with an associated integer value
Queries¶
tree.closest_point(query_point)- Find nearest point, returns associated valuetree.in_sphere(center, radius)- Find all points within radius
Information¶
tree.size()- Number of points in tree
MeshDistance Class¶
The MeshDistance class enables efficient distance computations to triangle meshes.
Creating a Distance Object¶
from pygel3d import MeshDistance
import pygel3d.hmesh as hmesh
# Load mesh
m = hmesh.load("model.obj")
# Create distance object
dist = MeshDistance(m)
Distance Queries¶
Point Queries¶
dist.signed_distance(point)- Signed distance to mesh (negative inside)dist.distance(point)- Unsigned distance to meshdist.ray_inside_test(point, direction)- Test if ray from point hits mesh
Information¶
- Returns scalar distance values
- Signed distance uses mesh orientation (closed meshes only)
Example Usage¶
k-Nearest Neighbors¶
from pygel3d import I3DTree
import numpy as np
# Generate random points
points = np.random.rand(1000, 3) * 10
# Build tree
tree = I3DTree()
for i, p in enumerate(points):
tree.insert(p, i)
# Find nearest point to query
query = [5.0, 5.0, 5.0]
nearest_idx = tree.closest_point(query)
nearest_point = points[nearest_idx]
print(f"Nearest point to {query}: {nearest_point}")
print(f"Index: {nearest_idx}")
Points in Sphere¶
from pygel3d import I3DTree
import numpy as np
# Build tree
tree = I3DTree()
points = np.random.rand(1000, 3) * 10
for i, p in enumerate(points):
tree.insert(p, i)
# Find all points within radius
center = [5.0, 5.0, 5.0]
radius = 2.0
indices = tree.in_sphere(center, radius)
print(f"Found {len(indices)} points within radius {radius}")
Distance Field Computation¶
from pygel3d import MeshDistance
import pygel3d.hmesh as hmesh
import numpy as np
# Load mesh
m = hmesh.load("bunny.obj")
# Create distance object
dist = MeshDistance(m)
# Create grid
grid_size = 50
x = np.linspace(-1, 1, grid_size)
y = np.linspace(-1, 1, grid_size)
z = np.linspace(-1, 1, grid_size)
# Compute distance field
distances = np.zeros((grid_size, grid_size, grid_size))
for i, xi in enumerate(x):
for j, yj in enumerate(y):
for k, zk in enumerate(z):
point = [xi, yj, zk]
distances[i, j, k] = dist.signed_distance(point)
print(f"Distance field shape: {distances.shape}")
print(f"Min distance: {distances.min()}")
print(f"Max distance: {distances.max()}")
Inside/Outside Testing¶
from pygel3d import MeshDistance
import pygel3d.hmesh as hmesh
# Load closed mesh
m = hmesh.load("sphere.obj")
dist = MeshDistance(m)
# Test points
test_points = [
[0, 0, 0], # Inside
[10, 10, 10], # Outside
[0.5, 0.5, 0.5] # Near surface
]
for point in test_points:
d = dist.signed_distance(point)
status = "inside" if d < 0 else "outside"
print(f"Point {point}: {status} (distance: {abs(d):.4f})")
Performance Tips¶
- Tree Construction: Build the tree once and reuse for multiple queries
- Batch Queries: Use vectorized operations when possible
- Mesh Simplification: For distance queries, simpler meshes are faster
- Precision: Consider using lower precision for large-scale computations