0
# Advanced Features
1
2
Specialized functionality including voxelization, vector path handling, primitive shape generation, and advanced algorithms. These features extend trimesh's capabilities for specialized applications and research.
3
4
## Capabilities
5
6
### Voxelization
7
8
Convert meshes to voxel representations for volumetric analysis and processing.
9
10
```python { .api }
11
def voxelized(self, pitch, method='subdivide', bounds=None) -> 'VoxelGrid':
12
"""
13
Convert mesh to voxel representation.
14
15
Parameters:
16
- pitch: float, voxel spacing/size
17
- method: str, voxelization method ('subdivide', 'binvox')
18
- bounds: (2, 3) custom bounds for voxelization
19
20
Returns:
21
VoxelGrid object
22
"""
23
24
class VoxelGrid:
25
"""3D voxel grid representation"""
26
27
@property
28
def shape(self) -> tuple:
29
"""Shape of voxel grid as (nx, ny, nz)"""
30
31
@property
32
def pitch(self) -> float:
33
"""Voxel spacing/size"""
34
35
@property
36
def bounds(self) -> np.ndarray:
37
"""Bounds of voxel grid"""
38
39
@property
40
def volume(self) -> float:
41
"""Total volume of filled voxels"""
42
43
def as_boxes(self, solid=True) -> 'Trimesh':
44
"""
45
Convert filled voxels to box meshes.
46
47
Parameters:
48
- solid: bool, create solid boxes or just faces
49
50
Returns:
51
Trimesh containing voxel boxes
52
"""
53
54
def marching_cubes(self, level=0.0) -> 'Trimesh':
55
"""
56
Extract mesh surface using marching cubes.
57
58
Parameters:
59
- level: float, iso-surface level
60
61
Returns:
62
Mesh representing voxel surface
63
"""
64
65
def fill_orthographic(self, direction=[0, 0, 1]) -> 'VoxelGrid':
66
"""
67
Fill voxels using orthographic projection.
68
69
Parameters:
70
- direction: (3,) projection direction
71
72
Returns:
73
Filled VoxelGrid
74
"""
75
```
76
77
### Primitive Shape Generation
78
79
Create parametric geometric primitives.
80
81
```python { .api }
82
def Sphere(radius=1.0, subdivisions=2, **kwargs) -> 'Trimesh':
83
"""
84
Create sphere mesh.
85
86
Parameters:
87
- radius: float, sphere radius
88
- subdivisions: int, subdivision level for smoothness
89
- **kwargs: additional mesh options
90
91
Returns:
92
Trimesh sphere
93
"""
94
95
def Box(extents=None, transform=None, **kwargs) -> 'Trimesh':
96
"""
97
Create box mesh.
98
99
Parameters:
100
- extents: (3,) box dimensions [width, height, depth]
101
- transform: (4, 4) transformation matrix
102
- **kwargs: additional mesh options
103
104
Returns:
105
Trimesh box
106
"""
107
108
def Cylinder(radius=1.0, height=1.0, sections=32, **kwargs) -> 'Trimesh':
109
"""
110
Create cylinder mesh.
111
112
Parameters:
113
- radius: float, cylinder radius
114
- height: float, cylinder height
115
- sections: int, number of circumferential sections
116
- **kwargs: additional mesh options
117
118
Returns:
119
Trimesh cylinder
120
"""
121
122
def Capsule(radius=1.0, height=1.0, **kwargs) -> 'Trimesh':
123
"""
124
Create capsule (cylinder with hemispherical caps).
125
126
Parameters:
127
- radius: float, capsule radius
128
- height: float, cylinder portion height
129
- **kwargs: additional mesh options
130
131
Returns:
132
Trimesh capsule
133
"""
134
135
def Cone(radius=1.0, height=1.0, sections=32, **kwargs) -> 'Trimesh':
136
"""
137
Create cone mesh.
138
139
Parameters:
140
- radius: float, base radius
141
- height: float, cone height
142
- sections: int, number of base sections
143
- **kwargs: additional mesh options
144
145
Returns:
146
Trimesh cone
147
"""
148
149
def Annulus(r_min=0.5, r_max=1.0, height=1.0, **kwargs) -> 'Trimesh':
150
"""
151
Create annulus (hollow cylinder).
152
153
Parameters:
154
- r_min: float, inner radius
155
- r_max: float, outer radius
156
- height: float, annulus height
157
- **kwargs: additional mesh options
158
159
Returns:
160
Trimesh annulus
161
"""
162
```
163
164
### Vector Path Handling
165
166
Work with 2D and 3D vector paths, curves, and sketches.
167
168
```python { .api }
169
class Path2D:
170
"""2D vector path representation"""
171
172
@property
173
def vertices(self) -> np.ndarray:
174
"""Path vertices as (n, 2) array"""
175
176
@property
177
def entities(self) -> list:
178
"""Path entities (lines, arcs, curves)"""
179
180
@property
181
def bounds(self) -> np.ndarray:
182
"""Path bounding box"""
183
184
@property
185
def length(self) -> float:
186
"""Total path length"""
187
188
@property
189
def is_closed(self) -> bool:
190
"""True if path forms closed loop"""
191
192
def extrude(self, height, **kwargs) -> 'Trimesh':
193
"""
194
Extrude path to create 3D mesh.
195
196
Parameters:
197
- height: float, extrusion height
198
- **kwargs: extrusion options
199
200
Returns:
201
Extruded Trimesh
202
"""
203
204
def buffer(self, distance, **kwargs) -> 'Path2D':
205
"""
206
Create offset path at specified distance.
207
208
Parameters:
209
- distance: float, offset distance
210
- **kwargs: buffer options
211
212
Returns:
213
Buffered Path2D
214
"""
215
216
class Path3D:
217
"""3D vector path representation"""
218
219
@property
220
def vertices(self) -> np.ndarray:
221
"""Path vertices as (n, 3) array"""
222
223
@property
224
def length(self) -> float:
225
"""Total path length"""
226
227
def to_planar(self, to_2D=None) -> 'Path2D':
228
"""
229
Convert to 2D path by projection.
230
231
Parameters:
232
- to_2D: (4, 4) transformation to 2D plane
233
234
Returns:
235
Projected Path2D
236
"""
237
```
238
239
### Mesh Parameterization
240
241
Advanced mesh parameterization and texture mapping.
242
243
```python { .api }
244
def unwrap(self, method='angle_based') -> tuple:
245
"""
246
UV unwrap mesh for texture mapping.
247
248
Parameters:
249
- method: str, unwrapping method
250
251
Returns:
252
tuple: (uv_coordinates, face_index_map)
253
"""
254
255
def parameterize_spherical(self) -> np.ndarray:
256
"""
257
Spherical parameterization of mesh.
258
259
Returns:
260
(n, 2) spherical coordinates for vertices
261
"""
262
263
def parameterize_cylindrical(self, axis=[0, 0, 1]) -> np.ndarray:
264
"""
265
Cylindrical parameterization of mesh.
266
267
Parameters:
268
- axis: (3,) cylinder axis direction
269
270
Returns:
271
(n, 2) cylindrical coordinates for vertices
272
"""
273
```
274
275
### Mesh Generation from Data
276
277
Create meshes from various data sources and mathematical functions.
278
279
```python { .api }
280
def from_heightmap(heightmap, pitch=1.0, **kwargs) -> 'Trimesh':
281
"""
282
Create mesh from 2D heightmap data.
283
284
Parameters:
285
- heightmap: (h, w) height values
286
- pitch: float, spacing between height samples
287
- **kwargs: mesh generation options
288
289
Returns:
290
Trimesh representing heightmap surface
291
"""
292
293
def from_function(func, bounds, resolution=50, **kwargs) -> 'Trimesh':
294
"""
295
Create mesh from mathematical function z = f(x, y).
296
297
Parameters:
298
- func: function taking (x, y) and returning z
299
- bounds: ((x_min, x_max), (y_min, y_max)) function domain
300
- resolution: int, sampling resolution
301
- **kwargs: mesh options
302
303
Returns:
304
Trimesh representing function surface
305
"""
306
307
def from_points(points, method='delaunay', **kwargs) -> 'Trimesh':
308
"""
309
Create mesh from point cloud using surface reconstruction.
310
311
Parameters:
312
- points: (n, 3) point coordinates
313
- method: str, reconstruction method
314
- **kwargs: reconstruction options
315
316
Returns:
317
Reconstructed Trimesh
318
"""
319
```
320
321
### Advanced Algorithms
322
323
Specialized algorithms for complex mesh processing tasks.
324
325
```python { .api }
326
def poisson_reconstruction(self, depth=8, **kwargs) -> 'Trimesh':
327
"""
328
Poisson surface reconstruction from point cloud with normals.
329
330
Parameters:
331
- depth: int, octree depth for reconstruction
332
- **kwargs: Poisson reconstruction options
333
334
Returns:
335
Reconstructed mesh surface
336
"""
337
338
def alpha_shape(points, alpha) -> 'Trimesh':
339
"""
340
Compute alpha shape of point set.
341
342
Parameters:
343
- points: (n, 3) point coordinates
344
- alpha: float, alpha parameter controlling shape
345
346
Returns:
347
Alpha shape mesh
348
"""
349
350
def medial_axis(self, **kwargs) -> tuple:
351
"""
352
Compute medial axis (skeleton) of mesh.
353
354
Parameters:
355
- **kwargs: medial axis computation options
356
357
Returns:
358
tuple: (skeleton_points, skeleton_radius)
359
"""
360
361
def geodesic_distance(self, start_vertices, **kwargs) -> np.ndarray:
362
"""
363
Compute geodesic distances on mesh surface.
364
365
Parameters:
366
- start_vertices: array of starting vertex indices
367
- **kwargs: geodesic computation options
368
369
Returns:
370
(n,) geodesic distances to each vertex
371
"""
372
```
373
374
### Mesh Optimization
375
376
Advanced mesh optimization and quality improvement algorithms.
377
378
```python { .api }
379
def optimize_vertex_order(self) -> 'Trimesh':
380
"""
381
Optimize vertex ordering for better cache performance.
382
383
Returns:
384
Mesh with optimized vertex order
385
"""
386
387
def optimize_face_order(self) -> 'Trimesh':
388
"""
389
Optimize face ordering for rendering efficiency.
390
391
Returns:
392
Mesh with optimized face order
393
"""
394
395
def isotropic_remeshing(self, target_edge_length, iterations=10) -> 'Trimesh':
396
"""
397
Isotropic remeshing for uniform triangle quality.
398
399
Parameters:
400
- target_edge_length: float, desired edge length
401
- iterations: int, number of remeshing iterations
402
403
Returns:
404
Remeshed Trimesh with improved quality
405
"""
406
407
def feature_preserving_smoothing(self, iterations=5, feature_angle=45.0) -> 'Trimesh':
408
"""
409
Smooth mesh while preserving sharp features.
410
411
Parameters:
412
- iterations: int, smoothing iterations
413
- feature_angle: float, angle threshold for feature detection
414
415
Returns:
416
Smoothed mesh with preserved features
417
"""
418
```
419
420
## Usage Examples
421
422
### Voxelization
423
424
```python
425
import trimesh
426
import numpy as np
427
428
# Load mesh
429
mesh = trimesh.load('model.stl')
430
431
# Convert to voxels
432
voxel_pitch = 0.1 # 0.1 unit voxel size
433
voxel_grid = mesh.voxelized(pitch=voxel_pitch)
434
435
print(f"Voxel grid shape: {voxel_grid.shape}")
436
print(f"Original volume: {mesh.volume:.4f}")
437
print(f"Voxel volume: {voxel_grid.volume:.4f}")
438
print(f"Volume error: {abs(mesh.volume - voxel_grid.volume)/mesh.volume*100:.2f}%")
439
440
# Convert voxels back to mesh
441
voxel_mesh = voxel_grid.as_boxes()
442
print(f"Voxel mesh faces: {len(voxel_mesh.faces)}")
443
444
# Smooth voxel surface with marching cubes
445
smooth_mesh = voxel_grid.marching_cubes()
446
print(f"Marching cubes mesh faces: {len(smooth_mesh.faces)}")
447
448
# Visualize results
449
scene = trimesh.Scene([
450
mesh, # Original
451
voxel_mesh.apply_translation([5, 0, 0]), # Voxel boxes
452
smooth_mesh.apply_translation([10, 0, 0]) # Marching cubes
453
])
454
scene.show()
455
```
456
457
### Primitive Shapes
458
459
```python
460
# Create various primitive shapes
461
primitives = [
462
('Sphere', trimesh.primitives.Sphere(radius=1.0, subdivisions=3)),
463
('Box', trimesh.primitives.Box(extents=[2, 1, 0.5])),
464
('Cylinder', trimesh.primitives.Cylinder(radius=0.8, height=2.0, sections=16)),
465
('Cone', trimesh.primitives.Cone(radius=1.0, height=1.5, sections=12)),
466
('Capsule', trimesh.primitives.Capsule(radius=0.6, height=1.0)),
467
('Annulus', trimesh.primitives.Annulus(r_min=0.3, r_max=0.8, height=1.0))
468
]
469
470
# Position primitives in a grid
471
scene = trimesh.Scene()
472
for i, (name, primitive) in enumerate(primitives):
473
x_pos = (i % 3) * 3
474
y_pos = (i // 3) * 3
475
transform = trimesh.transformations.translation_matrix([x_pos, y_pos, 0])
476
477
# Color each primitive differently
478
colors = [[1, 0, 0], [0, 1, 0], [0, 0, 1], [1, 1, 0], [1, 0, 1], [0, 1, 1]]
479
primitive.visual.face_colors = colors[i] + [1.0]
480
481
scene.add_geometry(primitive, transform=transform)
482
print(f"{name}: Volume={primitive.volume:.4f}, Area={primitive.area:.4f}")
483
484
scene.show()
485
```
486
487
### Vector Path Processing
488
489
```python
490
# Create 2D path from points
491
path_points = np.array([
492
[0, 0], [1, 0], [1.5, 0.5], [1, 1], [0, 1], [0, 0] # Closed path
493
])
494
path = trimesh.load_path(path_points)
495
496
print(f"Path length: {path.length:.4f}")
497
print(f"Path is closed: {path.is_closed}")
498
print(f"Path bounds: {path.bounds}")
499
500
# Extrude path to create 3D mesh
501
extruded_mesh = path.extrude(height=2.0)
502
print(f"Extruded mesh volume: {extruded_mesh.volume:.4f}")
503
504
# Create offset/buffer of path
505
buffered_path = path.buffer(distance=0.2)
506
buffered_mesh = buffered_path.extrude(height=1.0)
507
508
# Visualize original and buffered extrusions
509
scene = trimesh.Scene([
510
extruded_mesh,
511
buffered_mesh.apply_translation([3, 0, 0])
512
])
513
scene.show()
514
515
# Work with 3D paths
516
curve_points = np.array([
517
[np.cos(t), np.sin(t), t/5] for t in np.linspace(0, 4*np.pi, 100)
518
])
519
path_3d = trimesh.load_path(curve_points)
520
print(f"3D path length: {path_3d.length:.4f}")
521
522
# Convert 3D path to 2D by projection
523
path_2d = path_3d.to_planar()
524
path_2d_mesh = path_2d.extrude(height=0.5)
525
```
526
527
### Mesh Generation from Data
528
529
```python
530
# Generate mesh from mathematical function
531
def surface_function(x, y):
532
return 0.5 * np.sin(2*np.pi*x) * np.cos(2*np.pi*y) + 0.2 * np.sin(5*np.pi*x)
533
534
bounds = ((-1, 1), (-1, 1)) # x and y ranges
535
function_mesh = trimesh.creation.from_function(
536
surface_function,
537
bounds=bounds,
538
resolution=100
539
)
540
541
print(f"Function mesh: {len(function_mesh.vertices)} vertices, {len(function_mesh.faces)} faces")
542
function_mesh.show()
543
544
# Create mesh from heightmap
545
heightmap = np.random.rand(50, 50) * 0.5 # Random heightmap
546
heightmap += 2 * np.exp(-((np.arange(50)[:, None] - 25)**2 + (np.arange(50) - 25)**2) / 100) # Add peak
547
548
heightmap_mesh = trimesh.creation.from_heightmap(heightmap, pitch=0.1)
549
print(f"Heightmap mesh volume: {heightmap_mesh.volume:.4f}")
550
551
# Visualize heightmap with color mapping
552
heights = heightmap_mesh.vertices[:, 2]
553
normalized_heights = (heights - heights.min()) / (heights.max() - heights.min())
554
colors = plt.cm.terrain(normalized_heights)
555
heightmap_mesh.visual.vertex_colors = (colors * 255).astype(np.uint8)
556
heightmap_mesh.show()
557
```
558
559
### Point Cloud Reconstruction
560
561
```python
562
# Generate sample point cloud
563
n_points = 1000
564
theta = np.random.uniform(0, 2*np.pi, n_points)
565
phi = np.random.uniform(0, np.pi, n_points)
566
radius = 1 + 0.1 * np.random.randn(n_points) # Noisy sphere
567
568
points = np.column_stack([
569
radius * np.sin(phi) * np.cos(theta),
570
radius * np.sin(phi) * np.sin(theta),
571
radius * np.cos(phi)
572
])
573
574
# Create point cloud
575
point_cloud = trimesh.PointCloud(points)
576
print(f"Point cloud: {len(point_cloud.vertices)} points")
577
578
# Surface reconstruction
579
reconstructed_mesh = trimesh.creation.from_points(points, method='ball_pivoting')
580
if reconstructed_mesh is not None:
581
print(f"Reconstructed mesh: {len(reconstructed_mesh.faces)} faces")
582
print(f"Volume: {reconstructed_mesh.volume:.4f}")
583
584
# Visualize original points and reconstruction
585
scene = trimesh.Scene([
586
point_cloud.apply_translation([-3, 0, 0]),
587
reconstructed_mesh.apply_translation([3, 0, 0])
588
])
589
scene.show()
590
591
# Alpha shape reconstruction
592
alpha_mesh = trimesh.creation.alpha_shape(points, alpha=0.3)
593
if alpha_mesh is not None:
594
print(f"Alpha shape: {len(alpha_mesh.faces)} faces")
595
alpha_mesh.show()
596
```
597
598
### Advanced Mesh Processing
599
600
```python
601
# Load complex mesh
602
mesh = trimesh.load('complex_model.stl')
603
604
# Compute geodesic distance from a starting vertex
605
start_vertex = 0 # Start from first vertex
606
geodesic_distances = mesh.geodesic_distance([start_vertex])
607
608
# Visualize geodesic distances with colors
609
normalized_distances = geodesic_distances / geodesic_distances.max()
610
colors = plt.cm.plasma(normalized_distances)
611
mesh.visual.vertex_colors = (colors * 255).astype(np.uint8)
612
mesh.show()
613
614
# Isotropic remeshing for better triangle quality
615
target_edge_length = mesh.edge_lengths().mean()
616
remeshed = mesh.isotropic_remeshing(target_edge_length, iterations=5)
617
618
print(f"Original: {len(mesh.faces)} faces")
619
print(f"Remeshed: {len(remeshed.faces)} faces")
620
621
# Compare triangle quality
622
original_angles = mesh.face_angles()
623
remeshed_angles = remeshed.face_angles()
624
625
print(f"Original angle std: {original_angles.std():.4f}")
626
print(f"Remeshed angle std: {remeshed_angles.std():.4f}")
627
628
# Feature-preserving smoothing
629
smoothed = mesh.feature_preserving_smoothing(iterations=3, feature_angle=30.0)
630
631
# Visualize original, remeshed, and smoothed
632
scene = trimesh.Scene([
633
mesh,
634
remeshed.apply_translation([5, 0, 0]),
635
smoothed.apply_translation([10, 0, 0])
636
])
637
scene.show()
638
```
639
640
### Mesh Optimization
641
642
```python
643
# Optimize mesh for rendering performance
644
mesh = trimesh.load('large_model.obj')
645
646
print(f"Original mesh: {len(mesh.vertices)} vertices, {len(mesh.faces)} faces")
647
648
# Optimize vertex and face ordering
649
optimized_mesh = mesh.copy()
650
optimized_mesh = optimized_mesh.optimize_vertex_order()
651
optimized_mesh = optimized_mesh.optimize_face_order()
652
653
print("Mesh optimized for cache performance")
654
655
# Simplify mesh while preserving important features
656
simplified = mesh.simplify_quadratic_decimation(face_count=len(mesh.faces)//2)
657
print(f"Simplified mesh: {len(simplified.faces)} faces ({100*len(simplified.faces)/len(mesh.faces):.1f}% of original)")
658
659
# Compare volumes
660
print(f"Original volume: {mesh.volume:.6f}")
661
print(f"Simplified volume: {simplified.volume:.6f}")
662
print(f"Volume error: {abs(mesh.volume - simplified.volume)/mesh.volume*100:.2f}%")
663
664
# Visualize comparison
665
scene = trimesh.Scene([
666
mesh.apply_translation([-3, 0, 0]),
667
simplified.apply_translation([3, 0, 0])
668
])
669
scene.show()
670
```