brepjs 2.0.1 → 2.0.3

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/dist/brepjs.js CHANGED
@@ -51,921 +51,1017 @@ function uniqueIOFilename(prefix, ext) {
51
51
  function uniqueId() {
52
52
  return `_io_${++_counter}`;
53
53
  }
54
+ function exportSTEP$2(oc, shapes) {
55
+ const writer = new oc.STEPControl_Writer_1();
56
+ oc.Interface_Static.SetIVal("write.step.schema", 5);
57
+ writer.Model(true).delete();
58
+ const progress = new oc.Message_ProgressRange_1();
59
+ for (const shape of shapes) {
60
+ writer.Transfer(shape, oc.STEPControl_StepModelType.STEPControl_AsIs, true, progress);
61
+ }
62
+ const filename = uniqueIOFilename("_export", "step");
63
+ const done = writer.Write(filename);
64
+ writer.delete();
65
+ progress.delete();
66
+ if (done === oc.IFSelect_ReturnStatus.IFSelect_RetDone) {
67
+ const file = oc.FS.readFile("/" + filename);
68
+ oc.FS.unlink("/" + filename);
69
+ return new TextDecoder().decode(file);
70
+ }
71
+ throw new Error("STEP export failed: writer did not complete successfully");
72
+ }
73
+ function exportSTL$1(oc, shape, binary = false) {
74
+ const filename = uniqueIOFilename("_export", "stl");
75
+ const done = oc.StlAPI.Write(shape, filename, !binary);
76
+ if (done) {
77
+ const file = oc.FS.readFile("/" + filename);
78
+ oc.FS.unlink("/" + filename);
79
+ if (binary) return file.buffer;
80
+ return new TextDecoder().decode(file);
81
+ }
82
+ throw new Error("STL export failed: StlAPI.Write returned false");
83
+ }
84
+ function importSTEP$2(oc, data) {
85
+ const filename = uniqueIOFilename("_import", "step");
86
+ const buffer = typeof data === "string" ? new TextEncoder().encode(data) : new Uint8Array(data);
87
+ oc.FS.writeFile("/" + filename, buffer);
88
+ const reader = new oc.STEPControl_Reader_1();
89
+ if (reader.ReadFile(filename)) {
90
+ oc.FS.unlink("/" + filename);
91
+ const progress = new oc.Message_ProgressRange_1();
92
+ reader.TransferRoots(progress);
93
+ progress.delete();
94
+ const shape = reader.OneShape();
95
+ reader.delete();
96
+ return [shape];
97
+ }
98
+ oc.FS.unlink("/" + filename);
99
+ reader.delete();
100
+ throw new Error("Failed to import STEP file: reader could not parse the input data");
101
+ }
102
+ function importSTL$2(oc, data) {
103
+ const filename = uniqueIOFilename("_import", "stl");
104
+ const buffer = typeof data === "string" ? new TextEncoder().encode(data) : new Uint8Array(data);
105
+ oc.FS.writeFile("/" + filename, buffer);
106
+ const reader = new oc.StlAPI_Reader();
107
+ const readShape = new oc.TopoDS_Shell();
108
+ if (reader.Read(readShape, filename)) {
109
+ oc.FS.unlink("/" + filename);
110
+ const upgrader = new oc.ShapeUpgrade_UnifySameDomain_2(readShape, true, true, false);
111
+ upgrader.Build();
112
+ const upgraded = upgrader.Shape();
113
+ const solidBuilder = new oc.BRepBuilderAPI_MakeSolid_1();
114
+ solidBuilder.Add(oc.TopoDS.Shell_1(upgraded));
115
+ const solid = solidBuilder.Solid();
116
+ readShape.delete();
117
+ upgrader.delete();
118
+ solidBuilder.delete();
119
+ reader.delete();
120
+ return solid;
121
+ }
122
+ oc.FS.unlink("/" + filename);
123
+ readShape.delete();
124
+ reader.delete();
125
+ throw new Error("Failed to import STL file: reader could not parse the input data");
126
+ }
54
127
  const HASH_CODE_MAX$1 = 2147483647;
128
+ function volume(oc, shape) {
129
+ const props = new oc.GProp_GProps_1();
130
+ oc.BRepGProp.VolumeProperties_1(shape, props, true, false, false);
131
+ const vol = props.Mass();
132
+ props.delete();
133
+ return vol;
134
+ }
135
+ function area(oc, shape) {
136
+ const props = new oc.GProp_GProps_1();
137
+ oc.BRepGProp.SurfaceProperties_2(shape, props, 1e-7, true);
138
+ const a = props.Mass();
139
+ props.delete();
140
+ return a;
141
+ }
142
+ function length(oc, shape) {
143
+ const props = new oc.GProp_GProps_1();
144
+ oc.BRepGProp.LinearProperties(shape, props, true, false);
145
+ const len = props.Mass();
146
+ props.delete();
147
+ return len;
148
+ }
149
+ function centerOfMass(oc, shape) {
150
+ const props = new oc.GProp_GProps_1();
151
+ oc.BRepGProp.VolumeProperties_1(shape, props, true, false, false);
152
+ const center = props.CentreOfMass();
153
+ const result = [center.X(), center.Y(), center.Z()];
154
+ center.delete();
155
+ props.delete();
156
+ return result;
157
+ }
158
+ function boundingBox(oc, shape) {
159
+ const box = new oc.Bnd_Box_1();
160
+ oc.BRepBndLib.Add(shape, box, true);
161
+ const xMin = { current: 0 };
162
+ const yMin = { current: 0 };
163
+ const zMin = { current: 0 };
164
+ const xMax = { current: 0 };
165
+ const yMax = { current: 0 };
166
+ const zMax = { current: 0 };
167
+ box.Get(xMin, yMin, zMin, xMax, yMax, zMax);
168
+ box.delete();
169
+ return {
170
+ min: [xMin.current, yMin.current, zMin.current],
171
+ max: [xMax.current, yMax.current, zMax.current]
172
+ };
173
+ }
174
+ function transform(oc, shape, trsf) {
175
+ const transformer = new oc.BRepBuilderAPI_Transform_2(shape, trsf, true);
176
+ const result = transformer.ModifiedShape(shape);
177
+ transformer.delete();
178
+ return result;
179
+ }
180
+ function translate$1(oc, shape, x, y, z) {
181
+ const trsf = new oc.gp_Trsf_1();
182
+ const vec2 = new oc.gp_Vec_4(x, y, z);
183
+ trsf.SetTranslation_1(vec2);
184
+ const result = transform(oc, shape, trsf);
185
+ trsf.delete();
186
+ vec2.delete();
187
+ return result;
188
+ }
189
+ function rotate$1(oc, shape, angle, axis = [0, 0, 1], center = [0, 0, 0]) {
190
+ const trsf = new oc.gp_Trsf_1();
191
+ const origin = new oc.gp_Pnt_3(...center);
192
+ const dir = new oc.gp_Dir_4(...axis);
193
+ const ax1 = new oc.gp_Ax1_2(origin, dir);
194
+ trsf.SetRotation_1(ax1, angle * Math.PI / 180);
195
+ const result = transform(oc, shape, trsf);
196
+ trsf.delete();
197
+ ax1.delete();
198
+ origin.delete();
199
+ dir.delete();
200
+ return result;
201
+ }
202
+ function mirror$1(oc, shape, origin, normal) {
203
+ const trsf = new oc.gp_Trsf_1();
204
+ const pnt2 = new oc.gp_Pnt_3(...origin);
205
+ const dir = new oc.gp_Dir_4(...normal);
206
+ const ax2 = new oc.gp_Ax2_3(pnt2, dir);
207
+ trsf.SetMirror_3(ax2);
208
+ const result = transform(oc, shape, trsf);
209
+ trsf.delete();
210
+ ax2.delete();
211
+ pnt2.delete();
212
+ dir.delete();
213
+ return result;
214
+ }
215
+ function scale$1(oc, shape, center, factor) {
216
+ const trsf = new oc.gp_Trsf_1();
217
+ const pnt2 = new oc.gp_Pnt_3(...center);
218
+ trsf.SetScale(pnt2, factor);
219
+ const result = transform(oc, shape, trsf);
220
+ trsf.delete();
221
+ pnt2.delete();
222
+ return result;
223
+ }
224
+ function simplify(oc, shape) {
225
+ const upgrader = new oc.ShapeUpgrade_UnifySameDomain_2(shape, true, true, false);
226
+ upgrader.Build();
227
+ const result = upgrader.Shape();
228
+ upgrader.delete();
229
+ return result;
230
+ }
231
+ function applyGlue$2(oc, op, optimisation) {
232
+ if (optimisation === "commonFace") {
233
+ op.SetGlue(oc.BOPAlgo_GlueEnum.BOPAlgo_GlueShift);
234
+ }
235
+ if (optimisation === "sameFace") {
236
+ op.SetGlue(oc.BOPAlgo_GlueEnum.BOPAlgo_GlueFull);
237
+ }
238
+ }
239
+ function buildCompound$2(oc, shapes) {
240
+ const builder = new oc.TopoDS_Builder();
241
+ const compound = new oc.TopoDS_Compound();
242
+ builder.MakeCompound(compound);
243
+ for (const s of shapes) {
244
+ builder.Add(compound, s);
245
+ }
246
+ builder.delete();
247
+ return compound;
248
+ }
249
+ function fuse(oc, shape, tool, options = {}) {
250
+ const { optimisation, simplify: simplify2 = false } = options;
251
+ const progress = new oc.Message_ProgressRange_1();
252
+ const fuseOp = new oc.BRepAlgoAPI_Fuse_3(shape, tool, progress);
253
+ applyGlue$2(oc, fuseOp, optimisation);
254
+ fuseOp.Build(progress);
255
+ if (simplify2) fuseOp.SimplifyResult(true, true, 1e-3);
256
+ const result = fuseOp.Shape();
257
+ fuseOp.delete();
258
+ progress.delete();
259
+ return result;
260
+ }
261
+ function cut(oc, shape, tool, options = {}) {
262
+ const { optimisation, simplify: simplify2 = false } = options;
263
+ const progress = new oc.Message_ProgressRange_1();
264
+ const cutOp = new oc.BRepAlgoAPI_Cut_3(shape, tool, progress);
265
+ applyGlue$2(oc, cutOp, optimisation);
266
+ cutOp.Build(progress);
267
+ if (simplify2) cutOp.SimplifyResult(true, true, 1e-3);
268
+ const result = cutOp.Shape();
269
+ cutOp.delete();
270
+ progress.delete();
271
+ return result;
272
+ }
273
+ function intersect(oc, shape, tool, options = {}) {
274
+ const { optimisation, simplify: simplify2 = false } = options;
275
+ const progress = new oc.Message_ProgressRange_1();
276
+ const commonOp = new oc.BRepAlgoAPI_Common_3(shape, tool, progress);
277
+ applyGlue$2(oc, commonOp, optimisation);
278
+ commonOp.Build(progress);
279
+ if (simplify2) commonOp.SimplifyResult(true, true, 1e-3);
280
+ const result = commonOp.Shape();
281
+ commonOp.delete();
282
+ progress.delete();
283
+ return result;
284
+ }
285
+ function fuseAllBatch(oc, shapes, options = {}) {
286
+ const { optimisation, simplify: simplify2 = false } = options;
287
+ const batch = new oc.BooleanBatch();
288
+ for (const s of shapes) {
289
+ batch.addShape(s);
290
+ }
291
+ const glueMode = optimisation === "commonFace" ? 1 : optimisation === "sameFace" ? 2 : 0;
292
+ const result = batch.fuseAll(glueMode, simplify2);
293
+ batch.delete();
294
+ return result;
295
+ }
296
+ function fuseAllNative(oc, shapes, options = {}) {
297
+ const { optimisation, simplify: simplify2 = false } = options;
298
+ const argList = new oc.TopTools_ListOfShape_1();
299
+ for (const s of shapes) {
300
+ argList.Append_1(s);
301
+ }
302
+ const builder = new oc.BRepAlgoAPI_BuilderAlgo_1();
303
+ builder.SetArguments(argList);
304
+ applyGlue$2(oc, builder, optimisation);
305
+ const progress = new oc.Message_ProgressRange_1();
306
+ builder.Build(progress);
307
+ let result = builder.Shape();
308
+ if (simplify2) {
309
+ const upgrader = new oc.ShapeUpgrade_UnifySameDomain_2(result, true, true, false);
310
+ upgrader.Build();
311
+ result = upgrader.Shape();
312
+ upgrader.delete();
313
+ }
314
+ argList.delete();
315
+ builder.delete();
316
+ progress.delete();
317
+ return result;
318
+ }
319
+ function fuseAllPairwise(oc, shapes, options = {}) {
320
+ const mid = Math.ceil(shapes.length / 2);
321
+ const left = fuseAll$3(oc, shapes.slice(0, mid), {
322
+ ...options,
323
+ simplify: false,
324
+ strategy: "pairwise"
325
+ });
326
+ const right = fuseAll$3(oc, shapes.slice(mid), {
327
+ ...options,
328
+ simplify: false,
329
+ strategy: "pairwise"
330
+ });
331
+ return fuse(oc, left, right, options);
332
+ }
333
+ function fuseAll$3(oc, shapes, options = {}) {
334
+ if (shapes.length === 0) throw new Error("fuseAll requires at least one shape");
335
+ if (shapes.length === 1) return shapes[0];
336
+ const { strategy = "native" } = options;
337
+ if (strategy === "pairwise") {
338
+ return fuseAllPairwise(oc, shapes, options);
339
+ }
340
+ if (oc.BooleanBatch) {
341
+ return fuseAllBatch(oc, shapes, options);
342
+ }
343
+ return fuseAllNative(oc, shapes, options);
344
+ }
345
+ function cutAllBatch(oc, shape, tools, options = {}) {
346
+ const { optimisation, simplify: simplify2 = false } = options;
347
+ const batch = new oc.BooleanBatch();
348
+ for (const t of tools) {
349
+ batch.addShape(t);
350
+ }
351
+ const glueMode = optimisation === "commonFace" ? 1 : optimisation === "sameFace" ? 2 : 0;
352
+ const result = batch.cutAll(shape, glueMode, simplify2);
353
+ batch.delete();
354
+ return result;
355
+ }
356
+ function cutAll$2(oc, shape, tools, options = {}) {
357
+ if (tools.length === 0) return shape;
358
+ if (oc.BooleanBatch) {
359
+ return cutAllBatch(oc, shape, tools, options);
360
+ }
361
+ const toolCompound = buildCompound$2(oc, tools);
362
+ const result = cut(oc, shape, toolCompound, options);
363
+ toolCompound.delete();
364
+ return result;
365
+ }
366
+ function meshBulk(oc, shape, options) {
367
+ const raw = oc.MeshExtractor.extract(
368
+ shape,
369
+ options.tolerance,
370
+ options.angularTolerance,
371
+ !!options.skipNormals
372
+ );
373
+ const verticesSize = raw.getVerticesSize();
374
+ const normalsSize = raw.getNormalsSize();
375
+ const trianglesSize = raw.getTrianglesSize();
376
+ const faceGroupsSize = raw.getFaceGroupsSize();
377
+ const verticesPtr = raw.getVerticesPtr() / 4;
378
+ const vertices = oc.HEAPF32.slice(verticesPtr, verticesPtr + verticesSize);
379
+ let normals;
380
+ if (options.skipNormals || normalsSize === 0) {
381
+ normals = new Float32Array(0);
382
+ } else {
383
+ const normalsPtr = raw.getNormalsPtr() / 4;
384
+ normals = oc.HEAPF32.slice(normalsPtr, normalsPtr + normalsSize);
385
+ }
386
+ const trianglesPtr = raw.getTrianglesPtr() / 4;
387
+ const triangles = oc.HEAPU32.slice(trianglesPtr, trianglesPtr + trianglesSize);
388
+ const faceGroups = [];
389
+ if (faceGroupsSize > 0) {
390
+ const fgPtr = raw.getFaceGroupsPtr() / 4;
391
+ const fgRaw = oc.HEAP32.slice(fgPtr, fgPtr + faceGroupsSize);
392
+ for (let i = 0; i < fgRaw.length; i += 3) {
393
+ faceGroups.push({
394
+ start: fgRaw[i],
395
+ count: fgRaw[i + 1],
396
+ faceHash: fgRaw[i + 2]
397
+ });
398
+ }
399
+ }
400
+ raw.delete();
401
+ return { vertices, normals, triangles, faceGroups };
402
+ }
403
+ function meshJS(oc, shape, options) {
404
+ const mesher = new oc.BRepMesh_IncrementalMesh_2(
405
+ shape,
406
+ options.tolerance,
407
+ false,
408
+ options.angularTolerance,
409
+ false
410
+ );
411
+ mesher.delete();
412
+ let totalNodes = 0;
413
+ let totalTris = 0;
414
+ const explorer = new oc.TopExp_Explorer_2(
415
+ shape,
416
+ oc.TopAbs_ShapeEnum.TopAbs_FACE,
417
+ oc.TopAbs_ShapeEnum.TopAbs_SHAPE
418
+ );
419
+ while (explorer.More()) {
420
+ const face = oc.TopoDS.Face_1(explorer.Current());
421
+ const loc = new oc.TopLoc_Location_1();
422
+ const tri = oc.BRep_Tool.Triangulation(face, loc, 0);
423
+ if (!tri.IsNull()) {
424
+ const t = tri.get();
425
+ totalNodes += t.NbNodes();
426
+ totalTris += t.NbTriangles();
427
+ }
428
+ loc.delete();
429
+ tri.delete();
430
+ explorer.Next();
431
+ }
432
+ const vertices = new Float32Array(totalNodes * 3);
433
+ const normals = options.skipNormals ? new Float32Array(0) : new Float32Array(totalNodes * 3);
434
+ const triangles = new Uint32Array(totalTris * 3);
435
+ const faceGroups = [];
436
+ let vIdx = 0;
437
+ let nIdx = 0;
438
+ let tIdx = 0;
439
+ explorer.Init(shape, oc.TopAbs_ShapeEnum.TopAbs_FACE, oc.TopAbs_ShapeEnum.TopAbs_SHAPE);
440
+ while (explorer.More()) {
441
+ const face = oc.TopoDS.Face_1(explorer.Current());
442
+ const location = new oc.TopLoc_Location_1();
443
+ const triangulation = oc.BRep_Tool.Triangulation(face, location, 0);
444
+ if (!triangulation.IsNull()) {
445
+ const tri = triangulation.get();
446
+ const transformation = location.Transformation();
447
+ const nbNodes = tri.NbNodes();
448
+ const vertexOffset = vIdx / 3;
449
+ const triStart = tIdx;
450
+ for (let i = 1; i <= nbNodes; i++) {
451
+ const p = tri.Node(i).Transformed(transformation);
452
+ vertices[vIdx++] = p.X();
453
+ vertices[vIdx++] = p.Y();
454
+ vertices[vIdx++] = p.Z();
455
+ p.delete();
456
+ }
457
+ if (!options.skipNormals) {
458
+ const normalsArray = new oc.TColgp_Array1OfDir_2(1, nbNodes);
459
+ const pc = new oc.Poly_Connect_2(triangulation);
460
+ oc.StdPrs_ToolTriangulatedShape.Normal(face, pc, normalsArray);
461
+ for (let i = normalsArray.Lower(); i <= normalsArray.Upper(); i++) {
462
+ const d = normalsArray.Value(i).Transformed(transformation);
463
+ normals[nIdx++] = d.X();
464
+ normals[nIdx++] = d.Y();
465
+ normals[nIdx++] = d.Z();
466
+ d.delete();
467
+ }
468
+ normalsArray.delete();
469
+ pc.delete();
470
+ }
471
+ const orient = face.Orientation_1();
472
+ const isForward = orient === oc.TopAbs_Orientation.TopAbs_FORWARD;
473
+ const nbTriangles = tri.NbTriangles();
474
+ for (let nt = 1; nt <= nbTriangles; nt++) {
475
+ const t = tri.Triangle(nt);
476
+ let n1 = t.Value(1);
477
+ let n2 = t.Value(2);
478
+ const n3 = t.Value(3);
479
+ if (!isForward) {
480
+ const tmp = n1;
481
+ n1 = n2;
482
+ n2 = tmp;
483
+ }
484
+ triangles[tIdx++] = n1 - 1 + vertexOffset;
485
+ triangles[tIdx++] = n2 - 1 + vertexOffset;
486
+ triangles[tIdx++] = n3 - 1 + vertexOffset;
487
+ t.delete();
488
+ }
489
+ faceGroups.push({
490
+ start: triStart,
491
+ count: tIdx - triStart,
492
+ faceHash: face.HashCode(HASH_CODE_MAX$1)
493
+ });
494
+ transformation.delete();
495
+ }
496
+ location.delete();
497
+ triangulation.delete();
498
+ explorer.Next();
499
+ }
500
+ explorer.delete();
501
+ return { vertices, normals, triangles, faceGroups };
502
+ }
503
+ function mesh(oc, shape, options) {
504
+ if (oc.MeshExtractor) {
505
+ return meshBulk(oc, shape, options);
506
+ }
507
+ return meshJS(oc, shape, options);
508
+ }
509
+ function meshEdgesBulk(oc, shape, tolerance, angularTolerance) {
510
+ const raw = oc.EdgeMeshExtractor.extract(shape, tolerance, angularTolerance);
511
+ const linesSize = raw.getLinesSize();
512
+ const edgeGroupsSize = raw.getEdgeGroupsSize();
513
+ let lines;
514
+ if (linesSize > 0) {
515
+ const linesPtr = raw.getLinesPtr() / 4;
516
+ lines = oc.HEAPF32.slice(linesPtr, linesPtr + linesSize);
517
+ } else {
518
+ lines = new Float32Array(0);
519
+ }
520
+ const edgeGroups = [];
521
+ if (edgeGroupsSize > 0) {
522
+ const egPtr = raw.getEdgeGroupsPtr() / 4;
523
+ const egRaw = oc.HEAP32.slice(egPtr, egPtr + edgeGroupsSize);
524
+ for (let i = 0; i < egRaw.length; i += 3) {
525
+ edgeGroups.push({
526
+ start: egRaw[i],
527
+ count: egRaw[i + 1],
528
+ edgeHash: egRaw[i + 2]
529
+ });
530
+ }
531
+ }
532
+ raw.delete();
533
+ return { lines, edgeGroups };
534
+ }
535
+ function meshEdgesJS(oc, shape, tolerance, angularTolerance) {
536
+ const mesher = new oc.BRepMesh_IncrementalMesh_2(
537
+ shape,
538
+ tolerance,
539
+ false,
540
+ angularTolerance,
541
+ false
542
+ );
543
+ mesher.delete();
544
+ const lines = [];
545
+ const edgeGroups = [];
546
+ const seenHashes = /* @__PURE__ */ new Set();
547
+ const faceExplorer = new oc.TopExp_Explorer_2(
548
+ shape,
549
+ oc.TopAbs_ShapeEnum.TopAbs_FACE,
550
+ oc.TopAbs_ShapeEnum.TopAbs_SHAPE
551
+ );
552
+ while (faceExplorer.More()) {
553
+ const face = oc.TopoDS.Face_1(faceExplorer.Current());
554
+ const faceLoc = new oc.TopLoc_Location_1();
555
+ const tri = oc.BRep_Tool.Triangulation(face, faceLoc, 0);
556
+ if (!tri.IsNull()) {
557
+ const triObj = tri.get();
558
+ const edgeExplorer2 = new oc.TopExp_Explorer_2(
559
+ face,
560
+ oc.TopAbs_ShapeEnum.TopAbs_EDGE,
561
+ oc.TopAbs_ShapeEnum.TopAbs_SHAPE
562
+ );
563
+ while (edgeExplorer2.More()) {
564
+ const edgeShape = edgeExplorer2.Current();
565
+ const edge = oc.TopoDS.Edge_1(edgeShape);
566
+ const edgeHash = edge.HashCode(HASH_CODE_MAX$1);
567
+ if (!seenHashes.has(edgeHash)) {
568
+ seenHashes.add(edgeHash);
569
+ const edgeLoc = new oc.TopLoc_Location_1();
570
+ const polygon = oc.BRep_Tool.PolygonOnTriangulation_1(edge, tri, edgeLoc);
571
+ const edgeNodes = polygon && !polygon.IsNull() ? polygon.get().Nodes() : null;
572
+ if (edgeNodes) {
573
+ const lineStart = lines.length / 3;
574
+ let prevX = 0, prevY = 0, prevZ = 0;
575
+ let hasPrev = false;
576
+ for (let i = edgeNodes.Lower(); i <= edgeNodes.Upper(); i++) {
577
+ const p = triObj.Node(edgeNodes.Value(i)).Transformed(edgeLoc.Transformation());
578
+ const x = p.X(), y = p.Y(), z = p.Z();
579
+ if (hasPrev) {
580
+ lines.push(prevX, prevY, prevZ, x, y, z);
581
+ }
582
+ prevX = x;
583
+ prevY = y;
584
+ prevZ = z;
585
+ hasPrev = true;
586
+ p.delete();
587
+ }
588
+ edgeGroups.push({
589
+ start: lineStart,
590
+ count: lines.length / 3 - lineStart,
591
+ edgeHash
592
+ });
593
+ edgeNodes.delete();
594
+ }
595
+ if (polygon && !polygon.IsNull()) polygon.delete();
596
+ edgeLoc.delete();
597
+ }
598
+ edgeExplorer2.Next();
599
+ }
600
+ edgeExplorer2.delete();
601
+ }
602
+ tri.delete();
603
+ faceLoc.delete();
604
+ faceExplorer.Next();
605
+ }
606
+ faceExplorer.delete();
607
+ const edgeExplorer = new oc.TopExp_Explorer_2(
608
+ shape,
609
+ oc.TopAbs_ShapeEnum.TopAbs_EDGE,
610
+ oc.TopAbs_ShapeEnum.TopAbs_SHAPE
611
+ );
612
+ while (edgeExplorer.More()) {
613
+ const edgeShape = edgeExplorer.Current();
614
+ const edge = oc.TopoDS.Edge_1(edgeShape);
615
+ const edgeHash = edge.HashCode(HASH_CODE_MAX$1);
616
+ if (!seenHashes.has(edgeHash)) {
617
+ seenHashes.add(edgeHash);
618
+ const adaptor = new oc.BRepAdaptor_Curve_2(edge);
619
+ const tangDef = new oc.GCPnts_TangentialDeflection_2(
620
+ adaptor,
621
+ tolerance,
622
+ angularTolerance,
623
+ 2,
624
+ 1e-9,
625
+ 1e-7
626
+ );
627
+ const lineStart = lines.length / 3;
628
+ let prevX = 0, prevY = 0, prevZ = 0;
629
+ let hasPrev = false;
630
+ for (let j = 1; j <= tangDef.NbPoints(); j++) {
631
+ const p = tangDef.Value(j);
632
+ const x = p.X(), y = p.Y(), z = p.Z();
633
+ if (hasPrev) {
634
+ lines.push(prevX, prevY, prevZ, x, y, z);
635
+ }
636
+ prevX = x;
637
+ prevY = y;
638
+ prevZ = z;
639
+ hasPrev = true;
640
+ p.delete();
641
+ }
642
+ edgeGroups.push({
643
+ start: lineStart,
644
+ count: lines.length / 3 - lineStart,
645
+ edgeHash
646
+ });
647
+ tangDef.delete();
648
+ adaptor.delete();
649
+ }
650
+ edgeExplorer.Next();
651
+ }
652
+ edgeExplorer.delete();
653
+ return { lines: new Float32Array(lines), edgeGroups };
654
+ }
655
+ function meshEdges(oc, shape, tolerance, angularTolerance) {
656
+ if (oc.EdgeMeshExtractor) {
657
+ return meshEdgesBulk(oc, shape, tolerance, angularTolerance);
658
+ }
659
+ return meshEdgesJS(oc, shape, tolerance, angularTolerance);
660
+ }
661
+ function iterShapesBulk(oc, shape, type) {
662
+ const typeEnumMap = {
663
+ vertex: 7,
664
+ edge: 6,
665
+ wire: 5,
666
+ face: 4,
667
+ shell: 3,
668
+ solid: 2,
669
+ compsolid: 1,
670
+ compound: 0
671
+ };
672
+ const raw = oc.TopologyExtractor.extract(shape, typeEnumMap[type]);
673
+ const count = raw.getShapesCount();
674
+ const result = [];
675
+ for (let i = 0; i < count; i++) {
676
+ result.push(raw.getShape(i));
677
+ }
678
+ raw.delete();
679
+ return result;
680
+ }
681
+ function iterShapesJS(oc, shape, type) {
682
+ const typeMap = {
683
+ vertex: oc.TopAbs_ShapeEnum.TopAbs_VERTEX,
684
+ edge: oc.TopAbs_ShapeEnum.TopAbs_EDGE,
685
+ wire: oc.TopAbs_ShapeEnum.TopAbs_WIRE,
686
+ face: oc.TopAbs_ShapeEnum.TopAbs_FACE,
687
+ shell: oc.TopAbs_ShapeEnum.TopAbs_SHELL,
688
+ solid: oc.TopAbs_ShapeEnum.TopAbs_SOLID,
689
+ compsolid: oc.TopAbs_ShapeEnum.TopAbs_COMPSOLID,
690
+ compound: oc.TopAbs_ShapeEnum.TopAbs_COMPOUND
691
+ };
692
+ const explorer = new oc.TopExp_Explorer_2(shape, typeMap[type], oc.TopAbs_ShapeEnum.TopAbs_SHAPE);
693
+ const result = [];
694
+ const seen = /* @__PURE__ */ new Map();
695
+ while (explorer.More()) {
696
+ const item = explorer.Current();
697
+ const hash = item.HashCode(HASH_CODE_MAX$1);
698
+ const bucket = seen.get(hash);
699
+ if (!bucket) {
700
+ seen.set(hash, [item]);
701
+ result.push(item);
702
+ } else if (!bucket.some((s) => s.IsSame(item))) {
703
+ bucket.push(item);
704
+ result.push(item);
705
+ }
706
+ explorer.Next();
707
+ }
708
+ explorer.delete();
709
+ return result;
710
+ }
711
+ function iterShapes(oc, shape, type) {
712
+ if (oc.TopologyExtractor) {
713
+ return iterShapesBulk(oc, shape, type);
714
+ }
715
+ return iterShapesJS(oc, shape, type);
716
+ }
717
+ const shapeTypeMaps = /* @__PURE__ */ new WeakMap();
718
+ function getShapeTypeMap(oc) {
719
+ let map2 = shapeTypeMaps.get(oc);
720
+ if (!map2) {
721
+ const ta = oc.TopAbs_ShapeEnum;
722
+ map2 = /* @__PURE__ */ new Map([
723
+ [ta.TopAbs_VERTEX, "vertex"],
724
+ [ta.TopAbs_EDGE, "edge"],
725
+ [ta.TopAbs_WIRE, "wire"],
726
+ [ta.TopAbs_FACE, "face"],
727
+ [ta.TopAbs_SHELL, "shell"],
728
+ [ta.TopAbs_SOLID, "solid"],
729
+ [ta.TopAbs_COMPSOLID, "compsolid"],
730
+ [ta.TopAbs_COMPOUND, "compound"]
731
+ ]);
732
+ shapeTypeMaps.set(oc, map2);
733
+ }
734
+ return map2;
735
+ }
736
+ function shapeType$1(oc, shape) {
737
+ if (shape.IsNull()) throw new Error("Cannot determine shape type: shape is null");
738
+ const result = getShapeTypeMap(oc).get(shape.ShapeType());
739
+ if (!result) throw new Error(`Unknown shape type enum value: ${shape.ShapeType()}`);
740
+ return result;
741
+ }
742
+ function isSame(a, b) {
743
+ return a.IsSame(b);
744
+ }
745
+ function isEqual(a, b) {
746
+ return a.IsEqual(b);
747
+ }
748
+ function makeVertex$1(oc, x, y, z) {
749
+ const pnt2 = new oc.gp_Pnt_3(x, y, z);
750
+ const maker = new oc.BRepBuilderAPI_MakeVertex(pnt2);
751
+ const vertex = maker.Vertex();
752
+ maker.delete();
753
+ pnt2.delete();
754
+ return vertex;
755
+ }
756
+ function makeEdge(oc, curve, start, end) {
757
+ const maker = start !== void 0 && end !== void 0 ? new oc.BRepBuilderAPI_MakeEdge_24(curve, start, end) : new oc.BRepBuilderAPI_MakeEdge_24(curve);
758
+ const edge = maker.Edge();
759
+ maker.delete();
760
+ return edge;
761
+ }
762
+ function makeWire(oc, edges) {
763
+ const wireBuilder = new oc.BRepBuilderAPI_MakeWire_1();
764
+ for (const edge of edges) {
765
+ wireBuilder.Add_1(edge);
766
+ }
767
+ const progress = new oc.Message_ProgressRange_1();
768
+ wireBuilder.Build(progress);
769
+ const wire = wireBuilder.Wire();
770
+ wireBuilder.delete();
771
+ progress.delete();
772
+ return wire;
773
+ }
774
+ function makeFace$1(oc, wire, planar = true) {
775
+ if (planar) {
776
+ const builder2 = new oc.BRepBuilderAPI_MakeFace_15(wire, false);
777
+ const face = builder2.Face();
778
+ builder2.delete();
779
+ return face;
780
+ }
781
+ const builder = new oc.BRepOffsetAPI_MakeFilling(3, 15, 2, false, 1e-5, 1e-4, 0.01, 0.1, 8, 9);
782
+ const edges = iterShapes(oc, wire, "edge");
783
+ for (const edge of edges) {
784
+ builder.Add_1(edge, oc.GeomAbs_Shape.GeomAbs_C0, true);
785
+ }
786
+ const progress = new oc.Message_ProgressRange_1();
787
+ builder.Build(progress);
788
+ const shape = builder.Shape();
789
+ builder.delete();
790
+ progress.delete();
791
+ return shape;
792
+ }
793
+ function makeBox$1(oc, width, height, depth) {
794
+ const maker = new oc.BRepPrimAPI_MakeBox_2(width, height, depth);
795
+ const solid = maker.Solid();
796
+ maker.delete();
797
+ return solid;
798
+ }
799
+ function makeCylinder$1(oc, radius, height, center = [0, 0, 0], direction = [0, 0, 1]) {
800
+ const origin = new oc.gp_Pnt_3(...center);
801
+ const dir = new oc.gp_Dir_4(...direction);
802
+ const axis = new oc.gp_Ax2_3(origin, dir);
803
+ const maker = new oc.BRepPrimAPI_MakeCylinder_3(axis, radius, height);
804
+ const solid = maker.Shape();
805
+ maker.delete();
806
+ axis.delete();
807
+ origin.delete();
808
+ dir.delete();
809
+ return solid;
810
+ }
811
+ function makeSphere$1(oc, radius, center = [0, 0, 0]) {
812
+ const origin = new oc.gp_Pnt_3(...center);
813
+ const maker = new oc.BRepPrimAPI_MakeSphere_2(origin, radius);
814
+ const solid = maker.Shape();
815
+ maker.delete();
816
+ origin.delete();
817
+ return solid;
818
+ }
819
+ function extrude(oc, face, direction, length2) {
820
+ const vec2 = new oc.gp_Vec_4(direction[0] * length2, direction[1] * length2, direction[2] * length2);
821
+ const maker = new oc.BRepPrimAPI_MakePrism_1(face, vec2, false, true);
822
+ const result = maker.Shape();
823
+ maker.delete();
824
+ vec2.delete();
825
+ return result;
826
+ }
827
+ function revolve(oc, shape, axis, angle) {
828
+ const maker = new oc.BRepPrimAPI_MakeRevol_1(shape, axis, angle, false);
829
+ const result = maker.Shape();
830
+ maker.delete();
831
+ return result;
832
+ }
833
+ function loft$1(oc, wires, ruled = false, startShape, endShape) {
834
+ const loftBuilder = new oc.BRepOffsetAPI_ThruSections(true, ruled, 1e-6);
835
+ if (startShape) loftBuilder.AddVertex(startShape);
836
+ for (const wire of wires) {
837
+ loftBuilder.AddWire(wire);
838
+ }
839
+ if (endShape) loftBuilder.AddVertex(endShape);
840
+ const progress = new oc.Message_ProgressRange_1();
841
+ loftBuilder.Build(progress);
842
+ const result = loftBuilder.Shape();
843
+ loftBuilder.delete();
844
+ progress.delete();
845
+ return result;
846
+ }
847
+ function sweep$1(oc, wire, spine, options = {}) {
848
+ const { transitionMode } = options;
849
+ const sweepBuilder = new oc.BRepOffsetAPI_MakePipeShell(spine);
850
+ if (transitionMode !== void 0) {
851
+ sweepBuilder.SetTransitionMode(transitionMode);
852
+ }
853
+ sweepBuilder.Add_1(wire, false, false);
854
+ const progress = new oc.Message_ProgressRange_1();
855
+ sweepBuilder.Build(progress);
856
+ progress.delete();
857
+ sweepBuilder.MakeSolid();
858
+ const result = sweepBuilder.Shape();
859
+ sweepBuilder.delete();
860
+ return result;
861
+ }
862
+ function fillet(oc, shape, edges, radius) {
863
+ const builder = new oc.BRepFilletAPI_MakeFillet(shape, oc.ChFi3d_FilletShape.ChFi3d_Rational);
864
+ for (const edge of edges) {
865
+ const r = typeof radius === "function" ? radius(edge) : radius;
866
+ if (r > 0) builder.Add_2(r, edge);
867
+ }
868
+ const result = builder.Shape();
869
+ builder.delete();
870
+ return result;
871
+ }
872
+ function chamfer(oc, shape, edges, distance) {
873
+ const builder = new oc.BRepFilletAPI_MakeChamfer(shape);
874
+ for (const edge of edges) {
875
+ const d = typeof distance === "function" ? distance(edge) : distance;
876
+ if (d > 0) builder.Add_2(d, edge);
877
+ }
878
+ const result = builder.Shape();
879
+ builder.delete();
880
+ return result;
881
+ }
882
+ function shell(oc, shape, faces, thickness, tolerance = 1e-3) {
883
+ const facesToRemove = new oc.TopTools_ListOfShape_1();
884
+ for (const face of faces) {
885
+ facesToRemove.Append_1(face);
886
+ }
887
+ const progress = new oc.Message_ProgressRange_1();
888
+ const builder = new oc.BRepOffsetAPI_MakeThickSolid();
889
+ builder.MakeThickSolidByJoin(
890
+ shape,
891
+ facesToRemove,
892
+ -thickness,
893
+ tolerance,
894
+ oc.BRepOffset_Mode.BRepOffset_Skin,
895
+ false,
896
+ false,
897
+ oc.GeomAbs_JoinType.GeomAbs_Arc,
898
+ false,
899
+ progress
900
+ );
901
+ const result = builder.Shape();
902
+ builder.delete();
903
+ facesToRemove.delete();
904
+ progress.delete();
905
+ return result;
906
+ }
907
+ function offset$1(oc, shape, distance, tolerance = 1e-6) {
908
+ const progress = new oc.Message_ProgressRange_1();
909
+ const builder = new oc.BRepOffsetAPI_MakeOffsetShape();
910
+ builder.PerformByJoin(
911
+ shape,
912
+ distance,
913
+ tolerance,
914
+ oc.BRepOffset_Mode.BRepOffset_Skin,
915
+ false,
916
+ false,
917
+ oc.GeomAbs_JoinType.GeomAbs_Arc,
918
+ false,
919
+ progress
920
+ );
921
+ const result = builder.Shape();
922
+ builder.delete();
923
+ progress.delete();
924
+ return result;
925
+ }
55
926
  class OCCTAdapter {
56
927
  oc;
57
928
  constructor(oc) {
58
929
  this.oc = oc;
59
930
  }
60
- // --- Boolean operations ---
931
+ // --- Boolean operations (delegates to booleanOps.ts) ---
61
932
  fuse(shape, tool, options = {}) {
62
- const { optimisation, simplify = false } = options;
63
- const progress = new this.oc.Message_ProgressRange_1();
64
- const fuseOp = new this.oc.BRepAlgoAPI_Fuse_3(shape, tool, progress);
65
- this._applyGlue(fuseOp, optimisation);
66
- fuseOp.Build(progress);
67
- if (simplify) fuseOp.SimplifyResult(true, true, 1e-3);
68
- const result = fuseOp.Shape();
69
- fuseOp.delete();
70
- progress.delete();
71
- return result;
933
+ return fuse(this.oc, shape, tool, options);
72
934
  }
73
935
  cut(shape, tool, options = {}) {
74
- const { optimisation, simplify = false } = options;
75
- const progress = new this.oc.Message_ProgressRange_1();
76
- const cutOp = new this.oc.BRepAlgoAPI_Cut_3(shape, tool, progress);
77
- this._applyGlue(cutOp, optimisation);
78
- cutOp.Build(progress);
79
- if (simplify) cutOp.SimplifyResult(true, true, 1e-3);
80
- const result = cutOp.Shape();
81
- cutOp.delete();
82
- progress.delete();
83
- return result;
936
+ return cut(this.oc, shape, tool, options);
84
937
  }
85
938
  intersect(shape, tool, options = {}) {
86
- const { optimisation, simplify = false } = options;
87
- const progress = new this.oc.Message_ProgressRange_1();
88
- const commonOp = new this.oc.BRepAlgoAPI_Common_3(shape, tool, progress);
89
- this._applyGlue(commonOp, optimisation);
90
- commonOp.Build(progress);
91
- if (simplify) commonOp.SimplifyResult(true, true, 1e-3);
92
- const result = commonOp.Shape();
93
- commonOp.delete();
94
- progress.delete();
95
- return result;
939
+ return intersect(this.oc, shape, tool, options);
96
940
  }
97
941
  fuseAll(shapes, options = {}) {
98
- if (shapes.length === 0) throw new Error("fuseAll requires at least one shape");
99
- if (shapes.length === 1) return shapes[0];
100
- const { strategy = "native" } = options;
101
- if (strategy === "pairwise") {
102
- return this._fuseAllPairwise(shapes, options);
103
- }
104
- if (this.oc.BooleanBatch) {
105
- return this._fuseAllBatch(shapes, options);
106
- }
107
- return this._fuseAllNative(shapes, options);
108
- }
109
- _fuseAllBatch(shapes, options = {}) {
110
- const { optimisation, simplify = false } = options;
111
- const batch = new this.oc.BooleanBatch();
112
- for (const s of shapes) {
113
- batch.addShape(s);
114
- }
115
- const glueMode = optimisation === "commonFace" ? 1 : optimisation === "sameFace" ? 2 : 0;
116
- const result = batch.fuseAll(glueMode, simplify);
117
- batch.delete();
118
- return result;
119
- }
120
- _fuseAllNative(shapes, options = {}) {
121
- const { optimisation, simplify = false } = options;
122
- const argList = new this.oc.TopTools_ListOfShape_1();
123
- for (const s of shapes) {
124
- argList.Append_1(s);
125
- }
126
- const builder = new this.oc.BRepAlgoAPI_BuilderAlgo_1();
127
- builder.SetArguments(argList);
128
- this._applyGlue(builder, optimisation);
129
- const progress = new this.oc.Message_ProgressRange_1();
130
- builder.Build(progress);
131
- let result = builder.Shape();
132
- if (simplify) {
133
- const upgrader = new this.oc.ShapeUpgrade_UnifySameDomain_2(result, true, true, false);
134
- upgrader.Build();
135
- result = upgrader.Shape();
136
- upgrader.delete();
137
- }
138
- argList.delete();
139
- builder.delete();
140
- progress.delete();
141
- return result;
142
- }
143
- _fuseAllPairwise(shapes, options = {}) {
144
- const mid = Math.ceil(shapes.length / 2);
145
- const left = this.fuseAll(shapes.slice(0, mid), {
146
- ...options,
147
- simplify: false,
148
- strategy: "pairwise"
149
- });
150
- const right = this.fuseAll(shapes.slice(mid), {
151
- ...options,
152
- simplify: false,
153
- strategy: "pairwise"
154
- });
155
- return this.fuse(left, right, options);
942
+ return fuseAll$3(this.oc, shapes, options);
156
943
  }
157
944
  cutAll(shape, tools, options = {}) {
158
- if (tools.length === 0) return shape;
159
- if (this.oc.BooleanBatch) {
160
- return this._cutAllBatch(shape, tools, options);
161
- }
162
- const toolCompound = this._buildCompound(tools);
163
- const result = this.cut(shape, toolCompound, options);
164
- toolCompound.delete();
165
- return result;
945
+ return cutAll$2(this.oc, shape, tools, options);
166
946
  }
167
- _cutAllBatch(shape, tools, options = {}) {
168
- const { optimisation, simplify = false } = options;
169
- const batch = new this.oc.BooleanBatch();
170
- for (const t of tools) {
171
- batch.addShape(t);
172
- }
173
- const glueMode = optimisation === "commonFace" ? 1 : optimisation === "sameFace" ? 2 : 0;
174
- const result = batch.cutAll(shape, glueMode, simplify);
175
- batch.delete();
176
- return result;
177
- }
178
- // --- Shape construction ---
947
+ // --- Shape construction (delegates to constructorOps.ts) ---
179
948
  makeVertex(x, y, z) {
180
- const pnt2 = new this.oc.gp_Pnt_3(x, y, z);
181
- const maker = new this.oc.BRepBuilderAPI_MakeVertex(pnt2);
182
- const vertex = maker.Vertex();
183
- maker.delete();
184
- pnt2.delete();
185
- return vertex;
949
+ return makeVertex$1(this.oc, x, y, z);
186
950
  }
187
951
  makeEdge(curve, start, end) {
188
- const maker = start !== void 0 && end !== void 0 ? new this.oc.BRepBuilderAPI_MakeEdge_24(curve, start, end) : new this.oc.BRepBuilderAPI_MakeEdge_24(curve);
189
- const edge = maker.Edge();
190
- maker.delete();
191
- return edge;
952
+ return makeEdge(this.oc, curve, start, end);
192
953
  }
193
954
  makeWire(edges) {
194
- const wireBuilder = new this.oc.BRepBuilderAPI_MakeWire_1();
195
- for (const edge of edges) {
196
- wireBuilder.Add_1(edge);
197
- }
198
- const progress = new this.oc.Message_ProgressRange_1();
199
- wireBuilder.Build(progress);
200
- const wire = wireBuilder.Wire();
201
- wireBuilder.delete();
202
- progress.delete();
203
- return wire;
955
+ return makeWire(this.oc, edges);
204
956
  }
205
957
  makeFace(wire, planar = true) {
206
- if (planar) {
207
- const builder2 = new this.oc.BRepBuilderAPI_MakeFace_15(wire, false);
208
- const face = builder2.Face();
209
- builder2.delete();
210
- return face;
211
- }
212
- const builder = new this.oc.BRepOffsetAPI_MakeFilling(
213
- 3,
214
- 15,
215
- 2,
216
- false,
217
- 1e-5,
218
- 1e-4,
219
- 0.01,
220
- 0.1,
221
- 8,
222
- 9
223
- );
224
- const edges = this.iterShapes(wire, "edge");
225
- for (const edge of edges) {
226
- builder.Add_1(edge, this.oc.GeomAbs_Shape.GeomAbs_C0, true);
227
- }
228
- const progress = new this.oc.Message_ProgressRange_1();
229
- builder.Build(progress);
230
- const shape = builder.Shape();
231
- builder.delete();
232
- progress.delete();
233
- return shape;
958
+ return makeFace$1(this.oc, wire, planar);
234
959
  }
235
960
  makeBox(width, height, depth) {
236
- const maker = new this.oc.BRepPrimAPI_MakeBox_2(width, height, depth);
237
- const solid = maker.Solid();
238
- maker.delete();
239
- return solid;
961
+ return makeBox$1(this.oc, width, height, depth);
240
962
  }
241
963
  makeCylinder(radius, height, center = [0, 0, 0], direction = [0, 0, 1]) {
242
- const origin = new this.oc.gp_Pnt_3(...center);
243
- const dir = new this.oc.gp_Dir_4(...direction);
244
- const axis = new this.oc.gp_Ax2_3(origin, dir);
245
- const maker = new this.oc.BRepPrimAPI_MakeCylinder_3(axis, radius, height);
246
- const solid = maker.Shape();
247
- maker.delete();
248
- axis.delete();
249
- origin.delete();
250
- dir.delete();
251
- return solid;
964
+ return makeCylinder$1(this.oc, radius, height, center, direction);
252
965
  }
253
966
  makeSphere(radius, center = [0, 0, 0]) {
254
- const origin = new this.oc.gp_Pnt_3(...center);
255
- const maker = new this.oc.BRepPrimAPI_MakeSphere_2(origin, radius);
256
- const solid = maker.Shape();
257
- maker.delete();
258
- origin.delete();
259
- return solid;
967
+ return makeSphere$1(this.oc, radius, center);
260
968
  }
261
- // --- Extrusion / sweep / loft / revolution ---
262
- extrude(face, direction, length) {
263
- const vec2 = new this.oc.gp_Vec_4(
264
- direction[0] * length,
265
- direction[1] * length,
266
- direction[2] * length
267
- );
268
- const maker = new this.oc.BRepPrimAPI_MakePrism_1(face, vec2, false, true);
269
- const result = maker.Shape();
270
- maker.delete();
271
- vec2.delete();
272
- return result;
969
+ // --- Extrusion / sweep / loft / revolution (delegates to sweepOps.ts) ---
970
+ extrude(face, direction, length2) {
971
+ return extrude(this.oc, face, direction, length2);
273
972
  }
274
973
  revolve(shape, axis, angle) {
275
- const maker = new this.oc.BRepPrimAPI_MakeRevol_1(shape, axis, angle, false);
276
- const result = maker.Shape();
277
- maker.delete();
278
- return result;
974
+ return revolve(this.oc, shape, axis, angle);
279
975
  }
280
- loft(wires, ruled = false, startShape, endShape) {
281
- const loftBuilder = new this.oc.BRepOffsetAPI_ThruSections(true, ruled, 1e-6);
282
- if (startShape) loftBuilder.AddVertex(startShape);
283
- for (const wire of wires) {
284
- loftBuilder.AddWire(wire);
285
- }
286
- if (endShape) loftBuilder.AddVertex(endShape);
287
- const progress = new this.oc.Message_ProgressRange_1();
288
- loftBuilder.Build(progress);
289
- const result = loftBuilder.Shape();
290
- loftBuilder.delete();
291
- progress.delete();
292
- return result;
976
+ loft(wires, ruled = false, startShape, endShape) {
977
+ return loft$1(this.oc, wires, ruled, startShape, endShape);
293
978
  }
294
979
  sweep(wire, spine, options = {}) {
295
- const { transitionMode } = options;
296
- const sweepBuilder = new this.oc.BRepOffsetAPI_MakePipeShell(spine);
297
- if (transitionMode !== void 0) {
298
- sweepBuilder.SetTransitionMode(transitionMode);
299
- }
300
- sweepBuilder.Add_1(wire, false, false);
301
- const progress = new this.oc.Message_ProgressRange_1();
302
- sweepBuilder.Build(progress);
303
- progress.delete();
304
- sweepBuilder.MakeSolid();
305
- const result = sweepBuilder.Shape();
306
- sweepBuilder.delete();
307
- return result;
980
+ return sweep$1(this.oc, wire, spine, options);
308
981
  }
309
- // --- Modification ---
982
+ // --- Modification (delegates to modifierOps.ts) ---
310
983
  fillet(shape, edges, radius) {
311
- const builder = new this.oc.BRepFilletAPI_MakeFillet(
312
- shape,
313
- this.oc.ChFi3d_FilletShape.ChFi3d_Rational
314
- );
315
- for (const edge of edges) {
316
- const r = typeof radius === "function" ? radius(edge) : radius;
317
- if (r > 0) builder.Add_2(r, edge);
318
- }
319
- const result = builder.Shape();
320
- builder.delete();
321
- return result;
984
+ return fillet(this.oc, shape, edges, radius);
322
985
  }
323
986
  chamfer(shape, edges, distance) {
324
- const builder = new this.oc.BRepFilletAPI_MakeChamfer(shape);
325
- for (const edge of edges) {
326
- const d = typeof distance === "function" ? distance(edge) : distance;
327
- if (d > 0) builder.Add_2(d, edge);
328
- }
329
- const result = builder.Shape();
330
- builder.delete();
331
- return result;
987
+ return chamfer(this.oc, shape, edges, distance);
332
988
  }
333
989
  shell(shape, faces, thickness, tolerance = 1e-3) {
334
- const facesToRemove = new this.oc.TopTools_ListOfShape_1();
335
- for (const face of faces) {
336
- facesToRemove.Append_1(face);
337
- }
338
- const progress = new this.oc.Message_ProgressRange_1();
339
- const builder = new this.oc.BRepOffsetAPI_MakeThickSolid();
340
- builder.MakeThickSolidByJoin(
341
- shape,
342
- facesToRemove,
343
- -thickness,
344
- tolerance,
345
- this.oc.BRepOffset_Mode.BRepOffset_Skin,
346
- false,
347
- false,
348
- this.oc.GeomAbs_JoinType.GeomAbs_Arc,
349
- false,
350
- progress
351
- );
352
- const result = builder.Shape();
353
- builder.delete();
354
- facesToRemove.delete();
355
- progress.delete();
356
- return result;
990
+ return shell(this.oc, shape, faces, thickness, tolerance);
357
991
  }
358
992
  offset(shape, distance, tolerance = 1e-6) {
359
- const progress = new this.oc.Message_ProgressRange_1();
360
- const builder = new this.oc.BRepOffsetAPI_MakeOffsetShape();
361
- builder.PerformByJoin(
362
- shape,
363
- distance,
364
- tolerance,
365
- this.oc.BRepOffset_Mode.BRepOffset_Skin,
366
- false,
367
- false,
368
- this.oc.GeomAbs_JoinType.GeomAbs_Arc,
369
- false,
370
- progress
371
- );
372
- const result = builder.Shape();
373
- builder.delete();
374
- progress.delete();
375
- return result;
993
+ return offset$1(this.oc, shape, distance, tolerance);
376
994
  }
377
- // --- Transforms ---
995
+ // --- Transforms (delegates to transformOps.ts) ---
378
996
  transform(shape, trsf) {
379
- const transformer = new this.oc.BRepBuilderAPI_Transform_2(shape, trsf, true);
380
- const result = transformer.ModifiedShape(shape);
381
- transformer.delete();
382
- return result;
997
+ return transform(this.oc, shape, trsf);
383
998
  }
384
999
  translate(shape, x, y, z) {
385
- const trsf = new this.oc.gp_Trsf_1();
386
- const vec2 = new this.oc.gp_Vec_4(x, y, z);
387
- trsf.SetTranslation_1(vec2);
388
- const result = this.transform(shape, trsf);
389
- trsf.delete();
390
- vec2.delete();
391
- return result;
1000
+ return translate$1(this.oc, shape, x, y, z);
392
1001
  }
393
1002
  rotate(shape, angle, axis = [0, 0, 1], center = [0, 0, 0]) {
394
- const trsf = new this.oc.gp_Trsf_1();
395
- const origin = new this.oc.gp_Pnt_3(...center);
396
- const dir = new this.oc.gp_Dir_4(...axis);
397
- const ax1 = new this.oc.gp_Ax1_2(origin, dir);
398
- trsf.SetRotation_1(ax1, angle * Math.PI / 180);
399
- const result = this.transform(shape, trsf);
400
- trsf.delete();
401
- ax1.delete();
402
- origin.delete();
403
- dir.delete();
404
- return result;
1003
+ return rotate$1(this.oc, shape, angle, axis, center);
405
1004
  }
406
1005
  mirror(shape, origin, normal) {
407
- const trsf = new this.oc.gp_Trsf_1();
408
- const pnt2 = new this.oc.gp_Pnt_3(...origin);
409
- const dir = new this.oc.gp_Dir_4(...normal);
410
- const ax2 = new this.oc.gp_Ax2_3(pnt2, dir);
411
- trsf.SetMirror_3(ax2);
412
- const result = this.transform(shape, trsf);
413
- trsf.delete();
414
- ax2.delete();
415
- pnt2.delete();
416
- dir.delete();
417
- return result;
1006
+ return mirror$1(this.oc, shape, origin, normal);
418
1007
  }
419
1008
  scale(shape, center, factor) {
420
- const trsf = new this.oc.gp_Trsf_1();
421
- const pnt2 = new this.oc.gp_Pnt_3(...center);
422
- trsf.SetScale(pnt2, factor);
423
- const result = this.transform(shape, trsf);
424
- trsf.delete();
425
- pnt2.delete();
426
- return result;
1009
+ return scale$1(this.oc, shape, center, factor);
427
1010
  }
428
- // --- Meshing ---
1011
+ // --- Meshing (delegates to meshOps.ts) ---
429
1012
  mesh(shape, options) {
430
- if (this.oc.MeshExtractor) {
431
- return this._meshBulk(shape, options);
432
- }
433
- return this._meshJS(shape, options);
434
- }
435
- _meshBulk(shape, options) {
436
- const raw = this.oc.MeshExtractor.extract(
437
- shape,
438
- options.tolerance,
439
- options.angularTolerance,
440
- !!options.skipNormals
441
- );
442
- const verticesSize = raw.getVerticesSize();
443
- const normalsSize = raw.getNormalsSize();
444
- const trianglesSize = raw.getTrianglesSize();
445
- const faceGroupsSize = raw.getFaceGroupsSize();
446
- const verticesPtr = raw.getVerticesPtr() / 4;
447
- const vertices = this.oc.HEAPF32.slice(verticesPtr, verticesPtr + verticesSize);
448
- let normals;
449
- if (options.skipNormals || normalsSize === 0) {
450
- normals = new Float32Array(0);
451
- } else {
452
- const normalsPtr = raw.getNormalsPtr() / 4;
453
- normals = this.oc.HEAPF32.slice(normalsPtr, normalsPtr + normalsSize);
454
- }
455
- const trianglesPtr = raw.getTrianglesPtr() / 4;
456
- const triangles = this.oc.HEAPU32.slice(
457
- trianglesPtr,
458
- trianglesPtr + trianglesSize
459
- );
460
- const faceGroups = [];
461
- if (faceGroupsSize > 0) {
462
- const fgPtr = raw.getFaceGroupsPtr() / 4;
463
- const fgRaw = this.oc.HEAP32.slice(fgPtr, fgPtr + faceGroupsSize);
464
- for (let i = 0; i < fgRaw.length; i += 3) {
465
- faceGroups.push({
466
- start: fgRaw[i],
467
- count: fgRaw[i + 1],
468
- faceHash: fgRaw[i + 2]
469
- });
470
- }
471
- }
472
- raw.delete();
473
- return { vertices, normals, triangles, faceGroups };
474
- }
475
- _meshJS(shape, options) {
476
- const mesher = new this.oc.BRepMesh_IncrementalMesh_2(
477
- shape,
478
- options.tolerance,
479
- false,
480
- options.angularTolerance,
481
- false
482
- );
483
- mesher.delete();
484
- let totalNodes = 0;
485
- let totalTris = 0;
486
- const explorer = new this.oc.TopExp_Explorer_2(
487
- shape,
488
- this.oc.TopAbs_ShapeEnum.TopAbs_FACE,
489
- this.oc.TopAbs_ShapeEnum.TopAbs_SHAPE
490
- );
491
- while (explorer.More()) {
492
- const face = this.oc.TopoDS.Face_1(explorer.Current());
493
- const loc = new this.oc.TopLoc_Location_1();
494
- const tri = this.oc.BRep_Tool.Triangulation(face, loc, 0);
495
- if (!tri.IsNull()) {
496
- const t = tri.get();
497
- totalNodes += t.NbNodes();
498
- totalTris += t.NbTriangles();
499
- }
500
- loc.delete();
501
- tri.delete();
502
- explorer.Next();
503
- }
504
- const vertices = new Float32Array(totalNodes * 3);
505
- const normals = options.skipNormals ? new Float32Array(0) : new Float32Array(totalNodes * 3);
506
- const triangles = new Uint32Array(totalTris * 3);
507
- const faceGroups = [];
508
- let vIdx = 0;
509
- let nIdx = 0;
510
- let tIdx = 0;
511
- explorer.Init(
512
- shape,
513
- this.oc.TopAbs_ShapeEnum.TopAbs_FACE,
514
- this.oc.TopAbs_ShapeEnum.TopAbs_SHAPE
515
- );
516
- while (explorer.More()) {
517
- const face = this.oc.TopoDS.Face_1(explorer.Current());
518
- const location = new this.oc.TopLoc_Location_1();
519
- const triangulation = this.oc.BRep_Tool.Triangulation(face, location, 0);
520
- if (!triangulation.IsNull()) {
521
- const tri = triangulation.get();
522
- const transformation = location.Transformation();
523
- const nbNodes = tri.NbNodes();
524
- const vertexOffset = vIdx / 3;
525
- const triStart = tIdx;
526
- for (let i = 1; i <= nbNodes; i++) {
527
- const p = tri.Node(i).Transformed(transformation);
528
- vertices[vIdx++] = p.X();
529
- vertices[vIdx++] = p.Y();
530
- vertices[vIdx++] = p.Z();
531
- p.delete();
532
- }
533
- if (!options.skipNormals) {
534
- const normalsArray = new this.oc.TColgp_Array1OfDir_2(1, nbNodes);
535
- const pc = new this.oc.Poly_Connect_2(triangulation);
536
- this.oc.StdPrs_ToolTriangulatedShape.Normal(face, pc, normalsArray);
537
- for (let i = normalsArray.Lower(); i <= normalsArray.Upper(); i++) {
538
- const d = normalsArray.Value(i).Transformed(transformation);
539
- normals[nIdx++] = d.X();
540
- normals[nIdx++] = d.Y();
541
- normals[nIdx++] = d.Z();
542
- d.delete();
543
- }
544
- normalsArray.delete();
545
- pc.delete();
546
- }
547
- const orient = face.Orientation_1();
548
- const isForward = orient === this.oc.TopAbs_Orientation.TopAbs_FORWARD;
549
- const nbTriangles = tri.NbTriangles();
550
- for (let nt = 1; nt <= nbTriangles; nt++) {
551
- const t = tri.Triangle(nt);
552
- let n1 = t.Value(1);
553
- let n2 = t.Value(2);
554
- const n3 = t.Value(3);
555
- if (!isForward) {
556
- const tmp = n1;
557
- n1 = n2;
558
- n2 = tmp;
559
- }
560
- triangles[tIdx++] = n1 - 1 + vertexOffset;
561
- triangles[tIdx++] = n2 - 1 + vertexOffset;
562
- triangles[tIdx++] = n3 - 1 + vertexOffset;
563
- t.delete();
564
- }
565
- faceGroups.push({
566
- start: triStart,
567
- count: tIdx - triStart,
568
- faceHash: face.HashCode(HASH_CODE_MAX$1)
569
- });
570
- transformation.delete();
571
- }
572
- location.delete();
573
- triangulation.delete();
574
- explorer.Next();
575
- }
576
- explorer.delete();
577
- return { vertices, normals, triangles, faceGroups };
1013
+ return mesh(this.oc, shape, options);
578
1014
  }
579
1015
  meshEdges(shape, tolerance, angularTolerance) {
580
- if (this.oc.EdgeMeshExtractor) {
581
- return this._meshEdgesBulk(shape, tolerance, angularTolerance);
582
- }
583
- return this._meshEdgesJS(shape, tolerance, angularTolerance);
584
- }
585
- _meshEdgesBulk(shape, tolerance, angularTolerance) {
586
- const raw = this.oc.EdgeMeshExtractor.extract(shape, tolerance, angularTolerance);
587
- const linesSize = raw.getLinesSize();
588
- const edgeGroupsSize = raw.getEdgeGroupsSize();
589
- let lines;
590
- if (linesSize > 0) {
591
- const linesPtr = raw.getLinesPtr() / 4;
592
- lines = this.oc.HEAPF32.slice(linesPtr, linesPtr + linesSize);
593
- } else {
594
- lines = new Float32Array(0);
595
- }
596
- const edgeGroups = [];
597
- if (edgeGroupsSize > 0) {
598
- const egPtr = raw.getEdgeGroupsPtr() / 4;
599
- const egRaw = this.oc.HEAP32.slice(egPtr, egPtr + edgeGroupsSize);
600
- for (let i = 0; i < egRaw.length; i += 3) {
601
- edgeGroups.push({
602
- start: egRaw[i],
603
- count: egRaw[i + 1],
604
- edgeHash: egRaw[i + 2]
605
- });
606
- }
607
- }
608
- raw.delete();
609
- return { lines, edgeGroups };
610
- }
611
- _meshEdgesJS(shape, tolerance, angularTolerance) {
612
- const mesher = new this.oc.BRepMesh_IncrementalMesh_2(
613
- shape,
614
- tolerance,
615
- false,
616
- angularTolerance,
617
- false
618
- );
619
- mesher.delete();
620
- const lines = [];
621
- const edgeGroups = [];
622
- const seenHashes = /* @__PURE__ */ new Set();
623
- const faceExplorer = new this.oc.TopExp_Explorer_2(
624
- shape,
625
- this.oc.TopAbs_ShapeEnum.TopAbs_FACE,
626
- this.oc.TopAbs_ShapeEnum.TopAbs_SHAPE
627
- );
628
- while (faceExplorer.More()) {
629
- const face = this.oc.TopoDS.Face_1(faceExplorer.Current());
630
- const faceLoc = new this.oc.TopLoc_Location_1();
631
- const tri = this.oc.BRep_Tool.Triangulation(face, faceLoc, 0);
632
- if (!tri.IsNull()) {
633
- const triObj = tri.get();
634
- const edgeExplorer2 = new this.oc.TopExp_Explorer_2(
635
- face,
636
- this.oc.TopAbs_ShapeEnum.TopAbs_EDGE,
637
- this.oc.TopAbs_ShapeEnum.TopAbs_SHAPE
638
- );
639
- while (edgeExplorer2.More()) {
640
- const edgeShape = edgeExplorer2.Current();
641
- const edge = this.oc.TopoDS.Edge_1(edgeShape);
642
- const edgeHash = edge.HashCode(HASH_CODE_MAX$1);
643
- if (!seenHashes.has(edgeHash)) {
644
- seenHashes.add(edgeHash);
645
- const edgeLoc = new this.oc.TopLoc_Location_1();
646
- const polygon = this.oc.BRep_Tool.PolygonOnTriangulation_1(edge, tri, edgeLoc);
647
- const edgeNodes = polygon && !polygon.IsNull() ? polygon.get().Nodes() : null;
648
- if (edgeNodes) {
649
- const lineStart = lines.length / 3;
650
- let prevX = 0, prevY = 0, prevZ = 0;
651
- let hasPrev = false;
652
- for (let i = edgeNodes.Lower(); i <= edgeNodes.Upper(); i++) {
653
- const p = triObj.Node(edgeNodes.Value(i)).Transformed(edgeLoc.Transformation());
654
- const x = p.X(), y = p.Y(), z = p.Z();
655
- if (hasPrev) {
656
- lines.push(prevX, prevY, prevZ, x, y, z);
657
- }
658
- prevX = x;
659
- prevY = y;
660
- prevZ = z;
661
- hasPrev = true;
662
- p.delete();
663
- }
664
- edgeGroups.push({
665
- start: lineStart,
666
- count: lines.length / 3 - lineStart,
667
- edgeHash
668
- });
669
- edgeNodes.delete();
670
- }
671
- if (polygon && !polygon.IsNull()) polygon.delete();
672
- edgeLoc.delete();
673
- }
674
- edgeExplorer2.Next();
675
- }
676
- edgeExplorer2.delete();
677
- }
678
- tri.delete();
679
- faceLoc.delete();
680
- faceExplorer.Next();
681
- }
682
- faceExplorer.delete();
683
- const edgeExplorer = new this.oc.TopExp_Explorer_2(
684
- shape,
685
- this.oc.TopAbs_ShapeEnum.TopAbs_EDGE,
686
- this.oc.TopAbs_ShapeEnum.TopAbs_SHAPE
687
- );
688
- while (edgeExplorer.More()) {
689
- const edgeShape = edgeExplorer.Current();
690
- const edge = this.oc.TopoDS.Edge_1(edgeShape);
691
- const edgeHash = edge.HashCode(HASH_CODE_MAX$1);
692
- if (!seenHashes.has(edgeHash)) {
693
- seenHashes.add(edgeHash);
694
- const adaptor = new this.oc.BRepAdaptor_Curve_2(edge);
695
- const tangDef = new this.oc.GCPnts_TangentialDeflection_2(
696
- adaptor,
697
- tolerance,
698
- angularTolerance,
699
- 2,
700
- 1e-9,
701
- 1e-7
702
- );
703
- const lineStart = lines.length / 3;
704
- let prevX = 0, prevY = 0, prevZ = 0;
705
- let hasPrev = false;
706
- for (let j = 1; j <= tangDef.NbPoints(); j++) {
707
- const p = tangDef.Value(j);
708
- const x = p.X(), y = p.Y(), z = p.Z();
709
- if (hasPrev) {
710
- lines.push(prevX, prevY, prevZ, x, y, z);
711
- }
712
- prevX = x;
713
- prevY = y;
714
- prevZ = z;
715
- hasPrev = true;
716
- p.delete();
717
- }
718
- edgeGroups.push({
719
- start: lineStart,
720
- count: lines.length / 3 - lineStart,
721
- edgeHash
722
- });
723
- tangDef.delete();
724
- adaptor.delete();
725
- }
726
- edgeExplorer.Next();
727
- }
728
- edgeExplorer.delete();
729
- return { lines: new Float32Array(lines), edgeGroups };
1016
+ return meshEdges(this.oc, shape, tolerance, angularTolerance);
730
1017
  }
731
- // --- File I/O ---
1018
+ // --- File I/O (delegates to ioOps.ts) ---
732
1019
  exportSTEP(shapes) {
733
- const writer = new this.oc.STEPControl_Writer_1();
734
- this.oc.Interface_Static.SetIVal("write.step.schema", 5);
735
- writer.Model(true).delete();
736
- const progress = new this.oc.Message_ProgressRange_1();
737
- for (const shape of shapes) {
738
- writer.Transfer(shape, this.oc.STEPControl_StepModelType.STEPControl_AsIs, true, progress);
739
- }
740
- const filename = uniqueIOFilename("_export", "step");
741
- const done = writer.Write(filename);
742
- writer.delete();
743
- progress.delete();
744
- if (done === this.oc.IFSelect_ReturnStatus.IFSelect_RetDone) {
745
- const file = this.oc.FS.readFile("/" + filename);
746
- this.oc.FS.unlink("/" + filename);
747
- return new TextDecoder().decode(file);
748
- }
749
- throw new Error("STEP export failed: writer did not complete successfully");
1020
+ return exportSTEP$2(this.oc, shapes);
750
1021
  }
751
1022
  exportSTL(shape, binary = false) {
752
- const filename = uniqueIOFilename("_export", "stl");
753
- const done = this.oc.StlAPI.Write(shape, filename, !binary);
754
- if (done) {
755
- const file = this.oc.FS.readFile("/" + filename);
756
- this.oc.FS.unlink("/" + filename);
757
- if (binary) return file.buffer;
758
- return new TextDecoder().decode(file);
759
- }
760
- throw new Error("STL export failed: StlAPI.Write returned false");
1023
+ return exportSTL$1(this.oc, shape, binary);
761
1024
  }
762
1025
  importSTEP(data) {
763
- const filename = uniqueIOFilename("_import", "step");
764
- const buffer = typeof data === "string" ? new TextEncoder().encode(data) : new Uint8Array(data);
765
- this.oc.FS.writeFile("/" + filename, buffer);
766
- const reader = new this.oc.STEPControl_Reader_1();
767
- if (reader.ReadFile(filename)) {
768
- this.oc.FS.unlink("/" + filename);
769
- const progress = new this.oc.Message_ProgressRange_1();
770
- reader.TransferRoots(progress);
771
- progress.delete();
772
- const shape = reader.OneShape();
773
- reader.delete();
774
- return [shape];
775
- }
776
- this.oc.FS.unlink("/" + filename);
777
- reader.delete();
778
- throw new Error("Failed to import STEP file: reader could not parse the input data");
1026
+ return importSTEP$2(this.oc, data);
779
1027
  }
780
1028
  importSTL(data) {
781
- const filename = uniqueIOFilename("_import", "stl");
782
- const buffer = typeof data === "string" ? new TextEncoder().encode(data) : new Uint8Array(data);
783
- this.oc.FS.writeFile("/" + filename, buffer);
784
- const reader = new this.oc.StlAPI_Reader();
785
- const readShape = new this.oc.TopoDS_Shell();
786
- if (reader.Read(readShape, filename)) {
787
- this.oc.FS.unlink("/" + filename);
788
- const upgrader = new this.oc.ShapeUpgrade_UnifySameDomain_2(readShape, true, true, false);
789
- upgrader.Build();
790
- const upgraded = upgrader.Shape();
791
- const solidBuilder = new this.oc.BRepBuilderAPI_MakeSolid_1();
792
- solidBuilder.Add(this.oc.TopoDS.Shell_1(upgraded));
793
- const solid = solidBuilder.Solid();
794
- readShape.delete();
795
- upgrader.delete();
796
- solidBuilder.delete();
797
- reader.delete();
798
- return solid;
799
- }
800
- this.oc.FS.unlink("/" + filename);
801
- readShape.delete();
802
- reader.delete();
803
- throw new Error("Failed to import STL file: reader could not parse the input data");
1029
+ return importSTL$2(this.oc, data);
804
1030
  }
805
- // --- Measurement ---
1031
+ // --- Measurement (delegates to measureOps.ts) ---
806
1032
  volume(shape) {
807
- const props = new this.oc.GProp_GProps_1();
808
- this.oc.BRepGProp.VolumeProperties_1(shape, props, true, false, false);
809
- const vol = props.Mass();
810
- props.delete();
811
- return vol;
1033
+ return volume(this.oc, shape);
812
1034
  }
813
1035
  area(shape) {
814
- const props = new this.oc.GProp_GProps_1();
815
- this.oc.BRepGProp.SurfaceProperties_2(shape, props, 1e-7, true);
816
- const a = props.Mass();
817
- props.delete();
818
- return a;
1036
+ return area(this.oc, shape);
819
1037
  }
820
1038
  length(shape) {
821
- const props = new this.oc.GProp_GProps_1();
822
- this.oc.BRepGProp.LinearProperties(shape, props, true, false);
823
- const len = props.Mass();
824
- props.delete();
825
- return len;
1039
+ return length(this.oc, shape);
826
1040
  }
827
1041
  centerOfMass(shape) {
828
- const props = new this.oc.GProp_GProps_1();
829
- this.oc.BRepGProp.VolumeProperties_1(shape, props, true, false, false);
830
- const center = props.CentreOfMass();
831
- const result = [center.X(), center.Y(), center.Z()];
832
- center.delete();
833
- props.delete();
834
- return result;
1042
+ return centerOfMass(this.oc, shape);
835
1043
  }
836
1044
  boundingBox(shape) {
837
- const box = new this.oc.Bnd_Box_1();
838
- this.oc.BRepBndLib.Add(shape, box, true);
839
- const xMin = { current: 0 };
840
- const yMin = { current: 0 };
841
- const zMin = { current: 0 };
842
- const xMax = { current: 0 };
843
- const yMax = { current: 0 };
844
- const zMax = { current: 0 };
845
- box.Get(xMin, yMin, zMin, xMax, yMax, zMax);
846
- box.delete();
847
- return {
848
- min: [xMin.current, yMin.current, zMin.current],
849
- max: [xMax.current, yMax.current, zMax.current]
850
- };
1045
+ return boundingBox(this.oc, shape);
851
1046
  }
852
- // --- Topology iteration ---
1047
+ // --- Topology iteration (delegates to topologyOps.ts) ---
853
1048
  iterShapes(shape, type) {
854
- if (this.oc.TopologyExtractor) {
855
- return this._iterShapesBulk(shape, type);
856
- }
857
- return this._iterShapesJS(shape, type);
858
- }
859
- _iterShapesBulk(shape, type) {
860
- const typeEnumMap = {
861
- vertex: 7,
862
- edge: 6,
863
- wire: 5,
864
- face: 4,
865
- shell: 3,
866
- solid: 2,
867
- compsolid: 1,
868
- compound: 0
869
- };
870
- const raw = this.oc.TopologyExtractor.extract(shape, typeEnumMap[type]);
871
- const count = raw.getShapesCount();
872
- const result = [];
873
- for (let i = 0; i < count; i++) {
874
- result.push(raw.getShape(i));
875
- }
876
- raw.delete();
877
- return result;
878
- }
879
- _iterShapesJS(shape, type) {
880
- const typeMap = {
881
- vertex: this.oc.TopAbs_ShapeEnum.TopAbs_VERTEX,
882
- edge: this.oc.TopAbs_ShapeEnum.TopAbs_EDGE,
883
- wire: this.oc.TopAbs_ShapeEnum.TopAbs_WIRE,
884
- face: this.oc.TopAbs_ShapeEnum.TopAbs_FACE,
885
- shell: this.oc.TopAbs_ShapeEnum.TopAbs_SHELL,
886
- solid: this.oc.TopAbs_ShapeEnum.TopAbs_SOLID,
887
- compsolid: this.oc.TopAbs_ShapeEnum.TopAbs_COMPSOLID,
888
- compound: this.oc.TopAbs_ShapeEnum.TopAbs_COMPOUND
889
- };
890
- const explorer = new this.oc.TopExp_Explorer_2(
891
- shape,
892
- typeMap[type],
893
- this.oc.TopAbs_ShapeEnum.TopAbs_SHAPE
894
- );
895
- const result = [];
896
- const seen = /* @__PURE__ */ new Map();
897
- while (explorer.More()) {
898
- const item = explorer.Current();
899
- const hash = item.HashCode(HASH_CODE_MAX$1);
900
- const bucket = seen.get(hash);
901
- if (!bucket) {
902
- seen.set(hash, [item]);
903
- result.push(item);
904
- } else if (!bucket.some((s) => s.IsSame(item))) {
905
- bucket.push(item);
906
- result.push(item);
907
- }
908
- explorer.Next();
909
- }
910
- explorer.delete();
911
- return result;
912
- }
913
- _shapeTypeMap = null;
914
- _getShapeTypeMap() {
915
- if (!this._shapeTypeMap) {
916
- const ta = this.oc.TopAbs_ShapeEnum;
917
- this._shapeTypeMap = /* @__PURE__ */ new Map([
918
- [ta.TopAbs_VERTEX, "vertex"],
919
- [ta.TopAbs_EDGE, "edge"],
920
- [ta.TopAbs_WIRE, "wire"],
921
- [ta.TopAbs_FACE, "face"],
922
- [ta.TopAbs_SHELL, "shell"],
923
- [ta.TopAbs_SOLID, "solid"],
924
- [ta.TopAbs_COMPSOLID, "compsolid"],
925
- [ta.TopAbs_COMPOUND, "compound"]
926
- ]);
927
- }
928
- return this._shapeTypeMap;
1049
+ return iterShapes(this.oc, shape, type);
929
1050
  }
930
1051
  shapeType(shape) {
931
- if (shape.IsNull()) throw new Error("Cannot determine shape type: shape is null");
932
- const result = this._getShapeTypeMap().get(shape.ShapeType());
933
- if (!result) throw new Error(`Unknown shape type enum value: ${shape.ShapeType()}`);
934
- return result;
1052
+ return shapeType$1(this.oc, shape);
935
1053
  }
936
1054
  isSame(a, b) {
937
- return a.IsSame(b);
1055
+ return isSame(a, b);
938
1056
  }
939
1057
  isEqual(a, b) {
940
- return a.IsEqual(b);
1058
+ return isEqual(a, b);
941
1059
  }
942
1060
  // --- Simplification ---
943
1061
  simplify(shape) {
944
- const upgrader = new this.oc.ShapeUpgrade_UnifySameDomain_2(shape, true, true, false);
945
- upgrader.Build();
946
- const result = upgrader.Shape();
947
- upgrader.delete();
948
- return result;
1062
+ return simplify(this.oc, shape);
949
1063
  }
950
1064
  // --- Private helpers ---
951
- _buildCompound(shapes) {
952
- const builder = new this.oc.TopoDS_Builder();
953
- const compound = new this.oc.TopoDS_Compound();
954
- builder.MakeCompound(compound);
955
- for (const s of shapes) {
956
- builder.Add(compound, s);
957
- }
958
- builder.delete();
959
- return compound;
960
- }
961
- _applyGlue(op, optimisation) {
962
- if (optimisation === "commonFace") {
963
- op.SetGlue(this.oc.BOPAlgo_GlueEnum.BOPAlgo_GlueShift);
964
- }
965
- if (optimisation === "sameFace") {
966
- op.SetGlue(this.oc.BOPAlgo_GlueEnum.BOPAlgo_GlueFull);
967
- }
968
- }
969
1065
  }
970
1066
  let _kernel = null;
971
1067
  function getKernel() {
@@ -1587,9 +1683,9 @@ function asDir(coords) {
1587
1683
  return dir;
1588
1684
  }
1589
1685
  class Transformation extends WrappingObj {
1590
- constructor(transform) {
1686
+ constructor(transform2) {
1591
1687
  const oc = getKernel().oc;
1592
- super(transform || new oc.gp_Trsf_1());
1688
+ super(transform2 || new oc.gp_Trsf_1());
1593
1689
  }
1594
1690
  translate(xDistOrVector, yDist = 0, zDist = 0) {
1595
1691
  const translation = new Vector(
@@ -1997,7 +2093,7 @@ function meshShape(shape, {
1997
2093
  angularTolerance,
1998
2094
  skipNormals
1999
2095
  });
2000
- const mesh = {
2096
+ const mesh2 = {
2001
2097
  vertices: result.vertices,
2002
2098
  normals: result.normals,
2003
2099
  triangles: result.triangles,
@@ -2008,9 +2104,9 @@ function meshShape(shape, {
2008
2104
  }))
2009
2105
  };
2010
2106
  if (cache) {
2011
- setMeshForShape(shape.wrapped, cacheKey, mesh);
2107
+ setMeshForShape(shape.wrapped, cacheKey, mesh2);
2012
2108
  }
2013
- return mesh;
2109
+ return mesh2;
2014
2110
  }
2015
2111
  function meshShapeEdges(shape, { tolerance = 1e-3, angularTolerance = 0.1, cache = true } = {}) {
2016
2112
  const cacheKey = buildEdgeMeshCacheKey(0, tolerance, angularTolerance);
@@ -2203,6 +2299,73 @@ function deserializeShape(data) {
2203
2299
  const oc = getKernel().oc;
2204
2300
  return cast(oc.BRepToolsWrapper.Read(data));
2205
2301
  }
2302
+ function isShape3DInternal(shape) {
2303
+ const name = shape.constructor.name;
2304
+ return name === "Shell" || name === "Solid" || name === "CompSolid" || name === "Compound";
2305
+ }
2306
+ function buildCompoundOc(shapes) {
2307
+ const oc = getKernel().oc;
2308
+ const builder = new oc.TopoDS_Builder();
2309
+ const compound = new oc.TopoDS_Compound();
2310
+ builder.MakeCompound(compound);
2311
+ for (const s of shapes) {
2312
+ builder.Add(compound, s);
2313
+ }
2314
+ builder.delete();
2315
+ return compound;
2316
+ }
2317
+ function buildCompound$1(shapes) {
2318
+ return buildCompoundOc(shapes.map((s) => s.wrapped));
2319
+ }
2320
+ function applyGlue$1(op, optimisation) {
2321
+ const oc = getKernel().oc;
2322
+ if (optimisation === "commonFace") {
2323
+ op.SetGlue(oc.BOPAlgo_GlueEnum.BOPAlgo_GlueShift);
2324
+ }
2325
+ if (optimisation === "sameFace") {
2326
+ op.SetGlue(oc.BOPAlgo_GlueEnum.BOPAlgo_GlueFull);
2327
+ }
2328
+ }
2329
+ function fuseAll$2(shapes, { optimisation = "none", simplify: simplify2 = false, strategy = "native" } = {}) {
2330
+ if (shapes.length === 0)
2331
+ return err(validationError("FUSE_ALL_EMPTY", "fuseAll requires at least one shape"));
2332
+ if (shapes.length === 1) return ok(shapes[0]);
2333
+ if (strategy === "native") {
2334
+ const result = getKernel().fuseAll(
2335
+ shapes.map((s) => s.wrapped),
2336
+ { optimisation, simplify: simplify2, strategy }
2337
+ );
2338
+ return andThen(cast(result), (newShape) => {
2339
+ if (!isShape3DInternal(newShape))
2340
+ return err(typeCastError("FUSE_ALL_NOT_3D", "fuseAll did not produce a 3D shape"));
2341
+ return ok(newShape);
2342
+ });
2343
+ }
2344
+ const mid = Math.ceil(shapes.length / 2);
2345
+ const leftResult = fuseAll$2(shapes.slice(0, mid), { optimisation, simplify: false, strategy });
2346
+ if (isErr(leftResult)) return leftResult;
2347
+ const rightResult = fuseAll$2(shapes.slice(mid), { optimisation, simplify: false, strategy });
2348
+ if (isErr(rightResult)) return rightResult;
2349
+ return leftResult.value.fuse(rightResult.value, { optimisation, simplify: simplify2 });
2350
+ }
2351
+ function cutAll$1(base, tools, { optimisation = "none", simplify: simplify2 = false } = {}) {
2352
+ if (tools.length === 0) return ok(base);
2353
+ const oc = getKernel().oc;
2354
+ const r = gcWithScope();
2355
+ const toolCompound = r(buildCompound$1(tools));
2356
+ const progress = r(new oc.Message_ProgressRange_1());
2357
+ const cutOp = r(new oc.BRepAlgoAPI_Cut_3(base.wrapped, toolCompound, progress));
2358
+ applyGlue$1(cutOp, optimisation);
2359
+ cutOp.Build(progress);
2360
+ if (simplify2) {
2361
+ cutOp.SimplifyResult(true, true, 1e-3);
2362
+ }
2363
+ return andThen(cast(cutOp.Shape()), (newShape) => {
2364
+ if (!isShape3DInternal(newShape))
2365
+ return err(typeCastError("CUT_ALL_NOT_3D", "cutAll did not produce a 3D shape"));
2366
+ return ok(newShape);
2367
+ });
2368
+ }
2206
2369
  let _queryModule = null;
2207
2370
  function getQueryModule() {
2208
2371
  if (!_queryModule) {
@@ -2583,9 +2746,9 @@ class _1DShape extends Shape {
2583
2746
  get length() {
2584
2747
  const properties = new this.oc.GProp_GProps_1();
2585
2748
  this.oc.BRepGProp.LinearProperties(this.wrapped, properties, true, false);
2586
- const length = properties.Mass();
2749
+ const length2 = properties.Mass();
2587
2750
  properties.delete();
2588
- return length;
2751
+ return length2;
2589
2752
  }
2590
2753
  get orientation() {
2591
2754
  const orient = this.wrapped.Orientation_1();
@@ -2816,13 +2979,13 @@ class _3DShape extends Shape {
2816
2979
  *
2817
2980
  * @category Shape Modifications
2818
2981
  */
2819
- fuse(other, { optimisation = "none", simplify = false } = {}) {
2982
+ fuse(other, { optimisation = "none", simplify: simplify2 = false } = {}) {
2820
2983
  const r = gcWithScope();
2821
2984
  const progress = r(new this.oc.Message_ProgressRange_1());
2822
2985
  const newBody = r(new this.oc.BRepAlgoAPI_Fuse_3(this.wrapped, other.wrapped, progress));
2823
2986
  applyGlue$1(newBody, optimisation);
2824
2987
  newBody.Build(progress);
2825
- if (simplify) {
2988
+ if (simplify2) {
2826
2989
  newBody.SimplifyResult(true, true, 1e-3);
2827
2990
  }
2828
2991
  return andThen(cast(newBody.Shape()), (newShape) => {
@@ -2836,13 +2999,13 @@ class _3DShape extends Shape {
2836
2999
  *
2837
3000
  * @category Shape Modifications
2838
3001
  */
2839
- cut(tool, { optimisation = "none", simplify = false } = {}) {
3002
+ cut(tool, { optimisation = "none", simplify: simplify2 = false } = {}) {
2840
3003
  const r = gcWithScope();
2841
3004
  const progress = r(new this.oc.Message_ProgressRange_1());
2842
3005
  const cutter = r(new this.oc.BRepAlgoAPI_Cut_3(this.wrapped, tool.wrapped, progress));
2843
3006
  applyGlue$1(cutter, optimisation);
2844
3007
  cutter.Build(progress);
2845
- if (simplify) {
3008
+ if (simplify2) {
2846
3009
  cutter.SimplifyResult(true, true, 1e-3);
2847
3010
  }
2848
3011
  return andThen(cast(cutter.Shape()), (newShape) => {
@@ -2856,12 +3019,12 @@ class _3DShape extends Shape {
2856
3019
  *
2857
3020
  * @category Shape Modifications
2858
3021
  */
2859
- intersect(tool, { simplify = false } = {}) {
3022
+ intersect(tool, { simplify: simplify2 = false } = {}) {
2860
3023
  const r = gcWithScope();
2861
3024
  const progress = r(new this.oc.Message_ProgressRange_1());
2862
3025
  const intersector = r(new this.oc.BRepAlgoAPI_Common_3(this.wrapped, tool.wrapped, progress));
2863
3026
  intersector.Build(progress);
2864
- if (simplify) {
3027
+ if (simplify2) {
2865
3028
  intersector.SimplifyResult(true, true, 1e-3);
2866
3029
  }
2867
3030
  return andThen(cast(intersector.Shape()), (newShape) => {
@@ -3040,69 +3203,6 @@ class Compound extends _3DShape {
3040
3203
  function isShape3D$1(shape) {
3041
3204
  return shape instanceof Shell || shape instanceof Solid || shape instanceof CompSolid || shape instanceof Compound;
3042
3205
  }
3043
- function buildCompoundOc(shapes) {
3044
- const oc = getKernel().oc;
3045
- const builder = new oc.TopoDS_Builder();
3046
- const compound = new oc.TopoDS_Compound();
3047
- builder.MakeCompound(compound);
3048
- for (const s of shapes) {
3049
- builder.Add(compound, s);
3050
- }
3051
- builder.delete();
3052
- return compound;
3053
- }
3054
- function buildCompound$1(shapes) {
3055
- return buildCompoundOc(shapes.map((s) => s.wrapped));
3056
- }
3057
- function applyGlue$1(op, optimisation) {
3058
- const oc = getKernel().oc;
3059
- if (optimisation === "commonFace") {
3060
- op.SetGlue(oc.BOPAlgo_GlueEnum.BOPAlgo_GlueShift);
3061
- }
3062
- if (optimisation === "sameFace") {
3063
- op.SetGlue(oc.BOPAlgo_GlueEnum.BOPAlgo_GlueFull);
3064
- }
3065
- }
3066
- function fuseAll$2(shapes, { optimisation = "none", simplify = false, strategy = "native" } = {}) {
3067
- if (shapes.length === 0)
3068
- return err(validationError("FUSE_ALL_EMPTY", "fuseAll requires at least one shape"));
3069
- if (shapes.length === 1) return ok(shapes[0]);
3070
- if (strategy === "native") {
3071
- const result = getKernel().fuseAll(
3072
- shapes.map((s) => s.wrapped),
3073
- { optimisation, simplify, strategy }
3074
- );
3075
- return andThen(cast(result), (newShape) => {
3076
- if (!isShape3D$1(newShape))
3077
- return err(typeCastError("FUSE_ALL_NOT_3D", "fuseAll did not produce a 3D shape"));
3078
- return ok(newShape);
3079
- });
3080
- }
3081
- const mid = Math.ceil(shapes.length / 2);
3082
- const leftResult = fuseAll$2(shapes.slice(0, mid), { optimisation, simplify: false, strategy });
3083
- if (isErr(leftResult)) return leftResult;
3084
- const rightResult = fuseAll$2(shapes.slice(mid), { optimisation, simplify: false, strategy });
3085
- if (isErr(rightResult)) return rightResult;
3086
- return leftResult.value.fuse(rightResult.value, { optimisation, simplify });
3087
- }
3088
- function cutAll$1(base, tools, { optimisation = "none", simplify = false } = {}) {
3089
- if (tools.length === 0) return ok(base);
3090
- const oc = getKernel().oc;
3091
- const r = gcWithScope();
3092
- const toolCompound = r(buildCompound$1(tools));
3093
- const progress = r(new oc.Message_ProgressRange_1());
3094
- const cutOp = r(new oc.BRepAlgoAPI_Cut_3(base.wrapped, toolCompound, progress));
3095
- applyGlue$1(cutOp, optimisation);
3096
- cutOp.Build(progress);
3097
- if (simplify) {
3098
- cutOp.SimplifyResult(true, true, 1e-3);
3099
- }
3100
- return andThen(cast(cutOp.Shape()), (newShape) => {
3101
- if (!isShape3D$1(newShape))
3102
- return err(typeCastError("CUT_ALL_NOT_3D", "cutAll did not produce a 3D shape"));
3103
- return ok(newShape);
3104
- });
3105
- }
3106
3206
  const shapesModule = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
3107
3207
  __proto__: null,
3108
3208
  CompSolid,
@@ -3409,15 +3509,15 @@ class EllipsoidTransform extends WrappingObj {
3409
3509
  const ax1 = r(makeAx1([0, 0, 0], [0, 1, 0]));
3410
3510
  const ax2 = r(makeAx1([0, 0, 0], [0, 0, 1]));
3411
3511
  const ax3 = r(makeAx1([0, 0, 0], [1, 0, 0]));
3412
- const transform = new oc.gp_GTrsf_1();
3413
- transform.SetAffinity_1(ax1, xzRatio);
3512
+ const transform2 = new oc.gp_GTrsf_1();
3513
+ transform2.SetAffinity_1(ax1, xzRatio);
3414
3514
  const xy = r(new oc.gp_GTrsf_1());
3415
3515
  xy.SetAffinity_1(ax2, xyRatio);
3416
3516
  const yz = r(new oc.gp_GTrsf_1());
3417
3517
  yz.SetAffinity_1(ax3, yzRatio);
3418
- transform.Multiply(xy);
3419
- transform.Multiply(yz);
3420
- super(transform);
3518
+ transform2.Multiply(xy);
3519
+ transform2.Multiply(yz);
3520
+ super(transform2);
3421
3521
  }
3422
3522
  applyToPoint(p) {
3423
3523
  const oc = getKernel().oc;
@@ -3448,18 +3548,18 @@ const makeEllipsoid = (aLength, bLength, cLength) => {
3448
3548
  const baseSurface = oc.GeomConvert.SurfaceToBSplineSurface(sphericalSurface.UReversed()).get();
3449
3549
  try {
3450
3550
  const poles = convertToJSArray(baseSurface.Poles_2());
3451
- const transform = new EllipsoidTransform(aLength, bLength, cLength);
3551
+ const transform2 = new EllipsoidTransform(aLength, bLength, cLength);
3452
3552
  poles.forEach((columns, rowIdx) => {
3453
3553
  columns.forEach((value, colIdx) => {
3454
- const newPoint = transform.applyToPoint(value);
3554
+ const newPoint = transform2.applyToPoint(value);
3455
3555
  baseSurface.SetPole_1(rowIdx + 1, colIdx + 1, newPoint);
3456
3556
  newPoint.delete();
3457
3557
  });
3458
3558
  });
3459
- const shell = unwrap(
3559
+ const shell2 = unwrap(
3460
3560
  cast(r(new oc.BRepBuilderAPI_MakeShell_2(baseSurface.UReversed(), false)).Shell())
3461
3561
  );
3462
- return unwrap(makeSolid([shell]));
3562
+ return unwrap(makeSolid([shell2]));
3463
3563
  } finally {
3464
3564
  baseSurface.delete();
3465
3565
  }
@@ -3535,16 +3635,16 @@ function _weld(facesOrShells) {
3535
3635
  return unwrap(cast(unwrap(downcast(shellBuilder.SewedShape()))));
3536
3636
  }
3537
3637
  function weldShellsAndFaces(facesOrShells, ignoreType = false) {
3538
- const shell = _weld(facesOrShells);
3539
- if (!ignoreType && !(shell instanceof Shell))
3638
+ const shell2 = _weld(facesOrShells);
3639
+ if (!ignoreType && !(shell2 instanceof Shell))
3540
3640
  return err(typeCastError("WELD_NOT_SHELL", "Could not make a shell from faces and shells"));
3541
- return ok(shell);
3641
+ return ok(shell2);
3542
3642
  }
3543
3643
  function makeSolid(facesOrShells) {
3544
3644
  const r = gcWithScope();
3545
3645
  const oc = getKernel().oc;
3546
- const shell = _weld(facesOrShells);
3547
- return andThen(cast(r(new oc.ShapeFix_Solid_1()).SolidFromShell(shell.wrapped)), (solid) => {
3646
+ const shell2 = _weld(facesOrShells);
3647
+ return andThen(cast(r(new oc.ShapeFix_Solid_1()).SolidFromShell(shell2.wrapped)), (solid) => {
3548
3648
  if (!(solid instanceof Solid))
3549
3649
  return err(typeCastError("SOLID_BUILD_FAILED", "Could not make a solid of faces and shells"));
3550
3650
  return ok(solid);
@@ -4097,43 +4197,43 @@ function castToShape3D(shape, errorCode, errorMsg) {
4097
4197
  }
4098
4198
  return ok(wrapped);
4099
4199
  }
4100
- function fuseShapes(a, b, { optimisation = "none", simplify = false } = {}) {
4200
+ function fuseShapes(a, b, { optimisation = "none", simplify: simplify2 = false } = {}) {
4101
4201
  const oc = getKernel().oc;
4102
4202
  const r = gcWithScope();
4103
4203
  const progress = r(new oc.Message_ProgressRange_1());
4104
4204
  const fuseOp = r(new oc.BRepAlgoAPI_Fuse_3(a.wrapped, b.wrapped, progress));
4105
4205
  applyGlue(fuseOp, optimisation);
4106
4206
  fuseOp.Build(progress);
4107
- if (simplify) fuseOp.SimplifyResult(true, true, 1e-3);
4207
+ if (simplify2) fuseOp.SimplifyResult(true, true, 1e-3);
4108
4208
  return castToShape3D(fuseOp.Shape(), "FUSE_NOT_3D", "Fuse did not produce a 3D shape");
4109
4209
  }
4110
- function cutShape(base, tool, { optimisation = "none", simplify = false } = {}) {
4210
+ function cutShape(base, tool, { optimisation = "none", simplify: simplify2 = false } = {}) {
4111
4211
  const oc = getKernel().oc;
4112
4212
  const r = gcWithScope();
4113
4213
  const progress = r(new oc.Message_ProgressRange_1());
4114
4214
  const cutOp = r(new oc.BRepAlgoAPI_Cut_3(base.wrapped, tool.wrapped, progress));
4115
4215
  applyGlue(cutOp, optimisation);
4116
4216
  cutOp.Build(progress);
4117
- if (simplify) cutOp.SimplifyResult(true, true, 1e-3);
4217
+ if (simplify2) cutOp.SimplifyResult(true, true, 1e-3);
4118
4218
  return castToShape3D(cutOp.Shape(), "CUT_NOT_3D", "Cut did not produce a 3D shape");
4119
4219
  }
4120
- function intersectShapes(a, b, { simplify = false } = {}) {
4220
+ function intersectShapes(a, b, { simplify: simplify2 = false } = {}) {
4121
4221
  const oc = getKernel().oc;
4122
4222
  const r = gcWithScope();
4123
4223
  const progress = r(new oc.Message_ProgressRange_1());
4124
4224
  const intOp = r(new oc.BRepAlgoAPI_Common_3(a.wrapped, b.wrapped, progress));
4125
4225
  intOp.Build(progress);
4126
- if (simplify) intOp.SimplifyResult(true, true, 1e-3);
4226
+ if (simplify2) intOp.SimplifyResult(true, true, 1e-3);
4127
4227
  return castToShape3D(intOp.Shape(), "INTERSECT_NOT_3D", "Intersect did not produce a 3D shape");
4128
4228
  }
4129
- function fuseAll$1(shapes, { optimisation = "none", simplify = false, strategy = "native" } = {}) {
4229
+ function fuseAll$1(shapes, { optimisation = "none", simplify: simplify2 = false, strategy = "native" } = {}) {
4130
4230
  if (shapes.length === 0)
4131
4231
  return err(validationError("FUSE_ALL_EMPTY", "fuseAll requires at least one shape"));
4132
4232
  if (shapes.length === 1) return ok(shapes[0]);
4133
4233
  if (strategy === "native") {
4134
4234
  const result = getKernel().fuseAll(
4135
4235
  shapes.map((s) => s.wrapped),
4136
- { optimisation, simplify, strategy }
4236
+ { optimisation, simplify: simplify2, strategy }
4137
4237
  );
4138
4238
  return castToShape3D(result, "FUSE_ALL_NOT_3D", "fuseAll did not produce a 3D shape");
4139
4239
  }
@@ -4142,9 +4242,9 @@ function fuseAll$1(shapes, { optimisation = "none", simplify = false, strategy =
4142
4242
  if (isErr(leftResult)) return leftResult;
4143
4243
  const rightResult = fuseAll$1(shapes.slice(mid), { optimisation, simplify: false, strategy });
4144
4244
  if (isErr(rightResult)) return rightResult;
4145
- return fuseShapes(leftResult.value, rightResult.value, { optimisation, simplify });
4245
+ return fuseShapes(leftResult.value, rightResult.value, { optimisation, simplify: simplify2 });
4146
4246
  }
4147
- function cutAll(base, tools, { optimisation = "none", simplify = false } = {}) {
4247
+ function cutAll(base, tools, { optimisation = "none", simplify: simplify2 = false } = {}) {
4148
4248
  if (tools.length === 0) return ok(base);
4149
4249
  const oc = getKernel().oc;
4150
4250
  const r = gcWithScope();
@@ -4153,7 +4253,7 @@ function cutAll(base, tools, { optimisation = "none", simplify = false } = {}) {
4153
4253
  const cutOp = r(new oc.BRepAlgoAPI_Cut_3(base.wrapped, toolCompound, progress));
4154
4254
  applyGlue(cutOp, optimisation);
4155
4255
  cutOp.Build(progress);
4156
- if (simplify) cutOp.SimplifyResult(true, true, 1e-3);
4256
+ if (simplify2) cutOp.SimplifyResult(true, true, 1e-3);
4157
4257
  return castToShape3D(cutOp.Shape(), "CUT_ALL_NOT_3D", "cutAll did not produce a 3D shape");
4158
4258
  }
4159
4259
  function buildCompound(shapes) {
@@ -4421,12 +4521,12 @@ function exportSTEP(shapes = [], { unit, modelUnit } = {}) {
4421
4521
  doc.delete();
4422
4522
  }
4423
4523
  }
4424
- function fuseAllShapes(shapes, { optimisation = "none", simplify = false, strategy = "native" } = {}) {
4524
+ function fuseAllShapes(shapes, { optimisation = "none", simplify: simplify2 = false, strategy = "native" } = {}) {
4425
4525
  if (shapes.length === 0)
4426
4526
  return err(validationError("FUSE_ALL_EMPTY", "fuseAll requires at least one shape"));
4427
4527
  if (shapes.length === 1) return ok(shapes[0]);
4428
4528
  if (strategy === "native") {
4429
- const result = getKernel().fuseAll(shapes, { optimisation, simplify, strategy });
4529
+ const result = getKernel().fuseAll(shapes, { optimisation, simplify: simplify2, strategy });
4430
4530
  return ok(result);
4431
4531
  }
4432
4532
  const oc = getKernel().oc;
@@ -4444,12 +4544,12 @@ function fuseAllShapes(shapes, { optimisation = "none", simplify = false, strate
4444
4544
  const fuseOp = r(new oc.BRepAlgoAPI_Fuse_3(leftResult.value, rightResult.value, progress));
4445
4545
  applyGlue$1(fuseOp, optimisation);
4446
4546
  fuseOp.Build(progress);
4447
- if (simplify) {
4547
+ if (simplify2) {
4448
4548
  fuseOp.SimplifyResult(true, true, 1e-3);
4449
4549
  }
4450
4550
  return ok(fuseOp.Shape());
4451
4551
  }
4452
- function cutAllShapes(base, tools, { optimisation = "none", simplify = false } = {}) {
4552
+ function cutAllShapes(base, tools, { optimisation = "none", simplify: simplify2 = false } = {}) {
4453
4553
  if (tools.length === 0) return ok(base);
4454
4554
  const oc = getKernel().oc;
4455
4555
  const r = gcWithScope();
@@ -4458,7 +4558,7 @@ function cutAllShapes(base, tools, { optimisation = "none", simplify = false } =
4458
4558
  const cutOp = r(new oc.BRepAlgoAPI_Cut_3(base, toolCompound, progress));
4459
4559
  applyGlue$1(cutOp, optimisation);
4460
4560
  cutOp.Build(progress);
4461
- if (simplify) {
4561
+ if (simplify2) {
4462
4562
  cutOp.SimplifyResult(true, true, 1e-3);
4463
4563
  }
4464
4564
  return ok(cutOp.Shape());
@@ -5822,19 +5922,19 @@ class Transformation2D extends WrappingObj {
5822
5922
  const stretchTransform2d = (ratio, direction, origin = [0, 0]) => {
5823
5923
  const oc = getKernel().oc;
5824
5924
  const ax = axis2d(origin, direction);
5825
- const transform = new oc.gp_GTrsf2d_1();
5826
- transform.SetAffinity(ax, ratio);
5925
+ const transform2 = new oc.gp_GTrsf2d_1();
5926
+ transform2.SetAffinity(ax, ratio);
5827
5927
  ax.delete();
5828
- return new Transformation2D(transform);
5928
+ return new Transformation2D(transform2);
5829
5929
  };
5830
5930
  const translationTransform2d = (translation) => {
5831
5931
  const oc = getKernel().oc;
5832
5932
  const [r, gc] = localGC();
5833
5933
  const rotation = new oc.gp_Trsf2d_1();
5834
5934
  rotation.SetTranslation_1(r(vec(translation)));
5835
- const transform = new oc.gp_GTrsf2d_2(rotation);
5935
+ const transform2 = new oc.gp_GTrsf2d_2(rotation);
5836
5936
  gc();
5837
- return new Transformation2D(transform);
5937
+ return new Transformation2D(transform2);
5838
5938
  };
5839
5939
  const mirrorTransform2d = (centerOrDirection, origin = [0, 0], mode = "center") => {
5840
5940
  const oc = getKernel().oc;
@@ -5845,27 +5945,27 @@ const mirrorTransform2d = (centerOrDirection, origin = [0, 0], mode = "center")
5845
5945
  } else {
5846
5946
  rotation.SetMirror_2(r(axis2d(origin, centerOrDirection)));
5847
5947
  }
5848
- const transform = new oc.gp_GTrsf2d_2(rotation);
5948
+ const transform2 = new oc.gp_GTrsf2d_2(rotation);
5849
5949
  gc();
5850
- return new Transformation2D(transform);
5950
+ return new Transformation2D(transform2);
5851
5951
  };
5852
5952
  const rotateTransform2d = (angle, center = [0, 0]) => {
5853
5953
  const oc = getKernel().oc;
5854
5954
  const [r, gc] = localGC();
5855
5955
  const rotation = new oc.gp_Trsf2d_1();
5856
5956
  rotation.SetRotation(r(pnt(center)), angle);
5857
- const transform = new oc.gp_GTrsf2d_2(rotation);
5957
+ const transform2 = new oc.gp_GTrsf2d_2(rotation);
5858
5958
  gc();
5859
- return new Transformation2D(transform);
5959
+ return new Transformation2D(transform2);
5860
5960
  };
5861
5961
  const scaleTransform2d = (scaleFactor, center = [0, 0]) => {
5862
5962
  const oc = getKernel().oc;
5863
5963
  const [r, gc] = localGC();
5864
5964
  const scaling = new oc.gp_Trsf2d_1();
5865
5965
  scaling.SetScale(r(pnt(center)), scaleFactor);
5866
- const transform = new oc.gp_GTrsf2d_2(scaling);
5966
+ const transform2 = new oc.gp_GTrsf2d_2(scaling);
5867
5967
  gc();
5868
- return new Transformation2D(transform);
5968
+ return new Transformation2D(transform2);
5869
5969
  };
5870
5970
  function curvesAsEdgesOnFace(curves, face, scale2 = "original") {
5871
5971
  const [r, gc] = localGC();
@@ -5934,8 +6034,8 @@ const viewbox = (bbox, margin = 1) => {
5934
6034
  const minY = -bbox.bounds[1][1] - margin;
5935
6035
  return `${minX} ${minY} ${bbox.width + 2 * margin} ${bbox.height + 2 * margin}`;
5936
6036
  };
5937
- const asSVG = (body, boundingBox, margin = 1) => {
5938
- const vbox = viewbox(boundingBox, margin);
6037
+ const asSVG = (body, boundingBox2, margin = 1) => {
6038
+ const vbox = viewbox(boundingBox2, margin);
5939
6039
  return `<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="${vbox}" fill="none" stroke="black" stroke-width="0.6%" vector-effect="non-scaling-stroke">
5940
6040
  ${body}
5941
6041
  </svg>`;
@@ -7484,7 +7584,7 @@ const rotateToStartAtSegment = (curves, segment) => {
7484
7584
  const end = curves.slice(startIndex);
7485
7585
  return end.concat(start);
7486
7586
  };
7487
- const hashPoint = (p) => `${p[0].toFixed(6)},${p[1].toFixed(6)}`;
7587
+ const hashPoint = (p) => `${p[0].toFixed(9)},${p[1].toFixed(9)}`;
7488
7588
  const hashSegment = (first, last) => {
7489
7589
  const h1 = hashPoint(first);
7490
7590
  const h2 = hashPoint(last);
@@ -8011,8 +8111,8 @@ function intersect2D(first, second) {
8011
8111
  return intersect2D(wrapper, second);
8012
8112
  }
8013
8113
  let result = intersect2D(wrapper, second);
8014
- for (const cut of cuts) {
8015
- result = cut2D(result, cut);
8114
+ for (const cut2 of cuts) {
8115
+ result = cut2D(result, cut2);
8016
8116
  }
8017
8117
  return result;
8018
8118
  }
@@ -8026,8 +8126,8 @@ function intersect2D(first, second) {
8026
8126
  return intersect2D(wrapper, first);
8027
8127
  }
8028
8128
  let result = intersect2D(wrapper, first);
8029
- for (const cut of cuts) {
8030
- result = cut2D(result, cut);
8129
+ for (const cut2 of cuts) {
8130
+ result = cut2D(result, cut2);
8031
8131
  }
8032
8132
  return result;
8033
8133
  }
@@ -8121,10 +8221,10 @@ class EdgeFinder extends Finder3d {
8121
8221
  *
8122
8222
  * @category Filter
8123
8223
  */
8124
- ofLength(length) {
8224
+ ofLength(length2) {
8125
8225
  const check = ({ element }) => {
8126
- if (typeof length === "number") return Math.abs(element.length - length) < 1e-9;
8127
- return length(element.length);
8226
+ if (typeof length2 === "number") return Math.abs(element.length - length2) < 1e-9;
8227
+ return length2(element.length);
8128
8228
  };
8129
8229
  this.filters.push(check);
8130
8230
  return this;
@@ -8835,8 +8935,8 @@ const solidFromShellGenerator = (sketches, shellGenerator) => {
8835
8935
  const startWires = [];
8836
8936
  const endWires = [];
8837
8937
  sketches.forEach((sketch) => {
8838
- const [shell, startWire, endWire] = unwrap(shellGenerator(sketch));
8839
- shells.push(shell);
8938
+ const [shell2, startWire, endWire] = unwrap(shellGenerator(sketch));
8939
+ shells.push(shell2);
8840
8940
  startWires.push(startWire);
8841
8941
  endWires.push(endWire);
8842
8942
  });
@@ -10378,7 +10478,7 @@ function createEdgeFinder(filters) {
10378
10478
  return Math.abs(ang - DEG2RAD * angle) < 1e-6;
10379
10479
  });
10380
10480
  },
10381
- ofLength: (length, tolerance = 1e-3) => withFilter((edge) => Math.abs(curveLength(edge) - length) < tolerance),
10481
+ ofLength: (length2, tolerance = 1e-3) => withFilter((edge) => Math.abs(curveLength(edge) - length2) < tolerance),
10382
10482
  ofCurveType: (curveType) => withFilter((edge) => getCurveType(edge) === curveType),
10383
10483
  parallelTo: (dir = "Z") => createEdgeFinder([...filters]).inDirection(dir, 0),
10384
10484
  atDistance: (distance, point = [0, 0, 0]) => withFilter((edge) => {