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