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

analysis.mddocs/

0

# Analysis and Measurement

1

2

Comprehensive geometric analysis including mass properties, curvature analysis, mesh quality metrics, inertia calculations, and geometric measurements. These tools enable detailed mesh characterization and engineering analysis.

3

4

## Capabilities

5

6

### Mass Properties and Inertia

7

8

Calculate physical properties assuming uniform density.

9

10

```python { .api }

11

@property

12

def mass_properties(self) -> dict:

13

"""

14

Calculate mass properties including center of mass and inertia tensor.

15

16

Returns:

17

dict with keys:

18

- 'volume': float, mesh volume

19

- 'mass': float, mass (volume * density)

20

- 'density': float, material density

21

- 'center_mass': (3,) center of mass

22

- 'inertia': (3, 3) inertia tensor

23

"""

24

25

@property

26

def moment_inertia(self) -> np.ndarray:

27

"""

28

Moment of inertia tensor around center of mass.

29

30

Returns:

31

(3, 3) inertia tensor matrix

32

"""

33

34

@property

35

def principal_inertia_components(self) -> np.ndarray:

36

"""

37

Principal moments of inertia (eigenvalues of inertia tensor).

38

39

Returns:

40

(3,) principal inertia values in ascending order

41

"""

42

43

@property

44

def principal_inertia_vectors(self) -> np.ndarray:

45

"""

46

Principal inertia axes (eigenvectors of inertia tensor).

47

48

Returns:

49

(3, 3) matrix where columns are principal axes

50

"""

51

52

@property

53

def center_mass(self) -> np.ndarray:

54

"""

55

Center of mass (volume-weighted centroid).

56

57

Returns:

58

(3,) center of mass coordinates

59

"""

60

```

61

62

### Surface Curvature Analysis

63

64

Analyze mesh curvature properties and surface characteristics.

65

66

```python { .api }

67

def discrete_gaussian_curvature_measure(self) -> np.ndarray:

68

"""

69

Discrete Gaussian curvature at each vertex.

70

71

Returns:

72

(n,) Gaussian curvature values at vertices

73

"""

74

75

def discrete_mean_curvature_measure(self) -> np.ndarray:

76

"""

77

Discrete mean curvature at each vertex.

78

79

Returns:

80

(n,) mean curvature values at vertices

81

"""

82

83

def vertex_defects(self) -> np.ndarray:

84

"""

85

Angular defect at each vertex (2π - sum of incident angles).

86

87

Returns:

88

(n,) angular defects at vertices

89

"""

90

91

def face_angles(self) -> np.ndarray:

92

"""

93

Interior angles of each face.

94

95

Returns:

96

(m, 3) angles for each face corner

97

"""

98

99

def face_angles_sparse(self) -> np.ndarray:

100

"""

101

Sparse representation of face angles.

102

103

Returns:

104

(3*m,) flattened face angles

105

"""

106

```

107

108

### Geometric Measurements

109

110

Basic geometric properties and measurements.

111

112

```python { .api }

113

@property

114

def area(self) -> float:

115

"""Total surface area"""

116

117

@property

118

def area_faces(self) -> np.ndarray:

119

"""

120

Surface area of each face.

121

122

Returns:

123

(m,) area values for each face

124

"""

125

126

@property

127

def volume(self) -> float:

128

"""

129

Mesh volume (positive for watertight meshes).

130

131

Returns:

132

float, volume value

133

"""

134

135

@property

136

def bounds(self) -> np.ndarray:

137

"""

138

Axis-aligned bounding box.

139

140

Returns:

141

(2, 3) array: [[min_x, min_y, min_z], [max_x, max_y, max_z]]

142

"""

143

144

@property

145

def extents(self) -> np.ndarray:

146

"""

147

Size in each dimension.

148

149

Returns:

150

(3,) array: [width, height, depth]

151

"""

152

153

@property

154

def scale(self) -> float:

155

"""Scaling factor relative to unit cube"""

156

157

@property

158

def centroid(self) -> np.ndarray:

159

"""

160

Geometric centroid (average of vertices).

161

162

Returns:

163

(3,) centroid coordinates

164

"""

165

```

166

167

### Mesh Quality Metrics

168

169

Analyze mesh quality and identify potential issues.

170

171

```python { .api }

172

@property

173

def euler_number(self) -> int:

174

"""

175

Euler characteristic (V - E + F).

176

177

Returns:

178

int, Euler number (2 for closed surfaces)

179

"""

180

181

@property

182

def is_watertight(self) -> bool:

183

"""True if mesh is watertight (manifold and closed)"""

184

185

@property

186

def is_winding_consistent(self) -> bool:

187

"""True if face winding is consistent"""

188

189

@property

190

def is_volume(self) -> bool:

191

"""True if mesh encloses a volume"""

192

193

@property

194

def face_adjacency(self) -> np.ndarray:

195

"""

196

Face adjacency matrix.

197

198

Returns:

199

(m, m) sparse matrix showing face connectivity

200

"""

201

202

@property

203

def face_adjacency_edges(self) -> np.ndarray:

204

"""

205

Edges between adjacent faces.

206

207

Returns:

208

(p, 2) array of face indices sharing edges

209

"""

210

211

def face_adjacency_convex(self, tolerance=0.0) -> np.ndarray:

212

"""

213

Check if adjacent faces form convex angles.

214

215

Parameters:

216

- tolerance: float, angle tolerance

217

218

Returns:

219

(p,) boolean array indicating convex adjacencies

220

"""

221

222

def face_normals_from_vertices(self) -> np.ndarray:

223

"""

224

Calculate face normals from vertex positions.

225

226

Returns:

227

(m, 3) face normal vectors

228

"""

229

```

230

231

### Statistical Analysis

232

233

Compute statistical properties of mesh geometry.

234

235

```python { .api }

236

def vertex_degree(self) -> np.ndarray:

237

"""

238

Number of faces incident to each vertex.

239

240

Returns:

241

(n,) vertex degrees

242

"""

243

244

def edge_lengths(self) -> np.ndarray:

245

"""

246

Length of each unique edge.

247

248

Returns:

249

(e,) edge length values

250

"""

251

252

def edge_lengths_histogram(self, bins=20) -> tuple:

253

"""

254

Histogram of edge lengths.

255

256

Parameters:

257

- bins: int, number of histogram bins

258

259

Returns:

260

tuple: (counts, bin_edges)

261

"""

262

263

def face_areas_histogram(self, bins=20) -> tuple:

264

"""

265

Histogram of face areas.

266

267

Parameters:

268

- bins: int, number of histogram bins

269

270

Returns:

271

tuple: (counts, bin_edges)

272

"""

273

```

274

275

### Mesh Comparison and Metrics

276

277

Compare meshes and compute similarity metrics.

278

279

```python { .api }

280

def hausdorff_distance(self, other) -> float:

281

"""

282

Hausdorff distance to another mesh.

283

284

Parameters:

285

- other: Trimesh object

286

287

Returns:

288

float, maximum distance between meshes

289

"""

290

291

def symmetric_difference_volume(self, other) -> float:

292

"""

293

Volume of symmetric difference with another mesh.

294

295

Parameters:

296

- other: Trimesh object

297

298

Returns:

299

float, volume of non-overlapping regions

300

"""

301

302

def difference_volume(self, other) -> float:

303

"""

304

Volume difference with another mesh.

305

306

Parameters:

307

- other: Trimesh object

308

309

Returns:

310

float, volume difference

311

"""

312

```

313

314

### Advanced Geometric Analysis

315

316

Specialized geometric analysis functions.

317

318

```python { .api }

319

def integral_gaussian_curvature(self) -> float:

320

"""

321

Total Gaussian curvature (should equal 4π for closed surfaces).

322

323

Returns:

324

float, integrated Gaussian curvature

325

"""

326

327

def integral_mean_curvature(self) -> float:

328

"""

329

Total mean curvature over surface.

330

331

Returns:

332

float, integrated mean curvature

333

"""

334

335

def sphericity(self) -> float:

336

"""

337

Sphericity measure (how sphere-like the mesh is).

338

339

Returns:

340

float, sphericity value (1.0 for perfect sphere)

341

"""

342

343

def compactness(self) -> float:

344

"""

345

Compactness measure (surface area vs volume ratio).

346

347

Returns:

348

float, compactness value

349

"""

350

```

351

352

## Usage Examples

353

354

### Mass Properties Analysis

355

356

```python

357

import trimesh

358

import numpy as np

359

360

# Load mesh

361

mesh = trimesh.load('part.stl')

362

363

# Set material density (kg/m³)

364

mesh.density = 7850 # Steel density

365

366

# Get complete mass properties

367

props = mesh.mass_properties

368

print(f"Volume: {props['volume']:.6f} m³")

369

print(f"Mass: {props['mass']:.3f} kg")

370

print(f"Center of mass: {props['center_mass']}")

371

print(f"Inertia tensor:\n{props['inertia']}")

372

373

# Principal inertia analysis

374

principal_values = mesh.principal_inertia_components

375

principal_vectors = mesh.principal_inertia_vectors

376

377

print(f"Principal moments: {principal_values}")

378

print(f"Principal axes:\n{principal_vectors}")

379

380

# Transform to principal axes

381

transform = mesh.principal_inertia_transform

382

aligned_mesh = mesh.copy()

383

aligned_mesh.apply_transform(transform)

384

```

385

386

### Curvature Analysis

387

388

```python

389

# Calculate curvature properties

390

gaussian_curvature = mesh.discrete_gaussian_curvature_measure()

391

mean_curvature = mesh.discrete_mean_curvature_measure()

392

393

# Analyze curvature distribution

394

print(f"Gaussian curvature range: {gaussian_curvature.min():.4f} to {gaussian_curvature.max():.4f}")

395

print(f"Mean curvature range: {mean_curvature.min():.4f} to {mean_curvature.max():.4f}")

396

397

# Find high curvature regions

398

high_curvature_threshold = np.percentile(np.abs(mean_curvature), 90)

399

high_curvature_vertices = np.where(np.abs(mean_curvature) > high_curvature_threshold)[0]

400

401

print(f"High curvature vertices: {len(high_curvature_vertices)}")

402

403

# Visualize curvature

404

if mesh.visual.kind == 'vertex':

405

# Color vertices by curvature

406

curvature_normalized = (mean_curvature - mean_curvature.min()) / (mean_curvature.max() - mean_curvature.min())

407

colors = plt.cm.viridis(curvature_normalized)[:, :3] * 255

408

mesh.visual.vertex_colors = colors.astype(np.uint8)

409

mesh.show()

410

```

411

412

### Mesh Quality Assessment

413

414

```python

415

# Basic quality checks

416

print(f"Is watertight: {mesh.is_watertight}")

417

print(f"Is winding consistent: {mesh.is_winding_consistent}")

418

print(f"Euler number: {mesh.euler_number}")

419

print(f"Vertex count: {len(mesh.vertices)}")

420

print(f"Face count: {len(mesh.faces)}")

421

422

# Geometric properties

423

print(f"Volume: {mesh.volume:.6f}")

424

print(f"Surface area: {mesh.area:.6f}")

425

print(f"Bounds: {mesh.bounds}")

426

print(f"Extents: {mesh.extents}")

427

428

# Quality metrics

429

print(f"Sphericity: {mesh.sphericity():.4f}")

430

print(f"Compactness: {mesh.compactness():.4f}")

431

432

# Edge and face statistics

433

edge_lengths = mesh.edge_lengths()

434

face_areas = mesh.area_faces

435

436

print(f"Edge length range: {edge_lengths.min():.6f} to {edge_lengths.max():.6f}")

437

print(f"Face area range: {face_areas.min():.6f} to {face_areas.max():.6f}")

438

print(f"Mean edge length: {edge_lengths.mean():.6f}")

439

print(f"Mean face area: {face_areas.mean():.6f}")

440

```

441

442

### Mesh Comparison

443

444

```python

445

# Load two meshes to compare

446

mesh1 = trimesh.load('original.stl')

447

mesh2 = trimesh.load('modified.stl')

448

449

# Hausdorff distance (measure of maximum deviation)

450

hausdorff_dist = mesh1.hausdorff_distance(mesh2)

451

print(f"Hausdorff distance: {hausdorff_dist:.6f}")

452

453

# Volume comparison

454

vol_diff = abs(mesh1.volume - mesh2.volume)

455

vol_percent = (vol_diff / mesh1.volume) * 100

456

print(f"Volume difference: {vol_diff:.6f} ({vol_percent:.2f}%)")

457

458

# Symmetric difference volume

459

sym_diff_vol = mesh1.symmetric_difference_volume(mesh2)

460

print(f"Symmetric difference volume: {sym_diff_vol:.6f}")

461

462

# Surface area comparison

463

area_diff = abs(mesh1.area - mesh2.area)

464

area_percent = (area_diff / mesh1.area) * 100

465

print(f"Surface area difference: {area_diff:.6f} ({area_percent:.2f}%)")

466

```

467

468

### Statistical Analysis

469

470

```python

471

import matplotlib.pyplot as plt

472

473

# Vertex degree distribution

474

vertex_degrees = mesh.vertex_degree()

475

print(f"Vertex degree range: {vertex_degrees.min()} to {vertex_degrees.max()}")

476

print(f"Mean vertex degree: {vertex_degrees.mean():.2f}")

477

478

# Edge length histogram

479

edge_lengths = mesh.edge_lengths()

480

counts, bin_edges = mesh.edge_lengths_histogram(bins=50)

481

482

plt.figure(figsize=(10, 6))

483

plt.subplot(1, 2, 1)

484

plt.hist(edge_lengths, bins=50, alpha=0.7)

485

plt.xlabel('Edge Length')

486

plt.ylabel('Count')

487

plt.title('Edge Length Distribution')

488

489

# Face area histogram

490

face_areas = mesh.area_faces

491

plt.subplot(1, 2, 2)

492

plt.hist(face_areas, bins=50, alpha=0.7)

493

plt.xlabel('Face Area')

494

plt.ylabel('Count')

495

plt.title('Face Area Distribution')

496

497

plt.tight_layout()

498

plt.show()

499

500

# Find outliers

501

edge_mean = edge_lengths.mean()

502

edge_std = edge_lengths.std()

503

edge_outliers = np.where(edge_lengths > edge_mean + 3*edge_std)[0]

504

print(f"Edge length outliers: {len(edge_outliers)} edges")

505

```