@faicad/faijs 0.17.0 → 0.18.2

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 (84) hide show
  1. package/dist/api/api-namespace.js +2 -2
  2. package/dist/api/api-namespace.js.map +1 -1
  3. package/dist/api/boolean.d.ts.map +1 -1
  4. package/dist/api/boolean.js +64 -26
  5. package/dist/api/boolean.js.map +1 -1
  6. package/dist/api/brep-mirror/booleanFns.d.ts.map +1 -1
  7. package/dist/api/brep-mirror/booleanFns.js +11 -6
  8. package/dist/api/brep-mirror/booleanFns.js.map +1 -1
  9. package/dist/api/brep-mirror/topologyFns.d.ts.map +1 -1
  10. package/dist/api/brep-mirror/topologyFns.js +4 -1
  11. package/dist/api/brep-mirror/topologyFns.js.map +1 -1
  12. package/dist/api/chamfer.d.ts +12 -8
  13. package/dist/api/chamfer.d.ts.map +1 -1
  14. package/dist/api/chamfer.js +52 -23
  15. package/dist/api/chamfer.js.map +1 -1
  16. package/dist/api/extrude.d.ts.map +1 -1
  17. package/dist/api/extrude.js +69 -15
  18. package/dist/api/extrude.js.map +1 -1
  19. package/dist/api/generated/operations.js +5 -5
  20. package/dist/api/generated/operations.js.map +1 -1
  21. package/dist/api/generated/script-face-manifest.js +12 -12
  22. package/dist/api/generated/script-face-manifest.js.map +1 -1
  23. package/dist/api/generated/sketching.js +1 -1
  24. package/dist/api/generated/sketching.js.map +1 -1
  25. package/dist/api/generated/topology.js +7 -7
  26. package/dist/api/generated/topology.js.map +1 -1
  27. package/dist/api/index.d.ts +2 -1
  28. package/dist/api/index.d.ts.map +1 -1
  29. package/dist/api/index.js +1 -1
  30. package/dist/api/index.js.map +1 -1
  31. package/dist/api/internal/profile-wire.d.ts +3 -3
  32. package/dist/api/internal/profile-wire.js +3 -3
  33. package/dist/api/internal/profile-wire.js.map +1 -1
  34. package/dist/api/loft.d.ts +3 -3
  35. package/dist/api/loft.js +3 -3
  36. package/dist/api/loft.js.map +1 -1
  37. package/dist/api/profile.d.ts +93 -0
  38. package/dist/api/profile.d.ts.map +1 -0
  39. package/dist/api/profile.js +276 -0
  40. package/dist/api/profile.js.map +1 -0
  41. package/dist/api/replicate.d.ts.map +1 -1
  42. package/dist/api/replicate.js +15 -14
  43. package/dist/api/replicate.js.map +1 -1
  44. package/dist/api/surface/arg-spec.d.ts.map +1 -1
  45. package/dist/api/surface/arg-spec.js +20 -15
  46. package/dist/api/surface/arg-spec.js.map +1 -1
  47. package/dist/api/sweep.d.ts +2 -2
  48. package/dist/api/sweep.js +2 -2
  49. package/dist/api/sweep.js.map +1 -1
  50. package/dist/api/thicken.d.ts +3 -3
  51. package/dist/api/thicken.js +3 -3
  52. package/dist/api/thicken.js.map +1 -1
  53. package/dist/api/transform.d.ts +12 -8
  54. package/dist/api/transform.d.ts.map +1 -1
  55. package/dist/api/transform.js +62 -32
  56. package/dist/api/transform.js.map +1 -1
  57. package/dist/brep/engine/adapters/brepkit.d.ts.map +1 -1
  58. package/dist/brep/engine/adapters/brepkit.js +28 -1
  59. package/dist/brep/engine/adapters/brepkit.js.map +1 -1
  60. package/dist/brep/engine/adapters/occt.d.ts.map +1 -1
  61. package/dist/brep/engine/adapters/occt.js +12 -0
  62. package/dist/brep/engine/adapters/occt.js.map +1 -1
  63. package/dist/brep/engine/types.d.ts +1 -1
  64. package/dist/brep/engine/types.d.ts.map +1 -1
  65. package/dist/brep/engine/types.js.map +1 -1
  66. package/dist/brepkit-kernel/brepkitKernel.d.ts.map +1 -1
  67. package/dist/brepkit-kernel/brepkitKernel.js +463 -91
  68. package/dist/brepkit-kernel/brepkitKernel.js.map +1 -1
  69. package/dist/brepkit-kernel/brepkitWasm.d.ts +2 -1
  70. package/dist/brepkit-kernel/brepkitWasm.d.ts.map +1 -1
  71. package/dist/brepkit-kernel/brepkitWasm.js +48 -12
  72. package/dist/brepkit-kernel/brepkitWasm.js.map +1 -1
  73. package/dist/brepkit-kernel/multi-version-test.d.ts +40 -0
  74. package/dist/brepkit-kernel/multi-version-test.d.ts.map +1 -0
  75. package/dist/brepkit-kernel/multi-version-test.js +89 -0
  76. package/dist/brepkit-kernel/multi-version-test.js.map +1 -0
  77. package/dist/lang/symbol-table.generated.d.ts +1 -1
  78. package/dist/lang/symbol-table.generated.js +1 -1
  79. package/dist/lang/symbol-table.generated.js.map +1 -1
  80. package/dist/occt-kernel/occtKernel.d.ts +3 -1
  81. package/dist/occt-kernel/occtKernel.d.ts.map +1 -1
  82. package/dist/occt-kernel/occtKernel.js +73 -29
  83. package/dist/occt-kernel/occtKernel.js.map +1 -1
  84. package/package.json +2 -3
@@ -0,0 +1,276 @@
1
+ /**
2
+ * stdlib profile — 从 2D 轮廓构面(creator 函数,无输入,brep-only)。
3
+ *
4
+ * 用途:faijs 此前没有「从 2D 轮廓构造 planar face」的能力,导致草图轮廓无法喂给
5
+ * extrude/revolve。本 op 接收 2D 轮廓(线段 + 圆弧),在 z=0 平面用 OCCT 构面:
6
+ * makeLineEdge/makeArcEdge → makeWire → makeFace(+ addHolesInFace)。
7
+ *
8
+ * 设计:
9
+ * - 输入:{ contours: ProfileLoop[] },每个 loop = 有序 segments(line / arc,z=0)。
10
+ * - 环语义:嵌套 = 孔,不相交 = 独立岛(多岛 → face 的 compound),见 buildProfileShape。
11
+ * - 圆弧:用起点/中点/终点三点的 makeArcEdge;整圆(sweep≈2π)拆成两段弧。
12
+ * - 输出:Shape(mesh 三角化 + 句柄登记)。brep-only(下游 extrude/revolve 亦 brep-only)。
13
+ *
14
+ * 坐标系:输入 2D 点即 (x, y, 0),法向 +Z;草图在 Body 局部系内的定位由调用方(fcstd 端口)
15
+ * 在轮廓坐标里预先变换,或由下游特征的 Placement 承担。
16
+ */
17
+ import { getBrepApi } from '../brep/handle-bridge.js';
18
+ import { solidToShape } from '../brep/brep-ops.js';
19
+ import { fromBrep, fromBrepCurve } from '../shape.js';
20
+ import { defineOp } from '../sdk.js';
21
+ // ── 参数自校验 ──
22
+ /**
23
+ * Validate profile parameters: `contours` must be a non-empty array of loops,
24
+ * each with at least one segment.
25
+ * @param params the raw profile operation parameters.
26
+ */
27
+ export function assertProfileParams(params) {
28
+ const contours = params.contours;
29
+ if (!Array.isArray(contours) || contours.length === 0) {
30
+ throw new Error('E_PROFILE_NO_CONTOURS: profile requires at least one contour');
31
+ }
32
+ for (const loop of contours) {
33
+ if (!loop || typeof loop !== 'object' || !Array.isArray(loop.segments)) {
34
+ throw new Error('E_PROFILE_BAD_LOOP: each contour must have a segments array');
35
+ }
36
+ if (loop.segments.length === 0) {
37
+ throw new Error('E_PROFILE_EMPTY_LOOP: a contour must have at least one segment');
38
+ }
39
+ }
40
+ }
41
+ /**
42
+ * 单环带符号面积(对每段做有向面积积分,而非只用段起点 shoelace)。
43
+ *
44
+ * 直线段:1/2 (x1·y2 − x2·y1)。
45
+ * 圆弧段:1/2 ∫(x dy − y dx) 的解析解 = 1/2 [r²·sweep + cx·r(sin a1 − sin a0) − cy·r(cos a1 − cos a0)]。
46
+ * 整圆(单段弧、起终点重合)由此得到 πr²,不再是 0——否则「整圆 + 方孔」会把孔误判成外环。
47
+ */
48
+ function loopSignedArea(loop) {
49
+ let a = 0;
50
+ for (const seg of loop.segments) {
51
+ if (seg.kind === 'line') {
52
+ a += (seg.x1 * seg.y2 - seg.x2 * seg.y1) / 2;
53
+ continue;
54
+ }
55
+ let sweep = seg.endAngle - seg.startAngle;
56
+ while (sweep <= 0)
57
+ sweep += 2 * Math.PI;
58
+ while (sweep > 2 * Math.PI)
59
+ sweep -= 2 * Math.PI;
60
+ const { cx, cy, radius: r, startAngle: a0 } = seg;
61
+ const a1 = a0 + sweep;
62
+ a += 0.5 * (r * r * sweep + cx * r * (Math.sin(a1) - Math.sin(a0)) - cy * r * (Math.cos(a1) - Math.cos(a0)));
63
+ }
64
+ return a;
65
+ }
66
+ /** 圆弧 → 一条或两条 makeArcEdge(整圆拆分)。 */
67
+ function arcToHandles(kernel, seg) {
68
+ const { cx, cy, radius, startAngle, endAngle, ccw = true } = seg;
69
+ // GOTCHA(2026-09-25,A3 FCBL_tree_entourage):ccw 必须参与弧的几何方向。
70
+ // makeArcEdge 按「起点-中点-终点」三点定弧,旧实现一律取 CCW 中点
71
+ // ((start+end)/2 归一化到 (0,2π]),ccw:false 的弧被画成 CCW **长弧**(补角)。
72
+ // 实测后果:长弧穿过旋转轴 → revolve 产物退化(bbox NaN)→ BRepMesh 挂死
73
+ // (进程无声死亡);正确 CW 短弧下内核 revolve 仅 ~19ms。
74
+ let sweep;
75
+ let midAngle;
76
+ if (ccw) {
77
+ sweep = endAngle - startAngle;
78
+ while (sweep <= 0)
79
+ sweep += 2 * Math.PI;
80
+ while (sweep > 2 * Math.PI)
81
+ sweep -= 2 * Math.PI;
82
+ midAngle = startAngle + sweep / 2;
83
+ }
84
+ else {
85
+ // 顺时针:从 startAngle 递减到 endAngle,扫角取反向归一化
86
+ sweep = startAngle - endAngle;
87
+ while (sweep <= 0)
88
+ sweep += 2 * Math.PI;
89
+ while (sweep > 2 * Math.PI)
90
+ sweep -= 2 * Math.PI;
91
+ midAngle = startAngle - sweep / 2;
92
+ }
93
+ const makeOne = (a0, am, a1) => {
94
+ const start = { x: cx + radius * Math.cos(a0), y: cy + radius * Math.sin(a0), z: 0 };
95
+ const m = { x: cx + radius * Math.cos(am), y: cy + radius * Math.sin(am), z: 0 };
96
+ const end = { x: cx + radius * Math.cos(a1), y: cy + radius * Math.sin(a1), z: 0 };
97
+ return kernel.makeArcEdge(start, m, end);
98
+ };
99
+ // 整圆(sweep≈2π):拆成两段半圆,避免 makeArcEdge 起点≈终点退化
100
+ if (sweep >= 2 * Math.PI - 1e-9) {
101
+ const half = 2 * Math.PI / 2;
102
+ const dir = ccw ? 1 : -1;
103
+ return [
104
+ makeOne(startAngle, startAngle + dir * half / 2, startAngle + dir * half),
105
+ makeOne(startAngle + dir * half, startAngle + dir * (half + half / 2), startAngle + dir * 2 * Math.PI),
106
+ ];
107
+ }
108
+ return [makeOne(startAngle, midAngle, endAngle)];
109
+ }
110
+ /** 单环 → wire handle(仅构面,不释放中间句柄,遵循现有惯例)。 */
111
+ function loopToWire(kernel, loop) {
112
+ const edges = [];
113
+ for (const seg of loop.segments) {
114
+ if (seg.kind === 'line') {
115
+ edges.push(kernel.makeLineEdge({ x: seg.x1, y: seg.y1, z: 0 }, { x: seg.x2, y: seg.y2, z: 0 }));
116
+ }
117
+ else {
118
+ // 极小扫角(退化弧)→ 退化为线段,避免构边失败
119
+ let sweep = seg.endAngle - seg.startAngle;
120
+ while (sweep <= 0)
121
+ sweep += 2 * Math.PI;
122
+ while (sweep > 2 * Math.PI)
123
+ sweep -= 2 * Math.PI;
124
+ if (sweep < 1e-9) {
125
+ edges.push(kernel.makeLineEdge({ x: seg.x1, y: seg.y1, z: 0 }, { x: seg.x2, y: seg.y2, z: 0 }));
126
+ }
127
+ else {
128
+ edges.push(...arcToHandles(kernel, seg));
129
+ }
130
+ }
131
+ }
132
+ return kernel.makeWire(edges);
133
+ }
134
+ /** 环 → 2D 采样多边形(直线取端点、弧等角采样),用于环间包含性判定。 */
135
+ function loopToPolygon(loop) {
136
+ const pts = [];
137
+ for (const seg of loop.segments) {
138
+ if (seg.kind === 'line') {
139
+ pts.push({ x: seg.x1, y: seg.y1 });
140
+ continue;
141
+ }
142
+ let sweep = seg.endAngle - seg.startAngle;
143
+ while (sweep <= 0)
144
+ sweep += 2 * Math.PI;
145
+ while (sweep > 2 * Math.PI)
146
+ sweep -= 2 * Math.PI;
147
+ const n = Math.max(8, Math.ceil((sweep / (2 * Math.PI)) * 32));
148
+ for (let k = 0; k < n; k++) {
149
+ const a = seg.startAngle + (sweep * k) / n;
150
+ pts.push({ x: seg.cx + seg.radius * Math.cos(a), y: seg.cy + seg.radius * Math.sin(a) });
151
+ }
152
+ }
153
+ return pts;
154
+ }
155
+ /** 射线法:点是否在多边形内(采样多边形足够密,顶点/边界角落情形由环间不共边保证不出现)。 */
156
+ function polygonContains(poly, px, py) {
157
+ let inside = false;
158
+ for (let i = 0, j = poly.length - 1; i < poly.length; j = i++) {
159
+ const xi = poly[i].x;
160
+ const yi = poly[i].y;
161
+ const xj = poly[j].x;
162
+ const yj = poly[j].y;
163
+ if (yi > py !== yj > py && px < ((xj - xi) * (py - yi)) / (yj - yi) + xi)
164
+ inside = !inside;
165
+ }
166
+ return inside;
167
+ }
168
+ /**
169
+ * BREP 路径:2D 轮廓集合 → planar face 集合。
170
+ *
171
+ * GOTCHA(2026-09-26,Beds part16/39):环语义是「**嵌套 = 孔,不相交 = 独立岛**」
172
+ * (与 FreeCAD 草图一致),不是「面积最大者当外环、其余全当孔」。旧实现把双岛轮廓的
173
+ * 第二个岛判成「洞外面」→ `addHolesInFace` 收到与外环不相交的 wire → 构面退化
174
+ * (7 面、volume 0)。多岛产物 = compound(每岛一面、各带自己的孔),下游
175
+ * `cad.extrude` 对 compound 输入逐面挤出(kernel MakePrism 收复合形状)。
176
+ *
177
+ * @param params - 轮廓环集合与产物形态。
178
+ * @returns Shape(单岛为 face;多岛为 face 的 compound;`as:'wire'` 为 1D 曲线)。
179
+ */
180
+ export function buildProfileShape(params) {
181
+ const kernel = getBrepApi();
182
+ const as = params.as ?? 'face';
183
+ const loops = params.contours.map((loop) => ({ loop, area: Math.abs(loopSignedArea(loop)) }));
184
+ // 包含分类:每个环的直接父环 = 面积最小的严格包含它的环;深度偶数 = 岛,奇数 = 父环的孔。
185
+ const polys = loops.map((l) => loopToPolygon(l.loop));
186
+ const parent = new Array(loops.length).fill(-1);
187
+ for (let i = 0; i < loops.length; i++) {
188
+ const probe = polys[i][0];
189
+ for (let j = 0; j < loops.length; j++) {
190
+ if (i === j || loops[j].area <= loops[i].area)
191
+ continue;
192
+ if (!polygonContains(polys[j], probe.x, probe.y))
193
+ continue;
194
+ if (parent[i] === -1 || loops[j].area < loops[parent[i]].area)
195
+ parent[i] = j;
196
+ }
197
+ }
198
+ const depthOf = (i) => {
199
+ let d = 0;
200
+ let cur = i;
201
+ while (parent[cur] !== -1) {
202
+ d++;
203
+ cur = parent[cur];
204
+ }
205
+ return d;
206
+ };
207
+ const islands = [];
208
+ const holesOf = new Map();
209
+ for (let i = 0; i < loops.length; i++) {
210
+ if (depthOf(i) % 2 === 0)
211
+ islands.push(i);
212
+ else {
213
+ const p = parent[i];
214
+ const arr = holesOf.get(p);
215
+ if (arr)
216
+ arr.push(i);
217
+ else
218
+ holesOf.set(p, [i]);
219
+ }
220
+ }
221
+ // 'wire' 形态:只交最大岛的外环 wire(1D 曲线),不构面 —— 供扫掠族作 spine。
222
+ if (as === 'wire') {
223
+ let outer = islands[0];
224
+ for (const isl of islands) {
225
+ if (loops[isl].area > loops[outer].area)
226
+ outer = isl;
227
+ }
228
+ const wire = loopToWire(kernel, loops[outer].loop);
229
+ return fromBrepCurve(solidToShape(kernel, wire), { solid: wire });
230
+ }
231
+ // 每岛一面(岛环为外环,直接子环为孔)
232
+ const faces = [];
233
+ for (const isl of islands) {
234
+ const wire = loopToWire(kernel, loops[isl].loop);
235
+ const face = kernel.makeFace(wire);
236
+ const holes = holesOf.get(isl);
237
+ if (holes && holes.length > 0) {
238
+ const holeWires = holes.map((h) => loopToWire(kernel, loops[h].loop));
239
+ const faced = kernel.addHolesInFace(face, holeWires);
240
+ kernel.release(face);
241
+ faces.push(faced);
242
+ }
243
+ else {
244
+ faces.push(face);
245
+ }
246
+ }
247
+ if (faces.length === 1) {
248
+ const f = faces[0];
249
+ return fromBrep(solidToShape(kernel, f), { solid: f });
250
+ }
251
+ const compound = kernel.makeCompound(faces);
252
+ return fromBrep(solidToShape(kernel, compound), { solid: compound });
253
+ }
254
+ /**
255
+ * 从 2D 轮廓构造平面(creator,无输入)。仅 BREP 可用。
256
+ * @group 创建
257
+ * @inputs 0
258
+ * @async false
259
+ * @qual ok
260
+ * @name profile
261
+ * @returns Shape 平面几何(mesh 三角化 + BREP 句柄);`as:'wire'` 时返回 1D 曲线(kind:'curve')。
262
+ * @param params.contours - 有序 2D 轮廓(线段/圆弧;外环 + 孔)。type:ProfileLoop[] required:true
263
+ * @param params.as - 产物形态:'face'(默认)构面;'wire' 只交外环 wire(1D 曲线)。type:'face'|'wire' required:false
264
+ * @example
265
+ * const f = cad.profile({ contours: [{ segments: [{ kind:'line', x1:0,y1:0,x2:10,y2:0 }, ...] }] })
266
+ * const w = cad.profile({ contours: [{ segments: [{ kind:'line', x1:0,y1:0,x2:10,y2:0 }, ...] }], as: 'wire' })
267
+ */
268
+ export const profile = defineOp({
269
+ capabilities: ['directEdit'],
270
+ brep(params) {
271
+ assertProfileParams(params);
272
+ return buildProfileShape(params);
273
+ },
274
+ naming: { kind: 'construct', newFaces: { via: 'explicit', vocab: [] } },
275
+ });
276
+ //# sourceMappingURL=profile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile.js","sourceRoot":"","sources":["../../src/api/profile.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * stdlib profile — 从 2D 轮廓构面(creator 函数,无输入,brep-only)。\n *\n * 用途:faijs 此前没有「从 2D 轮廓构造 planar face」的能力,导致草图轮廓无法喂给\n * extrude/revolve。本 op 接收 2D 轮廓(线段 + 圆弧),在 z=0 平面用 OCCT 构面:\n * makeLineEdge/makeArcEdge → makeWire → makeFace(+ addHolesInFace)。\n *\n * 设计:\n * - 输入:{ contours: ProfileLoop[] },每个 loop = 有序 segments(line / arc,z=0)。\n * - 环语义:嵌套 = 孔,不相交 = 独立岛(多岛 → face 的 compound),见 buildProfileShape。\n * - 圆弧:用起点/中点/终点三点的 makeArcEdge;整圆(sweep≈2π)拆成两段弧。\n * - 输出:Shape(mesh 三角化 + 句柄登记)。brep-only(下游 extrude/revolve 亦 brep-only)。\n *\n * 坐标系:输入 2D 点即 (x, y, 0),法向 +Z;草图在 Body 局部系内的定位由调用方(fcstd 端口)\n * 在轮廓坐标里预先变换,或由下游特征的 Placement 承担。\n */\n\nimport type { Shape } from '../mesh/types'\nimport type { BrepEngineApi } from '../brep/engine/primitives'\nimport { getBrepApi } from '../brep/handle-bridge'\nimport { solidToShape } from '../brep/brep-ops'\nimport { fromBrep, fromBrepCurve } from '../shape'\nimport { defineOp } from '../sdk'\nimport type { Provenance } from '../topology/naming/lineage'\n\n// ── 参数形状(与 fcstd Contour 结构相同,避免引擎依赖端口层)──\n\n/** 直线段(2D,z=0;端点为绝对坐标)。 */\nexport interface ProfileLineSeg {\n kind: 'line'\n x1: number\n y1: number\n x2: number\n y2: number\n}\n\n/** 圆弧段(圆心 + 半径 + 起止角,弧度;z=0)。 */\nexport interface ProfileArcSeg {\n kind: 'arc'\n cx: number\n cy: number\n radius: number\n /** 起始角(弧度) */\n startAngle: number\n /** 终止角(弧度) */\n endAngle: number\n ccw: boolean\n x1: number\n y1: number\n x2: number\n y2: number\n}\n\n/** 一条有序 2D 轮廓段(直线或圆弧)。 */\nexport type ProfileSeg = ProfileLineSeg | ProfileArcSeg\n\n/** 单个轮廓环:有序段序列(首尾相接)。 */\nexport interface ProfileLoop {\n segments: ProfileSeg[]\n}\n\n/** `cad.profile` 参数:轮廓环集合。语义见 {@link buildProfileShape}(嵌套=孔,不相交=独立岛)。 */\nexport interface ProfileParams {\n contours: ProfileLoop[]\n /**\n * 产物形态:'face'(默认)构面;'wire' 只交出不带面的最大岛外环 wire(1D 曲线),\n * 供扫掠族(sweep/loft/…)直接作 spine。'wire' 形态丢弃孔环(扫掠脊柱为单闭合轮廓)。\n */\n as?: 'face' | 'wire'\n}\n\n// ── 参数自校验 ──\n\n/**\n * Validate profile parameters: `contours` must be a non-empty array of loops,\n * each with at least one segment.\n * @param params the raw profile operation parameters.\n */\nexport function assertProfileParams(params: Record<string, unknown>): void {\n const contours = params.contours\n if (!Array.isArray(contours) || contours.length === 0) {\n throw new Error('E_PROFILE_NO_CONTOURS: profile requires at least one contour')\n }\n for (const loop of contours) {\n if (!loop || typeof loop !== 'object' || !Array.isArray((loop as ProfileLoop).segments)) {\n throw new Error('E_PROFILE_BAD_LOOP: each contour must have a segments array')\n }\n if ((loop as ProfileLoop).segments.length === 0) {\n throw new Error('E_PROFILE_EMPTY_LOOP: a contour must have at least one segment')\n }\n }\n}\n\n/**\n * 单环带符号面积(对每段做有向面积积分,而非只用段起点 shoelace)。\n *\n * 直线段:1/2 (x1·y2 − x2·y1)。\n * 圆弧段:1/2 ∫(x dy − y dx) 的解析解 = 1/2 [r²·sweep + cx·r(sin a1 − sin a0) − cy·r(cos a1 − cos a0)]。\n * 整圆(单段弧、起终点重合)由此得到 πr²,不再是 0——否则「整圆 + 方孔」会把孔误判成外环。\n */\nfunction loopSignedArea(loop: ProfileLoop): number {\n let a = 0\n for (const seg of loop.segments) {\n if (seg.kind === 'line') {\n a += (seg.x1 * seg.y2 - seg.x2 * seg.y1) / 2\n continue\n }\n let sweep = seg.endAngle - seg.startAngle\n while (sweep <= 0) sweep += 2 * Math.PI\n while (sweep > 2 * Math.PI) sweep -= 2 * Math.PI\n const { cx, cy, radius: r, startAngle: a0 } = seg\n const a1 = a0 + sweep\n a += 0.5 * (r * r * sweep + cx * r * (Math.sin(a1) - Math.sin(a0)) - cy * r * (Math.cos(a1) - Math.cos(a0)))\n }\n return a\n}\n\n/** 圆弧 → 一条或两条 makeArcEdge(整圆拆分)。 */\nfunction arcToHandles(\n kernel: BrepEngineApi,\n seg: ProfileArcSeg,\n): ReturnType<BrepEngineApi['makeArcEdge']>[] {\n const { cx, cy, radius, startAngle, endAngle, ccw = true } = seg\n // GOTCHA(2026-09-25,A3 FCBL_tree_entourage):ccw 必须参与弧的几何方向。\n // makeArcEdge 按「起点-中点-终点」三点定弧,旧实现一律取 CCW 中点\n // ((start+end)/2 归一化到 (0,2π]),ccw:false 的弧被画成 CCW **长弧**(补角)。\n // 实测后果:长弧穿过旋转轴 → revolve 产物退化(bbox NaN)→ BRepMesh 挂死\n // (进程无声死亡);正确 CW 短弧下内核 revolve 仅 ~19ms。\n let sweep: number\n let midAngle: number\n if (ccw) {\n sweep = endAngle - startAngle\n while (sweep <= 0) sweep += 2 * Math.PI\n while (sweep > 2 * Math.PI) sweep -= 2 * Math.PI\n midAngle = startAngle + sweep / 2\n } else {\n // 顺时针:从 startAngle 递减到 endAngle,扫角取反向归一化\n sweep = startAngle - endAngle\n while (sweep <= 0) sweep += 2 * Math.PI\n while (sweep > 2 * Math.PI) sweep -= 2 * Math.PI\n midAngle = startAngle - sweep / 2\n }\n\n const makeOne = (a0: number, am: number, a1: number): ReturnType<BrepEngineApi['makeArcEdge']> => {\n const start = { x: cx + radius * Math.cos(a0), y: cy + radius * Math.sin(a0), z: 0 }\n const m = { x: cx + radius * Math.cos(am), y: cy + radius * Math.sin(am), z: 0 }\n const end = { x: cx + radius * Math.cos(a1), y: cy + radius * Math.sin(a1), z: 0 }\n return kernel.makeArcEdge(start, m, end)\n }\n\n // 整圆(sweep≈2π):拆成两段半圆,避免 makeArcEdge 起点≈终点退化\n if (sweep >= 2 * Math.PI - 1e-9) {\n const half = 2 * Math.PI / 2\n const dir = ccw ? 1 : -1\n return [\n makeOne(startAngle, startAngle + dir * half / 2, startAngle + dir * half),\n makeOne(startAngle + dir * half, startAngle + dir * (half + half / 2), startAngle + dir * 2 * Math.PI),\n ]\n }\n return [makeOne(startAngle, midAngle, endAngle)]\n}\n\n/** 单环 → wire handle(仅构面,不释放中间句柄,遵循现有惯例)。 */\nfunction loopToWire(kernel: BrepEngineApi, loop: ProfileLoop): ReturnType<BrepEngineApi['makeWire']> {\n const edges: ReturnType<BrepEngineApi['makeLineEdge']>[] = []\n for (const seg of loop.segments) {\n if (seg.kind === 'line') {\n edges.push(kernel.makeLineEdge({ x: seg.x1, y: seg.y1, z: 0 }, { x: seg.x2, y: seg.y2, z: 0 }))\n } else {\n // 极小扫角(退化弧)→ 退化为线段,避免构边失败\n let sweep = seg.endAngle - seg.startAngle\n while (sweep <= 0) sweep += 2 * Math.PI\n while (sweep > 2 * Math.PI) sweep -= 2 * Math.PI\n if (sweep < 1e-9) {\n edges.push(kernel.makeLineEdge({ x: seg.x1, y: seg.y1, z: 0 }, { x: seg.x2, y: seg.y2, z: 0 }))\n } else {\n edges.push(...arcToHandles(kernel, seg))\n }\n }\n }\n return kernel.makeWire(edges as ReturnType<BrepEngineApi['makeLineEdge']>[])\n}\n\n/** 环 → 2D 采样多边形(直线取端点、弧等角采样),用于环间包含性判定。 */\nfunction loopToPolygon(loop: ProfileLoop): Array<{ x: number; y: number }> {\n const pts: Array<{ x: number; y: number }> = []\n for (const seg of loop.segments) {\n if (seg.kind === 'line') {\n pts.push({ x: seg.x1, y: seg.y1 })\n continue\n }\n let sweep = seg.endAngle - seg.startAngle\n while (sweep <= 0) sweep += 2 * Math.PI\n while (sweep > 2 * Math.PI) sweep -= 2 * Math.PI\n const n = Math.max(8, Math.ceil((sweep / (2 * Math.PI)) * 32))\n for (let k = 0; k < n; k++) {\n const a = seg.startAngle + (sweep * k) / n\n pts.push({ x: seg.cx + seg.radius * Math.cos(a), y: seg.cy + seg.radius * Math.sin(a) })\n }\n }\n return pts\n}\n\n/** 射线法:点是否在多边形内(采样多边形足够密,顶点/边界角落情形由环间不共边保证不出现)。 */\nfunction polygonContains(poly: Array<{ x: number; y: number }>, px: number, py: number): boolean {\n let inside = false\n for (let i = 0, j = poly.length - 1; i < poly.length; j = i++) {\n const xi = poly[i]!.x\n const yi = poly[i]!.y\n const xj = poly[j]!.x\n const yj = poly[j]!.y\n if (yi > py !== yj > py && px < ((xj - xi) * (py - yi)) / (yj - yi) + xi) inside = !inside\n }\n return inside\n}\n\n/**\n * BREP 路径:2D 轮廓集合 → planar face 集合。\n *\n * GOTCHA(2026-09-26,Beds part16/39):环语义是「**嵌套 = 孔,不相交 = 独立岛**」\n * (与 FreeCAD 草图一致),不是「面积最大者当外环、其余全当孔」。旧实现把双岛轮廓的\n * 第二个岛判成「洞外面」→ `addHolesInFace` 收到与外环不相交的 wire → 构面退化\n * (7 面、volume 0)。多岛产物 = compound(每岛一面、各带自己的孔),下游\n * `cad.extrude` 对 compound 输入逐面挤出(kernel MakePrism 收复合形状)。\n *\n * @param params - 轮廓环集合与产物形态。\n * @returns Shape(单岛为 face;多岛为 face 的 compound;`as:'wire'` 为 1D 曲线)。\n */\nexport function buildProfileShape(params: ProfileParams): Shape {\n const kernel = getBrepApi()\n const as = params.as ?? 'face'\n\n const loops = params.contours.map((loop) => ({ loop, area: Math.abs(loopSignedArea(loop)) }))\n\n // 包含分类:每个环的直接父环 = 面积最小的严格包含它的环;深度偶数 = 岛,奇数 = 父环的孔。\n const polys = loops.map((l) => loopToPolygon(l.loop))\n const parent = new Array<number>(loops.length).fill(-1)\n for (let i = 0; i < loops.length; i++) {\n const probe = polys[i]![0]!\n for (let j = 0; j < loops.length; j++) {\n if (i === j || loops[j]!.area <= loops[i]!.area) continue\n if (!polygonContains(polys[j]!, probe.x, probe.y)) continue\n if (parent[i] === -1 || loops[j]!.area < loops[parent[i]]!.area) parent[i] = j\n }\n }\n const depthOf = (i: number): number => {\n let d = 0\n let cur = i\n while (parent[cur] !== -1) {\n d++\n cur = parent[cur]!\n }\n return d\n }\n\n const islands: number[] = []\n const holesOf = new Map<number, number[]>()\n for (let i = 0; i < loops.length; i++) {\n if (depthOf(i) % 2 === 0) islands.push(i)\n else {\n const p = parent[i]!\n const arr = holesOf.get(p)\n if (arr) arr.push(i)\n else holesOf.set(p, [i])\n }\n }\n\n // 'wire' 形态:只交最大岛的外环 wire(1D 曲线),不构面 —— 供扫掠族作 spine。\n if (as === 'wire') {\n let outer = islands[0]!\n for (const isl of islands) {\n if (loops[isl]!.area > loops[outer]!.area) outer = isl\n }\n const wire = loopToWire(kernel, loops[outer]!.loop)\n return fromBrepCurve(solidToShape(kernel, wire), { solid: wire })\n }\n\n // 每岛一面(岛环为外环,直接子环为孔)\n const faces: ReturnType<BrepEngineApi['makeFace']>[] = []\n for (const isl of islands) {\n const wire = loopToWire(kernel, loops[isl]!.loop)\n const face = kernel.makeFace(wire)\n const holes = holesOf.get(isl)\n if (holes && holes.length > 0) {\n const holeWires = holes.map((h) => loopToWire(kernel, loops[h]!.loop))\n const faced = kernel.addHolesInFace(face, holeWires)\n kernel.release(face)\n faces.push(faced)\n } else {\n faces.push(face)\n }\n }\n\n if (faces.length === 1) {\n const f = faces[0]!\n return fromBrep(solidToShape(kernel, f), { solid: f })\n }\n const compound = kernel.makeCompound(faces as never)\n return fromBrep(solidToShape(kernel, compound), { solid: compound })\n}\n\n/**\n * 从 2D 轮廓构造平面(creator,无输入)。仅 BREP 可用。\n * @group 创建\n * @inputs 0\n * @async false\n * @qual ok\n * @name profile\n * @returns Shape 平面几何(mesh 三角化 + BREP 句柄);`as:'wire'` 时返回 1D 曲线(kind:'curve')。\n * @param params.contours - 有序 2D 轮廓(线段/圆弧;外环 + 孔)。type:ProfileLoop[] required:true\n * @param params.as - 产物形态:'face'(默认)构面;'wire' 只交外环 wire(1D 曲线)。type:'face'|'wire' required:false\n * @example\n * const f = cad.profile({ contours: [{ segments: [{ kind:'line', x1:0,y1:0,x2:10,y2:0 }, ...] }] })\n * const w = cad.profile({ contours: [{ segments: [{ kind:'line', x1:0,y1:0,x2:10,y2:0 }, ...] }], as: 'wire' })\n */\nexport const profile = defineOp({\n capabilities: ['directEdit'],\n brep(params: Record<string, unknown>) {\n assertProfileParams(params)\n return buildProfileShape(params as unknown as ProfileParams)\n },\n naming: { kind: 'construct', newFaces: { via: 'explicit', vocab: [] } } as Provenance,\n})"]}
@@ -1 +1 @@
1
- {"version":3,"file":"replicate.d.ts","sourceRoot":"","sources":["../../src/api/replicate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAA;AAmBhD,8DAA8D;AAC9D,UAAU,aAAa;IACrB,wBAAwB;IACxB,MAAM,CAAC,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAChF,wBAAwB;IACxB,EAAE,CAAC,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAC7E;AAgDD;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,eAAe;;CAuC1B,CAAA;AAIF;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,WAAW;;CAuDtB,CAAA;AAIF,UAAU,yBAAyB;IACjC,IAAI,EAAE,IAAI,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,IAAI,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,kBAAkB;;CAqD7B,CAAA;AAIF,UAAU,iBAAiB;IACzB,MAAM,CAAC,EAAE,IAAI,CAAA;IACb,EAAE,CAAC,EAAE,IAAI,CAAA;CACV;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,UAAU;;CAiCrB,CAAA;AAIF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,MAAM;;CASjB,CAAA;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,KAAK;;CAOhB,CAAA"}
1
+ {"version":3,"file":"replicate.d.ts","sourceRoot":"","sources":["../../src/api/replicate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAA;AAiBhD,8DAA8D;AAC9D,UAAU,aAAa;IACrB,wBAAwB;IACxB,MAAM,CAAC,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAChF,wBAAwB;IACxB,EAAE,CAAC,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAC7E;AAgDD;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,eAAe;;CAuC1B,CAAA;AAIF;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,WAAW;;CAuDtB,CAAA;AAIF,UAAU,yBAAyB;IACjC,IAAI,EAAE,IAAI,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,IAAI,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,kBAAkB;;CAqD7B,CAAA;AAIF,UAAU,iBAAiB;IACzB,MAAM,CAAC,EAAE,IAAI,CAAA;IACb,EAAE,CAAC,EAAE,IAAI,CAAA;CACV;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,UAAU;;CA6BrB,CAAA;AAIF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,MAAM;;CAUjB,CAAA;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,KAAK;;CAOhB,CAAA"}
@@ -32,12 +32,10 @@
32
32
  * section/translateWithHistory 等 occt-only 虚名,capability-map 实证实现不依赖)。
33
33
  */
34
34
  import { solidToShape } from '../brep/brep-ops.js';
35
- import { getFaceHashes, HASH_UPPER_BOUND } from '../brep/face-evolution.js';
36
35
  import { getBrepApi } from '../brep/handle-bridge.js';
37
36
  import { getCurrentStmt, keep } from '../runtime-state.js';
38
37
  import { fromBrep, brepOf } from '../shape.js';
39
38
  import { defineOp } from '../sdk.js';
40
- import { getOcctKernel } from '../occt-kernel/occtKernel.js';
41
39
  import { buildReplicaRoleTable } from './internal/replica-role-table.js';
42
40
  // Generated compatOps (delegation targets for the thin single-copy overrides).
43
41
  // NOTE: transformCopy is NOT a script-face op (arg-spec skip: ComposedTransform
@@ -290,12 +288,14 @@ export const mirrorJoin = defineOp({
290
288
  const { kernel, solid, outStmt } = prelude(input, 'mirrorJoin');
291
289
  const n = norm(options?.normal ?? [1, 0, 0]);
292
290
  const o = toBrepVec(options?.at ?? [0, 0, 0]);
293
- const inputHashes = getFaceHashes(kernel, solid);
294
- // 平台面(D3):mirrorWithHistory 是 occt-only。BrepHandle ↔ ShapeHandle 运行时
295
- // 同构,品牌转换只发生在平台边界。
296
- const mirrored = getOcctKernel().mirrorWithHistory(solid, o, toBrepVec(n), inputHashes, HASH_UPPER_BOUND);
291
+ // 2026-09-26 C 批降级:原实现直调 getOcctKernel().mirrorWithHistory(occt-only history
292
+ // 镜像,返回 modified/newFaces 供细粒度 roleTable)。按用户指示「有没有历史 withhistory
293
+ // 并不重要」,降级为 L1 kernel.mirror(brepkit 已声明 mirror 能力)——几何结果一致,
294
+ // roleTable 仍由 buildReplicaRoleTable 经质心聚类重建(引擎无关),仅丢失 history 级
295
+ // modified 面映射(不影响几何与产物有效性)。
296
+ const mirrored = kernel.mirror(solid, o, toBrepVec(n));
297
297
  try {
298
- const resultSolid = kernel.fuse(solid, mirrored.result);
298
+ const resultSolid = kernel.fuse(solid, mirrored);
299
299
  const replicas = [
300
300
  { label: 'replica[0]', inverse: (c) => ({ x: c.x, y: c.y, z: c.z }) },
301
301
  { label: 'replica[1]', inverse: (c) => reflectAcrossPlane(c, o, n) },
@@ -304,12 +304,12 @@ export const mirrorJoin = defineOp({
304
304
  return fromBrep(solidToShape(kernel, resultSolid), { solid: resultSolid, roleTable });
305
305
  }
306
306
  finally {
307
- kernel.release(mirrored.result);
307
+ kernel.release(mirrored);
308
308
  }
309
309
  },
310
- // 平台 op(D11):实现依赖 occt-only `mirrorWithHistory`(D3 原生面)——
311
- // 声明 engines;不声明 capabilities(能力由平台身份本身界定)。
312
- engines: ['occt'],
310
+ // 2026-09-26 C 批:从 engines:[occt] 降级为 capabilities:['mirror','fuse'](L1 中立面,
311
+ // brepkit 已声明二者)。history 语义丢失(见上注释),几何不回退。
312
+ capabilities: ['mirror', 'fuse'],
313
313
  naming: { kind: 'replicate', k: 2 },
314
314
  });
315
315
  // ── single-copy thin overrides(keep + 委托生成 op)─────────────────────────
@@ -332,9 +332,10 @@ export const mirror = defineOp({
332
332
  keep(input);
333
333
  return (await generatedMirror(input, options));
334
334
  },
335
- // 平台 op(D11):委托 generatedMirror(vendored 实现调 occt-only
336
- // `mirrorWithHistory`,capability-map 实证)——声明 engines,不声明 capabilities。
337
- engines: ['occt'],
335
+ // 2026-09-26 B 批:generatedMirror 已降级为 L1 kernel.mirror(brepkit 已声明 mirror
336
+ // 能力),薄 override 同步从 engines:[occt] 降级为 capabilities:['mirror']——
337
+ // 与 clone 薄 override 同模式(外层门不拦 brepkit,内层 generatedMirror 已按能力路由)。
338
+ capabilities: ['mirror'],
338
339
  naming: { kind: 'kernel', newFaces: { via: 'byAdjacency' } },
339
340
  });
340
341
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"replicate.js","sourceRoot":"","sources":["../../src/api/replicate.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * replicate — handwritten overrides for the copy-family ops (keep semantics +\n * replica[k] role tables).\n *\n * @platform occt — 本文件 import occt-kernel(mirrorJoin 走 `mirrorWithHistory`\n * 平台面,D3)。文件级标注满足守卫①(平台 import 自证身份);文件内的**中立 op**\n * (circularPattern/gridPattern/rectangularPattern/clone 只用 L1 核心面)不声明\n * engines,运行时不拦截——标注只约束平台 import,不改变函数级中立性\n * (与 face-evolution.ts 同口径)。\n *\n * All 9 copy-like ops must NOT consume their input (same as `copy`): each brep\n * body declares `keep(input)` (function-body keep → KeepRegistry → live-shapes),\n * so the source stays a live terminal in both runtime and UI.\n *\n * Two groups:\n * - Multi-replica patterns (circularPattern / gridPattern / rectangularPattern /\n * mirrorJoin): promoted from generated compatOps to handwritten defineOps that\n * also build `replica[*]/<inner>` role tables (same treatment as linearPattern,\n * via the shared buildReplicaRoleTable helper).\n * - Single-copy ops (mirror / clone / transformCopy): thin overrides that keep\n * the input and delegate to the generated compatOp (borrow/adopt/capabilities/\n * naming preserved).\n *\n * The generated files stay untouched; overrides win via api-namespace spread\n * (same precedent as cut / split / linearPattern).\n *\n * 平台分层(narrowing plan Phase 5,D11):\n * - mirrorJoin / mirror:平台 op(依赖 occt-only `mirrorWithHistory`)→\n * `engines: ['occt']`,不声明 capabilities(能力由平台身份本身界定)。\n * - circularPattern / gridPattern / rectangularPattern / clone:中立 op(实现\n * 只用 L1 核心面)→ capabilities 收窄到真实 L1 名(删除 isNull/iterShapes/\n * section/translateWithHistory 等 occt-only 虚名,capability-map 实证实现不依赖)。\n */\n\nimport type { Shape, Vec3 } from '../mesh/types'\nimport { solidToShape } from '../brep/brep-ops'\nimport { getFaceHashes, HASH_UPPER_BOUND } from '../brep/face-evolution'\nimport { getBrepApi } from '../brep/handle-bridge'\nimport { getCurrentStmt, keep } from '../runtime-state'\nimport { fromBrep, brepOf } from '../shape'\nimport { defineOp } from '../sdk'\nimport type { Provenance } from '../topology/naming/lineage'\nimport type { BrepHandle, BrepVec3 } from '../brep/engine/types'\nimport type { BrepEngineApi } from '../brep/engine/primitives'\nimport { getOcctKernel, type ShapeHandle } from '../occt-kernel/occtKernel'\nimport { buildReplicaRoleTable, type ReplicaTransform } from './internal/replica-role-table'\n// Generated compatOps (delegation targets for the thin single-copy overrides).\n// NOTE: transformCopy is NOT a script-face op (arg-spec skip: ComposedTransform\n// is not constructible in .fai.js); it stays a TS-library-only re-export.\nimport {\n mirror as generatedMirror,\n clone as generatedClone,\n} from './generated/topology'\n/** 镜像面参数(与 vendored MirrorOptions 同形;G5 去 brepjs 依赖后本地自持)。 */\ninterface MirrorOptions {\n /** 镜像面法向。默认 [0,0,1]。 */\n normal?: readonly [number, number, number] | { x: number; y: number; z: number }\n /** 镜像面过点。默认 [0,0,0]。 */\n at?: readonly [number, number, number] | { x: number; y: number; z: number }\n}\n\n/** Normalize a vector (zero vector → [0,0,1] fallback, same as pattern.ts). */\nfunction norm(v: Vec3): Vec3 {\n const len = Math.hypot(v[0], v[1], v[2])\n if (len < 1e-9) return [0, 0, 1]\n return [v[0] / len, v[1] / len, v[2] / len]\n}\n\nfunction toBrepVec(v: Vec3): BrepVec3 {\n return { x: v[0], y: v[1], z: v[2] }\n}\n\n/** Shared prelude: L1 kernel(getBrepApi,D12)+ BREP input handle + output statement id. */\nfunction prelude(input: Shape, tag: string): { kernel: BrepEngineApi; solid: BrepHandle; outStmt: string } {\n const kernel = getBrepApi()\n const solid = brepOf(input) as BrepHandle | undefined\n if (!solid) throw new Error(`[stdlib/${tag}] input is not BREP`)\n return { kernel, solid, outStmt: String(getCurrentStmt()?.id ?? '') }\n}\n\n/** Rotate point p around the axis line (point `center`, unit direction `u`) by theta radians. */\nfunction rotateAroundAxis(p: BrepVec3, center: BrepVec3, u: Vec3, theta: number): BrepVec3 {\n const vx = p.x - center.x\n const vy = p.y - center.y\n const vz = p.z - center.z\n const cos = Math.cos(theta)\n const sin = Math.sin(theta)\n const dot = vx * u[0] + vy * u[1] + vz * u[2]\n // u × v\n const cx = u[1] * vz - u[2] * vy\n const cy = u[2] * vx - u[0] * vz\n const cz = u[0] * vy - u[1] * vx\n return {\n x: center.x + vx * cos + cx * sin + u[0] * dot * (1 - cos),\n y: center.y + vy * cos + cy * sin + u[1] * dot * (1 - cos),\n z: center.z + vz * cos + cz * sin + u[2] * dot * (1 - cos),\n }\n}\n\n/** Reflect point p across the plane (point `o`, unit normal `n`). Self-inverse. */\nfunction reflectAcrossPlane(p: BrepVec3, o: BrepVec3, n: Vec3): BrepVec3 {\n const d = (p.x - o.x) * n[0] + (p.y - o.y) * n[1] + (p.z - o.z) * n[2]\n return { x: p.x - 2 * d * n[0], y: p.y - 2 * d * n[1], z: p.z - 2 * d * n[2] }\n}\n\n// ── circularPattern ─────────────────────────────────────────────────────────\n\n/**\n * 环形阵列:绕 axis 均分 fullAngle(度,缺省 360)复制 count 份(含原位置)。\n * @group 特征\n * @inputs 1\n * @async true\n * @qual ok\n * @name circularPattern\n * @note BREP-only。keep 语义:不消费输入。结果面回投输入面角色,产出 `replica[k]/<inner>`。\n * @returns Shape 所有副本 fused 后的几何。\n * @param input - 目标几何。type:Shape required:true\n * @param axis - 旋转轴方向。type:[x,y,z] required:true\n * @param count - 副本总数(含原位置)。type:number required:true\n * @param fullAngle - 总角度(度,缺省 360)。type:number required:false\n * @param center - 旋转轴上一点(缺省原点)。type:[x,y,z] required:false\n * @example\n * const p = await cad.circularPattern(part0, [0, 0, 1], 6)\n */\nexport const circularPattern = defineOp({\n brep(input: Shape, axis: Vec3, count: number, fullAngle: number = 360, center: Vec3 = [0, 0, 0]) {\n keep(input)\n const { kernel, solid, outStmt } = prelude(input, 'circularPattern')\n const u = norm(axis)\n const step = fullAngle / count\n const raw = kernel.circularPattern(solid, toBrepVec(center), toBrepVec(u), step, count)\n\n let resultSolid: BrepHandle\n try {\n resultSolid = kernel.fuseAll(raw)\n } finally {\n for (const c of raw) kernel.release(c)\n }\n\n const replicas: ReplicaTransform[] = []\n for (let k = 0; k < count; k++) {\n const theta = (-k * step * Math.PI) / 180\n replicas.push({\n label: `replica[${k}]`,\n inverse: (c) => rotateAroundAxis(c, toBrepVec(center), u, theta),\n })\n }\n const roleTable = buildReplicaRoleTable(kernel, input, resultSolid, replicas, outStmt)\n return fromBrep(solidToShape(kernel, resultSolid), { solid: resultSolid, roleTable })\n },\n // 中立 op(D11):capabilities 收窄到实现真实调用的 L1 名(删除 isNull/iterShapes/\n // section 等 occt-only 虚名——实现只调 kernel.circularPattern/fuseAll)。\n capabilities: [\n 'circularPattern',\n 'dispose',\n 'fuseAll',\n 'hashCode',\n 'surfaceCenterOfMass',\n 'surfaceNormal',\n 'surfaceType',\n 'uvBounds',\n ],\n naming: { kind: 'replicate', k: 0 } as Provenance,\n})\n\n// ── gridPattern ─────────────────────────────────────────────────────────────\n\n/**\n * 二维栅格阵列:沿 directionX × directionY 复制 countX×countY 份(含原位置)。\n * @group 特征\n * @inputs 1\n * @async true\n * @qual ok\n * @name gridPattern\n * @note BREP-only。keep 语义:不消费输入。结果面回投输入面角色,产出 `replica[ix_iy]/<inner>`。\n * @returns Shape 全部副本的 compound。\n * @param input - 目标几何。type:Shape required:true\n * @param directionX - 第一方向。type:[x,y,z] required:true\n * @param directionY - 第二方向。type:[x,y,z] required:true\n * @param countX - X 向副本数。type:number required:true\n * @param countY - Y 向副本数。type:number required:true\n * @param spacingX - X 向间距。type:number required:true\n * @param spacingY - Y 向间距。type:number required:true\n * @example\n * const p = await cad.gridPattern(part0, [1, 0, 0], [0, 1, 0], 3, 2, 20, 20)\n */\nexport const gridPattern = defineOp({\n brep(\n input: Shape,\n directionX: Vec3,\n directionY: Vec3,\n countX: number,\n countY: number,\n spacingX: number,\n spacingY: number,\n ) {\n keep(input)\n const { kernel, solid, outStmt } = prelude(input, 'gridPattern')\n const dx = norm(directionX)\n const dy = norm(directionY)\n // kernel.gridPattern 返回 compound 单句柄(含全部副本),无需 fuse。\n const resultSolid = kernel.gridPattern(\n solid,\n toBrepVec(dx),\n toBrepVec(dy),\n spacingX,\n spacingY,\n countX,\n countY,\n )\n\n const replicas: ReplicaTransform[] = []\n for (let ix = 0; ix < countX; ix++) {\n for (let iy = 0; iy < countY; iy++) {\n const ox = ix * spacingX\n const oy = iy * spacingY\n replicas.push({\n label: `replica[${ix}_${iy}]`,\n inverse: (c) => ({\n x: c.x - (ox * dx[0] + oy * dy[0]),\n y: c.y - (ox * dx[1] + oy * dy[1]),\n z: c.z - (ox * dx[2] + oy * dy[2]),\n }),\n })\n }\n }\n const roleTable = buildReplicaRoleTable(kernel, input, resultSolid, replicas, outStmt)\n return fromBrep(solidToShape(kernel, resultSolid), { solid: resultSolid, roleTable })\n },\n capabilities: [\n 'dispose',\n 'fuseAll',\n 'gridPattern',\n 'hashCode',\n 'linearPattern',\n 'surfaceCenterOfMass',\n 'surfaceNormal',\n 'surfaceType',\n 'uvBounds',\n ],\n naming: { kind: 'replicate', k: 0 } as Provenance,\n})\n\n// ── rectangularPattern ──────────────────────────────────────────────────────\n\ninterface RectangularPatternOptions {\n xDir: Vec3\n xCount: number\n xSpacing: number\n yDir: Vec3\n yCount: number\n ySpacing: number\n}\n\n/**\n * 矩形阵列:按 options(xDir/xCount/xSpacing/yDir/yCount/ySpacing)复制并 fuse。\n * @group 特征\n * @inputs 1\n * @async true\n * @qual ok\n * @name rectangularPattern\n * @note BREP-only。keep 语义:不消费输入。结果面回投输入面角色,产出 `replica[ix_iy]/<inner>`。\n * @returns Shape 所有副本 fused 后的几何。\n * @param input - 目标几何。type:Shape required:true\n * @param options - 阵列参数。type:RectangularPatternOptions required:true\n * @example\n * const p = await cad.rectangularPattern(part0, { xDir: [1,0,0], xCount: 3, xSpacing: 20, yDir: [0,1,0], yCount: 2, ySpacing: 15 })\n */\nexport const rectangularPattern = defineOp({\n brep(input: Shape, options: RectangularPatternOptions) {\n keep(input)\n const { kernel, solid, outStmt } = prelude(input, 'rectangularPattern')\n const { xDir, xCount, xSpacing, yDir, yCount, ySpacing } = options\n const dx = norm(xDir)\n const dy = norm(yDir)\n // vendored rectangularPattern 是纯 JS 组合(translate + fuseAll),内核不声明\n // 该方法——与 vendored 同口径:逐份 translate 再 fuseAll。\n const copies: BrepHandle[] = []\n try {\n for (let ix = 0; ix < xCount; ix++) {\n for (let iy = 0; iy < yCount; iy++) {\n const ox = ix * xSpacing\n const oy = iy * ySpacing\n copies.push(kernel.translate(solid, ox * dx[0] + oy * dy[0], ox * dx[1] + oy * dy[1], ox * dx[2] + oy * dy[2]))\n }\n }\n const resultSolid = kernel.fuseAll(copies)\n\n const replicas: ReplicaTransform[] = []\n for (let ix = 0; ix < xCount; ix++) {\n for (let iy = 0; iy < yCount; iy++) {\n const ox = ix * xSpacing\n const oy = iy * ySpacing\n replicas.push({\n label: `replica[${ix}_${iy}]`,\n inverse: (c) => ({\n x: c.x - (ox * dx[0] + oy * dy[0]),\n y: c.y - (ox * dx[1] + oy * dy[1]),\n z: c.z - (ox * dx[2] + oy * dy[2]),\n }),\n })\n }\n }\n const roleTable = buildReplicaRoleTable(kernel, input, resultSolid, replicas, outStmt)\n return fromBrep(solidToShape(kernel, resultSolid), { solid: resultSolid, roleTable })\n } finally {\n for (const c of copies) kernel.release(c)\n }\n },\n capabilities: [\n 'dispose',\n 'fuse',\n 'fuseAll',\n 'fuseWithHistory',\n 'hashCode',\n 'surfaceCenterOfMass',\n 'surfaceNormal',\n 'surfaceType',\n 'uvBounds',\n ],\n naming: { kind: 'replicate', k: 0 } as Provenance,\n})\n\n// ── mirrorJoin ──────────────────────────────────────────────────────────────\n\ninterface MirrorJoinOptions {\n normal?: Vec3\n at?: Vec3\n}\n\n/**\n * 镜像并融合:原物(replica[0])+ 沿平面镜像(replica[1])fuse 成一体。\n * @group 特征\n * @inputs 1\n * @async true\n * @qual ok\n * @name mirrorJoin\n * @note BREP-only。keep 语义:不消费输入。结果面回投输入面角色,产出 `replica[0|1]/<inner>`。\n * @returns Shape fuse 后的几何。\n * @param input - 目标几何。type:Shape required:true\n * @param options - { normal?, at? } 镜像面法向与面上一点。type:MirrorJoinOptions required:false\n * @example\n * const p = await cad.mirrorJoin(part0, { normal: [1, 0, 0] })\n */\nexport const mirrorJoin = defineOp({\n brep(input: Shape, options?: MirrorJoinOptions) {\n keep(input)\n const { kernel, solid, outStmt } = prelude(input, 'mirrorJoin')\n const n = norm(options?.normal ?? [1, 0, 0])\n const o = toBrepVec(options?.at ?? [0, 0, 0])\n const inputHashes = getFaceHashes(kernel, solid)\n // 平台面(D3):mirrorWithHistory 是 occt-only。BrepHandle ↔ ShapeHandle 运行时\n // 同构,品牌转换只发生在平台边界。\n const mirrored = getOcctKernel().mirrorWithHistory(\n solid as unknown as ShapeHandle,\n o,\n toBrepVec(n),\n inputHashes,\n HASH_UPPER_BOUND,\n )\n try {\n const resultSolid = kernel.fuse(solid, mirrored.result as unknown as BrepHandle)\n\n const replicas: ReplicaTransform[] = [\n { label: 'replica[0]', inverse: (c) => ({ x: c.x, y: c.y, z: c.z }) },\n { label: 'replica[1]', inverse: (c) => reflectAcrossPlane(c, o, n) },\n ]\n const roleTable = buildReplicaRoleTable(kernel, input, resultSolid, replicas, outStmt)\n return fromBrep(solidToShape(kernel, resultSolid), { solid: resultSolid, roleTable })\n } finally {\n kernel.release(mirrored.result as unknown as BrepHandle)\n }\n },\n // 平台 op(D11):实现依赖 occt-only `mirrorWithHistory`(D3 原生面)——\n // 声明 engines;不声明 capabilities(能力由平台身份本身界定)。\n engines: ['occt'],\n naming: { kind: 'replicate', k: 2 } as Provenance,\n})\n\n// ── single-copy thin overrides(keep + 委托生成 op)─────────────────────────\n\n/**\n * 镜像:返回镜像后的新 Shape(源保留)。\n * @group 特征\n * @inputs 1\n * @async true\n * @qual ok\n * @name mirror\n * @note BREP-only。keep 语义:不消费输入(薄 override 委托生成 op,行为不变)。\n * @returns Shape 镜像后的新几何。\n * @param input - 目标几何。type:Shape required:true\n * @param options - { normal?, at? } 镜像面。type:MirrorOptions required:false\n * @example\n * const p = await cad.mirror(part0, { normal: [1, 0, 0] })\n */\nexport const mirror = defineOp({\n async brep(input: Shape, options?: MirrorOptions) {\n keep(input)\n return (await generatedMirror(input, options)) as Shape\n },\n // 平台 op(D11):委托 generatedMirror(vendored 实现调 occt-only\n // `mirrorWithHistory`,capability-map 实证)——声明 engines,不声明 capabilities。\n engines: ['occt'],\n naming: { kind: 'kernel', newFaces: { via: 'byAdjacency' } } as Provenance,\n})\n\n/**\n * 深拷贝句柄:返回独立副本(源保留)。\n * @group 特征\n * @inputs 1\n * @async true\n * @qual ok\n * @name clone\n * @note BREP-only。keep 语义:不消费输入(薄 override 委托生成 op,行为不变)。\n * @returns Shape 克隆的新几何。\n * @param input - 目标几何。type:Shape required:true\n * @example\n * const p = await cad.clone(part0)\n */\nexport const clone = defineOp({\n async brep(input: Shape) {\n keep(input)\n return (await generatedClone(input)) as Shape\n },\n capabilities: ['copyShape', 'dispose'],\n naming: { kind: 'identity' } as Provenance,\n})\n"]}
1
+ {"version":3,"file":"replicate.js","sourceRoot":"","sources":["../../src/api/replicate.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * replicate — handwritten overrides for the copy-family ops (keep semantics +\n * replica[k] role tables).\n *\n * @platform occt — 本文件 import occt-kernel(mirrorJoin 走 `mirrorWithHistory`\n * 平台面,D3)。文件级标注满足守卫①(平台 import 自证身份);文件内的**中立 op**\n * (circularPattern/gridPattern/rectangularPattern/clone 只用 L1 核心面)不声明\n * engines,运行时不拦截——标注只约束平台 import,不改变函数级中立性\n * (与 face-evolution.ts 同口径)。\n *\n * All 9 copy-like ops must NOT consume their input (same as `copy`): each brep\n * body declares `keep(input)` (function-body keep → KeepRegistry → live-shapes),\n * so the source stays a live terminal in both runtime and UI.\n *\n * Two groups:\n * - Multi-replica patterns (circularPattern / gridPattern / rectangularPattern /\n * mirrorJoin): promoted from generated compatOps to handwritten defineOps that\n * also build `replica[*]/<inner>` role tables (same treatment as linearPattern,\n * via the shared buildReplicaRoleTable helper).\n * - Single-copy ops (mirror / clone / transformCopy): thin overrides that keep\n * the input and delegate to the generated compatOp (borrow/adopt/capabilities/\n * naming preserved).\n *\n * The generated files stay untouched; overrides win via api-namespace spread\n * (same precedent as cut / split / linearPattern).\n *\n * 平台分层(narrowing plan Phase 5,D11):\n * - mirrorJoin / mirror:平台 op(依赖 occt-only `mirrorWithHistory`)→\n * `engines: ['occt']`,不声明 capabilities(能力由平台身份本身界定)。\n * - circularPattern / gridPattern / rectangularPattern / clone:中立 op(实现\n * 只用 L1 核心面)→ capabilities 收窄到真实 L1 名(删除 isNull/iterShapes/\n * section/translateWithHistory 等 occt-only 虚名,capability-map 实证实现不依赖)。\n */\n\nimport type { Shape, Vec3 } from '../mesh/types'\nimport { solidToShape } from '../brep/brep-ops'\nimport { getBrepApi } from '../brep/handle-bridge'\nimport { getCurrentStmt, keep } from '../runtime-state'\nimport { fromBrep, brepOf } from '../shape'\nimport { defineOp } from '../sdk'\nimport type { Provenance } from '../topology/naming/lineage'\nimport type { BrepHandle, BrepVec3 } from '../brep/engine/types'\nimport type { BrepEngineApi } from '../brep/engine/primitives'\nimport { buildReplicaRoleTable, type ReplicaTransform } from './internal/replica-role-table'\n// Generated compatOps (delegation targets for the thin single-copy overrides).\n// NOTE: transformCopy is NOT a script-face op (arg-spec skip: ComposedTransform\n// is not constructible in .fai.js); it stays a TS-library-only re-export.\nimport {\n mirror as generatedMirror,\n clone as generatedClone,\n} from './generated/topology'\n/** 镜像面参数(与 vendored MirrorOptions 同形;G5 去 brepjs 依赖后本地自持)。 */\ninterface MirrorOptions {\n /** 镜像面法向。默认 [0,0,1]。 */\n normal?: readonly [number, number, number] | { x: number; y: number; z: number }\n /** 镜像面过点。默认 [0,0,0]。 */\n at?: readonly [number, number, number] | { x: number; y: number; z: number }\n}\n\n/** Normalize a vector (zero vector → [0,0,1] fallback, same as pattern.ts). */\nfunction norm(v: Vec3): Vec3 {\n const len = Math.hypot(v[0], v[1], v[2])\n if (len < 1e-9) return [0, 0, 1]\n return [v[0] / len, v[1] / len, v[2] / len]\n}\n\nfunction toBrepVec(v: Vec3): BrepVec3 {\n return { x: v[0], y: v[1], z: v[2] }\n}\n\n/** Shared prelude: L1 kernel(getBrepApi,D12)+ BREP input handle + output statement id. */\nfunction prelude(input: Shape, tag: string): { kernel: BrepEngineApi; solid: BrepHandle; outStmt: string } {\n const kernel = getBrepApi()\n const solid = brepOf(input) as BrepHandle | undefined\n if (!solid) throw new Error(`[stdlib/${tag}] input is not BREP`)\n return { kernel, solid, outStmt: String(getCurrentStmt()?.id ?? '') }\n}\n\n/** Rotate point p around the axis line (point `center`, unit direction `u`) by theta radians. */\nfunction rotateAroundAxis(p: BrepVec3, center: BrepVec3, u: Vec3, theta: number): BrepVec3 {\n const vx = p.x - center.x\n const vy = p.y - center.y\n const vz = p.z - center.z\n const cos = Math.cos(theta)\n const sin = Math.sin(theta)\n const dot = vx * u[0] + vy * u[1] + vz * u[2]\n // u × v\n const cx = u[1] * vz - u[2] * vy\n const cy = u[2] * vx - u[0] * vz\n const cz = u[0] * vy - u[1] * vx\n return {\n x: center.x + vx * cos + cx * sin + u[0] * dot * (1 - cos),\n y: center.y + vy * cos + cy * sin + u[1] * dot * (1 - cos),\n z: center.z + vz * cos + cz * sin + u[2] * dot * (1 - cos),\n }\n}\n\n/** Reflect point p across the plane (point `o`, unit normal `n`). Self-inverse. */\nfunction reflectAcrossPlane(p: BrepVec3, o: BrepVec3, n: Vec3): BrepVec3 {\n const d = (p.x - o.x) * n[0] + (p.y - o.y) * n[1] + (p.z - o.z) * n[2]\n return { x: p.x - 2 * d * n[0], y: p.y - 2 * d * n[1], z: p.z - 2 * d * n[2] }\n}\n\n// ── circularPattern ─────────────────────────────────────────────────────────\n\n/**\n * 环形阵列:绕 axis 均分 fullAngle(度,缺省 360)复制 count 份(含原位置)。\n * @group 特征\n * @inputs 1\n * @async true\n * @qual ok\n * @name circularPattern\n * @note BREP-only。keep 语义:不消费输入。结果面回投输入面角色,产出 `replica[k]/<inner>`。\n * @returns Shape 所有副本 fused 后的几何。\n * @param input - 目标几何。type:Shape required:true\n * @param axis - 旋转轴方向。type:[x,y,z] required:true\n * @param count - 副本总数(含原位置)。type:number required:true\n * @param fullAngle - 总角度(度,缺省 360)。type:number required:false\n * @param center - 旋转轴上一点(缺省原点)。type:[x,y,z] required:false\n * @example\n * const p = await cad.circularPattern(part0, [0, 0, 1], 6)\n */\nexport const circularPattern = defineOp({\n brep(input: Shape, axis: Vec3, count: number, fullAngle: number = 360, center: Vec3 = [0, 0, 0]) {\n keep(input)\n const { kernel, solid, outStmt } = prelude(input, 'circularPattern')\n const u = norm(axis)\n const step = fullAngle / count\n const raw = kernel.circularPattern(solid, toBrepVec(center), toBrepVec(u), step, count)\n\n let resultSolid: BrepHandle\n try {\n resultSolid = kernel.fuseAll(raw)\n } finally {\n for (const c of raw) kernel.release(c)\n }\n\n const replicas: ReplicaTransform[] = []\n for (let k = 0; k < count; k++) {\n const theta = (-k * step * Math.PI) / 180\n replicas.push({\n label: `replica[${k}]`,\n inverse: (c) => rotateAroundAxis(c, toBrepVec(center), u, theta),\n })\n }\n const roleTable = buildReplicaRoleTable(kernel, input, resultSolid, replicas, outStmt)\n return fromBrep(solidToShape(kernel, resultSolid), { solid: resultSolid, roleTable })\n },\n // 中立 op(D11):capabilities 收窄到实现真实调用的 L1 名(删除 isNull/iterShapes/\n // section 等 occt-only 虚名——实现只调 kernel.circularPattern/fuseAll)。\n capabilities: [\n 'circularPattern',\n 'dispose',\n 'fuseAll',\n 'hashCode',\n 'surfaceCenterOfMass',\n 'surfaceNormal',\n 'surfaceType',\n 'uvBounds',\n ],\n naming: { kind: 'replicate', k: 0 } as Provenance,\n})\n\n// ── gridPattern ─────────────────────────────────────────────────────────────\n\n/**\n * 二维栅格阵列:沿 directionX × directionY 复制 countX×countY 份(含原位置)。\n * @group 特征\n * @inputs 1\n * @async true\n * @qual ok\n * @name gridPattern\n * @note BREP-only。keep 语义:不消费输入。结果面回投输入面角色,产出 `replica[ix_iy]/<inner>`。\n * @returns Shape 全部副本的 compound。\n * @param input - 目标几何。type:Shape required:true\n * @param directionX - 第一方向。type:[x,y,z] required:true\n * @param directionY - 第二方向。type:[x,y,z] required:true\n * @param countX - X 向副本数。type:number required:true\n * @param countY - Y 向副本数。type:number required:true\n * @param spacingX - X 向间距。type:number required:true\n * @param spacingY - Y 向间距。type:number required:true\n * @example\n * const p = await cad.gridPattern(part0, [1, 0, 0], [0, 1, 0], 3, 2, 20, 20)\n */\nexport const gridPattern = defineOp({\n brep(\n input: Shape,\n directionX: Vec3,\n directionY: Vec3,\n countX: number,\n countY: number,\n spacingX: number,\n spacingY: number,\n ) {\n keep(input)\n const { kernel, solid, outStmt } = prelude(input, 'gridPattern')\n const dx = norm(directionX)\n const dy = norm(directionY)\n // kernel.gridPattern 返回 compound 单句柄(含全部副本),无需 fuse。\n const resultSolid = kernel.gridPattern(\n solid,\n toBrepVec(dx),\n toBrepVec(dy),\n spacingX,\n spacingY,\n countX,\n countY,\n )\n\n const replicas: ReplicaTransform[] = []\n for (let ix = 0; ix < countX; ix++) {\n for (let iy = 0; iy < countY; iy++) {\n const ox = ix * spacingX\n const oy = iy * spacingY\n replicas.push({\n label: `replica[${ix}_${iy}]`,\n inverse: (c) => ({\n x: c.x - (ox * dx[0] + oy * dy[0]),\n y: c.y - (ox * dx[1] + oy * dy[1]),\n z: c.z - (ox * dx[2] + oy * dy[2]),\n }),\n })\n }\n }\n const roleTable = buildReplicaRoleTable(kernel, input, resultSolid, replicas, outStmt)\n return fromBrep(solidToShape(kernel, resultSolid), { solid: resultSolid, roleTable })\n },\n capabilities: [\n 'dispose',\n 'fuseAll',\n 'gridPattern',\n 'hashCode',\n 'linearPattern',\n 'surfaceCenterOfMass',\n 'surfaceNormal',\n 'surfaceType',\n 'uvBounds',\n ],\n naming: { kind: 'replicate', k: 0 } as Provenance,\n})\n\n// ── rectangularPattern ──────────────────────────────────────────────────────\n\ninterface RectangularPatternOptions {\n xDir: Vec3\n xCount: number\n xSpacing: number\n yDir: Vec3\n yCount: number\n ySpacing: number\n}\n\n/**\n * 矩形阵列:按 options(xDir/xCount/xSpacing/yDir/yCount/ySpacing)复制并 fuse。\n * @group 特征\n * @inputs 1\n * @async true\n * @qual ok\n * @name rectangularPattern\n * @note BREP-only。keep 语义:不消费输入。结果面回投输入面角色,产出 `replica[ix_iy]/<inner>`。\n * @returns Shape 所有副本 fused 后的几何。\n * @param input - 目标几何。type:Shape required:true\n * @param options - 阵列参数。type:RectangularPatternOptions required:true\n * @example\n * const p = await cad.rectangularPattern(part0, { xDir: [1,0,0], xCount: 3, xSpacing: 20, yDir: [0,1,0], yCount: 2, ySpacing: 15 })\n */\nexport const rectangularPattern = defineOp({\n brep(input: Shape, options: RectangularPatternOptions) {\n keep(input)\n const { kernel, solid, outStmt } = prelude(input, 'rectangularPattern')\n const { xDir, xCount, xSpacing, yDir, yCount, ySpacing } = options\n const dx = norm(xDir)\n const dy = norm(yDir)\n // vendored rectangularPattern 是纯 JS 组合(translate + fuseAll),内核不声明\n // 该方法——与 vendored 同口径:逐份 translate 再 fuseAll。\n const copies: BrepHandle[] = []\n try {\n for (let ix = 0; ix < xCount; ix++) {\n for (let iy = 0; iy < yCount; iy++) {\n const ox = ix * xSpacing\n const oy = iy * ySpacing\n copies.push(kernel.translate(solid, ox * dx[0] + oy * dy[0], ox * dx[1] + oy * dy[1], ox * dx[2] + oy * dy[2]))\n }\n }\n const resultSolid = kernel.fuseAll(copies)\n\n const replicas: ReplicaTransform[] = []\n for (let ix = 0; ix < xCount; ix++) {\n for (let iy = 0; iy < yCount; iy++) {\n const ox = ix * xSpacing\n const oy = iy * ySpacing\n replicas.push({\n label: `replica[${ix}_${iy}]`,\n inverse: (c) => ({\n x: c.x - (ox * dx[0] + oy * dy[0]),\n y: c.y - (ox * dx[1] + oy * dy[1]),\n z: c.z - (ox * dx[2] + oy * dy[2]),\n }),\n })\n }\n }\n const roleTable = buildReplicaRoleTable(kernel, input, resultSolid, replicas, outStmt)\n return fromBrep(solidToShape(kernel, resultSolid), { solid: resultSolid, roleTable })\n } finally {\n for (const c of copies) kernel.release(c)\n }\n },\n capabilities: [\n 'dispose',\n 'fuse',\n 'fuseAll',\n 'fuseWithHistory',\n 'hashCode',\n 'surfaceCenterOfMass',\n 'surfaceNormal',\n 'surfaceType',\n 'uvBounds',\n ],\n naming: { kind: 'replicate', k: 0 } as Provenance,\n})\n\n// ── mirrorJoin ──────────────────────────────────────────────────────────────\n\ninterface MirrorJoinOptions {\n normal?: Vec3\n at?: Vec3\n}\n\n/**\n * 镜像并融合:原物(replica[0])+ 沿平面镜像(replica[1])fuse 成一体。\n * @group 特征\n * @inputs 1\n * @async true\n * @qual ok\n * @name mirrorJoin\n * @note BREP-only。keep 语义:不消费输入。结果面回投输入面角色,产出 `replica[0|1]/<inner>`。\n * @returns Shape fuse 后的几何。\n * @param input - 目标几何。type:Shape required:true\n * @param options - { normal?, at? } 镜像面法向与面上一点。type:MirrorJoinOptions required:false\n * @example\n * const p = await cad.mirrorJoin(part0, { normal: [1, 0, 0] })\n */\nexport const mirrorJoin = defineOp({\n brep(input: Shape, options?: MirrorJoinOptions) {\n keep(input)\n const { kernel, solid, outStmt } = prelude(input, 'mirrorJoin')\n const n = norm(options?.normal ?? [1, 0, 0])\n const o = toBrepVec(options?.at ?? [0, 0, 0])\n // 2026-09-26 C 批降级:原实现直调 getOcctKernel().mirrorWithHistory(occt-only history\n // 镜像,返回 modified/newFaces 供细粒度 roleTable)。按用户指示「有没有历史 withhistory\n // 并不重要」,降级为 L1 kernel.mirror(brepkit 已声明 mirror 能力)——几何结果一致,\n // roleTable 仍由 buildReplicaRoleTable 经质心聚类重建(引擎无关),仅丢失 history 级\n // modified 面映射(不影响几何与产物有效性)。\n const mirrored = kernel.mirror(solid, o, toBrepVec(n))\n try {\n const resultSolid = kernel.fuse(solid, mirrored)\n\n const replicas: ReplicaTransform[] = [\n { label: 'replica[0]', inverse: (c) => ({ x: c.x, y: c.y, z: c.z }) },\n { label: 'replica[1]', inverse: (c) => reflectAcrossPlane(c, o, n) },\n ]\n const roleTable = buildReplicaRoleTable(kernel, input, resultSolid, replicas, outStmt)\n return fromBrep(solidToShape(kernel, resultSolid), { solid: resultSolid, roleTable })\n } finally {\n kernel.release(mirrored)\n }\n },\n // 2026-09-26 C 批:从 engines:[occt] 降级为 capabilities:['mirror','fuse'](L1 中立面,\n // brepkit 已声明二者)。history 语义丢失(见上注释),几何不回退。\n capabilities: ['mirror', 'fuse'],\n naming: { kind: 'replicate', k: 2 } as Provenance,\n})\n\n// ── single-copy thin overrides(keep + 委托生成 op)─────────────────────────\n\n/**\n * 镜像:返回镜像后的新 Shape(源保留)。\n * @group 特征\n * @inputs 1\n * @async true\n * @qual ok\n * @name mirror\n * @note BREP-only。keep 语义:不消费输入(薄 override 委托生成 op,行为不变)。\n * @returns Shape 镜像后的新几何。\n * @param input - 目标几何。type:Shape required:true\n * @param options - { normal?, at? } 镜像面。type:MirrorOptions required:false\n * @example\n * const p = await cad.mirror(part0, { normal: [1, 0, 0] })\n */\nexport const mirror = defineOp({\n async brep(input: Shape, options?: MirrorOptions) {\n keep(input)\n return (await generatedMirror(input, options)) as Shape\n },\n // 2026-09-26 B 批:generatedMirror 已降级为 L1 kernel.mirror(brepkit 已声明 mirror\n // 能力),薄 override 同步从 engines:[occt] 降级为 capabilities:['mirror']——\n // 与 clone 薄 override 同模式(外层门不拦 brepkit,内层 generatedMirror 已按能力路由)。\n capabilities: ['mirror'],\n naming: { kind: 'kernel', newFaces: { via: 'byAdjacency' } } as Provenance,\n})\n\n/**\n * 深拷贝句柄:返回独立副本(源保留)。\n * @group 特征\n * @inputs 1\n * @async true\n * @qual ok\n * @name clone\n * @note BREP-only。keep 语义:不消费输入(薄 override 委托生成 op,行为不变)。\n * @returns Shape 克隆的新几何。\n * @param input - 目标几何。type:Shape required:true\n * @example\n * const p = await cad.clone(part0)\n */\nexport const clone = defineOp({\n async brep(input: Shape) {\n keep(input)\n return (await generatedClone(input)) as Shape\n },\n capabilities: ['copyShape', 'dispose'],\n naming: { kind: 'identity' } as Provenance,\n})\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"arg-spec.d.ts","sourceRoot":"","sources":["../../../src/api/surface/arg-spec.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,kBAAkB;AAClB,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAA;AAErF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAA;AAC/D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AAC3D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAA;AAE5E,YAAY,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAA;AAE/D,uDAAuD;AAEvD;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,8CAA8C;IAC9C,IAAI,EAAE,MAAM,CAAA;IACZ,iDAAiD;IACjD,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,kBAAkB;IAClB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED;;;;;;GAMG;AACH,MAAM,MAAM,SAAS,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,CAAA;AAEzC;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,cAAc,CAAA;IACpB,6BAA6B;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,qDAAqD;IACrD,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,qEAAqE;IACrE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;IACvB;;OAEG;IACH,sBAAsB,CAAC,EAAE,MAAM,EAAE,CAAA;IACjC,8GAA8G;IAC9G,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,yFAAyF;IACzF,WAAW,CAAC,EAAE,UAAU,EAAE,CAAA;IAC1B,uNAAuN;IACvN,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,mEAAmE;IACnE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IACjB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,kBAAkB,EAAE,CAAA;IACnC;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,SAAS,YAAY,EAAE,CAAA;IACjC,iDAAiD;IACjD,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,UAAU,CAAA;IACnB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,kEAAkE;IAClE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,4DAA4D;IAC5D,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,8CAA8C;IAC9C,OAAO,CAAC,EAAE,OAAO,mCAAmC,EAAE,OAAO,CAAA;CAC9D;AAED;;;;GAIG;AACH,eAAO,MAAM,QAAQ,EAAE,YAAY,EA0zHlC,CAAA"}
1
+ {"version":3,"file":"arg-spec.d.ts","sourceRoot":"","sources":["../../../src/api/surface/arg-spec.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,kBAAkB;AAClB,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAA;AAErF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAA;AAC/D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AAC3D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAA;AAE5E,YAAY,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAA;AAE/D,uDAAuD;AAEvD;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,8CAA8C;IAC9C,IAAI,EAAE,MAAM,CAAA;IACZ,iDAAiD;IACjD,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,kBAAkB;IAClB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED;;;;;;GAMG;AACH,MAAM,MAAM,SAAS,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,CAAA;AAEzC;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,cAAc,CAAA;IACpB,6BAA6B;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,qDAAqD;IACrD,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,qEAAqE;IACrE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;IACvB;;OAEG;IACH,sBAAsB,CAAC,EAAE,MAAM,EAAE,CAAA;IACjC,8GAA8G;IAC9G,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,yFAAyF;IACzF,WAAW,CAAC,EAAE,UAAU,EAAE,CAAA;IAC1B,uNAAuN;IACvN,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,mEAAmE;IACnE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IACjB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,kBAAkB,EAAE,CAAA;IACnC;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,SAAS,YAAY,EAAE,CAAA;IACjC,iDAAiD;IACjD,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,UAAU,CAAA;IACnB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,kEAAkE;IAClE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,4DAA4D;IAC5D,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,8CAA8C;IAC9C,OAAO,CAAC,EAAE,OAAO,mCAAmC,EAAE,OAAO,CAAA;CAC9D;AAED;;;;GAIG;AACH,eAAO,MAAM,QAAQ,EAAE,YAAY,EA+zHlC,CAAA"}