@faicad/cq-compat 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/dist/assembly-compare.d.ts +135 -0
  2. package/dist/assembly-compare.d.ts.map +1 -0
  3. package/dist/assembly-compare.js +266 -0
  4. package/dist/assembly-compare.js.map +1 -0
  5. package/dist/assembly.d.ts +102 -0
  6. package/dist/assembly.d.ts.map +1 -0
  7. package/dist/assembly.js +403 -0
  8. package/dist/assembly.js.map +1 -0
  9. package/dist/browser.d.ts +13 -0
  10. package/dist/browser.d.ts.map +1 -0
  11. package/dist/browser.js +13 -0
  12. package/dist/browser.js.map +1 -0
  13. package/dist/gear-test-harness.d.ts +79 -0
  14. package/dist/gear-test-harness.d.ts.map +1 -0
  15. package/dist/gear-test-harness.js +112 -0
  16. package/dist/gear-test-harness.js.map +1 -0
  17. package/dist/gears.d.ts +226 -0
  18. package/dist/gears.d.ts.map +1 -0
  19. package/dist/gears.js +274 -0
  20. package/dist/gears.js.map +1 -0
  21. package/dist/geom-types.d.ts +7 -0
  22. package/dist/geom-types.d.ts.map +1 -0
  23. package/dist/geom-types.js +2 -0
  24. package/dist/geom-types.js.map +1 -0
  25. package/dist/index.d.ts +26 -0
  26. package/dist/index.d.ts.map +1 -0
  27. package/dist/index.js +23 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/step-compare.d.ts +83 -0
  30. package/dist/step-compare.d.ts.map +1 -0
  31. package/dist/step-compare.js +140 -0
  32. package/dist/step-compare.js.map +1 -0
  33. package/dist/transpile.d.ts +42 -0
  34. package/dist/transpile.d.ts.map +1 -0
  35. package/dist/transpile.js +557 -0
  36. package/dist/transpile.js.map +1 -0
  37. package/dist/workplane.d.ts +1216 -0
  38. package/dist/workplane.d.ts.map +1 -0
  39. package/dist/workplane.js +4026 -0
  40. package/dist/workplane.js.map +1 -0
  41. package/package.json +48 -0
@@ -0,0 +1,403 @@
1
+ /**
2
+ * cq-compat assembly helpers — CadQuery Assembly.constrain → faijs cad.assembly.
3
+ *
4
+ * Maps CadQuery constraint DSL ("part@faces@>Z[-2]", "Plane"/"Axis") to faijs
5
+ * AssemblyConstraint objects with EntityRef geometry snapshots.
6
+ *
7
+ * Constraint mapping (verified against faijs api/assembly/lower.ts):
8
+ * - "Plane" → mate (face-to-face: normal reversed + center coincident)
9
+ * - "Axis" → align (normal same direction + center coincident; plane face refs
10
+ * are encoded as axis via axisFromFace — concentric would reject
11
+ * plane faces because faceGeometryToSolverEntity maps plane→plane
12
+ * entity, not axis)
13
+ */
14
+ import { createApiNamespace } from '@faicad/faijs/api/api-namespace';
15
+ import { getSlot, brepOf, ensureSlot } from '@faicad/faijs/shape';
16
+ import { getBackends } from '@faicad/faijs/runtime-state';
17
+ import { applyTransform } from '@faicad/faijs/mesh/rigid-transform';
18
+ import { applyTransformBrep } from '@faicad/faijs/brep/brep-ops';
19
+ import { resolveFaceSelector, asBrepShape } from './workplane.js';
20
+ const cad = createApiNamespace();
21
+ /**
22
+ * faceRef
23
+ * @param partName - string
24
+ * @param selector - string
25
+ * @param shape - Shape
26
+ * @returns Promise<EntityRef>
27
+ */
28
+ export async function faceRef(partName, selector, shape) {
29
+ // Resolve via the same face enumeration as the Workplane API — this is
30
+ // required for CadQuery-style indexed selectors like "bp@faces@>Z[-2]"
31
+ // (second-highest Z face, e.g. a recess floor instead of the top annulus).
32
+ // The returned center is the face's area centroid (CadQuery face Center)
33
+ // and the normal is the outward direction.
34
+ const { center: faceCenter, normal } = await resolveFaceSelector(shape, selector);
35
+ return {
36
+ part: partName,
37
+ face: {
38
+ surfaceType: 'plane',
39
+ center: faceCenter,
40
+ normal,
41
+ },
42
+ };
43
+ }
44
+ /**
45
+ * constraint
46
+ * @param aPart - string
47
+ * @param aSelector - string
48
+ * @param aShape - Shape
49
+ * @param bPart - string
50
+ * @param bSelector - string
51
+ * @param bShape - Shape
52
+ * @param type - 'Plane' | 'Axis'
53
+ * @returns Promise<AssemblyConstraint>
54
+ */
55
+ export async function constraint(aPart, aSelector, aShape, bPart, bSelector, bShape, type) {
56
+ const out = await constraintEx(aPart, aSelector, aShape, bPart, bSelector, bShape, type);
57
+ return out[0];
58
+ }
59
+ /**
60
+ * pointRef — 字面坐标点引用(无需几何解析)。
61
+ * @param part - 部件名
62
+ * @param coords - [x,y,z](本地系 mm)
63
+ * @returns EntityRef(point)
64
+ */
65
+ export function pointRef(part, coords) {
66
+ return { part, point: [coords[0], coords[1], coords[2]] };
67
+ }
68
+ /**
69
+ * axisRef — 字面轴引用(无需几何解析)。
70
+ * @param part - 部件名
71
+ * @param origin - 轴上一点 [x,y,z](本地系 mm)
72
+ * @param direction - 单位方向 [x,y,z]
73
+ * @returns EntityRef(edge.axis)
74
+ */
75
+ export function axisRef(part, origin, direction) {
76
+ return { part, edge: { axis: { origin: [origin[0], origin[1], origin[2]], direction } } };
77
+ }
78
+ function parseCoords(sel) {
79
+ const m = sel.replace(/[[\]()]/g, '').trim().split(/[\s,]+/).filter(Boolean);
80
+ if (m.length !== 3)
81
+ return null;
82
+ const x = Number(m[0]);
83
+ const y = Number(m[1]);
84
+ const z = Number(m[2]);
85
+ if (!Number.isFinite(x) || !Number.isFinite(y) || !Number.isFinite(z))
86
+ return null;
87
+ return [x, y, z];
88
+ }
89
+ /**
90
+ * resolveAxisRef — 从形状里解析出一条轴(用于 Cylinder 配合)。
91
+ * 走 wireframe 取边折线,对闭合边做圆拟合(PCA 平面 + 2D 最小二乘圆),
92
+ * 返回第一条足够圆的边的轴。无内核/无圆边时抛错。
93
+ */
94
+ async function resolveAxisRef(part, shape) {
95
+ shape = asBrepShape(shape); // 提升边界:实参可能是借用视图
96
+ const handle = brepOf(shape);
97
+ const kernel = getBackends().kernel.brep;
98
+ if (!handle || !kernel)
99
+ throw new Error(`[cq-compat] axisRef: BREP unavailable for part "${part}"`);
100
+ // 整形状一次 wireframe,按 edgeGroups 逐边取折线区间。
101
+ // 依据 topologyExt.ts:wireframe() 与 getSubShapes 同用 TopExp::MapShapes +
102
+ // IndexedMap,故 edge 枚举顺序一致——第 i 条 edge 对应 edgeGroups[i*3..]。
103
+ const wf = kernel.wireframe(handle, 0.01);
104
+ const groups = wf.edgeGroups;
105
+ if (!groups || groups.length < 3)
106
+ throw new Error(`[cq-compat] axisRef: wireframe returned no edge groups for part "${part}"`);
107
+ const edgeCount = groups.length / 3;
108
+ for (let ei = 0; ei < edgeCount; ei++) {
109
+ const start = groups[ei * 3];
110
+ const count = groups[ei * 3 + 1]; // float units (3 floats / point)
111
+ const pts = [];
112
+ const numPts = Math.floor(count / 3);
113
+ for (let i = 0; i < numPts; i++) {
114
+ const o = start + i * 3;
115
+ pts.push([wf.points[o], wf.points[o + 1], wf.points[o + 2]]);
116
+ }
117
+ const axis = fitCircleAxis(pts);
118
+ if (axis)
119
+ return axisRef(part, axis.origin, axis.direction);
120
+ }
121
+ throw new Error(`[cq-compat] axisRef: no circular edge found in part "${part}"`);
122
+ }
123
+ /** 对一组(应共面、闭合)的 XYZ 点拟合圆轴,返回原点(圆心投影)与方向(法向),非圆/退化返回 null。 */
124
+ function fitCircleAxis(pts) {
125
+ const n = pts.length;
126
+ if (n < 6)
127
+ return null;
128
+ // 质心
129
+ const c = [0, 0, 0];
130
+ for (const p of pts) {
131
+ c[0] += p[0];
132
+ c[1] += p[1];
133
+ c[2] += p[2];
134
+ }
135
+ c[0] /= n;
136
+ c[1] /= n;
137
+ c[2] /= n;
138
+ // 相邻段叉积之和 → 平面法向(闭环平面点稳定)
139
+ let nx = 0, ny = 0, nz = 0;
140
+ for (let i = 0; i < n; i++) {
141
+ const a = pts[i];
142
+ const b = pts[(i + 1) % n];
143
+ const ax = a[0] - c[0], ay = a[1] - c[1], az = a[2] - c[2];
144
+ const bx = b[0] - c[0], by = b[1] - c[1], bz = b[2] - c[2];
145
+ nx += ay * bz - az * by;
146
+ ny += az * bx - ax * bz;
147
+ nz += ax * by - ay * bx;
148
+ }
149
+ const nl = Math.hypot(nx, ny, nz);
150
+ if (!(nl > 1e-9) || !Number.isFinite(nl))
151
+ return null;
152
+ nx /= nl;
153
+ ny /= nl;
154
+ nz /= nl;
155
+ // 平面正交基
156
+ let up = Math.abs(nz) < 0.9 ? [0, 0, 1] : [1, 0, 0];
157
+ let ux = ny * up[2] - nz * up[1], uy = nz * up[0] - nx * up[2], uz = nx * up[1] - ny * up[0];
158
+ let ul = Math.hypot(ux, uy, uz);
159
+ if (!(ul > 1e-9)) {
160
+ up = [1, 0, 0];
161
+ ux = ny * up[2] - nz * up[1];
162
+ uy = nz * up[0] - nx * up[2];
163
+ uz = nx * up[1] - ny * up[0];
164
+ ul = Math.hypot(ux, uy, uz);
165
+ if (!(ul > 1e-9))
166
+ return null;
167
+ }
168
+ const u = [ux / ul, uy / ul, uz / ul];
169
+ const v = [ny * u[2] - nz * u[1], nz * u[0] - nx * u[2], nx * u[1] - ny * u[0]];
170
+ // 投影到 2D
171
+ const xs = [];
172
+ const ys = [];
173
+ for (const p of pts) {
174
+ const dx = p[0] - c[0], dy = p[1] - c[1], dz = p[2] - c[2];
175
+ xs.push(dx * u[0] + dy * u[1] + dz * u[2]);
176
+ ys.push(dx * v[0] + dy * v[1] + dz * v[2]);
177
+ }
178
+ // 2D 最小二乘圆拟合(Kasa): a·xi + b·yi + c = -(xi²+yi²)
179
+ let sxx = 0, sxy = 0, syy = 0, sx = 0, sy = 0, sR = 0, sRx = 0, sRy = 0;
180
+ for (let i = 0; i < n; i++) {
181
+ const xi = xs[i], yi = ys[i], ri = xi * xi + yi * yi;
182
+ sxx += xi * xi;
183
+ sxy += xi * yi;
184
+ syy += yi * yi;
185
+ sx += xi;
186
+ sy += yi;
187
+ sR += ri;
188
+ sRx += ri * xi;
189
+ sRy += ri * yi;
190
+ }
191
+ const A = [
192
+ [sxx, sxy, sx],
193
+ [sxy, syy, sy],
194
+ [sx, sy, n],
195
+ ];
196
+ const B = [-sRx, -sRy, -sR];
197
+ const det = det3(A);
198
+ if (!(Math.abs(det) > 1e-12))
199
+ return null;
200
+ const a = det3([[B[0], A[0][1], A[0][2]], [B[1], A[1][1], A[1][2]], [B[2], A[2][1], A[2][2]]]) / det;
201
+ const b = det3([[A[0][0], B[0], A[0][2]], [A[1][0], B[1], A[1][2]], [A[2][0], B[2], A[2][2]]]) / det;
202
+ const cc = det3([[A[0][0], A[0][1], B[0]], [A[1][0], A[1][1], B[1]], [A[2][0], A[2][1], B[2]]]) / det;
203
+ const r2 = a * a / 4 + b * b / 4 - cc;
204
+ if (!(r2 > 0) || !Number.isFinite(r2))
205
+ return null;
206
+ // 圆度校验:卡萨拟合有偏,用 RMS 过滤非圆边
207
+ const R = Math.sqrt(r2);
208
+ let rms = 0;
209
+ for (let i = 0; i < n; i++) {
210
+ const dd = Math.hypot(xs[i] + a / 2, ys[i] + b / 2) - R;
211
+ rms += dd * dd;
212
+ }
213
+ rms = Math.sqrt(rms / n);
214
+ if (rms > R * 0.05)
215
+ return null;
216
+ // 圆心回投到 3D
217
+ const ox = c[0] + u[0] * (-a / 2) + v[0] * (-b / 2);
218
+ const oy = c[1] + u[1] * (-a / 2) + v[1] * (-b / 2);
219
+ const oz = c[2] + u[2] * (-a / 2) + v[2] * (-b / 2);
220
+ if (![ox, oy, oz, nx, ny, nz].every(Number.isFinite))
221
+ return null;
222
+ return { origin: [ox, oy, oz], direction: [nx, ny, nz] };
223
+ }
224
+ function det3(m) {
225
+ return (m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1]) -
226
+ m[0][1] * (m[1][0] * m[2][2] - m[1][2] * m[2][0]) +
227
+ m[0][2] * (m[1][0] * m[2][1] - m[1][1] * m[2][0]));
228
+ }
229
+ /**
230
+ * constraintEx — 统一约束构造,覆盖 CQ 公共种类并映射到 faijs 类型面。
231
+ *
232
+ * 映射(对齐 global 求解器 consuming 的 AssemblyConstraint):
233
+ * - 'Plane' → [mate](faceRef→plane)
234
+ * - 'Axis' → [angle:180](纯方向反平行、无点项——CQ 2.8.0 `axis_cost` 缺省语义)
235
+ * - 'Point' → [coincident](selector 为字面坐标 "x,y,z")
236
+ * - 'Cylinder' → [concentric, coincident(point_on_line)](圆边解析轴)
237
+ * - 'Distance' → [distance(value)](point-point 或 plane-plane)
238
+ * - 'Fixed' → [fixed](aPart 锁定)
239
+ * - 'Revolute' → [fixed](暂降级为锚定占位;旋转 DOF 后续走 joints 机制)
240
+ *
241
+ * @param aPart A 侧成员名。
242
+ * @param aSelector A 侧面选择器字符串(如 ">Z[-2]")。
243
+ * @param aShape A 侧成员几何(真实 Shape 或借用视图)。
244
+ * @param bPart B 侧成员名。
245
+ * @param bSelector B 侧面选择器字符串。
246
+ * @param bShape B 侧成员几何(真实 Shape 或借用视图)。
247
+ * @param kind 约束种类(Plane/Axis/Point/Cylinder/Distance/Fixed/Revolute)。
248
+ * @param param 可选参数(Distance 的距离值等)。
249
+ * @returns AssemblyConstraint[](Cylinder 拆两条,其余单条)
250
+ */
251
+ export async function constraintEx(aPart, aSelector, aShape, bPart, bSelector, bShape, kind, param) {
252
+ switch (kind) {
253
+ case 'Plane': {
254
+ if (!aShape || !bShape)
255
+ throw new Error(`constraintEx Plane: shapes required`);
256
+ // 提升边界归一:实参可能是借用视图(见 asBrepShape 注释)。faceRef 内部
257
+ // 亦归一,入口再归一保证直接调用路径(不经 compatOp 提升)行为一致。
258
+ const a = await faceRef(aPart, aSelector, asBrepShape(aShape));
259
+ const b = await faceRef(bPart, bSelector, asBrepShape(bShape));
260
+ return [{ type: 'mate', a, b }];
261
+ }
262
+ case 'Axis': {
263
+ if (!aShape || !bShape)
264
+ throw new Error(`constraintEx Axis: shapes required`);
265
+ const a = await faceRef(aPart, aSelector, asBrepShape(aShape));
266
+ const b = await faceRef(bPart, bSelector, asBrepShape(bShape));
267
+ // GOTCHA (2026-09-17,对照 CQ 2.8.0 `occ_impl/solver.py` 标定):CQ 独立 Axis 约束是
268
+ // **纯方向约束**——`ConstraintInvariants["Axis"]` 只收两个 gp_Dir(无点项),
269
+ // `axis_cost` 缺省 `val = pi`(反平行)。此前误映射为 'align'(同向 val=0 + 面心
270
+ // 重合)属双重分歧:真实 e2e 的 c4 被拖向 mb z=-1(参考 +6.1),且凭空多出一
271
+ // 个 CQ 没有的面心重合项。'angle' 在求解器里正是纯方向项(global-solver.ts
272
+ // case 'angle':axis 成本、无点项),value 单位 deg(180 = 反平行)。
273
+ return [{ type: 'angle', value: 180, a, b }];
274
+ }
275
+ case 'Point': {
276
+ const pa = parseCoords(aSelector);
277
+ const pb = parseCoords(bSelector);
278
+ if (!pa || !pb)
279
+ throw new Error(`constraintEx Point: selectors must be coords "x,y,z"`);
280
+ return [{ type: 'coincident', a: pointRef(aPart, pa), b: pointRef(bPart, pb) }];
281
+ }
282
+ case 'Cylinder': {
283
+ if (!aShape || !bShape)
284
+ throw new Error(`constraintEx Cylinder: shapes required`);
285
+ const aAxis = await resolveAxisRef(aPart, aShape);
286
+ const bAxis = await resolveAxisRef(bPart, bShape);
287
+ return [
288
+ { type: 'concentric', a: aAxis, b: bAxis },
289
+ { type: 'coincident', a: aAxis, b: bAxis },
290
+ ];
291
+ }
292
+ case 'Distance': {
293
+ const pa = parseCoords(aSelector);
294
+ const pb = parseCoords(bSelector);
295
+ const a = pa
296
+ ? pointRef(aPart, pa)
297
+ : await faceRef(aPart, aSelector, aShape);
298
+ const b = pb
299
+ ? pointRef(bPart, pb)
300
+ : await faceRef(bPart, bSelector, bShape);
301
+ const value = param ?? 0;
302
+ return [{ type: 'distance', value, a, b }];
303
+ }
304
+ case 'Fixed':
305
+ return [{ type: 'fixed', part: aPart }];
306
+ case 'Revolute':
307
+ // 暂降级为锚定占位(旋转 DOF 留待后续 joints 机制)
308
+ return [{ type: 'fixed', part: aPart }];
309
+ }
310
+ }
311
+ /**
312
+ * buildAssembly
313
+ * @param name - string
314
+ * @param members - Array<{ name: string; shape: Shape; color?: RGB }>
315
+ * @param constraints - AssemblyConstraint[]
316
+ * @param opts - optional: { solver?: 'chain' | 'global' };cq-compat = CadQuery 兼容,默认 'global'
317
+ * @returns CompoundShape
318
+ */
319
+ export function buildAssembly(name, members, constraints, opts) {
320
+ // 提升边界归一:经 runtime.execute 时 members[].shape 是借用 brepjs 视图
321
+ // (borrowDeep 产物),不是 faijs Shape。compound 的 children 必须持有 mesh
322
+ // (引擎 applyTransform 做顶点烘焙)+ BREP 身份槽(STEP 导出/刚体变换读
323
+ // slot.solid),借用视图两者皆无 → 必须还原为真实 Shape 再进 assembly。
324
+ const shapes = members.map((m) => asBrepShape(m.shape));
325
+ const memberNames = members.map((m) => m.name);
326
+ const memberColors = {};
327
+ for (const m of members) {
328
+ if (m.color)
329
+ memberColors[m.name] = m.color;
330
+ }
331
+ // cq-compat 是 CadQuery 兼容层:默认走 global 求解器(语义对齐 CQ solver.py)。
332
+ // 需要旧 chain 行为时可显式 opts.solver='chain'。
333
+ const solver = opts?.solver ?? 'global';
334
+ const compound = cad.assembly({
335
+ name,
336
+ members: shapes,
337
+ memberNames,
338
+ constraints,
339
+ memberColors,
340
+ solver,
341
+ });
342
+ // CadQuery's Assembly.save() solves constraints implicitly before export —
343
+ // mirror that here so CLI STEP export sees the solved part poses.
344
+ // GOTCHA (2026-09-18):引擎只有 direct-executor 路径消费 pending transforms
345
+ // (applyPendingAssemblyTransforms);CLI brep 模块路径无人消费 → 登记 pending
346
+ // 也没用,成员停在恒等位姿。因此这里直接 solveDetailed() 拿到 transforms,
347
+ // 在库侧把位姿烘焙进成员:mesh 顶点原地变换 + BREP slot.solid 刚体变换
348
+ // (与 direct-executor 同语义)。behavior.solve/compound.solve 的 pending 登记
349
+ // 保留(direct 路径仍走引擎烘焙),但本函数不再依赖它。
350
+ const behavior = getSlot(compound)?.behavior;
351
+ const transforms = behavior?.solveDetailed?.().transforms ?? [];
352
+ // CQ 语义对齐:无约束成员(如 assemb.py 里仅 .add 的 slide_top)在 CQ 求解器
353
+ // 中固定在初始位姿(不被拉入最小化);我方 global 求解器会给自由成员漂移解,
354
+ // 烘焙前按「是否被约束引用」过滤,未引用成员保持恒等。
355
+ const referenced = new Set();
356
+ for (const c of constraints) {
357
+ // StructuralConstraint 形态是 { a: EntityRef, b: EntityRef }(EntityRef.part
358
+ // = 成员名);cq-compat 的 constraint() 只产出该形态。FaceMateConstraint 无
359
+ // a/b,用 in 收窄跳过。
360
+ if ('a' in c && 'b' in c) {
361
+ for (const ref of [c.a, c.b]) {
362
+ if (ref && typeof ref.part === 'string')
363
+ referenced.add(ref.part);
364
+ }
365
+ }
366
+ }
367
+ const baked = transforms.filter((t) => referenced.has(behavior?.memberNames?.[t.index] ?? ''));
368
+ if (baked.length > 0) {
369
+ const kernel = getBackends().kernel.brep;
370
+ const children = compound.children ?? [];
371
+ for (const t of baked) {
372
+ const member = children[t.index];
373
+ if (!member || typeof member !== 'object')
374
+ continue;
375
+ // mesh 顶点原地变换(保留对象引用,ctx 与 compound.children 同步看到变更)
376
+ Object.assign(member, applyTransform(member, t.quaternion, t.pivot, t.translation, t.rotationMatrix));
377
+ // BREP 刚体变换:新 solid 写回身份槽(STEP 导出读 slot.solid)。
378
+ // GOTCHA:旧 solid 句柄**不能 release**——solidCache(partName 键)仍指向
379
+ // 它,库侧无法同步该缓存(setSolidHook 是宿主注入),release 后拓扑构建
380
+ // 读到悬空句柄报 INVALID_SHAPE_ID;保留旧句柄仅浪费少量内存。
381
+ if (kernel) {
382
+ const solid = brepOf(member);
383
+ if (solid) {
384
+ const transformed = applyTransformBrep(kernel, solid, t.quaternion, t.pivot, t.translation);
385
+ ensureSlot(member).solid = transformed;
386
+ }
387
+ }
388
+ }
389
+ }
390
+ return compound;
391
+ }
392
+ /**
393
+ * Color
394
+ * @param r - number
395
+ * @param g - number
396
+ * @param b - number
397
+ * @param _a - number
398
+ * @returns RGB
399
+ */
400
+ export function Color(r, g, b, _a) {
401
+ return [r, g, b];
402
+ }
403
+ //# sourceMappingURL=assembly.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assembly.js","sourceRoot":"","sources":["../src/assembly.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * cq-compat assembly helpers — CadQuery Assembly.constrain → faijs cad.assembly.\n *\n * Maps CadQuery constraint DSL (\"part@faces@>Z[-2]\", \"Plane\"/\"Axis\") to faijs\n * AssemblyConstraint objects with EntityRef geometry snapshots.\n *\n * Constraint mapping (verified against faijs api/assembly/lower.ts):\n * - \"Plane\" → mate (face-to-face: normal reversed + center coincident)\n * - \"Axis\" → align (normal same direction + center coincident; plane face refs\n * are encoded as axis via axisFromFace — concentric would reject\n * plane faces because faceGeometryToSolverEntity maps plane→plane\n * entity, not axis)\n */\n\nimport { createApiNamespace } from '@faicad/faijs/api/api-namespace'\nimport type { Shape } from '@faicad/faijs/mesh/types'\nimport type {\n AssemblyConstraint,\n EntityRef,\n} from '@faicad/faijs/api/assembly/types'\nimport type { CompoundShape } from '@faicad/faijs/shape'\nimport { getSlot, brepOf, ensureSlot } from '@faicad/faijs/shape'\nimport { getBackends } from '@faicad/faijs/runtime-state'\nimport { applyTransform } from '@faicad/faijs/mesh/rigid-transform'\nimport { applyTransformBrep } from '@faicad/faijs/brep/brep-ops'\nimport type { BrepEngineApi } from '@faicad/faijs/brep/engine/primitives'\nimport type { BrepHandle } from '@faicad/faijs/brep/engine/types'\nimport type { RGB } from './workplane'\nimport { resolveFaceSelector, asBrepShape } from './workplane'\n\nconst cad = createApiNamespace() as Record<string, (...args: unknown[]) => Promise<unknown>>\n\n/**\n * faceRef\n * @param partName - string\n * @param selector - string\n * @param shape - Shape\n * @returns Promise<EntityRef>\n */\nexport async function faceRef(\n partName: string,\n selector: string,\n shape: Shape,\n): Promise<EntityRef> {\n // Resolve via the same face enumeration as the Workplane API — this is\n // required for CadQuery-style indexed selectors like \"bp@faces@>Z[-2]\"\n // (second-highest Z face, e.g. a recess floor instead of the top annulus).\n // The returned center is the face's area centroid (CadQuery face Center)\n // and the normal is the outward direction.\n const { center: faceCenter, normal } = await resolveFaceSelector(shape, selector)\n return {\n part: partName,\n face: {\n surfaceType: 'plane',\n center: faceCenter,\n normal,\n },\n } as EntityRef\n}\n\n/**\n * constraint\n * @param aPart - string\n * @param aSelector - string\n * @param aShape - Shape\n * @param bPart - string\n * @param bSelector - string\n * @param bShape - Shape\n * @param type - 'Plane' | 'Axis'\n * @returns Promise<AssemblyConstraint>\n */\nexport async function constraint(\n aPart: string,\n aSelector: string,\n aShape: Shape,\n bPart: string,\n bSelector: string,\n bShape: Shape,\n type: 'Plane' | 'Axis',\n): Promise<AssemblyConstraint> {\n const out = await constraintEx(aPart, aSelector, aShape, bPart, bSelector, bShape, type)\n return out[0]\n}\n\n/**\n * pointRef — 字面坐标点引用(无需几何解析)。\n * @param part - 部件名\n * @param coords - [x,y,z](本地系 mm)\n * @returns EntityRef(point)\n */\nexport function pointRef(part: string, coords: [number, number, number]): EntityRef {\n return { part, point: [coords[0], coords[1], coords[2]] } as EntityRef\n}\n\n/**\n * axisRef — 字面轴引用(无需几何解析)。\n * @param part - 部件名\n * @param origin - 轴上一点 [x,y,z](本地系 mm)\n * @param direction - 单位方向 [x,y,z]\n * @returns EntityRef(edge.axis)\n */\nexport function axisRef(\n part: string,\n origin: [number, number, number],\n direction: [number, number, number],\n): EntityRef {\n return { part, edge: { axis: { origin: [origin[0], origin[1], origin[2]], direction } } } as EntityRef\n}\n\ntype AssemblyKind =\n | 'Plane'\n | 'Axis'\n | 'Point'\n | 'Cylinder'\n | 'Distance'\n | 'Fixed'\n | 'Revolute'\n\nfunction parseCoords(sel: string): [number, number, number] | null {\n const m = sel.replace(/[[\\]()]/g, '').trim().split(/[\\s,]+/).filter(Boolean)\n if (m.length !== 3) return null\n const x = Number(m[0])\n const y = Number(m[1])\n const z = Number(m[2])\n if (!Number.isFinite(x) || !Number.isFinite(y) || !Number.isFinite(z)) return null\n return [x, y, z]\n}\n\n/**\n * resolveAxisRef — 从形状里解析出一条轴(用于 Cylinder 配合)。\n * 走 wireframe 取边折线,对闭合边做圆拟合(PCA 平面 + 2D 最小二乘圆),\n * 返回第一条足够圆的边的轴。无内核/无圆边时抛错。\n */\nasync function resolveAxisRef(part: string, shape: Shape): Promise<EntityRef> {\n shape = asBrepShape(shape) // 提升边界:实参可能是借用视图\n const handle = brepOf(shape)\n const kernel = getBackends().kernel.brep as BrepEngineApi | null\n if (!handle || !kernel) throw new Error(`[cq-compat] axisRef: BREP unavailable for part \"${part}\"`)\n // 整形状一次 wireframe,按 edgeGroups 逐边取折线区间。\n // 依据 topologyExt.ts:wireframe() 与 getSubShapes 同用 TopExp::MapShapes +\n // IndexedMap,故 edge 枚举顺序一致——第 i 条 edge 对应 edgeGroups[i*3..]。\n const wf = kernel.wireframe(handle as never, 0.01)\n const groups = wf.edgeGroups\n if (!groups || groups.length < 3) throw new Error(`[cq-compat] axisRef: wireframe returned no edge groups for part \"${part}\"`)\n const edgeCount = groups.length / 3\n for (let ei = 0; ei < edgeCount; ei++) {\n const start = groups[ei * 3]\n const count = groups[ei * 3 + 1] // float units (3 floats / point)\n const pts: [number, number, number][] = []\n const numPts = Math.floor(count / 3)\n for (let i = 0; i < numPts; i++) {\n const o = start + i * 3\n pts.push([wf.points[o], wf.points[o + 1], wf.points[o + 2]])\n }\n const axis = fitCircleAxis(pts)\n if (axis) return axisRef(part, axis.origin, axis.direction)\n }\n throw new Error(`[cq-compat] axisRef: no circular edge found in part \"${part}\"`)\n}\n\n/** 对一组(应共面、闭合)的 XYZ 点拟合圆轴,返回原点(圆心投影)与方向(法向),非圆/退化返回 null。 */\nfunction fitCircleAxis(pts: [number, number, number][]): { origin: [number, number, number]; direction: [number, number, number] } | null {\n const n = pts.length\n if (n < 6) return null\n // 质心\n const c: [number, number, number] = [0, 0, 0]\n for (const p of pts) { c[0] += p[0]; c[1] += p[1]; c[2] += p[2] }\n c[0] /= n; c[1] /= n; c[2] /= n\n // 相邻段叉积之和 → 平面法向(闭环平面点稳定)\n let nx = 0, ny = 0, nz = 0\n for (let i = 0; i < n; i++) {\n const a = pts[i]\n const b = pts[(i + 1) % n]\n const ax = a[0] - c[0], ay = a[1] - c[1], az = a[2] - c[2]\n const bx = b[0] - c[0], by = b[1] - c[1], bz = b[2] - c[2]\n nx += ay * bz - az * by\n ny += az * bx - ax * bz\n nz += ax * by - ay * bx\n }\n const nl = Math.hypot(nx, ny, nz)\n if (!(nl > 1e-9) || !Number.isFinite(nl)) return null\n nx /= nl; ny /= nl; nz /= nl\n // 平面正交基\n let up: [number, number, number] = Math.abs(nz) < 0.9 ? [0, 0, 1] : [1, 0, 0]\n let ux = ny * up[2] - nz * up[1], uy = nz * up[0] - nx * up[2], uz = nx * up[1] - ny * up[0]\n let ul = Math.hypot(ux, uy, uz)\n if (!(ul > 1e-9)) {\n up = [1, 0, 0]\n ux = ny * up[2] - nz * up[1]; uy = nz * up[0] - nx * up[2]; uz = nx * up[1] - ny * up[0]\n ul = Math.hypot(ux, uy, uz)\n if (!(ul > 1e-9)) return null\n }\n const u: [number, number, number] = [ux / ul, uy / ul, uz / ul]\n const v: [number, number, number] = [ny * u[2] - nz * u[1], nz * u[0] - nx * u[2], nx * u[1] - ny * u[0]]\n // 投影到 2D\n const xs: number[] = []\n const ys: number[] = []\n for (const p of pts) {\n const dx = p[0] - c[0], dy = p[1] - c[1], dz = p[2] - c[2]\n xs.push(dx * u[0] + dy * u[1] + dz * u[2])\n ys.push(dx * v[0] + dy * v[1] + dz * v[2])\n }\n // 2D 最小二乘圆拟合(Kasa): a·xi + b·yi + c = -(xi²+yi²)\n let sxx = 0, sxy = 0, syy = 0, sx = 0, sy = 0, sR = 0, sRx = 0, sRy = 0\n for (let i = 0; i < n; i++) {\n const xi = xs[i], yi = ys[i], ri = xi * xi + yi * yi\n sxx += xi * xi; sxy += xi * yi; syy += yi * yi\n sx += xi; sy += yi; sR += ri\n sRx += ri * xi; sRy += ri * yi\n }\n const A = [\n [sxx, sxy, sx],\n [sxy, syy, sy],\n [sx, sy, n],\n ]\n const B = [-sRx, -sRy, -sR]\n const det = det3(A)\n if (!(Math.abs(det) > 1e-12)) return null\n const a = det3([[B[0], A[0][1], A[0][2]], [B[1], A[1][1], A[1][2]], [B[2], A[2][1], A[2][2]]]) / det\n const b = det3([[A[0][0], B[0], A[0][2]], [A[1][0], B[1], A[1][2]], [A[2][0], B[2], A[2][2]]]) / det\n const cc = det3([[A[0][0], A[0][1], B[0]], [A[1][0], A[1][1], B[1]], [A[2][0], A[2][1], B[2]]]) / det\n const r2 = a * a / 4 + b * b / 4 - cc\n if (!(r2 > 0) || !Number.isFinite(r2)) return null\n // 圆度校验:卡萨拟合有偏,用 RMS 过滤非圆边\n const R = Math.sqrt(r2)\n let rms = 0\n for (let i = 0; i < n; i++) {\n const dd = Math.hypot(xs[i] + a / 2, ys[i] + b / 2) - R\n rms += dd * dd\n }\n rms = Math.sqrt(rms / n)\n if (rms > R * 0.05) return null\n // 圆心回投到 3D\n const ox = c[0] + u[0] * (-a / 2) + v[0] * (-b / 2)\n const oy = c[1] + u[1] * (-a / 2) + v[1] * (-b / 2)\n const oz = c[2] + u[2] * (-a / 2) + v[2] * (-b / 2)\n if (![ox, oy, oz, nx, ny, nz].every(Number.isFinite)) return null\n return { origin: [ox, oy, oz], direction: [nx, ny, nz] }\n}\n\nfunction det3(m: number[][]): number {\n return (\n m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1]) -\n m[0][1] * (m[1][0] * m[2][2] - m[1][2] * m[2][0]) +\n m[0][2] * (m[1][0] * m[2][1] - m[1][1] * m[2][0])\n )\n}\n\n/**\n * constraintEx — 统一约束构造,覆盖 CQ 公共种类并映射到 faijs 类型面。\n *\n * 映射(对齐 global 求解器 consuming 的 AssemblyConstraint):\n * - 'Plane' → [mate](faceRef→plane)\n * - 'Axis' → [angle:180](纯方向反平行、无点项——CQ 2.8.0 `axis_cost` 缺省语义)\n * - 'Point' → [coincident](selector 为字面坐标 \"x,y,z\")\n * - 'Cylinder' → [concentric, coincident(point_on_line)](圆边解析轴)\n * - 'Distance' → [distance(value)](point-point 或 plane-plane)\n * - 'Fixed' → [fixed](aPart 锁定)\n * - 'Revolute' → [fixed](暂降级为锚定占位;旋转 DOF 后续走 joints 机制)\n *\n * @param aPart A 侧成员名。\n * @param aSelector A 侧面选择器字符串(如 \">Z[-2]\")。\n * @param aShape A 侧成员几何(真实 Shape 或借用视图)。\n * @param bPart B 侧成员名。\n * @param bSelector B 侧面选择器字符串。\n * @param bShape B 侧成员几何(真实 Shape 或借用视图)。\n * @param kind 约束种类(Plane/Axis/Point/Cylinder/Distance/Fixed/Revolute)。\n * @param param 可选参数(Distance 的距离值等)。\n * @returns AssemblyConstraint[](Cylinder 拆两条,其余单条)\n */\nexport async function constraintEx(\n aPart: string,\n aSelector: string,\n aShape: Shape | null,\n bPart: string,\n bSelector: string,\n bShape: Shape | null,\n kind: AssemblyKind,\n param?: number,\n): Promise<AssemblyConstraint[]> {\n switch (kind) {\n case 'Plane': {\n if (!aShape || !bShape) throw new Error(`constraintEx Plane: shapes required`)\n // 提升边界归一:实参可能是借用视图(见 asBrepShape 注释)。faceRef 内部\n // 亦归一,入口再归一保证直接调用路径(不经 compatOp 提升)行为一致。\n const a = await faceRef(aPart, aSelector, asBrepShape(aShape))\n const b = await faceRef(bPart, bSelector, asBrepShape(bShape))\n return [{ type: 'mate', a, b } as AssemblyConstraint]\n }\n case 'Axis': {\n if (!aShape || !bShape) throw new Error(`constraintEx Axis: shapes required`)\n const a = await faceRef(aPart, aSelector, asBrepShape(aShape))\n const b = await faceRef(bPart, bSelector, asBrepShape(bShape))\n // GOTCHA (2026-09-17,对照 CQ 2.8.0 `occ_impl/solver.py` 标定):CQ 独立 Axis 约束是\n // **纯方向约束**——`ConstraintInvariants[\"Axis\"]` 只收两个 gp_Dir(无点项),\n // `axis_cost` 缺省 `val = pi`(反平行)。此前误映射为 'align'(同向 val=0 + 面心\n // 重合)属双重分歧:真实 e2e 的 c4 被拖向 mb z=-1(参考 +6.1),且凭空多出一\n // 个 CQ 没有的面心重合项。'angle' 在求解器里正是纯方向项(global-solver.ts\n // case 'angle':axis 成本、无点项),value 单位 deg(180 = 反平行)。\n return [{ type: 'angle', value: 180, a, b } as AssemblyConstraint]\n }\n case 'Point': {\n const pa = parseCoords(aSelector)\n const pb = parseCoords(bSelector)\n if (!pa || !pb) throw new Error(`constraintEx Point: selectors must be coords \"x,y,z\"`)\n return [{ type: 'coincident', a: pointRef(aPart, pa), b: pointRef(bPart, pb) } as AssemblyConstraint]\n }\n case 'Cylinder': {\n if (!aShape || !bShape) throw new Error(`constraintEx Cylinder: shapes required`)\n const aAxis = await resolveAxisRef(aPart, aShape)\n const bAxis = await resolveAxisRef(bPart, bShape)\n return [\n { type: 'concentric', a: aAxis, b: bAxis } as AssemblyConstraint,\n { type: 'coincident', a: aAxis, b: bAxis } as AssemblyConstraint,\n ]\n }\n case 'Distance': {\n const pa = parseCoords(aSelector)\n const pb = parseCoords(bSelector)\n const a = pa\n ? pointRef(aPart, pa)\n : await faceRef(aPart, aSelector, aShape!)\n const b = pb\n ? pointRef(bPart, pb)\n : await faceRef(bPart, bSelector, bShape!)\n const value = param ?? 0\n return [{ type: 'distance', value, a, b } as AssemblyConstraint]\n }\n case 'Fixed':\n return [{ type: 'fixed', part: aPart } as AssemblyConstraint]\n case 'Revolute':\n // 暂降级为锚定占位(旋转 DOF 留待后续 joints 机制)\n return [{ type: 'fixed', part: aPart } as AssemblyConstraint]\n }\n}\n\n/**\n * buildAssembly\n * @param name - string\n * @param members - Array<{ name: string; shape: Shape; color?: RGB }>\n * @param constraints - AssemblyConstraint[]\n * @param opts - optional: { solver?: 'chain' | 'global' };cq-compat = CadQuery 兼容,默认 'global'\n * @returns CompoundShape\n */\nexport function buildAssembly(\n name: string,\n members: Array<{ name: string; shape: Shape; color?: RGB }>,\n constraints: AssemblyConstraint[],\n opts?: { solver?: 'chain' | 'global' },\n): CompoundShape {\n // 提升边界归一:经 runtime.execute 时 members[].shape 是借用 brepjs 视图\n // (borrowDeep 产物),不是 faijs Shape。compound 的 children 必须持有 mesh\n // (引擎 applyTransform 做顶点烘焙)+ BREP 身份槽(STEP 导出/刚体变换读\n // slot.solid),借用视图两者皆无 → 必须还原为真实 Shape 再进 assembly。\n const shapes = members.map((m) => asBrepShape(m.shape))\n const memberNames = members.map((m) => m.name)\n const memberColors: Record<string, [number, number, number]> = {}\n for (const m of members) {\n if (m.color) memberColors[m.name] = m.color\n }\n\n // cq-compat 是 CadQuery 兼容层:默认走 global 求解器(语义对齐 CQ solver.py)。\n // 需要旧 chain 行为时可显式 opts.solver='chain'。\n const solver = opts?.solver ?? 'global'\n\n const compound = cad.assembly({\n name,\n members: shapes,\n memberNames,\n constraints,\n memberColors,\n solver,\n }) as unknown as CompoundShape\n\n // CadQuery's Assembly.save() solves constraints implicitly before export —\n // mirror that here so CLI STEP export sees the solved part poses.\n // GOTCHA (2026-09-18):引擎只有 direct-executor 路径消费 pending transforms\n // (applyPendingAssemblyTransforms);CLI brep 模块路径无人消费 → 登记 pending\n // 也没用,成员停在恒等位姿。因此这里直接 solveDetailed() 拿到 transforms,\n // 在库侧把位姿烘焙进成员:mesh 顶点原地变换 + BREP slot.solid 刚体变换\n // (与 direct-executor 同语义)。behavior.solve/compound.solve 的 pending 登记\n // 保留(direct 路径仍走引擎烘焙),但本函数不再依赖它。\n const behavior = getSlot(compound)?.behavior as\n | { memberNames?: string[]; solveDetailed?: () => { transforms: Array<{ index: number; quaternion: [number, number, number, number]; pivot: [number, number, number]; translation: [number, number, number]; rotationMatrix: number[] }> } }\n | undefined\n const transforms = behavior?.solveDetailed?.().transforms ?? []\n // CQ 语义对齐:无约束成员(如 assemb.py 里仅 .add 的 slide_top)在 CQ 求解器\n // 中固定在初始位姿(不被拉入最小化);我方 global 求解器会给自由成员漂移解,\n // 烘焙前按「是否被约束引用」过滤,未引用成员保持恒等。\n const referenced = new Set<string>()\n for (const c of constraints) {\n // StructuralConstraint 形态是 { a: EntityRef, b: EntityRef }(EntityRef.part\n // = 成员名);cq-compat 的 constraint() 只产出该形态。FaceMateConstraint 无\n // a/b,用 in 收窄跳过。\n if ('a' in c && 'b' in c) {\n for (const ref of [c.a, c.b] as Array<{ part?: string }>) {\n if (ref && typeof ref.part === 'string') referenced.add(ref.part)\n }\n }\n }\n const baked = transforms.filter((t) => referenced.has(behavior?.memberNames?.[t.index] ?? ''))\n if (baked.length > 0) {\n const kernel = getBackends().kernel.brep as BrepEngineApi | null\n const children = (compound as unknown as { children?: Shape[] }).children ?? []\n for (const t of baked) {\n const member = children[t.index]\n if (!member || typeof member !== 'object') continue\n // mesh 顶点原地变换(保留对象引用,ctx 与 compound.children 同步看到变更)\n Object.assign(member, applyTransform(member, t.quaternion, t.pivot, t.translation, t.rotationMatrix))\n // BREP 刚体变换:新 solid 写回身份槽(STEP 导出读 slot.solid)。\n // GOTCHA:旧 solid 句柄**不能 release**——solidCache(partName 键)仍指向\n // 它,库侧无法同步该缓存(setSolidHook 是宿主注入),release 后拓扑构建\n // 读到悬空句柄报 INVALID_SHAPE_ID;保留旧句柄仅浪费少量内存。\n if (kernel) {\n const solid = brepOf(member) as BrepHandle | undefined\n if (solid) {\n const transformed = applyTransformBrep(kernel, solid, t.quaternion, t.pivot, t.translation)\n ensureSlot(member).solid = transformed\n }\n }\n }\n }\n return compound\n}\n\n/**\n * Color\n * @param r - number\n * @param g - number\n * @param b - number\n * @param _a - number\n * @returns RGB\n */\nexport function Color(r: number, g: number, b: number, _a?: number): RGB {\n return [r, g, b]\n}\n"]}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @faicad/cq-compat/browser — browser-safe entry for the CadQuery compatibility layer.
3
+ *
4
+ * Unlike the package root (`./index`), this entry does NOT re-export the STEP /
5
+ * assembly comparison helpers (`step-compare`, `assembly-compare`), which import
6
+ * `node:fs` and cannot be bundled into a browser (Vite/Rollup would fail on the
7
+ * builtin module). The faijs demo libLoader imports this entry statically and
8
+ * registers it under the `@faicad/cq-compat` specifier, so `.fai.js` scripts keep
9
+ * writing `import * as cq from '@faicad/cq-compat'`.
10
+ */
11
+ export * from './workplane.js';
12
+ export * from './assembly.js';
13
+ //# sourceMappingURL=browser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,cAAc,aAAa,CAAA;AAC3B,cAAc,YAAY,CAAA"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @faicad/cq-compat/browser — browser-safe entry for the CadQuery compatibility layer.
3
+ *
4
+ * Unlike the package root (`./index`), this entry does NOT re-export the STEP /
5
+ * assembly comparison helpers (`step-compare`, `assembly-compare`), which import
6
+ * `node:fs` and cannot be bundled into a browser (Vite/Rollup would fail on the
7
+ * builtin module). The faijs demo libLoader imports this entry statically and
8
+ * registers it under the `@faicad/cq-compat` specifier, so `.fai.js` scripts keep
9
+ * writing `import * as cq from '@faicad/cq-compat'`.
10
+ */
11
+ export * from './workplane.js';
12
+ export * from './assembly.js';
13
+ //# sourceMappingURL=browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,cAAc,aAAa,CAAA;AAC3B,cAAc,YAAY,CAAA","sourcesContent":["/**\n * @faicad/cq-compat/browser — browser-safe entry for the CadQuery compatibility layer.\n *\n * Unlike the package root (`./index`), this entry does NOT re-export the STEP /\n * assembly comparison helpers (`step-compare`, `assembly-compare`), which import\n * `node:fs` and cannot be bundled into a browser (Vite/Rollup would fail on the\n * builtin module). The faijs demo libLoader imports this entry statically and\n * registers it under the `@faicad/cq-compat` specifier, so `.fai.js` scripts keep\n * writing `import * as cq from '@faicad/cq-compat'`.\n */\nexport * from './workplane'\nexport * from './assembly'\n"]}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Shared harness for the E1–E4 gear-extension ops.
3
+ *
4
+ * These ops call the occt-wasm kernel directly via `getKernel()` (the native
5
+ * singleton that `registerOcctBrepEngine()` initializes) and wrap results with
6
+ * `fromHandle`. `fromHandle` needs `getBackends().kernel.brep` to be a MESHABLE
7
+ * kernel — the raw occt-wasm `OcctKernel` exposes `meshShape`, so we wire it
8
+ * straight into `configureBackends`. This is intentionally the SAME native
9
+ * instance the ops use, so handles stay consistent (no second kernel, no
10
+ * `createRuntime`, which only lazily builds its brep chain inside `execute`).
11
+ *
12
+ * This file is NOT a test (no `*.test.ts`); it is imported by the E1–E4 specs.
13
+ */
14
+ import { brepOf } from '@faicad/faijs/shape';
15
+ export { brepOf };
16
+ import type { OcctKernel } from 'occt-wasm';
17
+ import type { Shape } from '@faicad/faijs/mesh/types';
18
+ import type { Workplane } from './workplane.js';
19
+ /**
20
+ * Initialise the native occt-wasm kernel for the E1–E4 specs.
21
+ *
22
+ * Calls `registerOcctBrepEngine()` (which boots the kernel singleton and
23
+ * registers the OCCT engine) and then wires that SAME instance into the
24
+ * backend registry via `configureBackends`, so `fromHandle` can resolve a
25
+ * meshable kernel. Must be awaited in `beforeAll` before any op is invoked.
26
+ *
27
+ * @returns a promise that resolves once the kernel and backends are ready
28
+ */
29
+ export declare function setupNativeKernel(): Promise<void>;
30
+ /**
31
+ * Return the shared native occt-wasm kernel singleton.
32
+ *
33
+ * The same instance the E1–E4 ops obtain internally via `getKernel()`, so
34
+ * fixtures built here and op outputs share one handle space.
35
+ *
36
+ * @returns the live `OcctKernel` instance (valid after {@link setupNativeKernel})
37
+ */
38
+ export declare function kernel(): OcctKernel;
39
+ /**
40
+ * Build a minimal valid root `Workplane` without touching the `cad.*` backend.
41
+ *
42
+ * Defaults to the XY plane at the origin (normal +Z, xDir +X, yDir +Y) with no
43
+ * shape and no pending wires; pass `over` to override any field (e.g.
44
+ * `{ shape }` or `{ normal, origin }`).
45
+ *
46
+ * @param over - partial overrides merged onto the default workplane
47
+ * @returns a `Workplane` literal suitable as the first argument of an op
48
+ */
49
+ export declare function mkWP(over?: Partial<Workplane>): Workplane;
50
+ /**
51
+ * Axis-aligned bounding box of a shape, in the kernel's field naming.
52
+ *
53
+ * Mirrors the `BoundingBox` record returned by the native
54
+ * `getBoundingBox` call (all six min/max fields, no `minX`-style aliases).
55
+ */
56
+ export type BBox = {
57
+ xmin: number;
58
+ xmax: number;
59
+ ymin: number;
60
+ ymax: number;
61
+ zmin: number;
62
+ zmax: number;
63
+ };
64
+ /**
65
+ * Compute the axis-aligned bounding box of a shape through the native kernel.
66
+ *
67
+ * @param shape - a faijs `Shape` carrying a BREP handle (see `brepOf`)
68
+ * @returns the six-field bounding box
69
+ */
70
+ export declare function bbox(shape: Shape): BBox;
71
+ /**
72
+ * Surface area of a face (or total area of a shell/solid), via the native
73
+ * kernel's `getSurfaceArea`.
74
+ *
75
+ * @param shape - a faijs `Shape` carrying a BREP handle (see `brepOf`)
76
+ * @returns the area in model units squared
77
+ */
78
+ export declare function area(shape: Shape): number;
79
+ //# sourceMappingURL=gear-test-harness.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gear-test-harness.d.ts","sourceRoot":"","sources":["../src/gear-test-harness.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAC5C,OAAO,EAAE,MAAM,EAAE,CAAA;AACjB,OAAO,KAAK,EAAE,UAAU,EAAe,MAAM,WAAW,CAAA;AACxD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAA;AACrD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAE5C;;;;;;;;;GASG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CA0BvD;AAED;;;;;;;GAOG;AACH,wBAAgB,MAAM,IAAI,UAAU,CAEnC;AAED;;;;;;;;;GASG;AACH,wBAAgB,IAAI,CAAC,IAAI,GAAE,OAAO,CAAC,SAAS,CAAM,GAAG,SAAS,CAgB7D;AAED;;;;;GAKG;AACH,MAAM,MAAM,IAAI,GAAG;IACjB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED;;;;;GAKG;AACH,wBAAgB,IAAI,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAEvC;AAED;;;;;;GAMG;AACH,wBAAgB,IAAI,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAEzC"}