remesh-threejs 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +106 -5
- package/dist/index.d.ts +253 -0
- package/dist/remesh-threejs.cjs +1 -1
- package/dist/remesh-threejs.cjs.map +1 -1
- package/dist/remesh-threejs.js +363 -0
- package/dist/remesh-threejs.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
[](https://opensource.org/licenses/MIT)
|
|
6
6
|
[](https://github.com/RossGraeber/remesh-threejs/actions)
|
|
7
7
|
|
|
8
|
-
TypeScript library for
|
|
8
|
+
TypeScript library for repair and remeshing of non-manifold surfaces using Three.js.
|
|
9
9
|
|
|
10
10
|
Based on the EUROGRAPHICS 2008 paper ["Adaptive Remeshing of Non-Manifold Surfaces"](https://doi.org/10.1111/j.1467-8659.2008.01285.x) by Zilske, Lamecker, and Zachow.
|
|
11
11
|
|
|
@@ -14,6 +14,7 @@ Based on the EUROGRAPHICS 2008 paper ["Adaptive Remeshing of Non-Manifold Surfac
|
|
|
14
14
|
- **Non-manifold mesh support**: Extended halfedge data structure supporting edges with more than 2 incident faces
|
|
15
15
|
- **Feature skeleton**: Unified treatment of non-manifold edges, feature lines, and boundary edges
|
|
16
16
|
- **Adaptive remeshing**: Edge splitting, contraction, flipping, and vertex smoothing
|
|
17
|
+
- **Fast mesh repair**: Targeted repair operations 10-100x faster than full remeshing
|
|
17
18
|
- **Analysis tools**: Detect and classify non-manifold vertices and edges
|
|
18
19
|
- **Spatial acceleration**: SpatialHash and BVH for efficient queries on large meshes (500K+ triangles)
|
|
19
20
|
- **Three.js integration**: Import/export BufferGeometry with visualization helpers
|
|
@@ -42,6 +43,21 @@ console.log(`Remeshed in ${result.stats.iterations} iterations`);
|
|
|
42
43
|
const outputGeometry = result.geometry;
|
|
43
44
|
```
|
|
44
45
|
|
|
46
|
+
### Fast Mesh Repair
|
|
47
|
+
|
|
48
|
+
```typescript
|
|
49
|
+
import { repairMesh, removeIsolatedVertices } from 'remesh-threejs';
|
|
50
|
+
|
|
51
|
+
// Quick repair (removes isolated vertices, degenerate faces, duplicates)
|
|
52
|
+
const result = repairMesh(geometry);
|
|
53
|
+
console.log(`Fixed ${result.stats.totalDefectsFixed} defects in ${result.stats.totalTimeMs}ms`);
|
|
54
|
+
|
|
55
|
+
// Targeted repairs (10-100x faster than full remeshing)
|
|
56
|
+
const result2 = removeIsolatedVertices(geometry);
|
|
57
|
+
const result3 = removeDegenerateFaces(geometry, { areaThreshold: 1e-10 });
|
|
58
|
+
const result4 = removeDuplicateFaces(geometry);
|
|
59
|
+
```
|
|
60
|
+
|
|
45
61
|
### Analyze Mesh for Non-Manifold Issues
|
|
46
62
|
|
|
47
63
|
```typescript
|
|
@@ -105,6 +121,10 @@ const outputGeometry = exportBufferGeometry(mesh);
|
|
|
105
121
|
| Function | Description |
|
|
106
122
|
|----------|-------------|
|
|
107
123
|
| `remesh(geometry, options?)` | One-shot remeshing of a BufferGeometry |
|
|
124
|
+
| `repairMesh(geometry, options?)` | Fast repair for common defects |
|
|
125
|
+
| `removeIsolatedVertices(geometry)` | Remove orphaned vertices with no faces |
|
|
126
|
+
| `removeDegenerateFaces(geometry, options?)` | Remove zero-area triangles |
|
|
127
|
+
| `removeDuplicateFaces(geometry)` | Remove faces with identical vertices |
|
|
108
128
|
| `analyzeManifold(geometry)` | Analyze mesh for non-manifold features |
|
|
109
129
|
| `isManifold(geometry)` | Quick check if mesh is manifold |
|
|
110
130
|
| `validateTopology(mesh)` | Validate mesh topology integrity |
|
|
@@ -115,6 +135,7 @@ const outputGeometry = exportBufferGeometry(mesh);
|
|
|
115
135
|
|-------|-------------|
|
|
116
136
|
| `NonManifoldMesh` | Main mesh data structure with halfedge connectivity |
|
|
117
137
|
| `AdaptiveRemesher` | Iterative remeshing algorithm |
|
|
138
|
+
| `MeshRepairer` | Composable mesh repair operations |
|
|
118
139
|
| `ManifoldAnalyzer` | Analysis with caching support |
|
|
119
140
|
| `VertexClassifier` | Classify vertices by skeleton topology |
|
|
120
141
|
| `TopologyValidator` | Validate mesh topology invariants |
|
|
@@ -166,6 +187,64 @@ const bvh = createBVHFromMesh(mesh);
|
|
|
166
187
|
const result = bvh.closestPoint(queryPoint);
|
|
167
188
|
```
|
|
168
189
|
|
|
190
|
+
### Mesh Repair API
|
|
191
|
+
|
|
192
|
+
Fast, targeted repairs for common mesh defects. These operations are **10-100x faster** than full remeshing when you only need to fix specific issues.
|
|
193
|
+
|
|
194
|
+
#### Functional API (Simple)
|
|
195
|
+
|
|
196
|
+
```typescript
|
|
197
|
+
import {
|
|
198
|
+
repairMesh,
|
|
199
|
+
removeIsolatedVertices,
|
|
200
|
+
removeDegenerateFaces,
|
|
201
|
+
removeDuplicateFaces,
|
|
202
|
+
} from 'remesh-threejs';
|
|
203
|
+
|
|
204
|
+
// Run all repairs in optimal order
|
|
205
|
+
const result = repairMesh(geometry);
|
|
206
|
+
console.log(`Fixed ${result.stats.totalDefectsFixed} defects`);
|
|
207
|
+
|
|
208
|
+
// Or use targeted repairs
|
|
209
|
+
const result2 = removeIsolatedVertices(geometry); // 100x+ faster
|
|
210
|
+
const result3 = removeDegenerateFaces(geometry); // 50-100x faster
|
|
211
|
+
const result4 = removeDuplicateFaces(geometry); // 30-60x faster
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
#### Class-Based API (Advanced)
|
|
215
|
+
|
|
216
|
+
```typescript
|
|
217
|
+
import { MeshRepairer } from 'remesh-threejs';
|
|
218
|
+
|
|
219
|
+
// Compose multiple repairs with chaining
|
|
220
|
+
const repairer = new MeshRepairer(geometry, {
|
|
221
|
+
verbose: true, // Enable logging
|
|
222
|
+
validateAfterEach: true, // Validate topology after each operation
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
const stats = repairer
|
|
226
|
+
.removeIsolatedVertices()
|
|
227
|
+
.removeDegenerateFaces()
|
|
228
|
+
.removeDuplicateFaces()
|
|
229
|
+
.execute();
|
|
230
|
+
|
|
231
|
+
const repairedGeometry = repairer.toBufferGeometry();
|
|
232
|
+
|
|
233
|
+
// Validate results
|
|
234
|
+
const validation = repairer.validate();
|
|
235
|
+
if (!validation.isValid) {
|
|
236
|
+
console.error('Topology errors:', validation.errors);
|
|
237
|
+
}
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
#### Common Defects Repaired
|
|
241
|
+
|
|
242
|
+
| Defect | Operation | Speedup vs Remesh |
|
|
243
|
+
|--------|-----------|-------------------|
|
|
244
|
+
| Orphaned vertices | `removeIsolatedVertices()` | 100x+ |
|
|
245
|
+
| Zero-area triangles | `removeDegenerateFaces()` | 50-100x |
|
|
246
|
+
| Duplicate faces | `removeDuplicateFaces()` | 30-60x |
|
|
247
|
+
|
|
169
248
|
### Visualization Helpers
|
|
170
249
|
|
|
171
250
|
```typescript
|
|
@@ -187,6 +266,8 @@ const qualityMesh = exportQualityGeometry(mesh);
|
|
|
187
266
|
|
|
188
267
|
## Options
|
|
189
268
|
|
|
269
|
+
### Remesh Options
|
|
270
|
+
|
|
190
271
|
```typescript
|
|
191
272
|
interface RemeshOptions {
|
|
192
273
|
// Target edge length (default: auto-computed)
|
|
@@ -210,6 +291,30 @@ interface RemeshOptions {
|
|
|
210
291
|
}
|
|
211
292
|
```
|
|
212
293
|
|
|
294
|
+
### Repair Options
|
|
295
|
+
|
|
296
|
+
```typescript
|
|
297
|
+
interface RepairOptions {
|
|
298
|
+
// Use Web Workers for parallel processing (default: auto for large meshes)
|
|
299
|
+
useWorkers?: boolean;
|
|
300
|
+
|
|
301
|
+
// Number of worker threads (default: navigator.hardwareConcurrency || 4)
|
|
302
|
+
workerCount?: number;
|
|
303
|
+
|
|
304
|
+
// Use spatial acceleration structures (default: true)
|
|
305
|
+
useAcceleration?: boolean;
|
|
306
|
+
|
|
307
|
+
// Minimum mesh size to trigger parallelization (default: 10000 faces)
|
|
308
|
+
parallelThreshold?: number;
|
|
309
|
+
|
|
310
|
+
// Enable verbose logging (default: false)
|
|
311
|
+
verbose?: boolean;
|
|
312
|
+
|
|
313
|
+
// Validate topology after each operation (default: false)
|
|
314
|
+
validateAfterEach?: boolean;
|
|
315
|
+
}
|
|
316
|
+
```
|
|
317
|
+
|
|
213
318
|
## Development
|
|
214
319
|
|
|
215
320
|
```bash
|
|
@@ -265,7 +370,3 @@ Contributions are welcome! Please feel free to submit a Pull Request.
|
|
|
265
370
|
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
|
266
371
|
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
267
372
|
5. Open a Pull Request
|
|
268
|
-
|
|
269
|
-
## License
|
|
270
|
-
|
|
271
|
-
MIT
|
package/dist/index.d.ts
CHANGED
|
@@ -432,6 +432,32 @@ export declare function cross(a: Vec3, b: Vec3): Vec3;
|
|
|
432
432
|
*/
|
|
433
433
|
export declare const DEFAULT_REMESH_OPTIONS: Required<Omit<RemeshOptions, 'targetEdgeLength' | 'featureEdges'>>;
|
|
434
434
|
|
|
435
|
+
/**
|
|
436
|
+
* Defect information for analysis.
|
|
437
|
+
*/
|
|
438
|
+
export declare interface DefectInfo {
|
|
439
|
+
type: 'non-manifold' | 'hole' | 'degenerate' | 'intersection' | 'isolated' | 'duplicate' | 'normal';
|
|
440
|
+
count: number;
|
|
441
|
+
locations: {
|
|
442
|
+
faceIndex?: number;
|
|
443
|
+
vertexIndex?: number;
|
|
444
|
+
edgeIndex?: number;
|
|
445
|
+
}[];
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
/**
|
|
449
|
+
* Repairs degenerate faces (zero-area triangles, duplicate vertices).
|
|
450
|
+
*/
|
|
451
|
+
export declare class DegenerateFaceRepair extends RepairOperation {
|
|
452
|
+
private degenerateFaces;
|
|
453
|
+
private areaThreshold;
|
|
454
|
+
constructor(mesh: NonManifoldMesh, verbose?: boolean, areaThreshold?: number);
|
|
455
|
+
detect(): number;
|
|
456
|
+
repair(): number;
|
|
457
|
+
getName(): string;
|
|
458
|
+
canParallelize(): boolean;
|
|
459
|
+
}
|
|
460
|
+
|
|
435
461
|
/**
|
|
436
462
|
* Computes the Euclidean distance between two points.
|
|
437
463
|
*/
|
|
@@ -447,6 +473,21 @@ export declare function distanceSquared(a: Vec3, b: Vec3): number;
|
|
|
447
473
|
*/
|
|
448
474
|
export declare function dot(a: Vec3, b: Vec3): number;
|
|
449
475
|
|
|
476
|
+
/**
|
|
477
|
+
* Repairs duplicate faces (faces with identical vertices).
|
|
478
|
+
*/
|
|
479
|
+
export declare class DuplicateFaceRepair extends RepairOperation {
|
|
480
|
+
private duplicates;
|
|
481
|
+
detect(): number;
|
|
482
|
+
repair(): number;
|
|
483
|
+
/**
|
|
484
|
+
* Create canonical key from sorted vertex IDs.
|
|
485
|
+
*/
|
|
486
|
+
private makeFaceKey;
|
|
487
|
+
getName(): string;
|
|
488
|
+
canParallelize(): boolean;
|
|
489
|
+
}
|
|
490
|
+
|
|
450
491
|
/**
|
|
451
492
|
* Represents an undirected edge in the mesh.
|
|
452
493
|
* For non-manifold meshes, an edge can have more than 2 halfedges.
|
|
@@ -1215,6 +1256,17 @@ export declare function isDelaunay(edge: Edge): boolean;
|
|
|
1215
1256
|
*/
|
|
1216
1257
|
export declare function isManifold(geometry: BufferGeometry): boolean;
|
|
1217
1258
|
|
|
1259
|
+
/**
|
|
1260
|
+
* Repairs isolated vertices (vertices with no incident halfedges).
|
|
1261
|
+
*/
|
|
1262
|
+
export declare class IsolatedVertexRepair extends RepairOperation {
|
|
1263
|
+
private isolatedVertices;
|
|
1264
|
+
detect(): number;
|
|
1265
|
+
repair(): number;
|
|
1266
|
+
getName(): string;
|
|
1267
|
+
canParallelize(): boolean;
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1218
1270
|
/**
|
|
1219
1271
|
* Checks if a point lies inside a triangle (using barycentric coordinates).
|
|
1220
1272
|
*/
|
|
@@ -1379,6 +1431,62 @@ export declare interface MeshQualityStats {
|
|
|
1379
1431
|
totalArea: number;
|
|
1380
1432
|
}
|
|
1381
1433
|
|
|
1434
|
+
/**
|
|
1435
|
+
* Advanced mesh repair with fine-grained control and composition.
|
|
1436
|
+
*/
|
|
1437
|
+
export declare class MeshRepairer {
|
|
1438
|
+
private mesh;
|
|
1439
|
+
private options;
|
|
1440
|
+
private operations;
|
|
1441
|
+
private stats;
|
|
1442
|
+
constructor(meshOrGeometry: NonManifoldMesh | BufferGeometry, options?: RepairOptions);
|
|
1443
|
+
/**
|
|
1444
|
+
* Remove isolated vertices (vertices with no faces).
|
|
1445
|
+
* @returns this for chaining
|
|
1446
|
+
*/
|
|
1447
|
+
removeIsolatedVertices(): this;
|
|
1448
|
+
/**
|
|
1449
|
+
* Remove zero-area and degenerate triangles.
|
|
1450
|
+
* @param areaThreshold - Minimum area threshold (default: 1e-10)
|
|
1451
|
+
* @returns this for chaining
|
|
1452
|
+
*/
|
|
1453
|
+
removeDegenerateFaces(areaThreshold?: number): this;
|
|
1454
|
+
/**
|
|
1455
|
+
* Remove duplicate faces with identical vertices.
|
|
1456
|
+
* @returns this for chaining
|
|
1457
|
+
*/
|
|
1458
|
+
removeDuplicateFaces(): this;
|
|
1459
|
+
/**
|
|
1460
|
+
* Run all common repairs in optimal order.
|
|
1461
|
+
* @returns this for chaining
|
|
1462
|
+
*/
|
|
1463
|
+
repairAll(): this;
|
|
1464
|
+
/**
|
|
1465
|
+
* Execute all queued operations.
|
|
1466
|
+
* @returns Repair statistics
|
|
1467
|
+
*/
|
|
1468
|
+
execute(): RepairStats;
|
|
1469
|
+
/**
|
|
1470
|
+
* Get current statistics.
|
|
1471
|
+
*/
|
|
1472
|
+
getStats(): RepairStats;
|
|
1473
|
+
/**
|
|
1474
|
+
* Get the repaired mesh.
|
|
1475
|
+
*/
|
|
1476
|
+
getMesh(): NonManifoldMesh;
|
|
1477
|
+
/**
|
|
1478
|
+
* Export to BufferGeometry.
|
|
1479
|
+
*/
|
|
1480
|
+
toBufferGeometry(): BufferGeometry;
|
|
1481
|
+
/**
|
|
1482
|
+
* Validate the mesh after repairs.
|
|
1483
|
+
*/
|
|
1484
|
+
validate(): {
|
|
1485
|
+
isValid: boolean;
|
|
1486
|
+
errors: string[];
|
|
1487
|
+
};
|
|
1488
|
+
}
|
|
1489
|
+
|
|
1382
1490
|
/**
|
|
1383
1491
|
* Computes the midpoint between two points.
|
|
1384
1492
|
*/
|
|
@@ -1585,6 +1693,24 @@ export declare interface NonManifoldVertexInfo {
|
|
|
1585
1693
|
*/
|
|
1586
1694
|
export declare function normalize(v: Vec3): Vec3;
|
|
1587
1695
|
|
|
1696
|
+
/**
|
|
1697
|
+
* Statistics for a single repair operation.
|
|
1698
|
+
*/
|
|
1699
|
+
export declare interface OperationStats {
|
|
1700
|
+
/** Name of the operation */
|
|
1701
|
+
operation: string;
|
|
1702
|
+
/** Number of defects found */
|
|
1703
|
+
defectsFound: number;
|
|
1704
|
+
/** Number of defects fixed */
|
|
1705
|
+
defectsFixed: number;
|
|
1706
|
+
/** Processing time in milliseconds */
|
|
1707
|
+
timeMs: number;
|
|
1708
|
+
/** Whether the operation succeeded */
|
|
1709
|
+
success: boolean;
|
|
1710
|
+
/** Reason for failure (if any) */
|
|
1711
|
+
reason?: string;
|
|
1712
|
+
}
|
|
1713
|
+
|
|
1588
1714
|
/**
|
|
1589
1715
|
* Projects a point onto a line defined by two points.
|
|
1590
1716
|
* Returns the closest point on the line to the given point.
|
|
@@ -1783,6 +1909,133 @@ export declare interface RemeshStats {
|
|
|
1783
1909
|
processingTimeMs: number;
|
|
1784
1910
|
}
|
|
1785
1911
|
|
|
1912
|
+
/**
|
|
1913
|
+
* Remove degenerate faces (zero area, duplicate vertices).
|
|
1914
|
+
*
|
|
1915
|
+
* @param geometry - Input BufferGeometry
|
|
1916
|
+
* @param options - Repair options with optional areaThreshold
|
|
1917
|
+
* @returns Repaired geometry and statistics
|
|
1918
|
+
*/
|
|
1919
|
+
export declare function removeDegenerateFaces(geometry: BufferGeometry, options?: RepairOptions & {
|
|
1920
|
+
areaThreshold?: number;
|
|
1921
|
+
}): RepairResult;
|
|
1922
|
+
|
|
1923
|
+
/**
|
|
1924
|
+
* Remove duplicate faces with identical vertices.
|
|
1925
|
+
*
|
|
1926
|
+
* @param geometry - Input BufferGeometry
|
|
1927
|
+
* @param options - Repair options
|
|
1928
|
+
* @returns Repaired geometry and statistics
|
|
1929
|
+
*/
|
|
1930
|
+
export declare function removeDuplicateFaces(geometry: BufferGeometry, options?: RepairOptions): RepairResult;
|
|
1931
|
+
|
|
1932
|
+
/**
|
|
1933
|
+
* Remove isolated vertices (vertices with no incident faces).
|
|
1934
|
+
*
|
|
1935
|
+
* @param geometry - Input BufferGeometry
|
|
1936
|
+
* @param options - Repair options
|
|
1937
|
+
* @returns Repaired geometry and statistics
|
|
1938
|
+
*/
|
|
1939
|
+
export declare function removeIsolatedVertices(geometry: BufferGeometry, options?: RepairOptions): RepairResult;
|
|
1940
|
+
|
|
1941
|
+
/**
|
|
1942
|
+
* Repair a mesh by applying all repair operations in optimal order.
|
|
1943
|
+
* Fast alternative to full remeshing for common defects.
|
|
1944
|
+
*
|
|
1945
|
+
* @param geometry - Input BufferGeometry
|
|
1946
|
+
* @param options - Repair options
|
|
1947
|
+
* @returns Repaired geometry and statistics
|
|
1948
|
+
*/
|
|
1949
|
+
export declare function repairMesh(geometry: BufferGeometry, options?: RepairOptions): RepairResult;
|
|
1950
|
+
|
|
1951
|
+
/**
|
|
1952
|
+
* Base class for all repair operations.
|
|
1953
|
+
*/
|
|
1954
|
+
export declare abstract class RepairOperation {
|
|
1955
|
+
protected mesh: NonManifoldMesh;
|
|
1956
|
+
protected verbose: boolean;
|
|
1957
|
+
constructor(mesh: NonManifoldMesh, verbose?: boolean);
|
|
1958
|
+
/**
|
|
1959
|
+
* Detect defects in the mesh.
|
|
1960
|
+
* @returns Number of defects found
|
|
1961
|
+
*/
|
|
1962
|
+
abstract detect(): number;
|
|
1963
|
+
/**
|
|
1964
|
+
* Repair the detected defects.
|
|
1965
|
+
* @returns Number of defects fixed
|
|
1966
|
+
*/
|
|
1967
|
+
abstract repair(): number;
|
|
1968
|
+
/**
|
|
1969
|
+
* Execute the operation (detect + repair).
|
|
1970
|
+
* @returns Operation statistics
|
|
1971
|
+
*/
|
|
1972
|
+
execute(): OperationStats;
|
|
1973
|
+
/**
|
|
1974
|
+
* Get the name of this operation.
|
|
1975
|
+
*/
|
|
1976
|
+
abstract getName(): string;
|
|
1977
|
+
/**
|
|
1978
|
+
* Check if this operation can be parallelized.
|
|
1979
|
+
*/
|
|
1980
|
+
abstract canParallelize(): boolean;
|
|
1981
|
+
}
|
|
1982
|
+
|
|
1983
|
+
/**
|
|
1984
|
+
* Options for mesh repair operations.
|
|
1985
|
+
*/
|
|
1986
|
+
export declare interface RepairOptions {
|
|
1987
|
+
/** Use Web Workers for parallel processing (default: true for large meshes) */
|
|
1988
|
+
useWorkers?: boolean;
|
|
1989
|
+
/** Number of worker threads (default: navigator.hardwareConcurrency || 4) */
|
|
1990
|
+
workerCount?: number;
|
|
1991
|
+
/** Use spatial acceleration structures (default: true) */
|
|
1992
|
+
useAcceleration?: boolean;
|
|
1993
|
+
/** Minimum mesh size to trigger parallelization (default: 10000 faces) */
|
|
1994
|
+
parallelThreshold?: number;
|
|
1995
|
+
/** Enable verbose logging (default: false) */
|
|
1996
|
+
verbose?: boolean;
|
|
1997
|
+
/** Validate topology after each operation (default: false) */
|
|
1998
|
+
validateAfterEach?: boolean;
|
|
1999
|
+
}
|
|
2000
|
+
|
|
2001
|
+
/**
|
|
2002
|
+
* Result of a repair operation.
|
|
2003
|
+
*/
|
|
2004
|
+
export declare interface RepairResult {
|
|
2005
|
+
/** The repaired geometry */
|
|
2006
|
+
geometry: BufferGeometry;
|
|
2007
|
+
/** Repair statistics */
|
|
2008
|
+
stats: RepairStats;
|
|
2009
|
+
}
|
|
2010
|
+
|
|
2011
|
+
/**
|
|
2012
|
+
* Overall repair statistics.
|
|
2013
|
+
*/
|
|
2014
|
+
export declare interface RepairStats {
|
|
2015
|
+
/** Input mesh statistics */
|
|
2016
|
+
input: {
|
|
2017
|
+
vertices: number;
|
|
2018
|
+
faces: number;
|
|
2019
|
+
edges: number;
|
|
2020
|
+
};
|
|
2021
|
+
/** Output mesh statistics */
|
|
2022
|
+
output: {
|
|
2023
|
+
vertices: number;
|
|
2024
|
+
faces: number;
|
|
2025
|
+
edges: number;
|
|
2026
|
+
};
|
|
2027
|
+
/** Statistics for each operation performed */
|
|
2028
|
+
operations: OperationStats[];
|
|
2029
|
+
/** Total processing time in milliseconds */
|
|
2030
|
+
totalTimeMs: number;
|
|
2031
|
+
/** Whether all operations succeeded */
|
|
2032
|
+
success: boolean;
|
|
2033
|
+
/** Total defects found */
|
|
2034
|
+
totalDefectsFound: number;
|
|
2035
|
+
/** Total defects fixed */
|
|
2036
|
+
totalDefectsFixed: number;
|
|
2037
|
+
}
|
|
2038
|
+
|
|
1786
2039
|
/**
|
|
1787
2040
|
* Multiplies a vector by a scalar.
|
|
1788
2041
|
*/
|