Skip to content

Examples

This page provides complete, runnable examples demonstrating common PyGEL3D workflows.

Basic Mesh Processing

Load, Process, and Save

import pygel3d.hmesh as hmesh
from sys import argv

def print_stats(m):
    # Print statistics
    print(f"Vertices: {len(m.vertices())}")
    print(f"Faces: {len(m.faces())}")
    print(f"Valid: {hmesh.valid(m)}")
    print(f"Closed: {hmesh.closed(m)}")

# Load mesh
m = hmesh.load(argv[1])
print_stats(m)

# Close holes and clean
hmesh.close_holes(m)
hmesh.triangulate(m)
hmesh.remove_caps(m)
hmesh.remove_needles(m)

# Print statistics after cleaning
print("After cleaning:")
print_stats(m)

# Smooth
hmesh.taubin_smooth(m,30)

# Save result
hmesh.save(argv[2], m)

Mesh Simplification Pipeline

import pygel3d.hmesh as hmesh
import pygel3d.gl_display as gl
from sys import argv

# Load high-resolution mesh
m = hmesh.load(argv[1])
original_faces = len(m.faces())

# Simplify to 5% of original faces
hmesh.quadric_simplify(m, keep_fraction=0.05)
simplified_faces = len(m.faces())

print(f"Reduced from {original_faces} to {simplified_faces} faces")

# Visualize result
viewer = gl.Viewer()
viewer.display(m, mode='w', bg_col=(1,1,1), smooth=False)

Mesh Analysis

Curvature Visualization

import pygel3d.hmesh as hmesh
import pygel3d.gl_display as gl
from sys import argv

# Load mesh
m = hmesh.load(argv[1])

# Compute mean curvature at each vertex
curvatures = [m.mean_curvature(v) for v in m.vertices()]

# Display with color-coded curvature
viewer = gl.Viewer()
viewer.display(m, mode='s', data=curvatures)

Topology Analysis

import pygel3d.hmesh as hmesh
from sys import argv

def analyze_mesh(filename):
    m = hmesh.load(filename)

    # Topology
    components = hmesh.analyze_topology(m)
    for i,comp in enumerate(components):
        print(f"Component {i+1}:")
        print(f"- Vertices: {comp['V']}")
        print(f"- Edges: {comp['E']}")
        print(f"- Faces: {comp['F']}")
        print(f"- Number of boundary curves: {comp['b']}")
        print(f"- Genus: {comp['g']}")

    # Geometry
    bbox_min, bbox_max = hmesh.bbox(m)
    print(f"  Bounding box: {bbox_min} to {bbox_max}")

    sphere_center, sphere_radius = hmesh.bsphere(m)
    print(f"  Bounding sphere: center {sphere_center}, radius {sphere_radius}")

    print(f"  Total area: {hmesh.area(m):.4f}")
    if hmesh.closed(m):
        print(f"  Volume: {hmesh.volume(m):.4f}")

    # Edge statistics
    avg_len = hmesh.average_edge_length(m)
    med_len = hmesh.median_edge_length(m)
    print(f"  Average edge length: {avg_len:.4f}")
    print(f"  Median edge length: {med_len:.4f}")

# Analyze a mesh
analyze_mesh(argv[1])

Graph Processing

Skeleton Extraction and Visualization

from sys import argv
import pygel3d.hmesh as hmesh
import pygel3d.graph as graph
import pygel3d.gl_display as gl

# Load mesh
m = hmesh.load(argv[1])

# Extract graph
g = graph.from_mesh(m)
s = graph.MSLS_skeleton(g)


# Process skeleton
graph.prune(s)
l = s.average_edge_length()
graph.edge_contract(s, dist_thresh = l * 0.05)
graph.smooth(s, num_iter=10, alpha=0.1) 

# Convert to mesh for visualization
skeleton_mesh = hmesh.skeleton_to_feq(s, node_radii = 0.25 * l)

# Save
graph.save("skeleton.graph", s)
hmesh.save("skeleton.obj", skeleton_mesh)

# Visualize
viewer = gl.Viewer()
viewer.display(skeleton_mesh, s, mode='x')

Spatial Queries

Distance Field Computation

from sys import argv
from pygel3d import hmesh
import numpy as np

# Load mesh
m = hmesh.load(argv[1])

# Create distance object
dist = hmesh.MeshDistance(m)

# Create sampling grid
grid_res = 50
bbox_min, bbox_max = hmesh.bbox(m)

# Expand bbox slightly
margin = 0.1
bbox_min = [x - margin for x in bbox_min]
bbox_max = [x + margin for x in bbox_max]

# Sample points
x = np.linspace(bbox_min[0], bbox_max[0], grid_res)
y = np.linspace(bbox_min[1], bbox_max[1], grid_res)
z = np.linspace(bbox_min[2], bbox_max[2], grid_res)

# Compute distance field
distances = np.zeros((grid_res, grid_res, grid_res))
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 computed: {distances.shape}")
print(f"Min distance: {distances.min():.4f}")
print(f"Max distance: {distances.max():.4f}")

# Save distance field (e.g., as numpy array)
np.save("distance_field.npy", distances)
from pygel3d.spatial import I3DTree
import numpy as np
import time

# Generate random point cloud
n_points = 1000000
points = np.random.rand(n_points, 3) * 100

# Build kD-tree
print("Building tree...")
start = time.time()
tree = I3DTree()
for i, p in enumerate(points):
    tree.insert(p, i)
build_time = time.time() - start
print(f"Built tree with {n_points} points in {build_time:.2f}s")

# Query nearest neighbors
n_queries = 100000
query_points = np.random.rand(n_queries, 3) * 100

start = time.time()
for q in query_points:
    nearest_idx = tree.closest_point(q,1e20)
query_time = time.time() - start

print(f"Performed {n_queries} queries in {query_time:.2f}s")
print(f"Average query time: {query_time/n_queries*1000000:.2f}us")

Advanced Workflows

Mesh Reconstruction from Point Cloud

import pygel3d.hmesh as hmesh
import numpy as np

# Load or generate point cloud
# points: Nx3 numpy array
# normals: Nx3 numpy array

# Example usage (with synthetic data)
theta = np.linspace(0, 2*np.pi, 100)[:-1]
phi = np.linspace(0.1, np.pi-0.1, 50)
theta, phi = np.meshgrid(theta, phi)

x = np.sin(phi) * np.cos(theta)
y = np.sin(phi) * np.sin(theta)
z = np.cos(phi)

points = np.stack([x.flatten(), y.flatten(), z.flatten()], axis=1)
normals = points / np.linalg.norm(points, axis=1, keepdims=True)

m = hmesh.rsr_recon(points, normals, max_normal_ang=10)
hmesh.close_holes(m, max_size=1000)
hmesh.triangulate(m)
for _ in range(5):
    hmesh.maximize_min_angle(m)
hmesh.save("reconstructed.obj", m)

Jupyter Notebook Example

# Cell 1: Setup
from pygel3d import hmesh, jupyter_display as jd

# Cell 2: Load and display original
m = hmesh.load("/path/to/model") # replace with your model path
print("Original mesh:")
jd.display(m)

# Cell 3: Smooth and display
hmesh.taubin_smooth(m)
print("After smoothing:")
jd.display(m)

# Cell 4: Simplify and display
hmesh.quadric_simplify(m, keep_fraction=0.5)
print("After simplification:")
jd.display(m)

# Cell 5: Save result
hmesh.save("result.obj", m)
print("Saved result.obj")

These examples demonstrate the most common PyGEL3D workflows. Modify them to suit your specific needs!