occt-wasm 3.2.2 → 3.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 +410 -0
- package/dist/index.d.ts +76 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +142 -3
- package/dist/index.js.map +1 -1
- package/dist/occt-wasm.wasm +0 -0
- package/dist/svg.d.ts +75 -0
- package/dist/svg.d.ts.map +1 -0
- package/dist/svg.js +304 -0
- package/dist/svg.js.map +1 -0
- package/dist/types.d.ts +18 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +12 -0
- package/dist/types.js.map +1 -1
- package/dist/xcaf-document.d.ts +1 -0
- package/dist/xcaf-document.d.ts.map +1 -1
- package/dist/xcaf-document.js.map +1 -1
- package/package.json +2 -1
package/README.md
ADDED
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# occt-wasm
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/occt-wasm)
|
|
6
|
+
[](https://crates.io/crates/occt-wasm)
|
|
7
|
+
[](https://github.com/andymai/occt-wasm/actions/workflows/ci.yml)
|
|
8
|
+
[](https://github.com/andymai/occt-wasm/releases)
|
|
9
|
+
[](https://github.com/andymai/occt-wasm/commits/main)
|
|
10
|
+
[](#license) [](#license)
|
|
11
|
+
|
|
12
|
+
[OpenCascade](https://github.com/Open-Cascade-SAS/OCCT) V8 compiled to WebAssembly with a clean TypeScript API.
|
|
13
|
+
|
|
14
|
+
Smaller bundles, branded types, arena-based memory, and modern tooling.
|
|
15
|
+
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
> **Looking for a higher-level CAD library?** [brepjs](https://github.com/andymai/brepjs) builds on occt-wasm with a friendlier API for parametric modeling, sketching, and production CAD applications. Use occt-wasm directly when you need full control over OCCT operations.
|
|
19
|
+
|
|
20
|
+
## Highlights
|
|
21
|
+
|
|
22
|
+
- **~4.5 MB brotli** -- roughly 2x smaller than opencascade.js
|
|
23
|
+
- **Comprehensive API** -- primitives, booleans, sweeps, XCAF assemblies, curves, surfaces, STEP/STL/glTF/BREP I/O, topology, shape evolution tracking
|
|
24
|
+
- **Arena-based API** -- u32 shape handles, no manual `.delete()`, `Symbol.dispose` support
|
|
25
|
+
- **TypeScript-first** -- branded `ShapeHandle`, union types for shapes/surfaces/curves, structured returns
|
|
26
|
+
- **Structured error handling** -- `OcctErrorCode` enum for programmatic `switch/case` instead of string parsing
|
|
27
|
+
- **Web Worker support** -- `OcctWorker` class for off-main-thread CAD operations via [Comlink](https://github.com/GoogleChromeLabs/comlink)
|
|
28
|
+
- **Modern browser targets** -- WASM SIMD, relaxed-SIMD, tail calls, wasm-exceptions
|
|
29
|
+
|
|
30
|
+
## Scope
|
|
31
|
+
|
|
32
|
+
To set expectations, this library deliberately does not:
|
|
33
|
+
|
|
34
|
+
- **Provide a higher-level CAD modeling API** — parametric sketching, constraints, feature trees, and ergonomic modeling belong in [brepjs](https://github.com/andymai/brepjs), which wraps occt-wasm for that purpose
|
|
35
|
+
- **Manage memory automatically beyond arena handles** — shapes are freed when the kernel is disposed or you call `release()`; there is no per-shape garbage collection
|
|
36
|
+
- **Support non-WASM-SIMD browsers** — the build requires WASM SIMD (baseline `-msimd128`), tail calls, and wasm exceptions; Firefox lacks tail call support as of v130. Relaxed-SIMD is intentionally not used: some Safari/iOS WebKit builds fail to compile relaxed-SIMD modules, and it made geometry non-reproducible across CPUs
|
|
37
|
+
- **Include OCCT visualization or display modules** — TKV3d, TKHLR (except the HLR facade), and the AIS interactive context are excluded; bring your own renderer (Three.js, Babylon.js, etc.)
|
|
38
|
+
- **Support IGES import/export** -- TKDEIGES is excluded from the link; use STEP for interchange
|
|
39
|
+
|
|
40
|
+
## Install
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
npm install occt-wasm
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Quick Start
|
|
47
|
+
|
|
48
|
+
```typescript
|
|
49
|
+
import { OcctKernel } from "occt-wasm";
|
|
50
|
+
|
|
51
|
+
// Recommended: deterministic cleanup via Symbol.dispose
|
|
52
|
+
{
|
|
53
|
+
using kernel = await OcctKernel.init();
|
|
54
|
+
|
|
55
|
+
// Primitives
|
|
56
|
+
const box = kernel.makeBox(20, 20, 20);
|
|
57
|
+
const cyl = kernel.makeCylinder(8, 30);
|
|
58
|
+
|
|
59
|
+
// Booleans
|
|
60
|
+
const fused = kernel.fuse(box, cyl);
|
|
61
|
+
|
|
62
|
+
// Modeling
|
|
63
|
+
const edges = kernel.getSubShapes(fused, "edge");
|
|
64
|
+
const filleted = kernel.fillet(fused, edges.slice(0, 4), 2.0);
|
|
65
|
+
|
|
66
|
+
// Tessellation -> Three.js / Babylon.js
|
|
67
|
+
const mesh = kernel.tessellate(filleted);
|
|
68
|
+
// mesh.positions (Float32Array), mesh.normals, mesh.indices
|
|
69
|
+
|
|
70
|
+
// STEP I/O
|
|
71
|
+
const step = kernel.exportStep(filleted);
|
|
72
|
+
const reimported = kernel.importStep(step);
|
|
73
|
+
|
|
74
|
+
// Query
|
|
75
|
+
const vol = kernel.getVolume(filleted);
|
|
76
|
+
const bbox = kernel.getBoundingBox(filleted);
|
|
77
|
+
const com = kernel.getCenterOfMass(filleted);
|
|
78
|
+
|
|
79
|
+
// kernel is disposed at end of block
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Rust Crate
|
|
84
|
+
|
|
85
|
+
The same OCCT WASM is available as a [Rust crate](https://crates.io/crates/occt-wasm) for native targets (servers, CLIs, build scripts) — no C++ toolchain required:
|
|
86
|
+
|
|
87
|
+
```toml
|
|
88
|
+
[dependencies]
|
|
89
|
+
occt-wasm = "3"
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
```rust
|
|
93
|
+
use occt_wasm::OcctKernel;
|
|
94
|
+
|
|
95
|
+
let mut kernel = OcctKernel::new()?;
|
|
96
|
+
let box_shape = kernel.make_box(10.0, 20.0, 30.0)?;
|
|
97
|
+
let sphere = kernel.make_sphere(8.0)?;
|
|
98
|
+
let fused = kernel.fuse(box_shape, sphere)?;
|
|
99
|
+
let mesh = kernel.tessellate(fused, 0.1, 0.5)?;
|
|
100
|
+
let step = kernel.export_step(fused)?;
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
The crate embeds a brotli-compressed WASM binary (~4.7 MB) and runs it via [wasmtime](https://wasmtime.dev/). Same 170+ facade methods as the TS API. See [`crate/README.md`](./crate/README.md) and [docs.rs/occt-wasm](https://docs.rs/occt-wasm) for full details.
|
|
104
|
+
|
|
105
|
+
## Initialization
|
|
106
|
+
|
|
107
|
+
By default, `OcctKernel.init()` auto-locates the `.wasm` file next to the JS module. You can also provide explicit paths or pre-loaded binaries:
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
// Auto-detect (browser, Node.js, or Worker):
|
|
111
|
+
const kernel = await OcctKernel.init();
|
|
112
|
+
|
|
113
|
+
// Explicit URL or path:
|
|
114
|
+
const kernel = await OcctKernel.init({ wasm: "/assets/occt-wasm.wasm" });
|
|
115
|
+
|
|
116
|
+
// Pre-fetched binary (skip the fetch):
|
|
117
|
+
const binary = await fetch("/occt-wasm.wasm").then((r) => r.arrayBuffer());
|
|
118
|
+
const kernel = await OcctKernel.init({ wasm: binary });
|
|
119
|
+
|
|
120
|
+
// Uint8Array also accepted:
|
|
121
|
+
const kernel = await OcctKernel.init({ wasm: new Uint8Array(binary) });
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Error Handling
|
|
125
|
+
|
|
126
|
+
All errors are instances of `OcctError` with a structured `code` field for programmatic handling:
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
import { OcctError, OcctErrorCode } from "occt-wasm";
|
|
130
|
+
|
|
131
|
+
try {
|
|
132
|
+
kernel.fuse(a, b);
|
|
133
|
+
} catch (e) {
|
|
134
|
+
if (e instanceof OcctError) {
|
|
135
|
+
switch (e.code) {
|
|
136
|
+
case OcctErrorCode.BooleanFailed:
|
|
137
|
+
// retry with simpler geometry
|
|
138
|
+
break;
|
|
139
|
+
case OcctErrorCode.InvalidShapeId:
|
|
140
|
+
// shape was already released
|
|
141
|
+
break;
|
|
142
|
+
case OcctErrorCode.KernelError:
|
|
143
|
+
// OCCT internal error (Standard_Failure)
|
|
144
|
+
console.error(e.message);
|
|
145
|
+
break;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Available error codes:
|
|
152
|
+
|
|
153
|
+
| Code | When |
|
|
154
|
+
| -------------------- | ----------------------------------------------- |
|
|
155
|
+
| `ConstructionFailed` | `Build()`/`IsDone()` returned false |
|
|
156
|
+
| `BooleanFailed` | Boolean operation (fuse/cut/common/etc.) failed |
|
|
157
|
+
| `InvalidShapeId` | Shape ID not found in the arena |
|
|
158
|
+
| `InvalidLabelId` | XCAF label ID not found |
|
|
159
|
+
| `TessellationFailed` | Meshing operation failed |
|
|
160
|
+
| `ImportExportFailed` | STEP/STL/BREP I/O error |
|
|
161
|
+
| `HealingFailed` | Shape repair failed |
|
|
162
|
+
| `DocumentClosed` | Operation on a closed XCAF document |
|
|
163
|
+
| `KernelError` | OCCT `Standard_Failure` (unclassified) |
|
|
164
|
+
| `Unknown` | Error from outside the kernel |
|
|
165
|
+
|
|
166
|
+
## Named Enums
|
|
167
|
+
|
|
168
|
+
Sweep, offset, and boolean operations use self-documenting enums instead of opaque numbers:
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
import { TransitionMode, JoinType, BooleanOp } from "occt-wasm";
|
|
172
|
+
|
|
173
|
+
// Sweep with round-corner transitions
|
|
174
|
+
kernel.sweep(profile, spine, TransitionMode.RoundCorner);
|
|
175
|
+
|
|
176
|
+
// Offset wire with arc joins
|
|
177
|
+
kernel.offsetWire2D(wire, 2.0, JoinType.Arc);
|
|
178
|
+
|
|
179
|
+
// Boolean pipeline
|
|
180
|
+
kernel.booleanPipeline(base, [BooleanOp.Cut, BooleanOp.Fuse], [tool1, tool2]);
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Numeric values (0, 1, 2) are still accepted for backwards compatibility.
|
|
184
|
+
|
|
185
|
+
## Type Predicates
|
|
186
|
+
|
|
187
|
+
Convenience methods for checking shape topology:
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
if (kernel.isSolid(shape)) {
|
|
191
|
+
/* ... */
|
|
192
|
+
}
|
|
193
|
+
if (kernel.isFace(shape)) {
|
|
194
|
+
/* ... */
|
|
195
|
+
}
|
|
196
|
+
if (kernel.isEdge(shape)) {
|
|
197
|
+
/* ... */
|
|
198
|
+
}
|
|
199
|
+
if (kernel.isWire(shape)) {
|
|
200
|
+
/* ... */
|
|
201
|
+
}
|
|
202
|
+
if (kernel.isVertex(shape)) {
|
|
203
|
+
/* ... */
|
|
204
|
+
}
|
|
205
|
+
if (kernel.isShell(shape)) {
|
|
206
|
+
/* ... */
|
|
207
|
+
}
|
|
208
|
+
if (kernel.isCompound(shape)) {
|
|
209
|
+
/* ... */
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## Web Workers
|
|
214
|
+
|
|
215
|
+
For browser apps, heavy CAD operations can block the main thread. `OcctWorker` runs a full kernel in a Web Worker with the same API:
|
|
216
|
+
|
|
217
|
+
```typescript
|
|
218
|
+
import { OcctWorker } from "occt-wasm/worker";
|
|
219
|
+
|
|
220
|
+
// Spawn a worker with its own kernel
|
|
221
|
+
const worker = await OcctWorker.spawn({ wasm: "/occt-wasm.wasm" });
|
|
222
|
+
|
|
223
|
+
// Same API, every call returns a Promise
|
|
224
|
+
const box = await worker.makeBox(10, 20, 30);
|
|
225
|
+
const cyl = await worker.makeCylinder(5, 40);
|
|
226
|
+
const fused = await worker.fuse(box, cyl);
|
|
227
|
+
const mesh = await worker.tessellate(fused);
|
|
228
|
+
console.log(`${mesh.triangleCount} triangles`);
|
|
229
|
+
|
|
230
|
+
// Access the full kernel via .kernel for less common methods
|
|
231
|
+
const nurbs = await worker.kernel.getNurbsCurveData(edge);
|
|
232
|
+
|
|
233
|
+
// Clean up
|
|
234
|
+
worker.terminate();
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
The worker helper uses [Comlink](https://github.com/GoogleChromeLabs/comlink) (~1.2 KB gzipped) for transparent RPC. Each worker has its own WASM instance and arena -- shape handles are local to the worker.
|
|
238
|
+
|
|
239
|
+
## XCAF Assemblies
|
|
240
|
+
|
|
241
|
+
Create assembly documents with colors, names, and component hierarchies:
|
|
242
|
+
|
|
243
|
+
```typescript
|
|
244
|
+
// Factory method auto-injects Emscripten FS for glTF export
|
|
245
|
+
const doc = kernel.createXCAFDocument();
|
|
246
|
+
|
|
247
|
+
const housing = doc.addShape(box, { name: "housing", color: [0.8, 0.2, 0.1] });
|
|
248
|
+
doc.addChild(housing, gear, {
|
|
249
|
+
name: "gear-1",
|
|
250
|
+
location: { tx: 10, tz: 5 },
|
|
251
|
+
color: [0.5, 0.5, 0.5],
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
// Export
|
|
255
|
+
const step = doc.exportSTEP(); // preserves colors/names
|
|
256
|
+
const glb = doc.exportGLTF(); // no need to pass FS manually
|
|
257
|
+
doc.close();
|
|
258
|
+
|
|
259
|
+
// Import with preserved metadata
|
|
260
|
+
const imported = kernel.importXCAFFromSTEP(stepData);
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
## Bundler Configuration
|
|
264
|
+
|
|
265
|
+
### Vite
|
|
266
|
+
|
|
267
|
+
```typescript
|
|
268
|
+
// vite.config.ts
|
|
269
|
+
export default defineConfig({
|
|
270
|
+
optimizeDeps: {
|
|
271
|
+
exclude: ["occt-wasm"], // Don't pre-bundle WASM
|
|
272
|
+
},
|
|
273
|
+
build: {
|
|
274
|
+
target: "esnext", // Required for WASM features
|
|
275
|
+
},
|
|
276
|
+
});
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
### Webpack 5
|
|
280
|
+
|
|
281
|
+
```javascript
|
|
282
|
+
// webpack.config.js
|
|
283
|
+
module.exports = {
|
|
284
|
+
experiments: { asyncWebAssembly: true },
|
|
285
|
+
module: {
|
|
286
|
+
rules: [{ test: /\.wasm$/, type: "asset/resource" }],
|
|
287
|
+
},
|
|
288
|
+
};
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
### Node.js
|
|
292
|
+
|
|
293
|
+
```typescript
|
|
294
|
+
// Works out of the box with Node.js 18+
|
|
295
|
+
import { OcctKernel } from "occt-wasm";
|
|
296
|
+
const kernel = await OcctKernel.init();
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
## API Reference
|
|
300
|
+
|
|
301
|
+
Generate full docs locally: `cd ts && npm run docs` (TypeDoc output).
|
|
302
|
+
|
|
303
|
+
| Category | What's covered |
|
|
304
|
+
| ---------------- | -------------------------------------------------------------------------------------------------------------- |
|
|
305
|
+
| **Primitives** | Box, cylinder, sphere, cone, torus, ellipsoid, rectangle, half-space |
|
|
306
|
+
| **Booleans** | Fuse, cut, common, intersect, section + multi-shape variants, intersection cells |
|
|
307
|
+
| **Modeling** | Extrude, revolve, fillet, chamfer, shell, offset, draft |
|
|
308
|
+
| **Sweeps** | Pipe, loft, sweep, oriented sweep (fixed/Frenet/up-axis/auxiliary), draft prism, extrusion laws |
|
|
309
|
+
| **Construction** | Vertices, edges (line/arc/circle/ellipse/bezier/helix), wires, faces, solids, compounds, sewing |
|
|
310
|
+
| **Transforms** | Translate, rotate, scale, mirror, align to bounding box, 3x4 matrix, linear/circular patterns |
|
|
311
|
+
| **Topology** | Shape type queries, type predicates, sub-shape extraction, adjacency, hash codes |
|
|
312
|
+
| **Tessellation** | Triangle meshes (absolute or relative deflection), wireframe polylines, per-face groups, batched meshing |
|
|
313
|
+
| **I/O** | STEP, STL, BREP (text + binary) import/export |
|
|
314
|
+
| **Query** | Bounding box, volume, surface area, length, center of mass, inertia tensor, point-in-solid, curvature |
|
|
315
|
+
| **Surfaces** | Type, normal, UV bounds, point classification, B-spline construction |
|
|
316
|
+
| **Curves** | Type, point/tangent eval, parameters, NURBS data, interpolation (incl. clamped tangents), project point |
|
|
317
|
+
| **Projection** | Hidden line removal (HLR), multiview SVG render (Front/Top/Right/Iso) |
|
|
318
|
+
| **Modifiers** | Thicken, defeature, reverse, simplify, variable fillet, 2D wire offset |
|
|
319
|
+
| **Evolution** | Face-tracking history for translate, fuse, cut, fillet, rotate, mirror, scale, chamfer, shell, offset, thicken |
|
|
320
|
+
| **XCAF** | Assembly documents with colors, names, component hierarchies, STEP/glTF export |
|
|
321
|
+
| **Healing** | Fix shape, unify domain, heal solid/face/wire, fix orientations, remove degenerate edges |
|
|
322
|
+
| **Batch** | Multi-shape translate, chained boolean pipeline |
|
|
323
|
+
|
|
324
|
+
## Architecture
|
|
325
|
+
|
|
326
|
+
```
|
|
327
|
+
OCCT V8.0.0 C++ (git submodule)
|
|
328
|
+
-> emcmake cmake (48 static libs)
|
|
329
|
+
-> C++ facade (OcctKernel class, arena-based u32 IDs)
|
|
330
|
+
-> Embind bindings
|
|
331
|
+
-> emcc link (-O3, -flto, -fwasm-exceptions, SIMD) -> .wasm
|
|
332
|
+
-> wasm-opt -O4 --converge --gufa -> dist/ (20.8 MB)
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
Built with Rust xtask (`cargo xtask build`), tested with Vitest.
|
|
336
|
+
|
|
337
|
+
## Size & Performance
|
|
338
|
+
|
|
339
|
+
Compared against other OCCT-to-WASM builds (all include STEP, XCAF, glTF):
|
|
340
|
+
|
|
341
|
+
| Build | brotli |
|
|
342
|
+
| ------------------ | ------- |
|
|
343
|
+
| **occt-wasm** | ~4.5 MB |
|
|
344
|
+
| opencascade.js | ~9 MB |
|
|
345
|
+
| brepjs-opencascade | ~5 MB |
|
|
346
|
+
|
|
347
|
+
Run benchmarks locally: `npx tsx test/benchmark.ts`
|
|
348
|
+
|
|
349
|
+
## Development
|
|
350
|
+
|
|
351
|
+
### Building from Source
|
|
352
|
+
|
|
353
|
+
```bash
|
|
354
|
+
# Prerequisites: Rust 1.85+, emsdk 5.0.3
|
|
355
|
+
git clone --recurse-submodules https://github.com/andymai/occt-wasm
|
|
356
|
+
cd occt-wasm
|
|
357
|
+
npm install && cd ts && npm install && cd ..
|
|
358
|
+
|
|
359
|
+
cargo xtask build # Build OCCT + facade -> WASM
|
|
360
|
+
cargo xtask test # Run tests
|
|
361
|
+
|
|
362
|
+
# View the Three.js example
|
|
363
|
+
npx serve .
|
|
364
|
+
# Open http://localhost:3000/examples/three-js/
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
### Docker Build
|
|
368
|
+
|
|
369
|
+
No local emsdk or Rust needed -- everything runs in the container.
|
|
370
|
+
|
|
371
|
+
```bash
|
|
372
|
+
npm run docker:build # Build image (OCCT layer cached after first run)
|
|
373
|
+
npm run docker:dist # Build + copy dist/ artifacts to host
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
## Browser Compatibility
|
|
377
|
+
|
|
378
|
+
occt-wasm requires modern browsers with WASM SIMD, relaxed-SIMD, tail calls, and exception handling:
|
|
379
|
+
|
|
380
|
+
| Browser | Minimum Version | Notes |
|
|
381
|
+
| ------- | --------------- | -------------------------------------- |
|
|
382
|
+
| Chrome | 114+ | Relaxed-SIMD (114), tail calls (112) |
|
|
383
|
+
| Edge | 114+ | Same engine as Chrome |
|
|
384
|
+
| Safari | 17.2+ | Relaxed-SIMD (17.2), tail calls (15) |
|
|
385
|
+
| Firefox | Not supported | No tail call support as of Firefox 130 |
|
|
386
|
+
|
|
387
|
+
Node.js 22+ is recommended (tail calls via V8). Node.js 18+ works if your V8 version supports the required WASM features.
|
|
388
|
+
|
|
389
|
+
## Known Limitations
|
|
390
|
+
|
|
391
|
+
These are upstream OCCT V8.0.0 issues, not occt-wasm bugs:
|
|
392
|
+
|
|
393
|
+
- **IGES** -- TKDEIGES excluded from link; no IGES import/export
|
|
394
|
+
- **Zero-length extrusion** -- WASM exception escapes JS catch boundary (1 test skip)
|
|
395
|
+
- **Single WASM thread** -- each kernel instance is single-threaded; use `OcctWorker` (see above) to move work off the main thread
|
|
396
|
+
- **Firefox** -- not supported due to missing WASM tail call support
|
|
397
|
+
|
|
398
|
+
These will be addressed as upstream OCCT and browser support improve.
|
|
399
|
+
|
|
400
|
+
## Contributing
|
|
401
|
+
|
|
402
|
+
This project is open source. Bug reports and feature requests are welcome via GitHub Issues. For pull requests, please open an issue first to discuss the change.
|
|
403
|
+
|
|
404
|
+
## License
|
|
405
|
+
|
|
406
|
+
**Build tooling** (xtask, scripts, TypeScript wrapper): MIT OR Apache-2.0
|
|
407
|
+
|
|
408
|
+
**Compiled WASM output**: LGPL-2.1-only (inherits from [OCCT](https://dev.opencascade.org/resources/download))
|
|
409
|
+
|
|
410
|
+
The LGPL requires that end users can replace the LGPL component. For web applications, this is satisfied by loading the `.wasm` file from a URL (which users can override via `OcctKernel.init({ wasm: '...' })`). If you ship a desktop app with the WASM embedded, consult the [LGPL-2.1 FAQ](https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html).
|
package/dist/index.d.ts
CHANGED
|
@@ -12,11 +12,13 @@
|
|
|
12
12
|
* kernel.release(box);
|
|
13
13
|
* ```
|
|
14
14
|
*/
|
|
15
|
-
export { BooleanOp, JoinType, OcctError, OcctErrorCode, TransitionMode, type AddChildOptions, type AddShapeOptions, type BoundingBox, type Color3, type CurveKind, type CurvatureData, type EdgeData, type EvolutionData, type GLTFExportOptions, type InitOptions, type LabelInfo, type LabelTag, type Location, type Mesh, type MeshBatchData, type NurbsCurveData, type ShapeQueryResult, type PointClassification, type ProjectionData, type ShapeHandle, type ShapeOrientation, type ShapeType, type SurfaceKind, type TessellateOptions, type UVBounds, type Vec3, } from "./types.js";
|
|
15
|
+
export { BooleanOp, JoinType, OcctError, OcctErrorCode, SweepMode, TransitionMode, type AddChildOptions, type AddShapeOptions, type AlignAnchor, type BoundingBox, type Color3, type CurveKind, type CurvatureData, type EdgeData, type EvolutionData, type GLTFExportOptions, type InitOptions, type LabelInfo, type LabelTag, type Location, type Mesh, type MeshBatchData, type NurbsCurveData, type ShapeQueryResult, type PointClassification, type ProjectionData, type ShapeHandle, type ShapeOrientation, type ShapeType, type SurfaceKind, type TessellateOptions, type UVBounds, type Vec3, } from "./types.js";
|
|
16
16
|
export { XCAFDocument, type EmscriptenFS } from "./xcaf-document.js";
|
|
17
17
|
import { XCAFDocument as XCAFDocumentImpl, type EmscriptenFS } from "./xcaf-document.js";
|
|
18
|
-
|
|
19
|
-
import {
|
|
18
|
+
export { renderMultiviewSVG, renderShapeSVG, type MultiviewSvgOptions, type SvgViewOptions, type ViewName, } from "./svg.js";
|
|
19
|
+
import { type MultiviewSvgOptions, type SvgViewOptions, type ViewName } from "./svg.js";
|
|
20
|
+
import type { AlignAnchor, BoundingBox, CurveKind, CurvatureData, EdgeData, EvolutionData, InitOptions, Mesh, MeshBatchData, NurbsCurveData, PointClassification, ProjectionData, ShapeHandle, ShapeQueryResult, ShapeOrientation, ShapeType, SurfaceKind, TessellateOptions, BooleanOp, UVBounds, Vec3 } from "./types.js";
|
|
21
|
+
import { JoinType, SweepMode, TransitionMode } from "./types.js";
|
|
20
22
|
/**
|
|
21
23
|
* The Emscripten module exposed by `occt-wasm.js`. Provides Embind class
|
|
22
24
|
* constructors, std::vector wrappers, and typed-array views into WASM
|
|
@@ -129,6 +131,7 @@ export interface OcctRawKernel {
|
|
|
129
131
|
makeSphere(radius: number): number;
|
|
130
132
|
makeCone(r1: number, r2: number, height: number): number;
|
|
131
133
|
makeTorus(majorRadius: number, minorRadius: number): number;
|
|
134
|
+
halfSpace(ox: number, oy: number, oz: number, nx: number, ny: number, nz: number): number;
|
|
132
135
|
makeEllipsoid(rx: number, ry: number, rz: number): number;
|
|
133
136
|
makeRectangle(width: number, height: number): number;
|
|
134
137
|
fuse(a: number, b: number): number;
|
|
@@ -139,6 +142,7 @@ export interface OcctRawKernel {
|
|
|
139
142
|
fuseAll(shapeIds: EmbindVectorU32): number;
|
|
140
143
|
cutAll(shapeId: number, toolIds: EmbindVectorU32): number;
|
|
141
144
|
split(shapeId: number, toolIds: EmbindVectorU32): number;
|
|
145
|
+
intersectionCells(shapeIds: EmbindVectorU32): number;
|
|
142
146
|
extrude(id: number, dx: number, dy: number, dz: number): number;
|
|
143
147
|
revolve(id: number, px: number, py: number, pz: number, dx: number, dy: number, dz: number, angle: number): number;
|
|
144
148
|
fillet(solidId: number, edgeIds: EmbindVectorU32, radius: number): number;
|
|
@@ -153,6 +157,7 @@ export interface OcctRawKernel {
|
|
|
153
157
|
loftWithVertices(wireIds: EmbindVectorU32, isSolid: boolean, ruled: boolean, startVertexId: number, endVertexId: number): number;
|
|
154
158
|
sweep(wireId: number, spineId: number, transitionMode: number): number;
|
|
155
159
|
sweepPipeShell(profileId: number, spineId: number, freenet: boolean, smooth: boolean): number;
|
|
160
|
+
sweepOriented(profileId: number, spineId: number, mode: number, upX: number, upY: number, upZ: number, auxSpineId: number): number;
|
|
156
161
|
draftPrism(shapeId: number, dx: number, dy: number, dz: number, angleDeg: number): number;
|
|
157
162
|
revolveVec(shapeId: number, cx: number, cy: number, cz: number, dx: number, dy: number, dz: number, angle: number): number;
|
|
158
163
|
makeVertex(x: number, y: number, z: number): number;
|
|
@@ -211,6 +216,7 @@ export interface OcctRawKernel {
|
|
|
211
216
|
iterShapes(id: number): EmbindVectorU32;
|
|
212
217
|
edgeToFaceMap(id: number, hashUpperBound: number): EmbindVectorI32;
|
|
213
218
|
tessellate(id: number, linDefl: number, angDefl: number): RawMeshData;
|
|
219
|
+
tessellateRelative(id: number, linDefl: number, angDefl: number): RawMeshData;
|
|
214
220
|
wireframe(id: number, deflection: number): RawEdgeData;
|
|
215
221
|
hasTriangulation(id: number): boolean;
|
|
216
222
|
meshShape(id: number, linDefl: number, angDefl: number): RawMeshData;
|
|
@@ -221,11 +227,15 @@ export interface OcctRawKernel {
|
|
|
221
227
|
exportStl(id: number, linearDeflection: number, ascii: boolean): string;
|
|
222
228
|
toBREP(id: number): string;
|
|
223
229
|
fromBREP(data: string): number;
|
|
230
|
+
exportBrepBinary(id: number): string;
|
|
231
|
+
importBrepBinary(path: string): number;
|
|
224
232
|
getBoundingBox(id: number, useTriangulation: boolean): BoundingBox;
|
|
225
233
|
getVolume(id: number): number;
|
|
226
234
|
getSurfaceArea(id: number): number;
|
|
227
235
|
getLength(id: number): number;
|
|
228
236
|
getCenterOfMass(id: number): EmbindVectorF64;
|
|
237
|
+
getInertia(id: number): EmbindVectorF64;
|
|
238
|
+
containsPoint(id: number, x: number, y: number, z: number, tolerance: number): boolean;
|
|
229
239
|
getSurfaceCenterOfMass(faceId: number): EmbindVectorF64;
|
|
230
240
|
getLinearCenterOfMass(id: number): EmbindVectorF64;
|
|
231
241
|
surfaceCurvature(faceId: number, u: number, v: number): EmbindVectorF64;
|
|
@@ -248,6 +258,8 @@ export interface OcctRawKernel {
|
|
|
248
258
|
curveIsPeriodic(edgeId: number): boolean;
|
|
249
259
|
curveLength(edgeId: number): number;
|
|
250
260
|
interpolatePoints(flatPoints: EmbindVectorF64, periodic: boolean): number;
|
|
261
|
+
interpolatePointsWithTangents(flatPoints: EmbindVectorF64, startTanX: number, startTanY: number, startTanZ: number, endTanX: number, endTanY: number, endTanZ: number): number;
|
|
262
|
+
projectPointOnEdge(edgeId: number, x: number, y: number, z: number): EmbindVectorF64;
|
|
251
263
|
approximatePoints(flatPoints: EmbindVectorF64, tolerance: number): number;
|
|
252
264
|
getNurbsCurveData(edgeId: number): RawNurbsCurveData;
|
|
253
265
|
liftCurve2dToPlane(flatPoints2d: EmbindVectorF64, planeOx: number, planeOy: number, planeOz: number, planeZx: number, planeZy: number, planeZz: number, planeXx: number, planeXy: number, planeXz: number): number;
|
|
@@ -361,6 +373,12 @@ export declare class OcctKernel {
|
|
|
361
373
|
/** Create a torus solid at the origin (BRepPrimAPI_MakeTorus).
|
|
362
374
|
* @throws OcctError */
|
|
363
375
|
makeTorus(majorRadius: number, minorRadius: number): ShapeHandle;
|
|
376
|
+
/**
|
|
377
|
+
* Infinite half-space solid bounded by the plane through `origin` with the
|
|
378
|
+
* given `normal`. The solid fills the side the normal points into — useful
|
|
379
|
+
* as an unbounded boolean cutting tool.
|
|
380
|
+
*/
|
|
381
|
+
halfSpace(origin: Vec3, normal: Vec3): ShapeHandle;
|
|
364
382
|
/** Create an ellipsoid solid at the origin by scaling a sphere.
|
|
365
383
|
* @param rx - radius along X
|
|
366
384
|
* @param ry - radius along Y
|
|
@@ -396,6 +414,12 @@ export declare class OcctKernel {
|
|
|
396
414
|
* @returns A compound of the split fragments
|
|
397
415
|
* @throws OcctError */
|
|
398
416
|
split(shape: ShapeHandle, tools: ShapeHandle[]): ShapeHandle;
|
|
417
|
+
/**
|
|
418
|
+
* General-fuse cell selection: the union of all regions covered by two or
|
|
419
|
+
* more of the inputs. Unlike {@link fuseAll} (which keeps every cell), this
|
|
420
|
+
* keeps only the overlap regions via BOPAlgo_CellsBuilder.
|
|
421
|
+
*/
|
|
422
|
+
intersectionCells(shapes: ShapeHandle[]): ShapeHandle;
|
|
399
423
|
/** Extrude a shape along a direction vector (BRepPrimAPI_MakePrism).
|
|
400
424
|
* @param dx - extrusion vector X component
|
|
401
425
|
* @param dy - extrusion vector Y component
|
|
@@ -447,6 +471,13 @@ export declare class OcctKernel {
|
|
|
447
471
|
loftWithVertices(wires: ShapeHandle[], isSolid: boolean, ruled: boolean, startVertex: ShapeHandle, endVertex: ShapeHandle): ShapeHandle;
|
|
448
472
|
sweep(wire: ShapeHandle, spine: ShapeHandle, transitionMode?: TransitionMode): ShapeHandle;
|
|
449
473
|
sweepPipeShell(profile: ShapeHandle, spine: ShapeHandle, freenet?: boolean, smooth?: boolean): ShapeHandle;
|
|
474
|
+
/**
|
|
475
|
+
* Sweep a profile wire along a spine wire with explicit profile-orientation
|
|
476
|
+
* control. `up` is required for {@link SweepMode.FixedUp} (the constant
|
|
477
|
+
* binormal direction); `auxSpine` is required for {@link SweepMode.Auxiliary}
|
|
478
|
+
* (the guide wire). Both are ignored for the other modes.
|
|
479
|
+
*/
|
|
480
|
+
sweepOriented(profile: ShapeHandle, spine: ShapeHandle, mode?: SweepMode, up?: Vec3, auxSpine?: ShapeHandle): ShapeHandle;
|
|
450
481
|
draftPrism(shape: ShapeHandle, dx: number, dy: number, dz: number, angleDeg: number): ShapeHandle;
|
|
451
482
|
makeVertex(x: number, y: number, z: number): ShapeHandle;
|
|
452
483
|
makeEdge(v1: ShapeHandle, v2: ShapeHandle): ShapeHandle;
|
|
@@ -473,6 +504,15 @@ export declare class OcctKernel {
|
|
|
473
504
|
makeFaceOnSurface(face: ShapeHandle, wire: ShapeHandle): ShapeHandle;
|
|
474
505
|
makeNullShape(): ShapeHandle;
|
|
475
506
|
translate(shape: ShapeHandle, dx: number, dy: number, dz: number): ShapeHandle;
|
|
507
|
+
/**
|
|
508
|
+
* Translate along X so the chosen bounding-box anchor lands at `target`.
|
|
509
|
+
* Returns a new shape; the input is left untouched.
|
|
510
|
+
*/
|
|
511
|
+
alignX(shape: ShapeHandle, target?: number, anchor?: AlignAnchor): ShapeHandle;
|
|
512
|
+
/** Translate along Y so the chosen bounding-box anchor lands at `target`. */
|
|
513
|
+
alignY(shape: ShapeHandle, target?: number, anchor?: AlignAnchor): ShapeHandle;
|
|
514
|
+
/** Translate along Z so the chosen bounding-box anchor lands at `target`. */
|
|
515
|
+
alignZ(shape: ShapeHandle, target?: number, anchor?: AlignAnchor): ShapeHandle;
|
|
476
516
|
rotate(shape: ShapeHandle, axis: {
|
|
477
517
|
point: Vec3;
|
|
478
518
|
direction: Vec3;
|
|
@@ -553,6 +593,10 @@ export declare class OcctKernel {
|
|
|
553
593
|
exportStl(shape: ShapeHandle, linearDeflection?: number, ascii?: boolean): string;
|
|
554
594
|
toBREP(shape: ShapeHandle): string;
|
|
555
595
|
fromBREP(data: string): ShapeHandle;
|
|
596
|
+
/** Serialize a shape to binary BREP (smaller/faster than the text format). */
|
|
597
|
+
toBREPBinary(shape: ShapeHandle): Uint8Array;
|
|
598
|
+
/** Load a shape from binary BREP produced by {@link toBREPBinary}. */
|
|
599
|
+
fromBREPBinary(data: Uint8Array): ShapeHandle;
|
|
556
600
|
cacheStep(stepData: string | ArrayBuffer): string;
|
|
557
601
|
loadCached(brep: string): ShapeHandle;
|
|
558
602
|
/**
|
|
@@ -575,6 +619,13 @@ export declare class OcctKernel {
|
|
|
575
619
|
getSurfaceArea(shape: ShapeHandle): number;
|
|
576
620
|
getLength(shape: ShapeHandle): number;
|
|
577
621
|
getCenterOfMass(shape: ShapeHandle): Vec3;
|
|
622
|
+
/**
|
|
623
|
+
* Matrix of inertia about the center of mass, as a row-major 3×3 array
|
|
624
|
+
* (length 9). Symmetric: `[1]==[3]`, `[2]==[6]`, `[5]==[7]`.
|
|
625
|
+
*/
|
|
626
|
+
getInertia(shape: ShapeHandle): number[];
|
|
627
|
+
/** True if `point` lies inside (or on the boundary of) a solid. */
|
|
628
|
+
containsPoint(shape: ShapeHandle, point: Vec3, tolerance?: number): boolean;
|
|
578
629
|
/**
|
|
579
630
|
* Surface (area-weighted) center of mass for a face. Equivalent to
|
|
580
631
|
* `BRepGProp::SurfaceProperties(face, props).CentreOfMass()`.
|
|
@@ -626,6 +677,17 @@ export declare class OcctKernel {
|
|
|
626
677
|
curveIsPeriodic(edge: ShapeHandle): boolean;
|
|
627
678
|
curveLength(edge: ShapeHandle): number;
|
|
628
679
|
interpolatePoints(points: Vec3[], periodic?: boolean): ShapeHandle;
|
|
680
|
+
/**
|
|
681
|
+
* Interpolate a cubic B-spline through the points with clamped start/end
|
|
682
|
+
* tangent directions.
|
|
683
|
+
*/
|
|
684
|
+
interpolatePointsWithTangents(points: Vec3[], startTangent: Vec3, endTangent: Vec3): ShapeHandle;
|
|
685
|
+
/** Closest point on an edge to `point`, with the curve tangent and parameter there. */
|
|
686
|
+
projectPointOnEdge(edge: ShapeHandle, point: Vec3): {
|
|
687
|
+
point: Vec3;
|
|
688
|
+
tangent: Vec3;
|
|
689
|
+
parameter: number;
|
|
690
|
+
};
|
|
629
691
|
approximatePoints(points: Vec3[], tolerance?: number): ShapeHandle;
|
|
630
692
|
getNurbsCurveData(edge: ShapeHandle): NurbsCurveData;
|
|
631
693
|
liftCurve2dToPlane(points2d: Array<{
|
|
@@ -633,6 +695,17 @@ export declare class OcctKernel {
|
|
|
633
695
|
y: number;
|
|
634
696
|
}>, planeOrigin: Vec3, planeZ: Vec3, planeX: Vec3): ShapeHandle;
|
|
635
697
|
projectEdges(shape: ShapeHandle, viewOrigin: Vec3, viewDirection: Vec3, xAxis?: Vec3): ProjectionData;
|
|
698
|
+
/**
|
|
699
|
+
* Render a single named view of a shape to a standalone SVG string via
|
|
700
|
+
* hidden-line removal. Visible edges are solid, hidden edges dashed.
|
|
701
|
+
*/
|
|
702
|
+
toSVG(shape: ShapeHandle, view?: ViewName, options?: SvgViewOptions): string;
|
|
703
|
+
/**
|
|
704
|
+
* Render a multiview grid (default Front / Top / Right / Iso) of a shape to
|
|
705
|
+
* a single SVG string, with per-view gnomons and an overall size annotation.
|
|
706
|
+
* Aimed at giving an automated agent a readable picture of the geometry.
|
|
707
|
+
*/
|
|
708
|
+
toMultiviewSVG(shape: ShapeHandle, options?: MultiviewSvgOptions): string;
|
|
636
709
|
/**
|
|
637
710
|
* Thicken a face/shell into a solid (or grow a solid uniformly).
|
|
638
711
|
*
|