@faicad/fai-cq-gears 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 (57) hide show
  1. package/dist/bevel_gear.d.ts +113 -0
  2. package/dist/bevel_gear.d.ts.map +1 -0
  3. package/dist/bevel_gear.js +327 -0
  4. package/dist/bevel_gear.js.map +1 -0
  5. package/dist/crossed_helical_gear.d.ts +24 -0
  6. package/dist/crossed_helical_gear.d.ts.map +1 -0
  7. package/dist/crossed_helical_gear.js +24 -0
  8. package/dist/crossed_helical_gear.js.map +1 -0
  9. package/dist/crossed_pair.d.ts +177 -0
  10. package/dist/crossed_pair.d.ts.map +1 -0
  11. package/dist/crossed_pair.js +237 -0
  12. package/dist/crossed_pair.js.map +1 -0
  13. package/dist/features.d.ts +184 -0
  14. package/dist/features.d.ts.map +1 -0
  15. package/dist/features.js +408 -0
  16. package/dist/features.js.map +1 -0
  17. package/dist/index.d.ts +178 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.js +223 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/math.d.ts +200 -0
  22. package/dist/math.d.ts.map +1 -0
  23. package/dist/math.js +274 -0
  24. package/dist/math.js.map +1 -0
  25. package/dist/pairs.d.ts +161 -0
  26. package/dist/pairs.d.ts.map +1 -0
  27. package/dist/pairs.js +183 -0
  28. package/dist/pairs.js.map +1 -0
  29. package/dist/planetary.d.ts +96 -0
  30. package/dist/planetary.d.ts.map +1 -0
  31. package/dist/planetary.js +139 -0
  32. package/dist/planetary.js.map +1 -0
  33. package/dist/profile.d.ts +439 -0
  34. package/dist/profile.d.ts.map +1 -0
  35. package/dist/profile.js +592 -0
  36. package/dist/profile.js.map +1 -0
  37. package/dist/rack_gear.d.ts +125 -0
  38. package/dist/rack_gear.d.ts.map +1 -0
  39. package/dist/rack_gear.js +344 -0
  40. package/dist/rack_gear.js.map +1 -0
  41. package/dist/ring_gear.d.ts +54 -0
  42. package/dist/ring_gear.d.ts.map +1 -0
  43. package/dist/ring_gear.js +133 -0
  44. package/dist/ring_gear.js.map +1 -0
  45. package/dist/spline-face.d.ts +99 -0
  46. package/dist/spline-face.d.ts.map +1 -0
  47. package/dist/spline-face.js +94 -0
  48. package/dist/spline-face.js.map +1 -0
  49. package/dist/spur_gear.d.ts +112 -0
  50. package/dist/spur_gear.d.ts.map +1 -0
  51. package/dist/spur_gear.js +206 -0
  52. package/dist/spur_gear.js.map +1 -0
  53. package/dist/worm_gear.d.ts +78 -0
  54. package/dist/worm_gear.d.ts.map +1 -0
  55. package/dist/worm_gear.js +256 -0
  56. package/dist/worm_gear.js.map +1 -0
  57. package/package.json +47 -0
@@ -0,0 +1,125 @@
1
+ /**
2
+ * rack_gear — RackGear / HerringboneRackGear(齿条)实体构造
3
+ *
4
+ * 对应 `RackGear._build_gear_faces()` + `_build()`(`HerringboneRackGear` 只覆盖
5
+ * `_build_tooth_faces`,其余全部继承):
6
+ *
7
+ * ```
8
+ * ① 齿面:4 段梯形直线廓形 × 2 行(z=0 / z=width,行间 x 平移 tx=tan(h)·width)
9
+ * → 2×2 点阵 → spline 面(Herringbone:上下两半正反螺旋,共 8 面/齿)
10
+ * ② 沿 X 以 π·m 为步距复制齿(按螺旋方向多补 extra 个),端部用
11
+ * x=0 / x=length 两块大平面 `split` 裁剪(compound → 按 bbox 取碎片)
12
+ * ③ 左/右侧面:收 x=0 / x=length 平面上的齿面边 + 3 条轮廓线 → 组线 → 平面
13
+ * ④ 背面(y=ld−height 矩形)+ 顶/底盖面(收 z=width / z=0 的边组线成面)
14
+ * ⑤ sew → makeSolid → fixFaceOrientations
15
+ * ```
16
+ *
17
+ * 官方 `build()` 对齿条**无** bore/chamfer 特征(`_build` 只做 faces→shell→solid),
18
+ * 所以回归体积直接对照 regression json 的 expected。
19
+ */
20
+ import type { BrepHandle } from '@faicad/faijs';
21
+ import type { GearKernel } from '@faicad/cq-compat';
22
+ import { type RackGearGeometry, type RackGearParams } from './profile.js';
23
+ import { type SplineFaceStrategy } from './spline-face.js';
24
+ import { type Vec3 } from './math.js';
25
+ /** RackGear 实体构造选项。 */
26
+ export interface BuildRackGearOptions {
27
+ strategy?: SplineFaceStrategy;
28
+ /** 缝合容差(cq `shell_sewing_tol`)。 */
29
+ shellSewingTol?: number;
30
+ /** 组线容差(cq `wire_comb_tol`)。 */
31
+ wireCombTol?: number;
32
+ /** HerringboneRackGear:齿宽上下两半正反螺旋。 */
33
+ herringbone?: boolean;
34
+ }
35
+ /**
36
+ * ① 基础齿面(单个齿位,未平移):普通 4 面,Herringbone 上下两半共 8 面。
37
+ *
38
+ * @param kernel 原始 OCCT 内核
39
+ * @param geom 齿条几何量
40
+ * @param herringbone 是否人字齿(上下两半螺旋方向相反)
41
+ * @param strategy 样条建面策略
42
+ * @returns 基础齿面数组(4 或 8 个面)
43
+ */
44
+ export declare function rackToothFaces(kernel: GearKernel, geom: RackGearGeometry, herringbone: boolean, strategy: SplineFaceStrategy): BrepHandle[];
45
+ /**
46
+ * ② 单个齿位的齿面:基础齿面沿 X 平移 `π·m·i`,然后按 cq 顺序做左/右端裁剪。
47
+ *
48
+ * cq 的 split 语义(probe-rack.ts 已实测):
49
+ * - 工具平面与面相交 → compound,碎片按 bbox.xmax / xmin 取
50
+ * - 不相交 → 原面单返回(cq 返回 face 本身),再按 bbox 判断丢弃
51
+ *
52
+ * @param kernel 原始 OCCT 内核
53
+ * @param base 基础齿面数组(rackToothFaces 的产物)
54
+ * @param dx 齿位沿 X 的平移量(π·m·i)
55
+ * @param i 齿位序号(决定触发哪一侧裁剪分支)
56
+ * @param geom 齿条几何量
57
+ * @param extra 端部补齿数(Python `extra`)
58
+ * @param cutL 左端裁剪平面(x=0)
59
+ * @param cutR 右端裁剪平面(x=length)
60
+ * @returns 保留的面;完全被裁掉时返回空数组
61
+ */
62
+ export declare function toothAtPosition(kernel: GearKernel, base: BrepHandle[], dx: number, i: number, geom: RackGearGeometry, extra: number, cutL: BrepHandle, cutR: BrepHandle): BrepHandle[];
63
+ /**
64
+ * 大平面工具(cq `Face.makePlane(length, width, basePnt, dir)` 的等价物)。
65
+ *
66
+ * @param kernel 原始 OCCT 内核
67
+ * @param length 平面在局部 u 方向的长度
68
+ * @param width 平面在局部 v 方向的宽度
69
+ * @param basePnt 平面中心点
70
+ * @param dir 平面法向
71
+ * @returns 矩形平面 Face
72
+ */
73
+ export declare function cutPlane(kernel: GearKernel, length: number, width: number, basePnt: Vec3, dir: Vec3): BrepHandle;
74
+ /**
75
+ * 收集边集合里「边中心 X 为极值」的边(cq `edges('<X'/'>X')` 语义)。
76
+ *
77
+ * @param kernel 原始 OCCT 内核
78
+ * @param faces 候选面集合
79
+ * @param side 取最小(left)还是最大(right)
80
+ * @returns 中心落在极值 ±容差内的边
81
+ */
82
+ export declare function extremeXEdges(kernel: GearKernel, faces: BrepHandle[], side: 'left' | 'right'): BrepHandle[];
83
+ /**
84
+ * ③ 端面(cq 左/右侧面):裁剪后的齿面在端部截面上的边 + 3 条轮廓直线
85
+ * (沿截面到背面 y=ld−height 的两条横线 + 背面竖线),组线成面。
86
+ *
87
+ * cq 的辅助线从 `vertices('<Z')` / `vertices('>Z')` 出发——即截面链上 **z 最小/
88
+ * 最大的端点**(其 y 未必是链上 y 的极值,螺旋齿条下两者不同)。
89
+ *
90
+ * @param kernel 原始 OCCT 内核
91
+ * @param toothFaces 裁剪后的齿面集合
92
+ * @param side 左端(x=0)还是右端(x=length)
93
+ * @param geom 齿条几何量
94
+ * @param wireCombTol 组线容差
95
+ * @returns 端面 Face
96
+ */
97
+ export declare function endCapFace(kernel: GearKernel, toothFaces: BrepHandle[], side: 'left' | 'right', geom: RackGearGeometry, wireCombTol: number): BrepHandle;
98
+ /**
99
+ * ④ 背面:y = ld−height 平面上的 length×width 矩形(cq `.rect(length, width, centered=False)`)。
100
+ *
101
+ * @param kernel 原始 OCCT 内核
102
+ * @param geom 齿条几何量
103
+ * @returns 背面 Face
104
+ */
105
+ export declare function backFace(kernel: GearKernel, geom: RackGearGeometry): BrepHandle;
106
+ /**
107
+ * ④ 顶/底盖面:收所有面在 z=const 平面上的边界边 → 组线(外轮廓 1 条,含齿谷
108
+ * 波形与两侧背线)→ 平面。cq `.edges('>Z'/ '<Z').consolidateWires()` 后取第一条。
109
+ *
110
+ * @param kernel 原始 OCCT 内核
111
+ * @param faces 候选面集合(齿面 + 端面 + 背面)
112
+ * @param z 盖面所在高度(width 或 0)
113
+ * @returns 盖面 Face(开环 wire 建面,与 cq 语义一致)
114
+ */
115
+ export declare function planarCapAtZ(kernel: GearKernel, faces: BrepHandle[], z: number): BrepHandle;
116
+ /**
117
+ * ①–⑤:完整 RackGear / HerringboneRackGear 实体。
118
+ *
119
+ * @param kernel 原始 OCCT 内核
120
+ * @param params 齿条参数(逐字沿用 Python 构造参数名)
121
+ * @param build 构造选项(策略/容差覆盖)
122
+ * @returns solid
123
+ */
124
+ export declare function buildRackGearSolid(kernel: GearKernel, params: RackGearParams, build?: BuildRackGearOptions): BrepHandle;
125
+ //# sourceMappingURL=rack_gear.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rack_gear.d.ts","sourceRoot":"","sources":["../src/rack_gear.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AACnD,OAAO,EAEL,KAAK,gBAAgB,EAAE,KAAK,cAAc,EAC3C,MAAM,WAAW,CAAA;AAClB,OAAO,EAAiD,KAAK,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAEtG,OAAO,EAAQ,KAAK,IAAI,EAAE,MAAM,QAAQ,CAAA;AAaxC,uBAAuB;AACvB,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,EAAE,kBAAkB,CAAA;IAC7B,mCAAmC;IACnC,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,gCAAgC;IAChC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,sCAAsC;IACtC,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB;AAqBD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,gBAAgB,EACtB,WAAW,EAAE,OAAO,EACpB,QAAQ,EAAE,kBAAkB,GAC3B,UAAU,EAAE,CAuBd;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,UAAU,EAAE,EAClB,EAAE,EAAE,MAAM,EACV,CAAC,EAAE,MAAM,EACT,IAAI,EAAE,gBAAgB,EACtB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,UAAU,GACf,UAAU,EAAE,CAqCd;AAED;;;;;;;;;GASG;AACH,wBAAgB,QAAQ,CACtB,MAAM,EAAE,UAAU,EAClB,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAC7B,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,GACvB,UAAU,CAyBZ;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,GAC9D,UAAU,EAAE,CAad;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,UAAU,CACxB,MAAM,EAAE,UAAU,EAClB,UAAU,EAAE,UAAU,EAAE,EACxB,IAAI,EAAE,MAAM,GAAG,OAAO,EACtB,IAAI,EAAE,gBAAgB,EACtB,WAAW,EAAE,MAAM,GAClB,UAAU,CA2BZ;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,gBAAgB,GAAG,UAAU,CAU/E;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,UAAU,EAAE,EACnB,CAAC,EAAE,MAAM,GACR,UAAU,CAoBZ;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,UAAU,EAClB,MAAM,EAAE,cAAc,EACtB,KAAK,GAAE,oBAAyB,GAC/B,UAAU,CA4DZ"}
@@ -0,0 +1,344 @@
1
+ /**
2
+ * rack_gear — RackGear / HerringboneRackGear(齿条)实体构造
3
+ *
4
+ * 对应 `RackGear._build_gear_faces()` + `_build()`(`HerringboneRackGear` 只覆盖
5
+ * `_build_tooth_faces`,其余全部继承):
6
+ *
7
+ * ```
8
+ * ① 齿面:4 段梯形直线廓形 × 2 行(z=0 / z=width,行间 x 平移 tx=tan(h)·width)
9
+ * → 2×2 点阵 → spline 面(Herringbone:上下两半正反螺旋,共 8 面/齿)
10
+ * ② 沿 X 以 π·m 为步距复制齿(按螺旋方向多补 extra 个),端部用
11
+ * x=0 / x=length 两块大平面 `split` 裁剪(compound → 按 bbox 取碎片)
12
+ * ③ 左/右侧面:收 x=0 / x=length 平面上的齿面边 + 3 条轮廓线 → 组线 → 平面
13
+ * ④ 背面(y=ld−height 矩形)+ 顶/底盖面(收 z=width / z=0 的边组线成面)
14
+ * ⑤ sew → makeSolid → fixFaceOrientations
15
+ * ```
16
+ *
17
+ * 官方 `build()` 对齿条**无** bore/chamfer 特征(`_build` 只做 faces→shell→solid),
18
+ * 所以回归体积直接对照 regression json 的 expected。
19
+ */
20
+ import { GEAR_BASE_CONSTANTS, rackGearGeometry, } from './profile.js';
21
+ import { buildSplineFace, DEFAULT_SPLINE_FACE_STRATEGY } from './spline-face.js';
22
+ import { connectEdgesToWires, gearEdgeEnds as edgeEnds, gearShellToSolid as shellToSolid } from '@faicad/cq-compat';
23
+ import { vec3 } from './math.js';
24
+ /** 侧端裁剪平面比齿廓超出的余量(Python `cp_ext`)。 */
25
+ const CP_EXT = 10.0;
26
+ /** 判定「边完全落在某坐标平面」的容差(远小于 wire_comb_tol)。 */
27
+ const PLANAR_PICK_TOL = 1e-6;
28
+ /**
29
+ * 顶/底盖面组线合并容差:cq `consolidateWires` 链接样条近似边时依赖
30
+ * 样条容差量级的顶点合并(1e-2),不是拓扑容差 1e-6(probe-case26.py 实证)。
31
+ */
32
+ const CAP_WIRE_MERGE_TOL = 1e-2;
33
+ /**
34
+ * 一个齿面段的 2×2 点阵:底行在 `z`(x 平移 `x`),顶行在 `z+w`(x 再平移
35
+ * `tan(helix)·w`)。cq `_build_tooth_faces` 的 pts1/pts2 逐字对应。
36
+ */
37
+ function rackFaceGrid(segPts, seg, helixRad, x, z, w) {
38
+ const tx = Math.tan(helixRad) * w;
39
+ return {
40
+ segment: seg,
41
+ rows: 2,
42
+ cols: 2,
43
+ points: [
44
+ segPts.map((p) => vec3(p.x + x, p.y, z)),
45
+ segPts.map((p) => vec3(p.x + x + tx, p.y, z + w)),
46
+ ],
47
+ };
48
+ }
49
+ /**
50
+ * ① 基础齿面(单个齿位,未平移):普通 4 面,Herringbone 上下两半共 8 面。
51
+ *
52
+ * @param kernel 原始 OCCT 内核
53
+ * @param geom 齿条几何量
54
+ * @param herringbone 是否人字齿(上下两半螺旋方向相反)
55
+ * @param strategy 样条建面策略
56
+ * @returns 基础齿面数组(4 或 8 个面)
57
+ */
58
+ export function rackToothFaces(kernel, geom, herringbone, strategy) {
59
+ const segs = [
60
+ ['lflank', geom.t_lflank_pts],
61
+ ['tip', geom.t_tip_pts],
62
+ ['rflank', geom.t_rflank_pts],
63
+ ['root', geom.t_root_pts],
64
+ ];
65
+ const faces = [];
66
+ const half = geom.width / 2;
67
+ if (herringbone) {
68
+ const tx = Math.tan(geom.helixAngle) * half;
69
+ for (const [seg, pts] of segs) {
70
+ // 下半:正向螺旋,z ∈ [0, width/2]
71
+ faces.push(buildSplineFace(kernel, rackFaceGrid(pts, seg, geom.helixAngle, 0, 0, half), strategy));
72
+ // 上半:反向螺旋,起点 x 平移 tx,z ∈ [width/2, width]
73
+ faces.push(buildSplineFace(kernel, rackFaceGrid(pts, seg, -geom.helixAngle, tx, half, half), strategy));
74
+ }
75
+ }
76
+ else {
77
+ for (const [seg, pts] of segs) {
78
+ faces.push(buildSplineFace(kernel, rackFaceGrid(pts, seg, geom.helixAngle, 0, 0, geom.width), strategy));
79
+ }
80
+ }
81
+ return faces;
82
+ }
83
+ /**
84
+ * ② 单个齿位的齿面:基础齿面沿 X 平移 `π·m·i`,然后按 cq 顺序做左/右端裁剪。
85
+ *
86
+ * cq 的 split 语义(probe-rack.ts 已实测):
87
+ * - 工具平面与面相交 → compound,碎片按 bbox.xmax / xmin 取
88
+ * - 不相交 → 原面单返回(cq 返回 face 本身),再按 bbox 判断丢弃
89
+ *
90
+ * @param kernel 原始 OCCT 内核
91
+ * @param base 基础齿面数组(rackToothFaces 的产物)
92
+ * @param dx 齿位沿 X 的平移量(π·m·i)
93
+ * @param i 齿位序号(决定触发哪一侧裁剪分支)
94
+ * @param geom 齿条几何量
95
+ * @param extra 端部补齿数(Python `extra`)
96
+ * @param cutL 左端裁剪平面(x=0)
97
+ * @param cutR 右端裁剪平面(x=length)
98
+ * @returns 保留的面;完全被裁掉时返回空数组
99
+ */
100
+ export function toothAtPosition(kernel, base, dx, i, geom, extra, cutL, cutR) {
101
+ const faces = [];
102
+ for (const tf of base) {
103
+ let face = kernel.translate(tf, dx, 0, 0);
104
+ if (i <= extra + 1) {
105
+ const cpd = kernel.split(face, [cutL]);
106
+ const frags = kernel.isFace(cpd) ? [cpd] : kernel.getSubShapes(cpd, 'face');
107
+ if (frags.length > 1) {
108
+ // compound:取 bbox.xmax 最大的碎片(cq max(key=get_xmax))
109
+ let best = frags[0];
110
+ for (const f of frags) {
111
+ if (kernel.getBoundingBox(f).xmax > kernel.getBoundingBox(best).xmax)
112
+ best = f;
113
+ }
114
+ face = best;
115
+ }
116
+ else {
117
+ face = frags[0];
118
+ if (kernel.getBoundingBox(face).xmax < 0.0)
119
+ continue;
120
+ }
121
+ }
122
+ if (i >= geom.z - extra - 1) {
123
+ const cpd = kernel.split(face, [cutR]);
124
+ const frags = kernel.isFace(cpd) ? [cpd] : kernel.getSubShapes(cpd, 'face');
125
+ if (frags.length > 1) {
126
+ // compound:取 bbox.xmin 最小的碎片(cq min(key=get_xmin))
127
+ let best = frags[0];
128
+ for (const f of frags) {
129
+ if (kernel.getBoundingBox(f).xmin < kernel.getBoundingBox(best).xmin)
130
+ best = f;
131
+ }
132
+ face = best;
133
+ }
134
+ else {
135
+ face = frags[0];
136
+ if (kernel.getBoundingBox(face).xmin > geom.length)
137
+ continue;
138
+ }
139
+ }
140
+ faces.push(face);
141
+ }
142
+ return faces;
143
+ }
144
+ /**
145
+ * 大平面工具(cq `Face.makePlane(length, width, basePnt, dir)` 的等价物)。
146
+ *
147
+ * @param kernel 原始 OCCT 内核
148
+ * @param length 平面在局部 u 方向的长度
149
+ * @param width 平面在局部 v 方向的宽度
150
+ * @param basePnt 平面中心点
151
+ * @param dir 平面法向
152
+ * @returns 矩形平面 Face
153
+ */
154
+ export function cutPlane(kernel, length, width, basePnt, dir) {
155
+ // 面法向 dir,面内局部坐标:任取与 dir 垂直的两个轴
156
+ const ref = Math.abs(dir.z) < 0.9 ? vec3(0, 0, 1) : vec3(1, 0, 0);
157
+ let u = vec3(dir.y * ref.z - dir.z * ref.y, dir.z * ref.x - dir.x * ref.z, dir.x * ref.y - dir.y * ref.x);
158
+ const un = Math.hypot(u.x, u.y, u.z);
159
+ u = vec3(u.x / un, u.y / un, u.z / un);
160
+ const v = vec3(dir.y * u.z - dir.z * u.y, dir.z * u.x - dir.x * u.z, dir.x * u.y - dir.y * u.x);
161
+ const h = length / 2;
162
+ const w = width / 2;
163
+ const p = (a, b) => vec3(basePnt.x + u.x * a + v.x * b, basePnt.y + u.y * a + v.y * b, basePnt.z + u.z * a + v.z * b);
164
+ const es = [
165
+ kernel.makeLineEdge(p(-h, -w), p(h, -w)),
166
+ kernel.makeLineEdge(p(h, -w), p(h, w)),
167
+ kernel.makeLineEdge(p(h, w), p(-h, w)),
168
+ kernel.makeLineEdge(p(-h, w), p(-h, -w)),
169
+ ];
170
+ return kernel.makeFace(kernel.makeWire(es));
171
+ }
172
+ /**
173
+ * 收集边集合里「边中心 X 为极值」的边(cq `edges('<X'/'>X')` 语义)。
174
+ *
175
+ * @param kernel 原始 OCCT 内核
176
+ * @param faces 候选面集合
177
+ * @param side 取最小(left)还是最大(right)
178
+ * @returns 中心落在极值 ±容差内的边
179
+ */
180
+ export function extremeXEdges(kernel, faces, side) {
181
+ let extreme = side === 'left' ? Infinity : -Infinity;
182
+ const centers = [];
183
+ for (const f of faces) {
184
+ for (const e of kernel.getSubShapes(f, 'edge')) {
185
+ const bb = kernel.getBoundingBox(e);
186
+ const cx = (bb.xmin + bb.xmax) / 2;
187
+ centers.push({ e, cx });
188
+ extreme = side === 'left' ? Math.min(extreme, cx) : Math.max(extreme, cx);
189
+ }
190
+ }
191
+ // cq DirectionMinMaxSelector 的容差语义:中心在极值 ± tol 内都算选中
192
+ return centers.filter((c) => Math.abs(c.cx - extreme) <= PLANAR_PICK_TOL).map((c) => c.e);
193
+ }
194
+ /**
195
+ * ③ 端面(cq 左/右侧面):裁剪后的齿面在端部截面上的边 + 3 条轮廓直线
196
+ * (沿截面到背面 y=ld−height 的两条横线 + 背面竖线),组线成面。
197
+ *
198
+ * cq 的辅助线从 `vertices('<Z')` / `vertices('>Z')` 出发——即截面链上 **z 最小/
199
+ * 最大的端点**(其 y 未必是链上 y 的极值,螺旋齿条下两者不同)。
200
+ *
201
+ * @param kernel 原始 OCCT 内核
202
+ * @param toothFaces 裁剪后的齿面集合
203
+ * @param side 左端(x=0)还是右端(x=length)
204
+ * @param geom 齿条几何量
205
+ * @param wireCombTol 组线容差
206
+ * @returns 端面 Face
207
+ */
208
+ export function endCapFace(kernel, toothFaces, side, geom, wireCombTol) {
209
+ const picked = extremeXEdges(kernel, toothFaces, side);
210
+ if (picked.length === 0) {
211
+ throw new Error(`endCapFace(${side}): no edges selected`);
212
+ }
213
+ // 截面链的 z 最小 / 最大端点(cq pt1 / pt2)
214
+ let pt1;
215
+ let pt2;
216
+ for (const e of picked) {
217
+ const ends = edgeEnds(kernel, e);
218
+ for (const p of [ends.a, ends.b]) {
219
+ if (!pt1 || p.z < pt1.z)
220
+ pt1 = { y: p.y, z: p.z };
221
+ if (!pt2 || p.z > pt2.z)
222
+ pt2 = { y: p.y, z: p.z };
223
+ }
224
+ }
225
+ const backY = geom.ld - geom.height;
226
+ const pt = (y, z) => vec3(side === 'left' ? 0 : geom.length, y, z);
227
+ const lines = [
228
+ kernel.makeLineEdge(pt(pt1.y, pt1.z), pt(backY, pt1.z)),
229
+ kernel.makeLineEdge(pt(backY, pt1.z), pt(backY, pt2.z)),
230
+ kernel.makeLineEdge(pt(backY, pt2.z), pt(pt2.y, pt2.z)),
231
+ ];
232
+ const wires = connectEdgesToWires(kernel, [...picked, ...lines], wireCombTol);
233
+ if (wires.length !== 1) {
234
+ throw new Error(`endCapFace(${side}): expected 1 closed loop, got ${wires.length}`);
235
+ }
236
+ return kernel.makeFace(wires[0]);
237
+ }
238
+ /**
239
+ * ④ 背面:y = ld−height 平面上的 length×width 矩形(cq `.rect(length, width, centered=False)`)。
240
+ *
241
+ * @param kernel 原始 OCCT 内核
242
+ * @param geom 齿条几何量
243
+ * @returns 背面 Face
244
+ */
245
+ export function backFace(kernel, geom) {
246
+ const y = geom.ld - geom.height;
247
+ const p = (a, b) => vec3(a, y, b);
248
+ const es = [
249
+ kernel.makeLineEdge(p(0, 0), p(geom.length, 0)),
250
+ kernel.makeLineEdge(p(geom.length, 0), p(geom.length, geom.width)),
251
+ kernel.makeLineEdge(p(geom.length, geom.width), p(0, geom.width)),
252
+ kernel.makeLineEdge(p(0, geom.width), p(0, 0)),
253
+ ];
254
+ return kernel.makeFace(kernel.makeWire(es));
255
+ }
256
+ /**
257
+ * ④ 顶/底盖面:收所有面在 z=const 平面上的边界边 → 组线(外轮廓 1 条,含齿谷
258
+ * 波形与两侧背线)→ 平面。cq `.edges('>Z'/ '<Z').consolidateWires()` 后取第一条。
259
+ *
260
+ * @param kernel 原始 OCCT 内核
261
+ * @param faces 候选面集合(齿面 + 端面 + 背面)
262
+ * @param z 盖面所在高度(width 或 0)
263
+ * @returns 盖面 Face(开环 wire 建面,与 cq 语义一致)
264
+ */
265
+ export function planarCapAtZ(kernel, faces, z) {
266
+ const edges = [];
267
+ for (const f of faces) {
268
+ for (const e of kernel.getSubShapes(f, 'edge')) {
269
+ const bb = kernel.getBoundingBox(e);
270
+ if (Math.abs(bb.zmin - z) <= PLANAR_PICK_TOL && Math.abs(bb.zmax - z) <= PLANAR_PICK_TOL) {
271
+ edges.push(e);
272
+ }
273
+ }
274
+ }
275
+ if (edges.length === 0)
276
+ throw new Error(`planarCapAtZ: no edges at z=${z}`);
277
+ // cq 的 consolidateWires 依赖样条近似边的顶点容差(≈spline tol 量级)链接边,
278
+ // 且 makeFromWires 接受开环 wire(probe-case26.py 实测:cq 组出 1 条 closed=False
279
+ // 的 wire 仍建面成功、体积精确)。故这里用样条容差量级合并、取第一条 wire、
280
+ // 不强制闭合——与 cq 语义逐字对齐。
281
+ const wires = connectEdgesToWires(kernel, edges, CAP_WIRE_MERGE_TOL);
282
+ if (wires.length === 0) {
283
+ throw new Error(`planarCapAtZ(z=${z}): no wires consolidated from ${edges.length} edges`);
284
+ }
285
+ return kernel.makeFace(wires[0]);
286
+ }
287
+ /**
288
+ * ①–⑤:完整 RackGear / HerringboneRackGear 实体。
289
+ *
290
+ * @param kernel 原始 OCCT 内核
291
+ * @param params 齿条参数(逐字沿用 Python 构造参数名)
292
+ * @param build 构造选项(策略/容差覆盖)
293
+ * @returns solid
294
+ */
295
+ export function buildRackGearSolid(kernel, params, build = {}) {
296
+ const strategy = build.strategy ?? DEFAULT_SPLINE_FACE_STRATEGY;
297
+ const geom = rackGearGeometry(params);
298
+ const herringbone = build.herringbone ?? false;
299
+ const wireCombTol = build.wireCombTol ?? GEAR_BASE_CONSTANTS.wire_comb_tol;
300
+ const sewingTol = build.shellSewingTol ?? GEAR_BASE_CONSTANTS.shell_sewing_tol;
301
+ // ② 端部裁剪平面(x=0 左侧 / x=length 右侧,各外扩 cp_ext)
302
+ const cutL = cutPlane(kernel, geom.toothHeight + CP_EXT, geom.width + CP_EXT, vec3(0, 0, geom.width / 2), vec3(-1, 0, 0));
303
+ const cutR = cutPlane(kernel, geom.toothHeight + CP_EXT, geom.width + CP_EXT, vec3(geom.length, 0, geom.width / 2), vec3(1, 0, 0));
304
+ // extra = int(abs(ceil(tan(h)·width / (π·m))))——abs 在 ceil **之外**(Python 逐字:
305
+ // `int(abs(np.ceil(...)))`),负螺旋角时 ceil 为负、取 abs 后为正。
306
+ const extra = Math.abs(Math.ceil(Math.tan(geom.helixAngle) * geom.width / (Math.PI * geom.m)));
307
+ const base = rackToothFaces(kernel, geom, herringbone, strategy);
308
+ const toothFaces = [];
309
+ // tidx 按螺旋方向分三种(Python 逐字):正螺旋左侧多补、负螺旋右侧多补、直齿不补
310
+ const iLo = geom.helixAngle > 0 ? -extra : 0;
311
+ const iHi = geom.helixAngle > 0 ? geom.z : geom.z + extra;
312
+ for (let i = iLo; i <= iHi; i++) {
313
+ toothFaces.push(...toothAtPosition(kernel, base, Math.PI * geom.m * i, i, geom, extra, cutL, cutR));
314
+ }
315
+ if (toothFaces.length === 0) {
316
+ throw new Error('buildRackGearSolid: no tooth faces survived end trimming');
317
+ }
318
+ // ③ 端面 + ④ 背面 + 顶/底盖面
319
+ const lsFace = endCapFace(kernel, toothFaces, 'left', geom, wireCombTol);
320
+ const rsFace = endCapFace(kernel, toothFaces, 'right', geom, wireCombTol);
321
+ const bkFace = backFace(kernel, geom);
322
+ const all = [...toothFaces, lsFace, rsFace, bkFace];
323
+ const tpFace = planarCapAtZ(kernel, all, geom.width);
324
+ const btFace = planarCapAtZ(kernel, all, 0);
325
+ // ⑤ 缝合 → 实体化 → 朝向归一化
326
+ const solid = shellToSolid(kernel, [...all, tpFace, btFace], sewingTol);
327
+ // fixFaceOrientations 在微开口 shell(cq 同样存在:rs 端面只到 zmax≈width−0.18,
328
+ // 靠 sew 容差吸收)上会把 solid 拆回 shell(debug-rack-cap.ts 实测)。退化路径:
329
+ // makeSolid 的产物直接按体积符号归一化朝向。
330
+ let oriented = solid;
331
+ if (kernel.isSolid(solid)) {
332
+ const fixed = kernel.fixFaceOrientations(solid);
333
+ if (kernel.isSolid(fixed))
334
+ oriented = fixed;
335
+ }
336
+ if (!kernel.isSolid(oriented)) {
337
+ throw new Error(`buildRackGearSolid: result is not a solid (got ${String(kernel.getShapeType(oriented))})`);
338
+ }
339
+ if (kernel.getVolume(oriented) < 0) {
340
+ oriented = kernel.reverseShape(oriented);
341
+ }
342
+ return oriented;
343
+ }
344
+ //# sourceMappingURL=rack_gear.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rack_gear.js","sourceRoot":"","sources":["../src/rack_gear.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * ring_gear — RingGear(内部齿)实体构造
3
+ *
4
+ * 对应 `RingGear._build_gear_faces()` + `_build_rim_face()` + `_build()`:
5
+ *
6
+ * ```
7
+ * ① 4z 个齿面(复用 SpurGear 的 `buildToothFaces`,因为点集布局一致)
8
+ * ② 外圈 rim:两圈圆环 wire(z=0 / z=width)经 `loft(ruled=true)` 蒙成圆柱面
9
+ * ③ 顶/底面:在 z=width / z=0 收齿面边界边 → 组线成内孔 wire,
10
+ * 再用 `Face.makeFromWires(rimWire, [toothWire])` 做成**环形**盖面(外圆 rim_r、内孔齿廓)
11
+ * ④ sew(齿面 + rim + 2 盖面) → makeSolid → fixFaceOrientations
12
+ * ```
13
+ *
14
+ * 与 SpurGear 的关键差异:端面是**环形**(外 rim 圆 + 内齿廓孔),不是实心圆盘;
15
+ * 多了外圈 rim 圆柱面。倒角(chamfer)/ 轴孔(bore)属于 `_make_chamfer` / `_make_bore`,
16
+ * 在 sew 之后以旋转体 cutter 布尔差实现(见 `features.ts`,A1 已验证几何),
17
+ * 由 `BuildRingGearOptions.chamfer` / `boreD` 驱动。
18
+ */
19
+ import type { BrepHandle } from '@faicad/faijs';
20
+ import type { GearKernel } from '@faicad/cq-compat';
21
+ import { type RingGearParams } from './profile.js';
22
+ import { type SplineFaceOptions, type SplineFaceStrategy } from './spline-face.js';
23
+ import { type GearFeatureOptions } from './features.js';
24
+ /** RingGear 实体构造选项(在 `SplineFaceOptions` 上加容差、策略与镀铬特征覆盖)。 */
25
+ export interface BuildRingGearOptions extends SplineFaceOptions, GearFeatureOptions {
26
+ strategy?: SplineFaceStrategy;
27
+ /** 缝合容差(cq `shell_sewing_tol`)。 */
28
+ shellSewingTol?: number;
29
+ /** 组线容差(cq `wire_comb_tol`)。 */
30
+ wireCombTol?: number;
31
+ /** 人字齿:齿面沿宽度方向拆成上下两半、各以相反螺旋扭转(V 形)。 */
32
+ herringbone?: boolean;
33
+ }
34
+ /** ①–④:完整 RingGear 实体(内部齿,非倒角)。
35
+ *
36
+ * @param kernel 原始 OCCT 内核
37
+ * @param params 齿轮参数
38
+ * @param build 构造选项(策略/容差覆盖)
39
+ * @returns 朝向归一化后的 solid
40
+ */
41
+ export declare function buildRingGearSolid(kernel: GearKernel, params: RingGearParams, build?: BuildRingGearOptions): BrepHandle;
42
+ /** ①–④:完整 HerringboneRingGear 实体(人字内齿,裸齿轮)。
43
+ *
44
+ * 齿廓数学与 RingGear 同构(`gearGeometryForClass` 已分派到 `ringGearGeometry`),
45
+ * 差异只在建面阶段:齿面拆成上下两半、反向螺旋形成 V 形(复用
46
+ * `buildHerringboneToothFaces`);rim 圆柱面与环形盖面与 RingGear 一致。
47
+ *
48
+ * @param kernel 原始 OCCT 内核
49
+ * @param params 内齿参数(逐字沿用 Python 构造参数名)
50
+ * @param build 构造选项(策略/容差覆盖)
51
+ * @returns 朝向归一化后的 solid
52
+ */
53
+ export declare function buildHerringboneRingGearSolid(kernel: GearKernel, params: RingGearParams, build?: BuildRingGearOptions): BrepHandle;
54
+ //# sourceMappingURL=ring_gear.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ring_gear.d.ts","sourceRoot":"","sources":["../src/ring_gear.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AACnD,OAAO,EAAyC,KAAK,cAAc,EAAE,MAAM,WAAW,CAAA;AACtF,OAAO,EAEK,KAAK,iBAAiB,EAAE,KAAK,kBAAkB,EAC1D,MAAM,eAAe,CAAA;AAGtB,OAAO,EACoB,KAAK,kBAAkB,EACjD,MAAM,YAAY,CAAA;AAKnB,6DAA6D;AAC7D,MAAM,WAAW,oBAAqB,SAAQ,iBAAiB,EAAE,kBAAkB;IACjF,QAAQ,CAAC,EAAE,kBAAkB,CAAA;IAC7B,mCAAmC;IACnC,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,gCAAgC;IAChC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,uCAAuC;IACvC,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB;AAqED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,UAAU,EAClB,MAAM,EAAE,cAAc,EACtB,KAAK,GAAE,oBAAyB,GAC/B,UAAU,CAqCZ;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,UAAU,EAClB,MAAM,EAAE,cAAc,EACtB,KAAK,GAAE,oBAAyB,GAC/B,UAAU,CAEZ"}