CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-trimesh

Import, export, process, analyze and view triangular meshes.

Overview
Eval results
Files

advanced-features.mddocs/

Advanced Features

Specialized functionality including voxelization, vector path handling, primitive shape generation, and advanced algorithms. These features extend trimesh's capabilities for specialized applications and research.

Capabilities

Voxelization

Convert meshes to voxel representations for volumetric analysis and processing.

def voxelized(self, pitch, method='subdivide', bounds=None) -> 'VoxelGrid':
    """
    Convert mesh to voxel representation.
    
    Parameters:
    - pitch: float, voxel spacing/size
    - method: str, voxelization method ('subdivide', 'binvox')
    - bounds: (2, 3) custom bounds for voxelization
    
    Returns:
    VoxelGrid object
    """

class VoxelGrid:
    """3D voxel grid representation"""
    
    @property
    def shape(self) -> tuple:
        """Shape of voxel grid as (nx, ny, nz)"""
    
    @property
    def pitch(self) -> float:
        """Voxel spacing/size"""
    
    @property
    def bounds(self) -> np.ndarray:
        """Bounds of voxel grid"""
    
    @property
    def volume(self) -> float:
        """Total volume of filled voxels"""
    
    def as_boxes(self, solid=True) -> 'Trimesh':
        """
        Convert filled voxels to box meshes.
        
        Parameters:
        - solid: bool, create solid boxes or just faces
        
        Returns:
        Trimesh containing voxel boxes
        """
    
    def marching_cubes(self, level=0.0) -> 'Trimesh':
        """
        Extract mesh surface using marching cubes.
        
        Parameters:
        - level: float, iso-surface level
        
        Returns:
        Mesh representing voxel surface
        """
    
    def fill_orthographic(self, direction=[0, 0, 1]) -> 'VoxelGrid':
        """
        Fill voxels using orthographic projection.
        
        Parameters:
        - direction: (3,) projection direction
        
        Returns:
        Filled VoxelGrid
        """

Primitive Shape Generation

Create parametric geometric primitives.

def Sphere(radius=1.0, subdivisions=2, **kwargs) -> 'Trimesh':
    """
    Create sphere mesh.
    
    Parameters:
    - radius: float, sphere radius
    - subdivisions: int, subdivision level for smoothness
    - **kwargs: additional mesh options
    
    Returns:
    Trimesh sphere
    """

def Box(extents=None, transform=None, **kwargs) -> 'Trimesh':
    """
    Create box mesh.
    
    Parameters:
    - extents: (3,) box dimensions [width, height, depth]
    - transform: (4, 4) transformation matrix
    - **kwargs: additional mesh options
    
    Returns:
    Trimesh box
    """

def Cylinder(radius=1.0, height=1.0, sections=32, **kwargs) -> 'Trimesh':
    """
    Create cylinder mesh.
    
    Parameters:
    - radius: float, cylinder radius
    - height: float, cylinder height
    - sections: int, number of circumferential sections
    - **kwargs: additional mesh options
    
    Returns:
    Trimesh cylinder
    """

def Capsule(radius=1.0, height=1.0, **kwargs) -> 'Trimesh':
    """
    Create capsule (cylinder with hemispherical caps).
    
    Parameters:
    - radius: float, capsule radius
    - height: float, cylinder portion height
    - **kwargs: additional mesh options
    
    Returns:
    Trimesh capsule
    """

def Cone(radius=1.0, height=1.0, sections=32, **kwargs) -> 'Trimesh':
    """
    Create cone mesh.
    
    Parameters:
    - radius: float, base radius
    - height: float, cone height
    - sections: int, number of base sections  
    - **kwargs: additional mesh options
    
    Returns:
    Trimesh cone
    """

def Annulus(r_min=0.5, r_max=1.0, height=1.0, **kwargs) -> 'Trimesh':
    """
    Create annulus (hollow cylinder).
    
    Parameters:
    - r_min: float, inner radius
    - r_max: float, outer radius  
    - height: float, annulus height
    - **kwargs: additional mesh options
    
    Returns:
    Trimesh annulus
    """

Vector Path Handling

Work with 2D and 3D vector paths, curves, and sketches.

class Path2D:
    """2D vector path representation"""
    
    @property
    def vertices(self) -> np.ndarray:
        """Path vertices as (n, 2) array"""
    
    @property
    def entities(self) -> list:
        """Path entities (lines, arcs, curves)"""
    
    @property
    def bounds(self) -> np.ndarray:
        """Path bounding box"""
    
    @property
    def length(self) -> float:
        """Total path length"""
    
    @property
    def is_closed(self) -> bool:
        """True if path forms closed loop"""
    
    def extrude(self, height, **kwargs) -> 'Trimesh':
        """
        Extrude path to create 3D mesh.
        
        Parameters:
        - height: float, extrusion height
        - **kwargs: extrusion options
        
        Returns:
        Extruded Trimesh
        """
    
    def buffer(self, distance, **kwargs) -> 'Path2D':
        """
        Create offset path at specified distance.
        
        Parameters:
        - distance: float, offset distance
        - **kwargs: buffer options
        
        Returns:
        Buffered Path2D
        """

class Path3D:
    """3D vector path representation"""
    
    @property
    def vertices(self) -> np.ndarray:
        """Path vertices as (n, 3) array"""
    
    @property
    def length(self) -> float:
        """Total path length"""
    
    def to_planar(self, to_2D=None) -> 'Path2D':
        """
        Convert to 2D path by projection.
        
        Parameters:
        - to_2D: (4, 4) transformation to 2D plane
        
        Returns:
        Projected Path2D
        """

Mesh Parameterization

Advanced mesh parameterization and texture mapping.

def unwrap(self, method='angle_based') -> tuple:
    """
    UV unwrap mesh for texture mapping.
    
    Parameters:
    - method: str, unwrapping method
    
    Returns:
    tuple: (uv_coordinates, face_index_map)
    """

def parameterize_spherical(self) -> np.ndarray:
    """
    Spherical parameterization of mesh.
    
    Returns:
    (n, 2) spherical coordinates for vertices
    """

def parameterize_cylindrical(self, axis=[0, 0, 1]) -> np.ndarray:
    """
    Cylindrical parameterization of mesh.
    
    Parameters:
    - axis: (3,) cylinder axis direction
    
    Returns:
    (n, 2) cylindrical coordinates for vertices
    """

Mesh Generation from Data

Create meshes from various data sources and mathematical functions.

def from_heightmap(heightmap, pitch=1.0, **kwargs) -> 'Trimesh':
    """
    Create mesh from 2D heightmap data.
    
    Parameters:
    - heightmap: (h, w) height values
    - pitch: float, spacing between height samples
    - **kwargs: mesh generation options
    
    Returns:
    Trimesh representing heightmap surface
    """

def from_function(func, bounds, resolution=50, **kwargs) -> 'Trimesh':
    """
    Create mesh from mathematical function z = f(x, y).
    
    Parameters:
    - func: function taking (x, y) and returning z
    - bounds: ((x_min, x_max), (y_min, y_max)) function domain
    - resolution: int, sampling resolution
    - **kwargs: mesh options
    
    Returns:
    Trimesh representing function surface
    """

def from_points(points, method='delaunay', **kwargs) -> 'Trimesh':
    """
    Create mesh from point cloud using surface reconstruction.
    
    Parameters:
    - points: (n, 3) point coordinates
    - method: str, reconstruction method
    - **kwargs: reconstruction options
    
    Returns:
    Reconstructed Trimesh
    """

Advanced Algorithms

Specialized algorithms for complex mesh processing tasks.

def poisson_reconstruction(self, depth=8, **kwargs) -> 'Trimesh':
    """
    Poisson surface reconstruction from point cloud with normals.
    
    Parameters:
    - depth: int, octree depth for reconstruction
    - **kwargs: Poisson reconstruction options
    
    Returns:
    Reconstructed mesh surface
    """

def alpha_shape(points, alpha) -> 'Trimesh':
    """
    Compute alpha shape of point set.
    
    Parameters:
    - points: (n, 3) point coordinates
    - alpha: float, alpha parameter controlling shape
    
    Returns:
    Alpha shape mesh
    """

def medial_axis(self, **kwargs) -> tuple:
    """
    Compute medial axis (skeleton) of mesh.
    
    Parameters:
    - **kwargs: medial axis computation options
    
    Returns:
    tuple: (skeleton_points, skeleton_radius)
    """

def geodesic_distance(self, start_vertices, **kwargs) -> np.ndarray:
    """
    Compute geodesic distances on mesh surface.
    
    Parameters:
    - start_vertices: array of starting vertex indices
    - **kwargs: geodesic computation options
    
    Returns:
    (n,) geodesic distances to each vertex
    """

Mesh Optimization

Advanced mesh optimization and quality improvement algorithms.

def optimize_vertex_order(self) -> 'Trimesh':
    """
    Optimize vertex ordering for better cache performance.
    
    Returns:
    Mesh with optimized vertex order
    """

def optimize_face_order(self) -> 'Trimesh':
    """
    Optimize face ordering for rendering efficiency.
    
    Returns:
    Mesh with optimized face order
    """

def isotropic_remeshing(self, target_edge_length, iterations=10) -> 'Trimesh':
    """
    Isotropic remeshing for uniform triangle quality.
    
    Parameters:
    - target_edge_length: float, desired edge length
    - iterations: int, number of remeshing iterations
    
    Returns:
    Remeshed Trimesh with improved quality
    """

def feature_preserving_smoothing(self, iterations=5, feature_angle=45.0) -> 'Trimesh':
    """
    Smooth mesh while preserving sharp features.
    
    Parameters:
    - iterations: int, smoothing iterations
    - feature_angle: float, angle threshold for feature detection
    
    Returns:
    Smoothed mesh with preserved features
    """

Usage Examples

Voxelization

import trimesh
import numpy as np

# Load mesh
mesh = trimesh.load('model.stl')

# Convert to voxels
voxel_pitch = 0.1  # 0.1 unit voxel size
voxel_grid = mesh.voxelized(pitch=voxel_pitch)

print(f"Voxel grid shape: {voxel_grid.shape}")
print(f"Original volume: {mesh.volume:.4f}")
print(f"Voxel volume: {voxel_grid.volume:.4f}")
print(f"Volume error: {abs(mesh.volume - voxel_grid.volume)/mesh.volume*100:.2f}%")

# Convert voxels back to mesh
voxel_mesh = voxel_grid.as_boxes()
print(f"Voxel mesh faces: {len(voxel_mesh.faces)}")

# Smooth voxel surface with marching cubes
smooth_mesh = voxel_grid.marching_cubes()
print(f"Marching cubes mesh faces: {len(smooth_mesh.faces)}")

# Visualize results
scene = trimesh.Scene([
    mesh,  # Original
    voxel_mesh.apply_translation([5, 0, 0]),  # Voxel boxes
    smooth_mesh.apply_translation([10, 0, 0])  # Marching cubes
])
scene.show()

Primitive Shapes

# Create various primitive shapes
primitives = [
    ('Sphere', trimesh.primitives.Sphere(radius=1.0, subdivisions=3)),
    ('Box', trimesh.primitives.Box(extents=[2, 1, 0.5])),
    ('Cylinder', trimesh.primitives.Cylinder(radius=0.8, height=2.0, sections=16)),
    ('Cone', trimesh.primitives.Cone(radius=1.0, height=1.5, sections=12)),
    ('Capsule', trimesh.primitives.Capsule(radius=0.6, height=1.0)),
    ('Annulus', trimesh.primitives.Annulus(r_min=0.3, r_max=0.8, height=1.0))
]

# Position primitives in a grid
scene = trimesh.Scene()
for i, (name, primitive) in enumerate(primitives):
    x_pos = (i % 3) * 3
    y_pos = (i // 3) * 3
    transform = trimesh.transformations.translation_matrix([x_pos, y_pos, 0])
    
    # Color each primitive differently
    colors = [[1, 0, 0], [0, 1, 0], [0, 0, 1], [1, 1, 0], [1, 0, 1], [0, 1, 1]]
    primitive.visual.face_colors = colors[i] + [1.0]
    
    scene.add_geometry(primitive, transform=transform)
    print(f"{name}: Volume={primitive.volume:.4f}, Area={primitive.area:.4f}")

scene.show()

Vector Path Processing

# Create 2D path from points
path_points = np.array([
    [0, 0], [1, 0], [1.5, 0.5], [1, 1], [0, 1], [0, 0]  # Closed path
])
path = trimesh.load_path(path_points)

print(f"Path length: {path.length:.4f}")
print(f"Path is closed: {path.is_closed}")
print(f"Path bounds: {path.bounds}")

# Extrude path to create 3D mesh
extruded_mesh = path.extrude(height=2.0)
print(f"Extruded mesh volume: {extruded_mesh.volume:.4f}")

# Create offset/buffer of path
buffered_path = path.buffer(distance=0.2)
buffered_mesh = buffered_path.extrude(height=1.0)

# Visualize original and buffered extrusions
scene = trimesh.Scene([
    extruded_mesh,
    buffered_mesh.apply_translation([3, 0, 0])
])
scene.show()

# Work with 3D paths
curve_points = np.array([
    [np.cos(t), np.sin(t), t/5] for t in np.linspace(0, 4*np.pi, 100)
])
path_3d = trimesh.load_path(curve_points)
print(f"3D path length: {path_3d.length:.4f}")

# Convert 3D path to 2D by projection
path_2d = path_3d.to_planar()
path_2d_mesh = path_2d.extrude(height=0.5)

Mesh Generation from Data

# Generate mesh from mathematical function
def surface_function(x, y):
    return 0.5 * np.sin(2*np.pi*x) * np.cos(2*np.pi*y) + 0.2 * np.sin(5*np.pi*x)

bounds = ((-1, 1), (-1, 1))  # x and y ranges
function_mesh = trimesh.creation.from_function(
    surface_function, 
    bounds=bounds, 
    resolution=100
)

print(f"Function mesh: {len(function_mesh.vertices)} vertices, {len(function_mesh.faces)} faces")
function_mesh.show()

# Create mesh from heightmap
heightmap = np.random.rand(50, 50) * 0.5  # Random heightmap
heightmap += 2 * np.exp(-((np.arange(50)[:, None] - 25)**2 + (np.arange(50) - 25)**2) / 100)  # Add peak

heightmap_mesh = trimesh.creation.from_heightmap(heightmap, pitch=0.1)
print(f"Heightmap mesh volume: {heightmap_mesh.volume:.4f}")

# Visualize heightmap with color mapping
heights = heightmap_mesh.vertices[:, 2]
normalized_heights = (heights - heights.min()) / (heights.max() - heights.min())
colors = plt.cm.terrain(normalized_heights)
heightmap_mesh.visual.vertex_colors = (colors * 255).astype(np.uint8)
heightmap_mesh.show()

Point Cloud Reconstruction

# Generate sample point cloud
n_points = 1000
theta = np.random.uniform(0, 2*np.pi, n_points)
phi = np.random.uniform(0, np.pi, n_points)
radius = 1 + 0.1 * np.random.randn(n_points)  # Noisy sphere

points = np.column_stack([
    radius * np.sin(phi) * np.cos(theta),
    radius * np.sin(phi) * np.sin(theta),
    radius * np.cos(phi)
])

# Create point cloud
point_cloud = trimesh.PointCloud(points)
print(f"Point cloud: {len(point_cloud.vertices)} points")

# Surface reconstruction
reconstructed_mesh = trimesh.creation.from_points(points, method='ball_pivoting')
if reconstructed_mesh is not None:
    print(f"Reconstructed mesh: {len(reconstructed_mesh.faces)} faces")
    print(f"Volume: {reconstructed_mesh.volume:.4f}")
    
    # Visualize original points and reconstruction
    scene = trimesh.Scene([
        point_cloud.apply_translation([-3, 0, 0]),
        reconstructed_mesh.apply_translation([3, 0, 0])
    ])
    scene.show()

# Alpha shape reconstruction
alpha_mesh = trimesh.creation.alpha_shape(points, alpha=0.3)
if alpha_mesh is not None:
    print(f"Alpha shape: {len(alpha_mesh.faces)} faces")
    alpha_mesh.show()

Advanced Mesh Processing

# Load complex mesh
mesh = trimesh.load('complex_model.stl')

# Compute geodesic distance from a starting vertex
start_vertex = 0  # Start from first vertex
geodesic_distances = mesh.geodesic_distance([start_vertex])

# Visualize geodesic distances with colors
normalized_distances = geodesic_distances / geodesic_distances.max()
colors = plt.cm.plasma(normalized_distances)
mesh.visual.vertex_colors = (colors * 255).astype(np.uint8)
mesh.show()

# Isotropic remeshing for better triangle quality
target_edge_length = mesh.edge_lengths().mean()
remeshed = mesh.isotropic_remeshing(target_edge_length, iterations=5)

print(f"Original: {len(mesh.faces)} faces")
print(f"Remeshed: {len(remeshed.faces)} faces")

# Compare triangle quality
original_angles = mesh.face_angles()
remeshed_angles = remeshed.face_angles()

print(f"Original angle std: {original_angles.std():.4f}")
print(f"Remeshed angle std: {remeshed_angles.std():.4f}")

# Feature-preserving smoothing
smoothed = mesh.feature_preserving_smoothing(iterations=3, feature_angle=30.0)

# Visualize original, remeshed, and smoothed
scene = trimesh.Scene([
    mesh,
    remeshed.apply_translation([5, 0, 0]),
    smoothed.apply_translation([10, 0, 0])
])
scene.show()

Mesh Optimization

# Optimize mesh for rendering performance
mesh = trimesh.load('large_model.obj')

print(f"Original mesh: {len(mesh.vertices)} vertices, {len(mesh.faces)} faces")

# Optimize vertex and face ordering
optimized_mesh = mesh.copy()
optimized_mesh = optimized_mesh.optimize_vertex_order()
optimized_mesh = optimized_mesh.optimize_face_order()

print("Mesh optimized for cache performance")

# Simplify mesh while preserving important features
simplified = mesh.simplify_quadratic_decimation(face_count=len(mesh.faces)//2)
print(f"Simplified mesh: {len(simplified.faces)} faces ({100*len(simplified.faces)/len(mesh.faces):.1f}% of original)")

# Compare volumes
print(f"Original volume: {mesh.volume:.6f}")
print(f"Simplified volume: {simplified.volume:.6f}")
print(f"Volume error: {abs(mesh.volume - simplified.volume)/mesh.volume*100:.2f}%")

# Visualize comparison
scene = trimesh.Scene([
    mesh.apply_translation([-3, 0, 0]),
    simplified.apply_translation([3, 0, 0])
])
scene.show()

Install with Tessl CLI

npx tessl i tessl/pypi-trimesh

docs

advanced-features.md

analysis.md

core-operations.md

file-io.md

index.md

mesh-processing.md

point-clouds.md

spatial-queries.md

visualization.md

tile.json