or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-features.mdanalysis.mdcore-operations.mdfile-io.mdindex.mdmesh-processing.mdpoint-clouds.mdspatial-queries.mdvisualization.md

advanced-features.mddocs/

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

```