brepjs 18.35.3 → 18.35.5

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 (85) hide show
  1. package/dist/2d.cjs +6 -6
  2. package/dist/2d.js +6 -6
  3. package/dist/{blueprint-BugZrlJZ.js → blueprint-DFX9Mice.js} +5 -5
  4. package/dist/{blueprint-BZtQ37hZ.cjs → blueprint-Dt8UBapg.cjs} +5 -5
  5. package/dist/{blueprintFns-DZreBQDw.js → blueprintFns-DKm_TMpq.js} +2 -2
  6. package/dist/{blueprintFns-Cd6RX-3U.cjs → blueprintFns-DUrh_Vuo.cjs} +2 -2
  7. package/dist/{blueprintSketcher-CeUtlreY.cjs → blueprintSketcher-CSWQy4s0.cjs} +3 -3
  8. package/dist/{blueprintSketcher-Br9S5j8n.js → blueprintSketcher-CqdAW9fb.js} +3 -3
  9. package/dist/{boolean2D-jMwDLuLK.js → boolean2D-CAMPcmle.js} +4 -4
  10. package/dist/{boolean2D-B30MyM5A.cjs → boolean2D-LKA2WvT1.cjs} +4 -4
  11. package/dist/{booleanFns-NkgP7bZA.cjs → booleanFns-BherB6vd.cjs} +4 -4
  12. package/dist/{booleanFns-BPWMgD1t.js → booleanFns-ky-zHUHR.js} +4 -4
  13. package/dist/brepjs.cjs +25 -25
  14. package/dist/brepjs.js +25 -25
  15. package/dist/{cameraFns-B5FrSRRP.js → cameraFns-AIlIbZXo.js} +2 -2
  16. package/dist/{cameraFns-Bb5fmsNi.cjs → cameraFns-D_6uvLNa.cjs} +2 -2
  17. package/dist/core.cjs +1 -1
  18. package/dist/core.js +1 -1
  19. package/dist/{cornerFinder-NT0nEY2D.js → cornerFinder-CHrWbA9J.js} +1 -1
  20. package/dist/{cornerFinder-Nd00yMHA.cjs → cornerFinder-D0D01Iv4.cjs} +1 -1
  21. package/dist/{curveFns-D1IaRpWu.js → curveFns-DC4gwhim.js} +1 -1
  22. package/dist/{curveFns-tBJhB6jA.cjs → curveFns-DplagD2s.cjs} +1 -1
  23. package/dist/{drawFns-BetA5msk.js → drawFns-2FS4bc0v.js} +12 -12
  24. package/dist/{drawFns-C9WFdiAW.cjs → drawFns-shtE96tg.cjs} +12 -12
  25. package/dist/{extrudeFns-DWeYb6cu.js → extrudeFns-B2koxf8d.js} +1 -1
  26. package/dist/{extrudeFns-Bg-IXT_O.cjs → extrudeFns-CGXjoiA3.cjs} +1 -1
  27. package/dist/{faceFns-ThsHosgU.cjs → faceFns-D-i7rp7Y.cjs} +2 -2
  28. package/dist/{faceFns-DBEEcVC-.js → faceFns-D9IXo1EY.js} +2 -2
  29. package/dist/{helpers-D2RrISk0.js → helpers-6tUnAb2m.js} +6 -6
  30. package/dist/{helpers-D6XMORWy.cjs → helpers-DoflJrR5.cjs} +6 -6
  31. package/dist/{historyFns-DrjICLPB.cjs → historyFns-1a841VzH.cjs} +4 -4
  32. package/dist/{historyFns-BSSA9qoA.js → historyFns-Y0v0weT9.js} +4 -4
  33. package/dist/{importFns-Cq-bKeDn.js → importFns-BsE_nugZ.js} +2 -2
  34. package/dist/{importFns-B7nffQNd.cjs → importFns-CzArHdFY.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/hullOps.d.ts +1 -5
  40. package/dist/kernel/occtWasm/kernel2dOps.d.ts +7 -1
  41. package/dist/kernel/occtWasm/occtWasmAdapter.cjs +1 -1
  42. package/dist/kernel/occtWasm/occtWasmAdapter.d.ts +1 -1
  43. package/dist/kernel/occtWasm/occtWasmAdapter.js +1 -1
  44. package/dist/kernel/occtWasm/occtWasmTypes.d.ts +2 -0
  45. package/dist/{measureFns-BT_G8lXZ.cjs → measureFns-gkq2sYtY.cjs} +3 -3
  46. package/dist/{measureFns-BTn_t0LK.js → measureFns-ry6_O167.js} +3 -3
  47. package/dist/measurement.cjs +1 -1
  48. package/dist/measurement.js +1 -1
  49. package/dist/{meshFns-CR68GwS8.js → meshFns-CEECiqKQ.js} +3 -3
  50. package/dist/{meshFns-BcYvu4zj.cjs → meshFns-D-4VAld_.cjs} +3 -3
  51. package/dist/{occtWasmAdapter-DUruQhFF.js → occtWasmAdapter-DNXBos24.js} +360 -132
  52. package/dist/{occtWasmAdapter-R8zCS1h7.cjs → occtWasmAdapter-sH6wg1Z6.cjs} +365 -131
  53. package/dist/operations.cjs +2 -2
  54. package/dist/operations.js +2 -2
  55. package/dist/{primitiveFns-BjeLfI12.js → primitiveFns-BiEXbXUy.js} +7 -7
  56. package/dist/{primitiveFns-DtY84t7q.cjs → primitiveFns-IFpwC8fs.cjs} +7 -7
  57. package/dist/projection.cjs +1 -1
  58. package/dist/projection.js +1 -1
  59. package/dist/query.cjs +2 -2
  60. package/dist/query.js +2 -2
  61. package/dist/{shapeFns-oS8Us7JQ.js → shapeFns-2ZBm7gZd.js} +2 -2
  62. package/dist/{shapeFns-lDEvCF5Q.cjs → shapeFns-BsNw-egb.cjs} +2 -2
  63. package/dist/shapeRef.cjs +1 -1
  64. package/dist/shapeRef.js +1 -1
  65. package/dist/{shapeRefFns-DHioZfFV.cjs → shapeRefFns-4I03ZCKU.cjs} +4 -4
  66. package/dist/{shapeRefFns-C2DbyKEO.js → shapeRefFns-VuIGZejB.js} +4 -4
  67. package/dist/{shapeTypes-BiX2PjaO.cjs → shapeTypes-CUTaIMCC.cjs} +5 -243
  68. package/dist/{shapeTypes-BH-9bXON.js → shapeTypes-CiEgOVu3.js} +3 -241
  69. package/dist/sketching.cjs +3 -3
  70. package/dist/sketching.js +3 -3
  71. package/dist/{solidBuilders-DR3oU7Fb.cjs → solidBuilders-0Y1U2uMs.cjs} +2 -2
  72. package/dist/{solidBuilders-BiduNSRx.js → solidBuilders-DV8lvLq3.js} +2 -2
  73. package/dist/{surfaceBuilders-xmm7fFbW.js → surfaceBuilders-DYzjeM-y.js} +2 -2
  74. package/dist/{surfaceBuilders-s2Uo2ard.cjs → surfaceBuilders-OUTnDgr5.cjs} +2 -2
  75. package/dist/text.cjs +2 -2
  76. package/dist/text.js +2 -2
  77. package/dist/{textBlueprints-DRh48_Fo.js → textBlueprints-00P4WdIq.js} +7 -7
  78. package/dist/{textBlueprints-Ca1NcWQg.cjs → textBlueprints-DQcSGfcQ.cjs} +7 -7
  79. package/dist/{textMetrics-BU6Ow8mb.js → textMetrics-8KJFgEn5.js} +1 -1
  80. package/dist/{textMetrics-CGN19mAp.cjs → textMetrics-Av8N82V_.cjs} +1 -1
  81. package/dist/topology.cjs +7 -7
  82. package/dist/topology.js +7 -7
  83. package/dist/{topologyQueryFns-B8uqQlEU.js → topologyQueryFns-DXKyoFvA.js} +1 -1
  84. package/dist/{topologyQueryFns-BoMkI1jZ.cjs → topologyQueryFns-j7sTNssl.cjs} +1 -1
  85. package/package.json +2 -2
@@ -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) {
@@ -1115,6 +1366,12 @@ function mesh(k, Module, shape, options) {
1115
1366
  for (let i = 0; i < posCount; i++) vertices[i] = Module.HEAPF32[posPtr + i] ?? 0;
1116
1367
  const normals = new Float32Array(normCount);
1117
1368
  if (!options.skipNormals) for (let i = 0; i < normCount; i++) normals[i] = Module.HEAPF32[normPtr + i] ?? 0;
1369
+ const uvCount = meshData.uvCount;
1370
+ const uvs = new Float32Array(options.includeUVs ? uvCount : 0);
1371
+ if (options.includeUVs && uvCount > 0) {
1372
+ const uvPtr = meshData.getUvsPtr() >> 2;
1373
+ for (let i = 0; i < uvCount; i++) uvs[i] = Module.HEAPF32[uvPtr + i] ?? 0;
1374
+ }
1118
1375
  const triangles = new Uint32Array(idxCount);
1119
1376
  for (let i = 0; i < idxCount; i++) triangles[i] = Module.HEAPU32[idxPtr + i] ?? 0;
1120
1377
  const faceGroups = [];
@@ -1131,7 +1388,7 @@ function mesh(k, Module, shape, options) {
1131
1388
  vertices,
1132
1389
  normals: options.skipNormals ? new Float32Array(0) : normals,
1133
1390
  triangles,
1134
- uvs: new Float32Array(0),
1391
+ uvs,
1135
1392
  faceGroups
1136
1393
  };
1137
1394
  } finally {
@@ -2974,10 +3231,27 @@ function makeEllipseArc2d(cx, cy, majorRadius, minorRadius, startAngle, endAngle
2974
3231
  function makeBezier2d(points) {
2975
3232
  return c2dWrap(makeBezier2d$1(points));
2976
3233
  }
2977
- function makeBSpline2d(points) {
2978
- if (points.length <= 25) return c2dWrap(makeBezier2d$1(points));
2979
- const step = Math.max(1, Math.floor(points.length / 24));
2980
- return c2dWrap(makeBezier2d$1(points.filter((_, i) => i % step === 0 || i === points.length - 1)));
3234
+ function makeBSpline2d(points, options) {
3235
+ const poles = points;
3236
+ const n = poles.length;
3237
+ const degree = Math.max(1, Math.min(options?.degMax ?? 3, n - 1));
3238
+ const knots = [0];
3239
+ const mults = [degree + 1];
3240
+ const nInternalKnots = n - degree - 1;
3241
+ for (let i = 1; i <= nInternalKnots; i++) {
3242
+ knots.push(i / (nInternalKnots + 1));
3243
+ mults.push(1);
3244
+ }
3245
+ knots.push(1);
3246
+ mults.push(degree + 1);
3247
+ return c2dWrap({
3248
+ __bk2d: "bspline",
3249
+ poles,
3250
+ knots,
3251
+ multiplicities: mults,
3252
+ degree,
3253
+ isPeriodic: false
3254
+ });
2981
3255
  }
2982
3256
  function evaluateCurve2d(curve, param) {
2983
3257
  return evaluateCurve2d$1(c2d(curve), param);
@@ -3222,16 +3496,53 @@ function approximateCurve2dAsBSpline(curve, maxSegments) {
3222
3496
  });
3223
3497
  }
3224
3498
  function decomposeBSpline2dToBeziers(curve) {
3225
- const knots = c2d(curve).knots ?? [];
3226
- if (knots.length < 2) return [curve];
3227
- const result = [];
3228
- for (let i = 0; i < knots.length - 1; i++) {
3229
- const k0 = knots[i];
3230
- const k1 = knots[i + 1];
3231
- if (Math.abs(k1 - k0) < 1e-15) continue;
3232
- result.push(trimCurve2d(curve, k0, k1));
3499
+ let cu = c2d(curve);
3500
+ while (cu.__bk2d === "trimmed" && cu.basis) cu = cu.basis;
3501
+ if (cu.__bk2d !== "bspline") return [curve];
3502
+ const poles = cu.poles;
3503
+ const p = cu.degree;
3504
+ const U = [];
3505
+ for (let i = 0; i < cu.knots.length; i++) for (let j = 0; j < cu.multiplicities[i]; j++) U.push(cu.knots[i]);
3506
+ const m = poles.length - 1 + p + 1;
3507
+ if (p < 1 || U.length !== m + 1) return [c2dWrap(makeBezier2d$1(poles))];
3508
+ const clone = (pt) => [pt[0], pt[1]];
3509
+ const segments = [];
3510
+ let a = p;
3511
+ let b = p + 1;
3512
+ let segPoles = [];
3513
+ for (let i = 0; i <= p; i++) segPoles[i] = clone(poles[i]);
3514
+ let nextPoles = [];
3515
+ while (b < m) {
3516
+ const i0 = b;
3517
+ while (b < m && U[b + 1] === U[b]) b++;
3518
+ const mult = b - i0 + 1;
3519
+ if (mult < p) {
3520
+ const numer = U[b] - U[a];
3521
+ const alphas = [];
3522
+ for (let j = p; j > mult; j--) alphas[j - mult - 1] = numer / (U[a + j] - U[a]);
3523
+ const r = p - mult;
3524
+ for (let j = 1; j <= r; j++) {
3525
+ const save = r - j;
3526
+ const s = mult + j;
3527
+ for (let k = p; k >= s; k--) {
3528
+ const alpha = alphas[k - s];
3529
+ const cur = segPoles[k];
3530
+ const prev = segPoles[k - 1];
3531
+ segPoles[k] = [alpha * cur[0] + (1 - alpha) * prev[0], alpha * cur[1] + (1 - alpha) * prev[1]];
3532
+ }
3533
+ if (b < m) nextPoles[save] = clone(segPoles[p]);
3534
+ }
3535
+ }
3536
+ segments.push(segPoles);
3537
+ if (b < m) {
3538
+ for (let i = p - mult; i <= p; i++) nextPoles[i] = clone(poles[b - p + i]);
3539
+ segPoles = nextPoles;
3540
+ nextPoles = [];
3541
+ a = b;
3542
+ b++;
3543
+ }
3233
3544
  }
3234
- return result.length > 0 ? result : [curve];
3545
+ return segments.map((sp) => c2dWrap(makeBezier2d$1(sp)));
3235
3546
  }
3236
3547
  function createBoundingBox2d() {
3237
3548
  return createBBox2d();
@@ -3684,124 +3995,41 @@ function applyComposedTransformWithHistory(transformFn, iterShapesFn, hashCodeFn
3684
3995
  }
3685
3996
  //#endregion
3686
3997
  //#region src/kernel/occtWasm/hullOps.ts
3687
- function findHorizonEdges(faces, visible) {
3688
- const visSet = new Set(visible);
3689
- const horizon = [];
3690
- for (const fi of visible) {
3691
- const f = faces[fi];
3692
- for (let ei = 0; ei < 3; ei++) {
3693
- const a = f[ei], b = f[(ei + 1) % 3];
3694
- if (faces.some((g, fj) => fj !== fi && !visSet.has(fj) && [
3695
- 0,
3696
- 1,
3697
- 2
3698
- ].some((ej) => g[ej] === b && g[(ej + 1) % 3] === a))) horizon.push([a, b]);
3699
- }
3700
- }
3701
- return horizon;
3998
+ function hullFromPoints(k, Module, points, tolerance) {
3999
+ if (points.length < 4) throw new Error("hullFromPoints: need at least 4 points");
4000
+ const { points: hullPoints, faces } = quickHull(points, tolerance);
4001
+ if (faces.length < 4) throw new Error("hullFromPoints: degenerate hull (fewer than 4 faces)");
4002
+ return buildSolidFromFaces(k, Module, [...hullPoints], [...faces], tolerance);
3702
4003
  }
3703
- function computeConvexHullFaces(pts) {
3704
- const cross = (a, b) => ({
3705
- x: a.y * b.z - a.z * b.y,
3706
- y: a.z * b.x - a.x * b.z,
3707
- z: a.x * b.y - a.y * b.x
3708
- });
3709
- const sub = (a, b) => ({
3710
- x: a.x - b.x,
3711
- y: a.y - b.y,
3712
- z: a.z - b.z
3713
- });
3714
- const dot = (a, b) => a.x * b.x + a.y * b.y + a.z * b.z;
3715
- const n = pts.length;
3716
- const faces = [];
3717
- const p0 = pts[0];
3718
- let i1 = 1;
3719
- while (i1 < n) {
3720
- const p = wasmIndex(pts, i1);
3721
- if (Math.hypot(p.x - p0.x, p.y - p0.y, p.z - p0.z) >= 1e-10) break;
3722
- i1++;
3723
- }
3724
- let i2 = i1 + 1;
3725
- const e01 = sub(pts[i1], p0);
3726
- while (i2 < n) {
3727
- const c = cross(e01, sub(pts[i2], p0));
3728
- if (Math.hypot(c.x, c.y, c.z) > 1e-10) break;
3729
- i2++;
3730
- }
3731
- let i3 = i2 + 1;
3732
- const norm = cross(e01, sub(pts[i2], p0));
3733
- while (i3 < n) {
3734
- if (Math.abs(dot(norm, sub(pts[i3], p0))) > 1e-10) break;
3735
- i3++;
3736
- }
3737
- if (i3 >= n) return [[
3738
- 0,
3739
- 1,
3740
- 2
3741
- ]];
3742
- if (dot(cross(sub(pts[i1], p0), sub(pts[i2], p0)), sub(pts[i3], p0)) > 0) faces.push([
3743
- 0,
3744
- i1,
3745
- i2
3746
- ], [
3747
- 0,
3748
- i2,
3749
- i3
3750
- ], [
3751
- 0,
3752
- i3,
3753
- i1
3754
- ], [
3755
- i1,
3756
- i3,
3757
- i2
3758
- ]);
3759
- else faces.push([
3760
- 0,
3761
- i2,
3762
- i1
3763
- ], [
3764
- 0,
3765
- i3,
3766
- i2
3767
- ], [
3768
- 0,
3769
- i1,
3770
- i3
3771
- ], [
3772
- i2,
3773
- i3,
3774
- i1
3775
- ]);
3776
- const used = new Set([
3777
- 0,
3778
- i1,
3779
- i2,
3780
- i3
3781
- ]);
3782
- for (let pi = 0; pi < n; pi++) {
3783
- if (used.has(pi)) continue;
3784
- const p = pts[pi];
3785
- const visible = [];
3786
- for (let fi = 0; fi < faces.length; fi++) {
3787
- const f = faces[fi];
3788
- 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);
4004
+ /**
4005
+ * Sample surface vertices of each shape via tessellation. A coarse deflection
4006
+ * keeps the point count low the convex hull only needs extreme points, and
4007
+ * fine meshes on curved surfaces explode the hull cost.
4008
+ */
4009
+ function extractVertices(k, Module, shapes, tolerance) {
4010
+ const deflection = Math.max(tolerance, 1);
4011
+ const points = [];
4012
+ for (const shape of shapes) {
4013
+ const meshData = k.tessellate(unwrap(shape), deflection, deflection * .5);
4014
+ try {
4015
+ const posCount = meshData.positionCount;
4016
+ const posPtr = meshData.getPositionsPtr() >> 2;
4017
+ for (let i = 0; i < posCount; i += 3) points.push({
4018
+ x: Module.HEAPF32[posPtr + i] ?? 0,
4019
+ y: Module.HEAPF32[posPtr + i + 1] ?? 0,
4020
+ z: Module.HEAPF32[posPtr + i + 2] ?? 0
4021
+ });
4022
+ } finally {
4023
+ meshData.delete();
3789
4024
  }
3790
- if (visible.length === 0) continue;
3791
- const horizon = findHorizonEdges(faces, visible);
3792
- visible.sort((a2, b2) => b2 - a2);
3793
- for (const fi of visible) faces.splice(fi, 1);
3794
- for (const [a, b] of horizon) faces.push([
3795
- a,
3796
- b,
3797
- pi
3798
- ]);
3799
- }
3800
- return faces;
4025
+ }
4026
+ return points;
3801
4027
  }
3802
- function hullFromPoints(k, Module, points, tolerance) {
3803
- if (points.length < 4) throw new Error("hullFromPoints: need at least 4 points");
3804
- return buildSolidFromFaces(k, Module, points, computeConvexHullFaces(points), tolerance);
4028
+ function hull(k, Module, shapes, tolerance) {
4029
+ if (shapes.length === 0) throw new Error("hull: no shapes provided");
4030
+ const points = extractVertices(k, Module, shapes, tolerance);
4031
+ if (points.length < 4) throw new Error("hull: fewer than 4 vertices extracted from input shapes");
4032
+ return hullFromPoints(k, Module, points, tolerance);
3805
4033
  }
3806
4034
  //#endregion
3807
4035
  //#region src/kernel/occtWasm/occtWasmAdapter.ts
@@ -3957,8 +4185,8 @@ var OcctWasmAdapter = class OcctWasmAdapter {
3957
4185
  solidFromShell(shell) {
3958
4186
  return solidFromShell(this.k, shell);
3959
4187
  }
3960
- hull(_shapes, _tolerance) {
3961
- notImplemented("hull");
4188
+ hull(shapes, tolerance) {
4189
+ return hull(this.k, this.Module, shapes, tolerance);
3962
4190
  }
3963
4191
  hullFromPoints(points, tolerance) {
3964
4192
  return hullFromPoints(this.k, this.Module, points, tolerance);
@@ -4620,4 +4848,4 @@ var OcctWasmAdapter = class OcctWasmAdapter {
4620
4848
  }
4621
4849
  };
4622
4850
  //#endregion
4623
- 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 };
4851
+ 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 };