brepjs 18.35.2 → 18.35.4

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.
Files changed (88) hide show
  1. package/dist/2d.cjs +6 -6
  2. package/dist/2d.js +6 -6
  3. package/dist/{blueprint-BF0DcVwE.cjs → blueprint-C9feKfjM.cjs} +5 -5
  4. package/dist/{blueprint-KwH2JNPU.js → blueprint-PV2EbBko.js} +5 -5
  5. package/dist/{blueprintFns-X7jVGGUE.js → blueprintFns-CohoA3Ly.js} +2 -2
  6. package/dist/{blueprintFns-CbPsMijw.cjs → blueprintFns-Diu8oFPr.cjs} +2 -2
  7. package/dist/{blueprintSketcher-m18T1U1T.cjs → blueprintSketcher-B1TC4tuf.cjs} +3 -3
  8. package/dist/{blueprintSketcher-BwFpbp0B.js → blueprintSketcher-BC22SEkZ.js} +3 -3
  9. package/dist/{boolean2D-BzlbvCIH.cjs → boolean2D-CHza20uz.cjs} +4 -4
  10. package/dist/{boolean2D-DAq015PP.js → boolean2D-D42Z6h-L.js} +4 -4
  11. package/dist/{booleanFns-D19tR8Gn.cjs → booleanFns-CCJFmZf6.cjs} +4 -4
  12. package/dist/{booleanFns-nHsLqZ7Y.js → booleanFns-D7A-hqSP.js} +4 -4
  13. package/dist/brepjs.cjs +25 -25
  14. package/dist/brepjs.js +25 -25
  15. package/dist/{cameraFns-Bhjy2SuC.js → cameraFns-BvZw_Bje.js} +2 -2
  16. package/dist/{cameraFns-D_8-JO0p.cjs → cameraFns-D79etXJw.cjs} +2 -2
  17. package/dist/core.cjs +1 -1
  18. package/dist/core.js +1 -1
  19. package/dist/{cornerFinder-U6kzoCXY.js → cornerFinder-BPz7nFlt.js} +1 -1
  20. package/dist/{cornerFinder-Bmp3Vm5g.cjs → cornerFinder-D3m1OkXN.cjs} +1 -1
  21. package/dist/{curveFns-rUkX4tEm.js → curveFns-BJNwNm66.js} +1 -1
  22. package/dist/{curveFns-p1YEnmZu.cjs → curveFns-CiI0h04W.cjs} +1 -1
  23. package/dist/{drawFns-BGIQ1IeV.cjs → drawFns-Cx7RJEdL.cjs} +12 -12
  24. package/dist/{drawFns-ZhKR7xa0.js → drawFns-E68sfFlE.js} +12 -12
  25. package/dist/{extrudeFns-Cl_azGgy.js → extrudeFns-D49C5SBL.js} +1 -1
  26. package/dist/{extrudeFns-DpRGUaxD.cjs → extrudeFns-DympFQua.cjs} +1 -1
  27. package/dist/{faceFns-C6qUr_gw.cjs → faceFns-3HqgY1VN.cjs} +2 -2
  28. package/dist/{faceFns-eVWgSIzt.js → faceFns-DLjTsZIu.js} +2 -2
  29. package/dist/{helpers-DNVILwHA.cjs → helpers-BSU8Ilxm.cjs} +6 -6
  30. package/dist/{helpers-BhJOo535.js → helpers-DI2r-O_h.js} +6 -6
  31. package/dist/{historyFns-ByJG4mBP.js → historyFns-D89ZUO18.js} +4 -4
  32. package/dist/{historyFns-C2glA6vu.cjs → historyFns-DoMVl9Wf.cjs} +4 -4
  33. package/dist/{importFns-DuAmdf0Q.js → importFns-CpKXeRz6.js} +2 -2
  34. package/dist/{importFns-CJc5NYJp.cjs → importFns-SQNeOpGa.cjs} +2 -2
  35. package/dist/io.cjs +2 -2
  36. package/dist/io.js +2 -2
  37. package/dist/kernel/hullGeometry.d.ts +22 -0
  38. package/dist/kernel/occt/hullOps.d.ts +1 -6
  39. package/dist/kernel/occtWasm/constructionOps.d.ts +1 -0
  40. package/dist/kernel/occtWasm/hullOps.d.ts +1 -5
  41. package/dist/kernel/occtWasm/ioOps.d.ts +1 -1
  42. package/dist/kernel/occtWasm/kernel2dOps.d.ts +7 -1
  43. package/dist/kernel/occtWasm/occtWasmAdapter.cjs +1 -1
  44. package/dist/kernel/occtWasm/occtWasmAdapter.d.ts +1 -1
  45. package/dist/kernel/occtWasm/occtWasmAdapter.js +1 -1
  46. package/dist/kernel/occtWasm/occtWasmTypes.d.ts +7 -2
  47. package/dist/kernel/occtWasm/sweepOps.d.ts +1 -1
  48. package/dist/{measureFns-BiflqrZ_.js → measureFns-BMSt38re.js} +3 -3
  49. package/dist/{measureFns-D7lxkIjt.cjs → measureFns-CG36omJ5.cjs} +3 -3
  50. package/dist/measurement.cjs +1 -1
  51. package/dist/measurement.js +1 -1
  52. package/dist/{meshFns-DM2mLIlu.cjs → meshFns-B08Sq0xg.cjs} +10 -3
  53. package/dist/{meshFns-F9QLm-Bk.js → meshFns-B6dmwjJL.js} +10 -3
  54. package/dist/{occtWasmAdapter-COKB8ItA.js → occtWasmAdapter-DfdUU9UU.js} +395 -171
  55. package/dist/{occtWasmAdapter-CdyaMnBW.cjs → occtWasmAdapter-ZiJfgmS1.cjs} +400 -170
  56. package/dist/operations.cjs +2 -2
  57. package/dist/operations.js +2 -2
  58. package/dist/{primitiveFns-vQh7Lz7B.js → primitiveFns-BD6YZbCJ.js} +7 -7
  59. package/dist/{primitiveFns-CXn9Jl4q.cjs → primitiveFns-DFnQlGVV.cjs} +7 -7
  60. package/dist/projection.cjs +1 -1
  61. package/dist/projection.js +1 -1
  62. package/dist/query.cjs +2 -2
  63. package/dist/query.js +2 -2
  64. package/dist/{shapeFns-BbHQjI5-.js → shapeFns-C8pitNme.js} +2 -2
  65. package/dist/{shapeFns-B3v9_keQ.cjs → shapeFns-CnNKfmw8.cjs} +2 -2
  66. package/dist/shapeRef.cjs +1 -1
  67. package/dist/shapeRef.js +1 -1
  68. package/dist/{shapeRefFns-BOsX8Tim.js → shapeRefFns-BQlYDeCD.js} +4 -4
  69. package/dist/{shapeRefFns-CkafUjdM.cjs → shapeRefFns-DtCBv52A.cjs} +4 -4
  70. package/dist/{shapeTypes-C-MpR5-e.js → shapeTypes-BKeiP62J.js} +3 -241
  71. package/dist/{shapeTypes-Bbh2doYh.cjs → shapeTypes-D5Nua1z1.cjs} +5 -243
  72. package/dist/sketching.cjs +3 -3
  73. package/dist/sketching.js +3 -3
  74. package/dist/{solidBuilders-Ck6gpdQR.cjs → solidBuilders-0ZZGbPt3.cjs} +2 -2
  75. package/dist/{solidBuilders-C44fKbQQ.js → solidBuilders-DjPCyWCd.js} +2 -2
  76. package/dist/{surfaceBuilders-DsISMCwj.cjs → surfaceBuilders-6QimO9vi.cjs} +2 -2
  77. package/dist/{surfaceBuilders-D4p1YPCz.js → surfaceBuilders-d4o4OoWy.js} +2 -2
  78. package/dist/text.cjs +2 -2
  79. package/dist/text.js +2 -2
  80. package/dist/{textBlueprints-C93RophN.cjs → textBlueprints-BUkh-dID.cjs} +7 -7
  81. package/dist/{textBlueprints-BKdQqBn8.js → textBlueprints-DOPJs2t6.js} +7 -7
  82. package/dist/{textMetrics-2vq4PFfz.cjs → textMetrics-DNQplzf7.cjs} +1 -1
  83. package/dist/{textMetrics-DEmVsP5C.js → textMetrics-h6jI-oL_.js} +1 -1
  84. package/dist/topology.cjs +7 -7
  85. package/dist/topology.js +7 -7
  86. package/dist/{topologyQueryFns-C0kAqcn5.cjs → topologyQueryFns-BNv_2PHm.cjs} +1 -1
  87. package/dist/{topologyQueryFns-B81GSST_.js → topologyQueryFns-DhdAOL0M.js} +1 -1
  88. package/package.json +1 -1
@@ -1,4 +1,255 @@
1
1
  import { n as wasmIndex } from "./vec3-Dpha8d5k.js";
2
+ //#region src/kernel/hullGeometry.ts
3
+ function sub(a, b) {
4
+ return {
5
+ x: a.x - b.x,
6
+ y: a.y - b.y,
7
+ z: a.z - b.z
8
+ };
9
+ }
10
+ function cross(a, b) {
11
+ return {
12
+ x: a.y * b.z - a.z * b.y,
13
+ y: a.z * b.x - a.x * b.z,
14
+ z: a.x * b.y - a.y * b.x
15
+ };
16
+ }
17
+ function dot(a, b) {
18
+ return a.x * b.x + a.y * b.y + a.z * b.z;
19
+ }
20
+ function lengthVec(v) {
21
+ return Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
22
+ }
23
+ function distSq(a, b) {
24
+ const dx = a.x - b.x;
25
+ const dy = a.y - b.y;
26
+ const dz = a.z - b.z;
27
+ return dx * dx + dy * dy + dz * dz;
28
+ }
29
+ /** Safe array access — throws on out-of-bounds instead of returning undefined. */
30
+ function at(arr, i) {
31
+ const v = arr[i];
32
+ if (v === void 0) throw new Error(`Index ${i} out of bounds`);
33
+ return v;
34
+ }
35
+ /** Safe number array access. */
36
+ function atN(arr, i) {
37
+ const v = arr[i];
38
+ if (v === void 0) throw new Error(`Index ${i} out of bounds`);
39
+ return v;
40
+ }
41
+ function makeFace$1(points, a, b, c) {
42
+ const normal = cross(sub(at(points, b), at(points, a)), sub(at(points, c), at(points, a)));
43
+ const len = lengthVec(normal);
44
+ const n = len > 1e-14 ? {
45
+ x: normal.x / len,
46
+ y: normal.y / len,
47
+ z: normal.z / len
48
+ } : normal;
49
+ return {
50
+ a,
51
+ b,
52
+ c,
53
+ normal: n,
54
+ offset: dot(n, at(points, a)),
55
+ alive: true,
56
+ outsidePoints: []
57
+ };
58
+ }
59
+ function signedDist(face, point) {
60
+ return dot(face.normal, point) - face.offset;
61
+ }
62
+ function deduplicatePoints(points, tolerance) {
63
+ const tolSq = tolerance * tolerance;
64
+ const result = [];
65
+ for (const p of points) {
66
+ let isDuplicate = false;
67
+ for (const q of result) if (distSq(p, q) < tolSq) {
68
+ isDuplicate = true;
69
+ break;
70
+ }
71
+ if (!isDuplicate) result.push(p);
72
+ }
73
+ return result;
74
+ }
75
+ function findInitialTetrahedron(points) {
76
+ const n = points.length;
77
+ if (n < 4) return null;
78
+ let i0 = 0;
79
+ let i1 = 1;
80
+ let maxDist = distSq(at(points, 0), at(points, 1));
81
+ for (let i = 0; i < n; i++) for (let j = i + 1; j < n; j++) {
82
+ const d = distSq(at(points, i), at(points, j));
83
+ if (d > maxDist) {
84
+ maxDist = d;
85
+ i0 = i;
86
+ i1 = j;
87
+ }
88
+ }
89
+ if (maxDist < 1e-20) return null;
90
+ const lineDir = sub(at(points, i1), at(points, i0));
91
+ let i2 = -1;
92
+ let maxLineDist = -1;
93
+ for (let i = 0; i < n; i++) {
94
+ if (i === i0 || i === i1) continue;
95
+ const c = cross(lineDir, sub(at(points, i), at(points, i0)));
96
+ const d = dot(c, c);
97
+ if (d > maxLineDist) {
98
+ maxLineDist = d;
99
+ i2 = i;
100
+ }
101
+ }
102
+ if (i2 === -1 || maxLineDist < 1e-20) return null;
103
+ const planeNormal = cross(sub(at(points, i1), at(points, i0)), sub(at(points, i2), at(points, i0)));
104
+ const planeLen = lengthVec(planeNormal);
105
+ if (planeLen < 1e-14) return null;
106
+ const pn = {
107
+ x: planeNormal.x / planeLen,
108
+ y: planeNormal.y / planeLen,
109
+ z: planeNormal.z / planeLen
110
+ };
111
+ const planeOffset = dot(pn, at(points, i0));
112
+ let i3 = -1;
113
+ let maxPlaneDist = -1;
114
+ for (let i = 0; i < n; i++) {
115
+ if (i === i0 || i === i1 || i === i2) continue;
116
+ const d = Math.abs(dot(pn, at(points, i)) - planeOffset);
117
+ if (d > maxPlaneDist) {
118
+ maxPlaneDist = d;
119
+ i3 = i;
120
+ }
121
+ }
122
+ if (i3 === -1 || maxPlaneDist < 1e-14) return null;
123
+ if (dot(pn, at(points, i3)) - planeOffset > 0) return [
124
+ i0,
125
+ i2,
126
+ i1,
127
+ i3
128
+ ];
129
+ return [
130
+ i0,
131
+ i1,
132
+ i2,
133
+ i3
134
+ ];
135
+ }
136
+ /**
137
+ * Compute the 3D convex hull of a point set.
138
+ *
139
+ * @throws if fewer than 4 non-coincident, non-coplanar points are supplied.
140
+ */
141
+ function quickHull(inputPoints, tolerance) {
142
+ const points = deduplicatePoints(inputPoints, tolerance);
143
+ if (points.length < 4) throw new Error(points.length === 0 ? "No points provided for convex hull" : "Fewer than 4 non-coincident points; cannot form a 3D convex hull");
144
+ const tet = findInitialTetrahedron(points);
145
+ if (tet === null) throw new Error("All points are coplanar; cannot form a 3D convex hull");
146
+ const [t0, t1, t2, t3] = tet;
147
+ const centroid = {
148
+ x: (at(points, t0).x + at(points, t1).x + at(points, t2).x + at(points, t3).x) / 4,
149
+ y: (at(points, t0).y + at(points, t1).y + at(points, t2).y + at(points, t3).y) / 4,
150
+ z: (at(points, t0).z + at(points, t1).z + at(points, t2).z + at(points, t3).z) / 4
151
+ };
152
+ function makeOutwardFace(a, b, c) {
153
+ const face = makeFace$1(points, a, b, c);
154
+ const toCentroid = sub(centroid, {
155
+ x: (at(points, a).x + at(points, b).x + at(points, c).x) / 3,
156
+ y: (at(points, a).y + at(points, b).y + at(points, c).y) / 3,
157
+ z: (at(points, a).z + at(points, b).z + at(points, c).z) / 3
158
+ });
159
+ if (dot(face.normal, toCentroid) > 0) return makeFace$1(points, a, c, b);
160
+ return face;
161
+ }
162
+ const faces = [
163
+ makeOutwardFace(t0, t1, t2),
164
+ makeOutwardFace(t0, t2, t3),
165
+ makeOutwardFace(t0, t3, t1),
166
+ makeOutwardFace(t1, t3, t2)
167
+ ];
168
+ const tetSet = new Set([
169
+ t0,
170
+ t1,
171
+ t2,
172
+ t3
173
+ ]);
174
+ const epsilon = 1e-10;
175
+ for (let i = 0; i < points.length; i++) {
176
+ if (tetSet.has(i)) continue;
177
+ for (const face of faces) if (signedDist(face, at(points, i)) > epsilon) {
178
+ face.outsidePoints.push(i);
179
+ break;
180
+ }
181
+ }
182
+ for (let iteration = 0; iteration < points.length * 4; iteration++) {
183
+ let currentFace = null;
184
+ for (const face of faces) if (face.alive && face.outsidePoints.length > 0) {
185
+ currentFace = face;
186
+ break;
187
+ }
188
+ if (currentFace === null) break;
189
+ let furthestIdx = atN(currentFace.outsidePoints, 0);
190
+ let furthestDist = signedDist(currentFace, at(points, furthestIdx));
191
+ for (let i = 1; i < currentFace.outsidePoints.length; i++) {
192
+ const idx = atN(currentFace.outsidePoints, i);
193
+ const d = signedDist(currentFace, at(points, idx));
194
+ if (d > furthestDist) {
195
+ furthestDist = d;
196
+ furthestIdx = idx;
197
+ }
198
+ }
199
+ const visibleFaces = [];
200
+ for (const face of faces) if (face.alive && signedDist(face, at(points, furthestIdx)) > epsilon) visibleFaces.push(face);
201
+ const edgeCount = /* @__PURE__ */ new Map();
202
+ for (const face of visibleFaces) {
203
+ const edges = [
204
+ [face.a, face.b],
205
+ [face.b, face.c],
206
+ [face.c, face.a]
207
+ ];
208
+ for (const [ea, eb] of edges) {
209
+ const key = ea < eb ? `${ea}-${eb}` : `${eb}-${ea}`;
210
+ const entry = edgeCount.get(key);
211
+ if (entry) entry.count++;
212
+ else edgeCount.set(key, {
213
+ a: ea,
214
+ b: eb,
215
+ count: 1
216
+ });
217
+ }
218
+ }
219
+ const horizonEdges = [];
220
+ for (const entry of edgeCount.values()) if (entry.count === 1) horizonEdges.push({
221
+ a: entry.a,
222
+ b: entry.b
223
+ });
224
+ const orphanedPoints = [];
225
+ for (const face of visibleFaces) {
226
+ for (const idx of face.outsidePoints) if (idx !== furthestIdx) orphanedPoints.push(idx);
227
+ face.alive = false;
228
+ face.outsidePoints = [];
229
+ }
230
+ const newFaces = [];
231
+ for (const edge of horizonEdges) {
232
+ const newFaceObj = makeFace$1(points, edge.a, edge.b, furthestIdx);
233
+ newFaces.push(newFaceObj);
234
+ faces.push(newFaceObj);
235
+ }
236
+ for (const idx of orphanedPoints) for (const face of newFaces) if (signedDist(face, at(points, idx)) > epsilon) {
237
+ face.outsidePoints.push(idx);
238
+ break;
239
+ }
240
+ }
241
+ const resultFaces = [];
242
+ for (const face of faces) if (face.alive) resultFaces.push([
243
+ face.a,
244
+ face.b,
245
+ face.c
246
+ ]);
247
+ return {
248
+ faces: resultFaces,
249
+ points
250
+ };
251
+ }
252
+ //#endregion
2
253
  //#region src/kernel/geometry2d.ts
3
254
  function evaluateCurve2d$1(c, t) {
4
255
  switch (c.__bk2d) {
@@ -1894,9 +2145,12 @@ function revolve(k, shape, axis, angle) {
1894
2145
  const d = axis.direction;
1895
2146
  return wrapResult(k, k.revolve(unwrap(shape), o.x, o.y, o.z, d.x, d.y, d.z, angle));
1896
2147
  }
1897
- function loft(k, Module, wires, ruled, _startShape, _endShape) {
2148
+ function loft(k, Module, wires, ruled, startShape, endShape) {
2149
+ const startV = startShape ? unwrap(startShape) : 0;
2150
+ const endV = endShape ? unwrap(endShape) : 0;
1898
2151
  const vec = makeVecU32(Module, wires.map(unwrap));
1899
2152
  try {
2153
+ if (startV || endV) return wrapResult(k, k.loftWithVertices(vec, true, ruled ?? false, startV, endV));
1900
2154
  return wrapResult(k, k.loft(vec, true, ruled ?? false));
1901
2155
  } finally {
1902
2156
  vec.delete();
@@ -2520,52 +2774,33 @@ function toBREP(k, shape) {
2520
2774
  function fromBREP(k, data) {
2521
2775
  return wrapResult(k, k.fromBREP(data));
2522
2776
  }
2523
- function createXCAFDocument(k, Module, shapes) {
2524
- const ids = new Module.VectorUint32();
2525
- const colors = new Module.VectorDouble();
2526
- const nameParts = [];
2777
+ function createXCAFDocument(k, _Module, shapes) {
2778
+ const docId = k.xcafNewDocument();
2527
2779
  for (const entry of shapes) {
2528
- ids.push_back(unwrap(entry.shape));
2529
- nameParts.push(entry.name);
2530
- const [r, g, b, a] = entry.color ?? [
2531
- .5,
2532
- .5,
2533
- .5,
2534
- 1
2535
- ];
2536
- colors.push_back(r);
2537
- colors.push_back(g);
2538
- colors.push_back(b);
2539
- colors.push_back(a);
2540
- }
2541
- try {
2542
- const joinedNames = nameParts.join("\0");
2543
- return handle("compound", k.createXCAFDocument(ids, joinedNames, colors));
2544
- } finally {
2545
- ids.delete();
2546
- colors.delete();
2780
+ const labelId = k.xcafAddShape(docId, unwrap(entry.shape));
2781
+ if (entry.name) k.xcafSetName(docId, labelId, entry.name);
2782
+ if (entry.color) {
2783
+ const [r, g, b] = entry.color;
2784
+ k.xcafSetColor(docId, labelId, r / 255, g / 255, b / 255);
2785
+ }
2547
2786
  }
2787
+ return handle("compound", docId);
2548
2788
  }
2549
2789
  function writeXCAFToSTEP(k, doc, _options) {
2550
- const id = unwrap(doc);
2551
- const subs = k.getSubShapes(id, "solid");
2552
- if (!(() => {
2790
+ const docId = unwrap(doc);
2791
+ const roots = k.xcafGetRootLabels(docId);
2792
+ const hasShapes = (() => {
2553
2793
  try {
2554
- return subs.size() > 0;
2794
+ return roots.size() > 0;
2555
2795
  } finally {
2556
- subs.delete();
2796
+ roots.delete();
2557
2797
  }
2558
- })()) {
2559
- const faces = k.getSubShapes(id, "face");
2560
- if (!(() => {
2561
- try {
2562
- return faces.size() > 0;
2563
- } finally {
2564
- faces.delete();
2565
- }
2566
- })()) return "";
2798
+ })();
2799
+ try {
2800
+ return hasShapes ? k.xcafExportSTEP(docId) : "";
2801
+ } finally {
2802
+ k.xcafClose(docId);
2567
2803
  }
2568
- return k.writeXCAFToSTEP(id);
2569
2804
  }
2570
2805
  function exportSTEPConfigured(k, Module, shapes, _options) {
2571
2806
  if (shapes.length === 0) return "";
@@ -2597,6 +2832,24 @@ function makeWire(k, Module, edges) {
2597
2832
  vec.delete();
2598
2833
  }
2599
2834
  }
2835
+ function makeWireFromMixed(k, Module, items) {
2836
+ const edgeIds = [];
2837
+ for (const item of items) {
2838
+ const sub = k.getSubShapes(unwrap(item), "edge");
2839
+ try {
2840
+ const n = sub.size();
2841
+ for (let i = 0; i < n; i++) edgeIds.push(sub.get(i));
2842
+ } finally {
2843
+ sub.delete();
2844
+ }
2845
+ }
2846
+ const vec = makeVecU32(Module, edgeIds);
2847
+ try {
2848
+ return handle("wire", k.makeWire(vec));
2849
+ } finally {
2850
+ vec.delete();
2851
+ }
2852
+ }
2600
2853
  function makeFace(k, wire, _planar) {
2601
2854
  return handle("face", k.makeFace(unwrap(wire)));
2602
2855
  }
@@ -2972,10 +3225,27 @@ function makeEllipseArc2d(cx, cy, majorRadius, minorRadius, startAngle, endAngle
2972
3225
  function makeBezier2d(points) {
2973
3226
  return c2dWrap(makeBezier2d$1(points));
2974
3227
  }
2975
- function makeBSpline2d(points) {
2976
- if (points.length <= 25) return c2dWrap(makeBezier2d$1(points));
2977
- const step = Math.max(1, Math.floor(points.length / 24));
2978
- return c2dWrap(makeBezier2d$1(points.filter((_, i) => i % step === 0 || i === points.length - 1)));
3228
+ function makeBSpline2d(points, options) {
3229
+ const poles = points;
3230
+ const n = poles.length;
3231
+ const degree = Math.max(1, Math.min(options?.degMax ?? 3, n - 1));
3232
+ const knots = [0];
3233
+ const mults = [degree + 1];
3234
+ const nInternalKnots = n - degree - 1;
3235
+ for (let i = 1; i <= nInternalKnots; i++) {
3236
+ knots.push(i / (nInternalKnots + 1));
3237
+ mults.push(1);
3238
+ }
3239
+ knots.push(1);
3240
+ mults.push(degree + 1);
3241
+ return c2dWrap({
3242
+ __bk2d: "bspline",
3243
+ poles,
3244
+ knots,
3245
+ multiplicities: mults,
3246
+ degree,
3247
+ isPeriodic: false
3248
+ });
2979
3249
  }
2980
3250
  function evaluateCurve2d(curve, param) {
2981
3251
  return evaluateCurve2d$1(c2d(curve), param);
@@ -3220,16 +3490,53 @@ function approximateCurve2dAsBSpline(curve, maxSegments) {
3220
3490
  });
3221
3491
  }
3222
3492
  function decomposeBSpline2dToBeziers(curve) {
3223
- const knots = c2d(curve).knots ?? [];
3224
- if (knots.length < 2) return [curve];
3225
- const result = [];
3226
- for (let i = 0; i < knots.length - 1; i++) {
3227
- const k0 = knots[i];
3228
- const k1 = knots[i + 1];
3229
- if (Math.abs(k1 - k0) < 1e-15) continue;
3230
- result.push(trimCurve2d(curve, k0, k1));
3493
+ let cu = c2d(curve);
3494
+ while (cu.__bk2d === "trimmed" && cu.basis) cu = cu.basis;
3495
+ if (cu.__bk2d !== "bspline") return [curve];
3496
+ const poles = cu.poles;
3497
+ const p = cu.degree;
3498
+ const U = [];
3499
+ for (let i = 0; i < cu.knots.length; i++) for (let j = 0; j < cu.multiplicities[i]; j++) U.push(cu.knots[i]);
3500
+ const m = poles.length - 1 + p + 1;
3501
+ if (p < 1 || U.length !== m + 1) return [c2dWrap(makeBezier2d$1(poles))];
3502
+ const clone = (pt) => [pt[0], pt[1]];
3503
+ const segments = [];
3504
+ let a = p;
3505
+ let b = p + 1;
3506
+ let segPoles = [];
3507
+ for (let i = 0; i <= p; i++) segPoles[i] = clone(poles[i]);
3508
+ let nextPoles = [];
3509
+ while (b < m) {
3510
+ const i0 = b;
3511
+ while (b < m && U[b + 1] === U[b]) b++;
3512
+ const mult = b - i0 + 1;
3513
+ if (mult < p) {
3514
+ const numer = U[b] - U[a];
3515
+ const alphas = [];
3516
+ for (let j = p; j > mult; j--) alphas[j - mult - 1] = numer / (U[a + j] - U[a]);
3517
+ const r = p - mult;
3518
+ for (let j = 1; j <= r; j++) {
3519
+ const save = r - j;
3520
+ const s = mult + j;
3521
+ for (let k = p; k >= s; k--) {
3522
+ const alpha = alphas[k - s];
3523
+ const cur = segPoles[k];
3524
+ const prev = segPoles[k - 1];
3525
+ segPoles[k] = [alpha * cur[0] + (1 - alpha) * prev[0], alpha * cur[1] + (1 - alpha) * prev[1]];
3526
+ }
3527
+ if (b < m) nextPoles[save] = clone(segPoles[p]);
3528
+ }
3529
+ }
3530
+ segments.push(segPoles);
3531
+ if (b < m) {
3532
+ for (let i = p - mult; i <= p; i++) nextPoles[i] = clone(poles[b - p + i]);
3533
+ segPoles = nextPoles;
3534
+ nextPoles = [];
3535
+ a = b;
3536
+ b++;
3537
+ }
3231
3538
  }
3232
- return result.length > 0 ? result : [curve];
3539
+ return segments.map((sp) => c2dWrap(makeBezier2d$1(sp)));
3233
3540
  }
3234
3541
  function createBoundingBox2d() {
3235
3542
  return createBBox2d();
@@ -3682,124 +3989,41 @@ function applyComposedTransformWithHistory(transformFn, iterShapesFn, hashCodeFn
3682
3989
  }
3683
3990
  //#endregion
3684
3991
  //#region src/kernel/occtWasm/hullOps.ts
3685
- function findHorizonEdges(faces, visible) {
3686
- const visSet = new Set(visible);
3687
- const horizon = [];
3688
- for (const fi of visible) {
3689
- const f = faces[fi];
3690
- for (let ei = 0; ei < 3; ei++) {
3691
- const a = f[ei], b = f[(ei + 1) % 3];
3692
- if (faces.some((g, fj) => fj !== fi && !visSet.has(fj) && [
3693
- 0,
3694
- 1,
3695
- 2
3696
- ].some((ej) => g[ej] === b && g[(ej + 1) % 3] === a))) horizon.push([a, b]);
3697
- }
3698
- }
3699
- return horizon;
3992
+ function hullFromPoints(k, Module, points, tolerance) {
3993
+ if (points.length < 4) throw new Error("hullFromPoints: need at least 4 points");
3994
+ const { points: hullPoints, faces } = quickHull(points, tolerance);
3995
+ if (faces.length < 4) throw new Error("hullFromPoints: degenerate hull (fewer than 4 faces)");
3996
+ return buildSolidFromFaces(k, Module, [...hullPoints], [...faces], tolerance);
3700
3997
  }
3701
- function computeConvexHullFaces(pts) {
3702
- const cross = (a, b) => ({
3703
- x: a.y * b.z - a.z * b.y,
3704
- y: a.z * b.x - a.x * b.z,
3705
- z: a.x * b.y - a.y * b.x
3706
- });
3707
- const sub = (a, b) => ({
3708
- x: a.x - b.x,
3709
- y: a.y - b.y,
3710
- z: a.z - b.z
3711
- });
3712
- const dot = (a, b) => a.x * b.x + a.y * b.y + a.z * b.z;
3713
- const n = pts.length;
3714
- const faces = [];
3715
- const p0 = pts[0];
3716
- let i1 = 1;
3717
- while (i1 < n) {
3718
- const p = wasmIndex(pts, i1);
3719
- if (Math.hypot(p.x - p0.x, p.y - p0.y, p.z - p0.z) >= 1e-10) break;
3720
- i1++;
3721
- }
3722
- let i2 = i1 + 1;
3723
- const e01 = sub(pts[i1], p0);
3724
- while (i2 < n) {
3725
- const c = cross(e01, sub(pts[i2], p0));
3726
- if (Math.hypot(c.x, c.y, c.z) > 1e-10) break;
3727
- i2++;
3728
- }
3729
- let i3 = i2 + 1;
3730
- const norm = cross(e01, sub(pts[i2], p0));
3731
- while (i3 < n) {
3732
- if (Math.abs(dot(norm, sub(pts[i3], p0))) > 1e-10) break;
3733
- i3++;
3734
- }
3735
- if (i3 >= n) return [[
3736
- 0,
3737
- 1,
3738
- 2
3739
- ]];
3740
- if (dot(cross(sub(pts[i1], p0), sub(pts[i2], p0)), sub(pts[i3], p0)) > 0) faces.push([
3741
- 0,
3742
- i1,
3743
- i2
3744
- ], [
3745
- 0,
3746
- i2,
3747
- i3
3748
- ], [
3749
- 0,
3750
- i3,
3751
- i1
3752
- ], [
3753
- i1,
3754
- i3,
3755
- i2
3756
- ]);
3757
- else faces.push([
3758
- 0,
3759
- i2,
3760
- i1
3761
- ], [
3762
- 0,
3763
- i3,
3764
- i2
3765
- ], [
3766
- 0,
3767
- i1,
3768
- i3
3769
- ], [
3770
- i2,
3771
- i3,
3772
- i1
3773
- ]);
3774
- const used = new Set([
3775
- 0,
3776
- i1,
3777
- i2,
3778
- i3
3779
- ]);
3780
- for (let pi = 0; pi < n; pi++) {
3781
- if (used.has(pi)) continue;
3782
- const p = pts[pi];
3783
- const visible = [];
3784
- for (let fi = 0; fi < faces.length; fi++) {
3785
- const f = faces[fi];
3786
- if (dot(cross(sub(pts[f[1]], pts[f[0]]), sub(pts[f[2]], pts[f[0]])), sub(p, pts[f[0]])) > 1e-10) visible.push(fi);
3998
+ /**
3999
+ * Sample surface vertices of each shape via tessellation. A coarse deflection
4000
+ * keeps the point count low the convex hull only needs extreme points, and
4001
+ * fine meshes on curved surfaces explode the hull cost.
4002
+ */
4003
+ function extractVertices(k, Module, shapes, tolerance) {
4004
+ const deflection = Math.max(tolerance, 1);
4005
+ const points = [];
4006
+ for (const shape of shapes) {
4007
+ const meshData = k.tessellate(unwrap(shape), deflection, deflection * .5);
4008
+ try {
4009
+ const posCount = meshData.positionCount;
4010
+ const posPtr = meshData.getPositionsPtr() >> 2;
4011
+ for (let i = 0; i < posCount; i += 3) points.push({
4012
+ x: Module.HEAPF32[posPtr + i] ?? 0,
4013
+ y: Module.HEAPF32[posPtr + i + 1] ?? 0,
4014
+ z: Module.HEAPF32[posPtr + i + 2] ?? 0
4015
+ });
4016
+ } finally {
4017
+ meshData.delete();
3787
4018
  }
3788
- if (visible.length === 0) continue;
3789
- const horizon = findHorizonEdges(faces, visible);
3790
- visible.sort((a2, b2) => b2 - a2);
3791
- for (const fi of visible) faces.splice(fi, 1);
3792
- for (const [a, b] of horizon) faces.push([
3793
- a,
3794
- b,
3795
- pi
3796
- ]);
3797
- }
3798
- return faces;
4019
+ }
4020
+ return points;
3799
4021
  }
3800
- function hullFromPoints(k, Module, points, tolerance) {
3801
- if (points.length < 4) throw new Error("hullFromPoints: need at least 4 points");
3802
- return buildSolidFromFaces(k, Module, points, computeConvexHullFaces(points), tolerance);
4022
+ function hull(k, Module, shapes, tolerance) {
4023
+ if (shapes.length === 0) throw new Error("hull: no shapes provided");
4024
+ const points = extractVertices(k, Module, shapes, tolerance);
4025
+ if (points.length < 4) throw new Error("hull: fewer than 4 vertices extracted from input shapes");
4026
+ return hullFromPoints(k, Module, points, tolerance);
3803
4027
  }
3804
4028
  //#endregion
3805
4029
  //#region src/kernel/occtWasm/occtWasmAdapter.ts
@@ -3947,7 +4171,7 @@ var OcctWasmAdapter = class OcctWasmAdapter {
3947
4171
  return makeHelixWire(this.k, pitch, height, radius, center, direction);
3948
4172
  }
3949
4173
  makeWireFromMixed(items) {
3950
- return this.makeWire(items);
4174
+ return makeWireFromMixed(this.k, this.Module, items);
3951
4175
  }
3952
4176
  makeCompound(shapes) {
3953
4177
  return makeCompound(this.k, this.Module, shapes);
@@ -3955,8 +4179,8 @@ var OcctWasmAdapter = class OcctWasmAdapter {
3955
4179
  solidFromShell(shell) {
3956
4180
  return solidFromShell(this.k, shell);
3957
4181
  }
3958
- hull(_shapes, _tolerance) {
3959
- notImplemented("hull");
4182
+ hull(shapes, tolerance) {
4183
+ return hull(this.k, this.Module, shapes, tolerance);
3960
4184
  }
3961
4185
  hullFromPoints(points, tolerance) {
3962
4186
  return hullFromPoints(this.k, this.Module, points, tolerance);
@@ -4618,4 +4842,4 @@ var OcctWasmAdapter = class OcctWasmAdapter {
4618
4842
  }
4619
4843
  };
4620
4844
  //#endregion
4621
- export { serializeCurve2d$1 as _, curveTypeName as a, intersectCurves2dFn as c, makeEllipse2d$1 as d, makeLine2d$1 as f, scaleCurve2d$1 as g, rotateCurve2d$1 as h, curveBounds as i, makeBezier2d$1 as l, mirrorAtPoint as m, addCurveToBBox as n, deserializeCurve2d$1 as o, mirrorAcrossAxis as p, createBBox2d as r, evaluateCurve2d$1 as s, OcctWasmAdapter as t, makeCircle2d$1 as u, tangentCurve2d as v, translateCurve2d$1 as y };
4845
+ export { serializeCurve2d$1 as _, curveTypeName as a, quickHull as b, intersectCurves2dFn as c, makeEllipse2d$1 as d, makeLine2d$1 as f, scaleCurve2d$1 as g, rotateCurve2d$1 as h, curveBounds as i, makeBezier2d$1 as l, mirrorAtPoint as m, addCurveToBBox as n, deserializeCurve2d$1 as o, mirrorAcrossAxis as p, createBBox2d as r, evaluateCurve2d$1 as s, OcctWasmAdapter as t, makeCircle2d$1 as u, tangentCurve2d as v, translateCurve2d$1 as y };