@faicad/faijs-extra 0.16.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 (99) hide show
  1. package/LICENSE +29 -0
  2. package/NOTICE +29 -0
  3. package/dist/browser.d.ts +12 -0
  4. package/dist/browser.d.ts.map +1 -0
  5. package/dist/browser.js +12 -0
  6. package/dist/browser.js.map +1 -0
  7. package/dist/editor-ops.d.ts +50 -0
  8. package/dist/editor-ops.d.ts.map +1 -0
  9. package/dist/editor-ops.js +77 -0
  10. package/dist/editor-ops.js.map +1 -0
  11. package/dist/extras/svg-extrude.d.ts +43 -0
  12. package/dist/extras/svg-extrude.d.ts.map +1 -0
  13. package/dist/extras/svg-extrude.js +78 -0
  14. package/dist/extras/svg-extrude.js.map +1 -0
  15. package/dist/extras/text-cjk.d.ts +36 -0
  16. package/dist/extras/text-cjk.d.ts.map +1 -0
  17. package/dist/extras/text-cjk.js +146 -0
  18. package/dist/extras/text-cjk.js.map +1 -0
  19. package/dist/extras/text-geometry.d.ts +47 -0
  20. package/dist/extras/text-geometry.d.ts.map +1 -0
  21. package/dist/extras/text-geometry.js +127 -0
  22. package/dist/extras/text-geometry.js.map +1 -0
  23. package/dist/index.d.ts +47 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +47 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/mesh/drill-hole/DrillHoleCore.d.ts +90 -0
  28. package/dist/mesh/drill-hole/DrillHoleCore.d.ts.map +1 -0
  29. package/dist/mesh/drill-hole/DrillHoleCore.js +287 -0
  30. package/dist/mesh/drill-hole/DrillHoleCore.js.map +1 -0
  31. package/dist/mesh/drill-hole/drill-types.d.ts +34 -0
  32. package/dist/mesh/drill-hole/drill-types.d.ts.map +1 -0
  33. package/dist/mesh/drill-hole/drill-types.js +7 -0
  34. package/dist/mesh/drill-hole/drill-types.js.map +1 -0
  35. package/dist/mesh/engrave-decoration.d.ts +13 -0
  36. package/dist/mesh/engrave-decoration.d.ts.map +1 -0
  37. package/dist/mesh/engrave-decoration.js +39 -0
  38. package/dist/mesh/engrave-decoration.js.map +1 -0
  39. package/dist/mesh/fai_drill.d.ts +21 -0
  40. package/dist/mesh/fai_drill.d.ts.map +1 -0
  41. package/dist/mesh/fai_drill.js +92 -0
  42. package/dist/mesh/fai_drill.js.map +1 -0
  43. package/dist/mesh/fai_extrude.d.ts +24 -0
  44. package/dist/mesh/fai_extrude.d.ts.map +1 -0
  45. package/dist/mesh/fai_extrude.js +42 -0
  46. package/dist/mesh/fai_extrude.js.map +1 -0
  47. package/dist/mesh/fai_split.d.ts +164 -0
  48. package/dist/mesh/fai_split.d.ts.map +1 -0
  49. package/dist/mesh/fai_split.js +269 -0
  50. package/dist/mesh/fai_split.js.map +1 -0
  51. package/dist/mesh/index.d.ts +57 -0
  52. package/dist/mesh/index.d.ts.map +1 -0
  53. package/dist/mesh/index.js +34 -0
  54. package/dist/mesh/index.js.map +1 -0
  55. package/dist/mesh/primitives.d.ts +17 -0
  56. package/dist/mesh/primitives.d.ts.map +1 -0
  57. package/dist/mesh/primitives.js +53 -0
  58. package/dist/mesh/primitives.js.map +1 -0
  59. package/dist/namespace.d.ts +82 -0
  60. package/dist/namespace.d.ts.map +1 -0
  61. package/dist/namespace.js +109 -0
  62. package/dist/namespace.js.map +1 -0
  63. package/dist/op-names.d.ts +36 -0
  64. package/dist/op-names.d.ts.map +1 -0
  65. package/dist/op-names.js +45 -0
  66. package/dist/op-names.js.map +1 -0
  67. package/dist/ops/compound.d.ts +110 -0
  68. package/dist/ops/compound.d.ts.map +1 -0
  69. package/dist/ops/compound.js +164 -0
  70. package/dist/ops/compound.js.map +1 -0
  71. package/dist/ops/copy.d.ts +40 -0
  72. package/dist/ops/copy.d.ts.map +1 -0
  73. package/dist/ops/copy.js +83 -0
  74. package/dist/ops/copy.js.map +1 -0
  75. package/dist/ops/fai_drill.d.ts +46 -0
  76. package/dist/ops/fai_drill.d.ts.map +1 -0
  77. package/dist/ops/fai_drill.js +243 -0
  78. package/dist/ops/fai_drill.js.map +1 -0
  79. package/dist/ops/fai_extrude.d.ts +36 -0
  80. package/dist/ops/fai_extrude.d.ts.map +1 -0
  81. package/dist/ops/fai_extrude.js +79 -0
  82. package/dist/ops/fai_extrude.js.map +1 -0
  83. package/dist/ops/fai_split.d.ts +46 -0
  84. package/dist/ops/fai_split.d.ts.map +1 -0
  85. package/dist/ops/fai_split.js +255 -0
  86. package/dist/ops/fai_split.js.map +1 -0
  87. package/dist/ops/load.d.ts +41 -0
  88. package/dist/ops/load.d.ts.map +1 -0
  89. package/dist/ops/load.js +84 -0
  90. package/dist/ops/load.js.map +1 -0
  91. package/dist/ops/svg-extrude.d.ts +32 -0
  92. package/dist/ops/svg-extrude.d.ts.map +1 -0
  93. package/dist/ops/svg-extrude.js +74 -0
  94. package/dist/ops/svg-extrude.js.map +1 -0
  95. package/dist/ops/text.d.ts +34 -0
  96. package/dist/ops/text.d.ts.map +1 -0
  97. package/dist/ops/text.js +101 -0
  98. package/dist/ops/text.js.map +1 -0
  99. package/package.json +60 -0
@@ -0,0 +1,109 @@
1
+ /**
2
+ * namespace — the full editor `cad` namespace assembly point.
3
+ *
4
+ * Core's `createApiNamespace()` returns the platform surface only. The ops that
5
+ * serve the editor's canvas/drag/timeline model and the two non-basic-three
6
+ * creators are assembled here with the exact keys they had inside core:
7
+ *
8
+ * - A group (`createEditorOpsNamespace()`, from `./editor-ops`): `fai_drill`,
9
+ * `fai_extrude`, `fai_split`, `group`, `assembly`, `copy`, `load`;
10
+ * - B group: `text`, `svgExtrude`.
11
+ *
12
+ * The host merges the two namespaces and registers the result as its `cad`
13
+ * library:
14
+ *
15
+ * ```ts
16
+ * import { createRuntime } from '@faicad/faijs/browser'
17
+ * import { createEditorCadNamespace, registerEditorSymbols, installEditorMeshProviders }
18
+ * from '@faicad/faijs-extra/browser'
19
+ *
20
+ * const rt = createRuntime(ports, mode)
21
+ * rt.registerLib('cad', createEditorCadNamespace(), { default: true })
22
+ * registerEditorSymbols()
23
+ * installEditorMeshProviders()
24
+ * ```
25
+ *
26
+ * Hosts that must not bundle three's non-basic chain (the weapp worker) use
27
+ * `@faicad/faijs-extra/editor-ops` and `createEditorOwnedCadNamespace()` instead.
28
+ *
29
+ * Existing `.fai.js` scripts are unaffected: op names, signatures and semantics
30
+ * are unchanged.
31
+ */
32
+ import { CONTRACT_VERSION } from '@faicad/faijs/runtime-state';
33
+ import { registerSymbolTableEntries, unregisterSymbolTableEntries } from '@faicad/faijs/symbol-table';
34
+ import { createApiNamespace } from '@faicad/faijs/api/api-namespace';
35
+ import { setEngraveDecorationProvider } from '@faicad/faijs/mesh/decoration-provider';
36
+ import { ALL_EDITOR_OPS } from './op-names.js';
37
+ import { createEditorOpsNamespace } from './editor-ops.js';
38
+ import { text } from './ops/text.js';
39
+ import { svgExtrude } from './ops/svg-extrude.js';
40
+ import { createEngraveDecorationProvider } from './mesh/engrave-decoration.js';
41
+ /**
42
+ * Assemble the whole editor-owned op set (A + B) into a `cad`-shaped namespace.
43
+ *
44
+ * Keys match the pre-split core namespace exactly, so a host that already
45
+ * carried these ops keeps working after swapping the import source.
46
+ *
47
+ * @returns the editor namespace, ready to be spread over the platform surface.
48
+ */
49
+ export function createEditorNamespace() {
50
+ return {
51
+ ...createEditorOpsNamespace(),
52
+ contractVersion: CONTRACT_VERSION,
53
+ text,
54
+ svgExtrude,
55
+ };
56
+ }
57
+ /**
58
+ * Merge the editor namespace over a platform namespace.
59
+ *
60
+ * Pure: no registration side effects. Editor keys win on collision — today there
61
+ * is none, and the membership guard fails loudly if one is ever introduced.
62
+ *
63
+ * @param platform - the platform namespace (`createApiNamespace()`).
64
+ * @returns the merged namespace to register as the host's `cad` library.
65
+ */
66
+ export function mergeEditorNamespace(platform) {
67
+ return { ...platform, ...createEditorNamespace() };
68
+ }
69
+ /**
70
+ * The `cad` namespace a host registers: core's platform surface plus the whole
71
+ * editor op set.
72
+ *
73
+ * Saves hosts from importing `createApiNamespace()` themselves; the extension
74
+ * library is the party that knows the platform surface it extends.
75
+ *
76
+ * @returns the namespace to hand to `registerLib('cad', …)`.
77
+ */
78
+ export function createEditorCadNamespace() {
79
+ return mergeEditorNamespace(createApiNamespace());
80
+ }
81
+ /**
82
+ * Register every editor op name in the core symbol table (P5).
83
+ *
84
+ * Static analysis that reads `SYMBOL_TABLE` (callee lookup, the fcstd boundary
85
+ * guard) then sees the editor ops. The runtime `check()` does not validate
86
+ * callee existence, so this is an analysis aid, not a gate.
87
+ */
88
+ export function registerEditorSymbols() {
89
+ registerSymbolTableEntries(ALL_EDITOR_OPS);
90
+ }
91
+ /** Undo `registerEditorSymbols()`. */
92
+ export function unregisterEditorSymbols() {
93
+ unregisterSymbolTableEntries(ALL_EDITOR_OPS);
94
+ }
95
+ /**
96
+ * Install the mesh-level capabilities core asks its host for.
97
+ *
98
+ * Today: the `cad.engrave` mesh decoration provider (text/SVG → geometry). The
99
+ * BREP path of `engrave` needs nothing from here — it uses OCCT directly.
100
+ */
101
+ export function installEditorMeshProviders() {
102
+ setEngraveDecorationProvider(createEngraveDecorationProvider());
103
+ }
104
+ /** Uninstall the providers installed by `installEditorMeshProviders()`. */
105
+ export function uninstallEditorMeshProviders() {
106
+ setEngraveDecorationProvider(null);
107
+ }
108
+ export { ALL_EDITOR_OPS, CREATOR_OPS } from './op-names.js';
109
+ //# sourceMappingURL=namespace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"namespace.js","sourceRoot":"","sources":["../src/namespace.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,OAAO,EAAE,gBAAgB,EAAwB,MAAM,6BAA6B,CAAA;AACpF,OAAO,EAAE,0BAA0B,EAAE,4BAA4B,EAAE,MAAM,4BAA4B,CAAA;AACrG,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAA;AACpE,OAAO,EAAE,4BAA4B,EAAE,MAAM,wCAAwC,CAAA;AACrF,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAC3C,OAAO,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAA;AACvD,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAC9C,OAAO,EAAE,+BAA+B,EAAE,MAAM,2BAA2B,CAAA;AAE3E;;;;;;;GAOG;AACH,MAAM,UAAU,qBAAqB;IACnC,OAAO;QACL,GAAG,wBAAwB,EAAE;QAC7B,eAAe,EAAE,gBAAgB;QACjC,IAAI;QACJ,UAAU;KACmB,CAAA;AACjC,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,oBAAoB,CAAC,QAAyB;IAC5D,OAAO,EAAE,GAAG,QAAQ,EAAE,GAAG,qBAAqB,EAAE,EAAE,CAAA;AACpD,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,wBAAwB;IACtC,OAAO,oBAAoB,CAAC,kBAAkB,EAAE,CAAC,CAAA;AACnD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB;IACnC,0BAA0B,CAAC,cAAc,CAAC,CAAA;AAC5C,CAAC;AAED,sCAAsC;AACtC,MAAM,UAAU,uBAAuB;IACrC,4BAA4B,CAAC,cAAc,CAAC,CAAA;AAC9C,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,0BAA0B;IACxC,4BAA4B,CAAC,+BAA+B,EAAE,CAAC,CAAA;AACjE,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,4BAA4B;IAC1C,4BAA4B,CAAC,IAAI,CAAC,CAAA;AACpC,CAAC;AAED,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA","sourcesContent":["/**\n * namespace — the full editor `cad` namespace assembly point.\n *\n * Core's `createApiNamespace()` returns the platform surface only. The ops that\n * serve the editor's canvas/drag/timeline model and the two non-basic-three\n * creators are assembled here with the exact keys they had inside core:\n *\n * - A group (`createEditorOpsNamespace()`, from `./editor-ops`): `fai_drill`,\n * `fai_extrude`, `fai_split`, `group`, `assembly`, `copy`, `load`;\n * - B group: `text`, `svgExtrude`.\n *\n * The host merges the two namespaces and registers the result as its `cad`\n * library:\n *\n * ```ts\n * import { createRuntime } from '@faicad/faijs/browser'\n * import { createEditorCadNamespace, registerEditorSymbols, installEditorMeshProviders }\n * from '@faicad/faijs-extra/browser'\n *\n * const rt = createRuntime(ports, mode)\n * rt.registerLib('cad', createEditorCadNamespace(), { default: true })\n * registerEditorSymbols()\n * installEditorMeshProviders()\n * ```\n *\n * Hosts that must not bundle three's non-basic chain (the weapp worker) use\n * `@faicad/faijs-extra/editor-ops` and `createEditorOwnedCadNamespace()` instead.\n *\n * Existing `.fai.js` scripts are unaffected: op names, signatures and semantics\n * are unchanged.\n */\nimport { CONTRACT_VERSION, type StdlibNamespace } from '@faicad/faijs/runtime-state'\nimport { registerSymbolTableEntries, unregisterSymbolTableEntries } from '@faicad/faijs/symbol-table'\nimport { createApiNamespace } from '@faicad/faijs/api/api-namespace'\nimport { setEngraveDecorationProvider } from '@faicad/faijs/mesh/decoration-provider'\nimport { ALL_EDITOR_OPS } from './op-names'\nimport { createEditorOpsNamespace } from './editor-ops'\nimport { text } from './ops/text'\nimport { svgExtrude } from './ops/svg-extrude'\nimport { createEngraveDecorationProvider } from './mesh/engrave-decoration'\n\n/**\n * Assemble the whole editor-owned op set (A + B) into a `cad`-shaped namespace.\n *\n * Keys match the pre-split core namespace exactly, so a host that already\n * carried these ops keeps working after swapping the import source.\n *\n * @returns the editor namespace, ready to be spread over the platform surface.\n */\nexport function createEditorNamespace(): StdlibNamespace {\n return {\n ...createEditorOpsNamespace(),\n contractVersion: CONTRACT_VERSION,\n text,\n svgExtrude,\n } as unknown as StdlibNamespace\n}\n\n/**\n * Merge the editor namespace over a platform namespace.\n *\n * Pure: no registration side effects. Editor keys win on collision — today there\n * is none, and the membership guard fails loudly if one is ever introduced.\n *\n * @param platform - the platform namespace (`createApiNamespace()`).\n * @returns the merged namespace to register as the host's `cad` library.\n */\nexport function mergeEditorNamespace(platform: StdlibNamespace): StdlibNamespace {\n return { ...platform, ...createEditorNamespace() }\n}\n\n/**\n * The `cad` namespace a host registers: core's platform surface plus the whole\n * editor op set.\n *\n * Saves hosts from importing `createApiNamespace()` themselves; the extension\n * library is the party that knows the platform surface it extends.\n *\n * @returns the namespace to hand to `registerLib('cad', …)`.\n */\nexport function createEditorCadNamespace(): StdlibNamespace {\n return mergeEditorNamespace(createApiNamespace())\n}\n\n/**\n * Register every editor op name in the core symbol table (P5).\n *\n * Static analysis that reads `SYMBOL_TABLE` (callee lookup, the fcstd boundary\n * guard) then sees the editor ops. The runtime `check()` does not validate\n * callee existence, so this is an analysis aid, not a gate.\n */\nexport function registerEditorSymbols(): void {\n registerSymbolTableEntries(ALL_EDITOR_OPS)\n}\n\n/** Undo `registerEditorSymbols()`. */\nexport function unregisterEditorSymbols(): void {\n unregisterSymbolTableEntries(ALL_EDITOR_OPS)\n}\n\n/**\n * Install the mesh-level capabilities core asks its host for.\n *\n * Today: the `cad.engrave` mesh decoration provider (text/SVG → geometry). The\n * BREP path of `engrave` needs nothing from here — it uses OCCT directly.\n */\nexport function installEditorMeshProviders(): void {\n setEngraveDecorationProvider(createEngraveDecorationProvider())\n}\n\n/** Uninstall the providers installed by `installEditorMeshProviders()`. */\nexport function uninstallEditorMeshProviders(): void {\n setEngraveDecorationProvider(null)\n}\n\nexport { ALL_EDITOR_OPS, CREATOR_OPS } from './op-names'\n"]}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * op-names — the editor-owned op name lists (single source).
3
+ *
4
+ * These names live in `@faicad/faijs-extra`; core's `createApiNamespace()`
5
+ * carries the platform surface only. The lists serve two consumers:
6
+ *
7
+ * 1. the cad-namespace membership guards (platform keys ∪ editor keys), and
8
+ * 2. `registerEditorSymbols()` — the static symbol-table extension, so
9
+ * `cad.fai_drill` stays queryable by static analysis that reads the table
10
+ * (the runtime `check()` deliberately does not validate callee existence).
11
+ *
12
+ * `EDITOR_OPS` is the editor-owned op group (plan §4.2 A) and `CREATOR_OPS` the
13
+ * svg / 3D-text creator group (plan §4.2 B). The split is not cosmetic: the A
14
+ * group uses three's basic API only, so the weapp worker can mount it (see the
15
+ * `@faicad/faijs-extra/editor-ops` entry) while the B group — which carries
16
+ * `three/examples`' `SVGLoader` and the `Shape`/`ExtrudeGeometry` chain — stays
17
+ * off the end-side bundle.
18
+ */
19
+ /** A group (plan §4.2): editor-owned ops, three basic API only. */
20
+ export declare const EDITOR_OPS: readonly ["fai_drill", "fai_extrude", "fai_split", "group", "assembly", "copy", "load"];
21
+ /** B group (plan §4.2): svg / 3D-text creators; carry the non-basic three chain. */
22
+ export declare const CREATOR_OPS: readonly ["text", "svgExtrude"];
23
+ /** Every op name `createEditorNamespace()` carries, in assembly order. */
24
+ export declare const ALL_EDITOR_OPS: readonly ["fai_drill", "fai_extrude", "fai_split", "group", "assembly", "copy", "load", "text", "svgExtrude"];
25
+ /** Name of an editor-owned op (`cad.<name>`). */
26
+ export type EditorOpName = (typeof EDITOR_OPS)[number];
27
+ /** Name of a creator op (`cad.<name>`). */
28
+ export type CreatorOpName = (typeof CREATOR_OPS)[number];
29
+ /**
30
+ * Membership test for the editor-owned op list (A group).
31
+ *
32
+ * @param name - the `cad.<name>` candidate to test.
33
+ * @returns true when the name is one of `EDITOR_OPS`.
34
+ */
35
+ export declare function isEditorOp(name: string): name is EditorOpName;
36
+ //# sourceMappingURL=op-names.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"op-names.d.ts","sourceRoot":"","sources":["../src/op-names.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,mEAAmE;AACnE,eAAO,MAAM,UAAU,yFAQb,CAAA;AAEV,oFAAoF;AACpF,eAAO,MAAM,WAAW,iCAGd,CAAA;AAEV,0EAA0E;AAC1E,eAAO,MAAM,cAAc,+GAA2C,CAAA;AAEtE,iDAAiD;AACjD,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAA;AAEtD,2CAA2C;AAC3C,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAA;AAExD;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,IAAI,YAAY,CAE7D"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * op-names — the editor-owned op name lists (single source).
3
+ *
4
+ * These names live in `@faicad/faijs-extra`; core's `createApiNamespace()`
5
+ * carries the platform surface only. The lists serve two consumers:
6
+ *
7
+ * 1. the cad-namespace membership guards (platform keys ∪ editor keys), and
8
+ * 2. `registerEditorSymbols()` — the static symbol-table extension, so
9
+ * `cad.fai_drill` stays queryable by static analysis that reads the table
10
+ * (the runtime `check()` deliberately does not validate callee existence).
11
+ *
12
+ * `EDITOR_OPS` is the editor-owned op group (plan §4.2 A) and `CREATOR_OPS` the
13
+ * svg / 3D-text creator group (plan §4.2 B). The split is not cosmetic: the A
14
+ * group uses three's basic API only, so the weapp worker can mount it (see the
15
+ * `@faicad/faijs-extra/editor-ops` entry) while the B group — which carries
16
+ * `three/examples`' `SVGLoader` and the `Shape`/`ExtrudeGeometry` chain — stays
17
+ * off the end-side bundle.
18
+ */
19
+ /** A group (plan §4.2): editor-owned ops, three basic API only. */
20
+ export const EDITOR_OPS = [
21
+ 'fai_drill',
22
+ 'fai_extrude',
23
+ 'fai_split',
24
+ 'group',
25
+ 'assembly',
26
+ 'copy',
27
+ 'load',
28
+ ];
29
+ /** B group (plan §4.2): svg / 3D-text creators; carry the non-basic three chain. */
30
+ export const CREATOR_OPS = [
31
+ 'text',
32
+ 'svgExtrude',
33
+ ];
34
+ /** Every op name `createEditorNamespace()` carries, in assembly order. */
35
+ export const ALL_EDITOR_OPS = [...EDITOR_OPS, ...CREATOR_OPS];
36
+ /**
37
+ * Membership test for the editor-owned op list (A group).
38
+ *
39
+ * @param name - the `cad.<name>` candidate to test.
40
+ * @returns true when the name is one of `EDITOR_OPS`.
41
+ */
42
+ export function isEditorOp(name) {
43
+ return EDITOR_OPS.includes(name);
44
+ }
45
+ //# sourceMappingURL=op-names.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"op-names.js","sourceRoot":"","sources":["../src/op-names.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,mEAAmE;AACnE,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,WAAW;IACX,aAAa;IACb,WAAW;IACX,OAAO;IACP,UAAU;IACV,MAAM;IACN,MAAM;CACE,CAAA;AAEV,oFAAoF;AACpF,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,MAAM;IACN,YAAY;CACJ,CAAA;AAEV,0EAA0E;AAC1E,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,GAAG,UAAU,EAAE,GAAG,WAAW,CAAU,CAAA;AAQtE;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,OAAQ,UAAgC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;AACzD,CAAC","sourcesContent":["/**\n * op-names — the editor-owned op name lists (single source).\n *\n * These names live in `@faicad/faijs-extra`; core's `createApiNamespace()`\n * carries the platform surface only. The lists serve two consumers:\n *\n * 1. the cad-namespace membership guards (platform keys ∪ editor keys), and\n * 2. `registerEditorSymbols()` — the static symbol-table extension, so\n * `cad.fai_drill` stays queryable by static analysis that reads the table\n * (the runtime `check()` deliberately does not validate callee existence).\n *\n * `EDITOR_OPS` is the editor-owned op group (plan §4.2 A) and `CREATOR_OPS` the\n * svg / 3D-text creator group (plan §4.2 B). The split is not cosmetic: the A\n * group uses three's basic API only, so the weapp worker can mount it (see the\n * `@faicad/faijs-extra/editor-ops` entry) while the B group — which carries\n * `three/examples`' `SVGLoader` and the `Shape`/`ExtrudeGeometry` chain — stays\n * off the end-side bundle.\n */\n\n/** A group (plan §4.2): editor-owned ops, three basic API only. */\nexport const EDITOR_OPS = [\n 'fai_drill',\n 'fai_extrude',\n 'fai_split',\n 'group',\n 'assembly',\n 'copy',\n 'load',\n] as const\n\n/** B group (plan §4.2): svg / 3D-text creators; carry the non-basic three chain. */\nexport const CREATOR_OPS = [\n 'text',\n 'svgExtrude',\n] as const\n\n/** Every op name `createEditorNamespace()` carries, in assembly order. */\nexport const ALL_EDITOR_OPS = [...EDITOR_OPS, ...CREATOR_OPS] as const\n\n/** Name of an editor-owned op (`cad.<name>`). */\nexport type EditorOpName = (typeof EDITOR_OPS)[number]\n\n/** Name of a creator op (`cad.<name>`). */\nexport type CreatorOpName = (typeof CREATOR_OPS)[number]\n\n/**\n * Membership test for the editor-owned op list (A group).\n *\n * @param name - the `cad.<name>` candidate to test.\n * @returns true when the name is one of `EDITOR_OPS`.\n */\nexport function isEditorOp(name: string): name is EditorOpName {\n return (EDITOR_OPS as readonly string[]).includes(name)\n}\n"]}
@@ -0,0 +1,110 @@
1
+ /**
2
+ * stdlib compound — group/assembly 库函数(compound Shape + AssemblyBehavior)
3
+ *
4
+ *
5
+ * 从 src/ops/assemble.ts 迁出并改写为 stdlib 形态:
6
+ * - `group(params)` → compound Shape(kind='compound',children 为成员 Shape 引用)
7
+ * - `assembly(params)` → compound Shape + AssemblyBehavior(约束列表 + solve 方法)
8
+ * - 装配求解(P1 起)委派 api/assembly/(brepjs solverAdapter 内核):
9
+ * do_assemble/solve 触发求解 → 引擎应用
10
+ * (mesh 顶点烘焙 + BREP 刚体变换 + 下游传播)。
11
+ * P2-f5:旧装配算法与自有四元数实现已删除,求解全链路走 api/assembly。
12
+ *
13
+ * compound 自身无独立 mesh——几何由 children 承载,意义是结构(层级)。
14
+ * do_assemble 编译为 `await ctx.<asm>.do_assemble()`:调用 compound 的求解方法,
15
+ * 对约束定位的成员施加装配变换(mesh 顶点烘焙 + BREP 刚体变换 + 下游传播)。
16
+ */
17
+ import type { Shape } from '@faicad/faijs/mesh/types';
18
+ import { type CompoundShape } from '@faicad/faijs/shape';
19
+ import { type AssemblyTransform } from '@faicad/faijs/runtime-state';
20
+ import { type AssemblySolveResult } from '@faicad/faijs/api/assembly/solve';
21
+ import { type JointSpec } from '@faicad/faijs/api/assembly/joints';
22
+ import type { AssemblyConstraint } from '@faicad/faijs/api/assembly/types';
23
+ import type { SolverStyle } from '@faicad/faijs/api/assembly/solvers/types';
24
+ /** Parameters for the `group` stdlib function: an optional name and ordered members. */
25
+ export interface GroupParams {
26
+ name?: string;
27
+ /** Compound members: read-only references, never mutated by group/assembly. */
28
+ members?: Shape[];
29
+ memberNames?: string[];
30
+ }
31
+ /** Parameters for the `assembly` stdlib function: group params plus assembly constraints. */
32
+ export interface AssemblyParams extends GroupParams {
33
+ constraints?: AssemblyConstraint[];
34
+ /** P3:运动副声明(可选;parent/child 必须是 members 里的名字)。 */
35
+ joints?: JointSpec[];
36
+ /** P3:驱动值覆盖(键 = child 成员名;值 = 主 DOF 数值或多 DOF 数组)。 */
37
+ drive?: Record<string, number | number[]>;
38
+ /** cq-compat:成员颜色(sRGB 0..1),导出 STEP 时写入 XCAF。 */
39
+ memberColors?: Record<string, [number, number, number]>;
40
+ /** P1:求解风格。'chain'(默认,vendored brepjs 解析链式)| 'global'(CadQuery 兼容全局最小二乘)。 */
41
+ solver?: SolverStyle;
42
+ }
43
+ export type { AssemblyConstraint, FaceMateConstraint, FaceMateFace, EntityRef, FaceRef, EdgeRef, MateConstraint, AlignConstraint, CoincidentConstraint, ConcentricConstraint, DistanceConstraint, AngleConstraint, ParallelConstraint, PerpendicularConstraint, FixedConstraint, StructuralConstraint, AssemblyVec3, } from '@faicad/faijs/api/assembly/types';
44
+ export type { AssemblySolveResult } from '@faicad/faijs/api/assembly/solve';
45
+ export { applyTransform } from '@faicad/faijs/mesh/rigid-transform';
46
+ /** Behavior attached to an assembly compound: its members, constraints, and solver. */
47
+ export interface AssemblyBehavior {
48
+ name?: string;
49
+ memberNames: string[];
50
+ constraints: AssemblyConstraint[];
51
+ /** P3:运动副声明(无 joints 时为空数组)。 */
52
+ joints?: JointSpec[];
53
+ /** P3:驱动值覆盖(键 = child 成员名;缺省 undefined = 用 joint 存储值)。 */
54
+ drive?: Record<string, number | number[]>;
55
+ /** cq-compat:成员颜色(sRGB 0..1)。 */
56
+ memberColors?: Record<string, [number, number, number]>;
57
+ /** P1:求解风格。 */
58
+ solver?: SolverStyle;
59
+ /** 只求解(P6):返回"成员下标 → 变换"列表。不改写入参、不传播;可重复调用(幂等)。 */
60
+ solve(): AssemblyTransform[];
61
+ /** 只求解并带诊断量(P1):transforms + dof/converged/unsupported(方案 P1⑤);P3 增 kinematics/warnings。 */
62
+ solveDetailed(): AssemblySolveResult;
63
+ }
64
+ /**
65
+ * `cad.group({ name, members })` → compound Shape。
66
+ * members 是成员 Shape(编译产物 ctx.<var> 引用),成员名经 keep() 反查。
67
+ *
68
+ * 函数体 keep 声明(keep-syntax 设计 §2.5):group 保留其成员且可见(R6)。
69
+ */
70
+ /**
71
+ * 分组:零约束,保持当前布局。结构语句,无几何输出,成员用变量名引用。
72
+ * @group 结构
73
+ * @inputs 1
74
+ * @async false
75
+ * @qual ok
76
+ * @name group
77
+ * @deprecated **`../3d_editor` 消费面**(原 `@deprecated` 措辞已于 2026-09-22 校正):该 op 为编辑器应用提供(无几何输出,服务于编辑器画布与时间线),不属 faijs 平台面,但**不是废弃项**——它服务真实负载。**变更其 API 形态必须同步更新 `../3d_editor`**(见 `docs/plans/2026-09-22-topology-identity-development-plan.md` §2)。**平台侧需要几何复合体请用 `cad.compound`**(内核 `makeCompound`,持 OCCT 句柄,可变换/可导出)。
78
+ * @returns CompoundShape 复合几何(kind='compound',children 为成员 Shape 引用)。
79
+ * @param params.name - 组名。type:string
80
+ * @param params.members - 成员(编译产物 ctx.<var> 引用;结构语句里是裸变量引用,非字符串数组)。type:Shape[]
81
+ * @note members 在 .fai.js 里是裸变量引用(编译为 ctx.<var>),字符串数组形态的成员名经 keep() 反查兼容历史 IR。
82
+ * @example
83
+ * const part0 = cad.box(30, 20, 10, { centered: true })
84
+ * cad.group({ name: '底板组', members: [part0] })
85
+ */
86
+ export declare function group(params: GroupParams): CompoundShape;
87
+ /**
88
+ * 装配:成员 + 约束。结构语句,无几何输出,成员用变量名引用、实体用 EntityRef / 拓扑引用。
89
+ * 求解内核复用 vendored brepjs solverAdapter.solveConstraints(链式拓扑调度 / DOF / converged /
90
+ * unsupported 诊断);输出为 per-member 终态变换(每成员一条,恒等位姿不输出)。
91
+ * @group 结构
92
+ * @inputs 1
93
+ * @async false
94
+ * @qual warn
95
+ * @name assembly
96
+ * @deprecated **`../3d_editor` 消费面**(原 `@deprecated` 措辞已于 2026-09-22 校正):该 op 为编辑器应用提供(成员以编辑器结构语句形态声明,服务于画布与时间线),不属 faijs 平台面,但**不是废弃项**——它服务真实负载。**变更其 API 形态必须同步更新 `../3d_editor`**(见 `docs/plans/2026-09-22-topology-identity-development-plan.md` §2)。faijs 平台面不提供等价 op(需要时须按平台需求另行设计,不得直接搬用本 op)。
97
+ * @returns CompoundShape + AssemblyBehavior(含 do_assemble / solve 方法)。
98
+ * @note 约束类型(a=参考、b=从动,移动 b 去贴合 a):`mate` 面对面贴合(法向反向+面中心重合,遗留 face_mate 的新名,求解降级为 concentric + 轴编码);`align` 同向对齐(法向同向+面中心重合);`coincident` 共面/共点/共线(保留面内 2 个平移 DOF);`concentric` 轴重合(孔轴配合,圆柱/圆锥面需 hint.axis,直边/圆边需 EdgeHint.axis);`distance` 定距(mm,带 value);`angle` 夹角(deg,带 value);`parallel`/`perpendicular` 平行/垂直(angle 0°/90° 语法糖);`fixed` 锚定部件(地基);`face_mate` 为遗留别名(规范化为 mate,新代码不再使用)。
99
+ * @note EntityRef 四种形态:`{ part, face: { topoRef } | { surfaceType?, center, normal } }`、`{ part, edge: { topoRef } | { axis: { origin, direction } } }`、`{ part, point: [x,y,z] }`、`{ part, faceIndex }`(1 起,仅调试简写)。
100
+ * @note 不收敛(实体类型不匹配/环/参考不可达)→ 抛错并带 unsupported 明细;成员名为空串 → 求解前抛错;mesh 快照缺 axis 的圆柱/圆锥面作轴实体 → E_TOPO_NOT_FOUND(绝不静默降级)。`mate`(中心重合)与 `coincident`(只共面)是两种不同语义,不互相映射。
101
+ * @note 早期文档/示例曾用 `fixedPartId`/`movingPartId`/`faceRowIndex`/`faceId`/`invalid`——这些键在代码中不存在。真实契约是 `fixedPartName`/`movingPartName` + `fixedFace`/`movingFace`(遗留 face_mate)。`faceId` 字段随 §6.2 移除,不再写入。
102
+ * @param params.name - 装配名。type:string
103
+ * @param params.members - 成员(裸变量引用)。type:Shape[]
104
+ * @param params.constraints - 约束数组(遗留 face_mate 形态或上述新形态 { type, a, b })。type:AssemblyConstraint[]
105
+ * @example
106
+ * let asm1 = cad.assembly({ name: '主轴组件', members: [part0, part1, part2], constraints: [ { type: 'fixed', part: 'part0' }, { type: 'mate', a: { part: 'part0', face: { topoRef: { kind: 'face', origin: 'part0', role: 'box:top', hint: { kind: 'face', surfaceType: 'plane' } } } }, b: { part: 'part1', face: { topoRef: { kind: 'face', origin: 'part1', role: 'box:bottom', hint: { kind: 'face', surfaceType: 'plane' } } } } }, { type: 'concentric', a: { part: 'part1', face: { topoRef: { kind: 'face', origin: 'part1', role: '', hint: { kind: 'face', surfaceType: 'cylinder' } } } }, b: { part: 'part2', face: { topoRef: { kind: 'face', origin: 'part2', role: 'cylinder:lateral', hint: { kind: 'face', surfaceType: 'cylinder' } } } } } ] })
107
+ * asm1.solve()
108
+ */
109
+ export declare function assembly(params: AssemblyParams): CompoundShape;
110
+ //# sourceMappingURL=compound.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compound.d.ts","sourceRoot":"","sources":["../../src/ops/compound.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAA;AACrD,OAAO,EAAwC,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAC9F,OAAO,EAA4E,KAAK,iBAAiB,EAAE,MAAM,6BAA6B,CAAA;AAC9I,OAAO,EAA8B,KAAK,mBAAmB,EAAE,MAAM,kCAAkC,CAAA;AAEvG,OAAO,EAAsB,KAAK,SAAS,EAAE,MAAM,mCAAmC,CAAA;AACtF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAA;AAC1E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0CAA0C,CAAA;AAI3E,wFAAwF;AACxF,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,+EAA+E;IAC/E,OAAO,CAAC,EAAE,KAAK,EAAE,CAAA;IACjB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;CACvB;AAED,6FAA6F;AAC7F,MAAM,WAAW,cAAe,SAAQ,WAAW;IACjD,WAAW,CAAC,EAAE,kBAAkB,EAAE,CAAA;IAClC,kDAAkD;IAClD,MAAM,CAAC,EAAE,SAAS,EAAE,CAAA;IACpB,qDAAqD;IACrD,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAA;IACzC,kDAAkD;IAClD,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IACvD,6EAA6E;IAC7E,MAAM,CAAC,EAAE,WAAW,CAAA;CACrB;AAID,YAAY,EACV,kBAAkB,EAClB,kBAAkB,EAClB,YAAY,EACZ,SAAS,EACT,OAAO,EACP,OAAO,EACP,cAAc,EACd,eAAe,EACf,oBAAoB,EACpB,oBAAoB,EACpB,kBAAkB,EAClB,eAAe,EACf,kBAAkB,EAClB,uBAAuB,EACvB,eAAe,EACf,oBAAoB,EACpB,YAAY,GACb,MAAM,kCAAkC,CAAA;AACzC,YAAY,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAA;AAQ3E,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAA;AAInE,uFAAuF;AACvF,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,WAAW,EAAE,kBAAkB,EAAE,CAAA;IACjC,gCAAgC;IAChC,MAAM,CAAC,EAAE,SAAS,EAAE,CAAA;IACpB,0DAA0D;IAC1D,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAA;IACzC,iCAAiC;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IACvD,eAAe;IACf,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,mDAAmD;IACnD,KAAK,IAAI,iBAAiB,EAAE,CAAA;IAC5B,4FAA4F;IAC5F,aAAa,IAAI,mBAAmB,CAAA;CACrC;AAyCD;;;;;GAKG;AACH;;;;;;;;;;;;;;;IAeI;AACJ,wBAAgB,KAAK,CAAC,MAAM,EAAE,WAAW,GAAG,aAAa,CAcxD;AAED;;;;;;;;;;;;;;;;;;;;;IAqBI;AACJ,wBAAgB,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,aAAa,CAqD9D"}
@@ -0,0 +1,164 @@
1
+ /**
2
+ * stdlib compound — group/assembly 库函数(compound Shape + AssemblyBehavior)
3
+ *
4
+ *
5
+ * 从 src/ops/assemble.ts 迁出并改写为 stdlib 形态:
6
+ * - `group(params)` → compound Shape(kind='compound',children 为成员 Shape 引用)
7
+ * - `assembly(params)` → compound Shape + AssemblyBehavior(约束列表 + solve 方法)
8
+ * - 装配求解(P1 起)委派 api/assembly/(brepjs solverAdapter 内核):
9
+ * do_assemble/solve 触发求解 → 引擎应用
10
+ * (mesh 顶点烘焙 + BREP 刚体变换 + 下游传播)。
11
+ * P2-f5:旧装配算法与自有四元数实现已删除,求解全链路走 api/assembly。
12
+ *
13
+ * compound 自身无独立 mesh——几何由 children 承载,意义是结构(层级)。
14
+ * do_assemble 编译为 `await ctx.<asm>.do_assemble()`:调用 compound 的求解方法,
15
+ * 对约束定位的成员施加装配变换(mesh 顶点烘焙 + BREP 刚体变换 + 下游传播)。
16
+ */
17
+ import { compound as makeCompound, ensureSlot } from '@faicad/faijs/shape';
18
+ import { keep, nameOf, setPendingAssemblyTransforms, setPendingAssemblyKinematics } from '@faicad/faijs/runtime-state';
19
+ import { solveAssemblyAndKinematics } from '@faicad/faijs/api/assembly/solve';
20
+ import { validateConstraints } from '@faicad/faijs/api/assembly/validate';
21
+ import { buildKinematicTree } from '@faicad/faijs/api/assembly/joints';
22
+ // ── 求解器 ──
23
+ // P2-f5:旧装配算法与自有四元数实现已整体删除——旋转计算一律走
24
+ // brepjs utils/quaternion.ts,输出经 api/assembly/pose.ts fromBrepjsQuat 重排。
25
+ // 应用变换(mesh 顶点烘焙)下沉到引擎侧 src/mesh/rigid-transform.ts(E-b:
26
+ // 引擎不得 import stdlib/compound;公共 API 经本 re-export 保持)。
27
+ export { applyTransform } from '@faicad/faijs/mesh/rigid-transform';
28
+ /**
29
+ * 纯求解(P6:求解 ≠ 传播):委派 api/assembly/solveAssembly(P1 起)。
30
+ * 不修改任何输入、不触碰引擎状态——引擎负责应用变换并让下游失效重算(F2)。
31
+ *
32
+ * 约束形态(方案 §5):
33
+ * - 遗留 face_mate:规范化为 mate 后降级为 brepjs concentric + 轴编码求解(§3.7.2);
34
+ * - 新形态 mate/align/coincident/concentric/distance/angle/parallel/perpendicular/fixed;
35
+ * - 面参数 `{ topoRef }` 执行期解析(BREP 现场/mesh 行快照),旧 `{ center, normal }`
36
+ * 快照直接使用(兼容已持久化的历史脚本);
37
+ * - 输出为 per-member 终态(L6 修复),锚定成员不输出变换。
38
+ */
39
+ function solveTransforms(members, behavior) {
40
+ return solveAssemblyAndKinematics(members, behavior.memberNames, behavior.constraints, behavior.joints ?? [], behavior.drive, { solver: behavior.solver, name: behavior.name }).transforms;
41
+ }
42
+ // ── group / assembly 库函数 ──
43
+ /**
44
+ * 成员名推导:显式 memberNames 兼容旧手工构造 IR;否则经 keep() 反查
45
+ * (P3 起经 keep()/nameOfShapes 反查成员名——库不再访问执行上下文,F1)。
46
+ */
47
+ function memberNamesOf(params, members) {
48
+ if (Array.isArray(params.memberNames) && params.memberNames.length > 0) {
49
+ return params.memberNames;
50
+ }
51
+ return members.map((m) => {
52
+ // 兼容字符串形态的 members(历史 IR 直传 partName):字符串本身就是名字
53
+ if (typeof m === 'string')
54
+ return m;
55
+ return String(nameOf(m) ?? '');
56
+ });
57
+ }
58
+ /**
59
+ * `cad.group({ name, members })` → compound Shape。
60
+ * members 是成员 Shape(编译产物 ctx.<var> 引用),成员名经 keep() 反查。
61
+ *
62
+ * 函数体 keep 声明(keep-syntax 设计 §2.5):group 保留其成员且可见(R6)。
63
+ */
64
+ /**
65
+ * 分组:零约束,保持当前布局。结构语句,无几何输出,成员用变量名引用。
66
+ * @group 结构
67
+ * @inputs 1
68
+ * @async false
69
+ * @qual ok
70
+ * @name group
71
+ * @deprecated **`../3d_editor` 消费面**(原 `@deprecated` 措辞已于 2026-09-22 校正):该 op 为编辑器应用提供(无几何输出,服务于编辑器画布与时间线),不属 faijs 平台面,但**不是废弃项**——它服务真实负载。**变更其 API 形态必须同步更新 `../3d_editor`**(见 `docs/plans/2026-09-22-topology-identity-development-plan.md` §2)。**平台侧需要几何复合体请用 `cad.compound`**(内核 `makeCompound`,持 OCCT 句柄,可变换/可导出)。
72
+ * @returns CompoundShape 复合几何(kind='compound',children 为成员 Shape 引用)。
73
+ * @param params.name - 组名。type:string
74
+ * @param params.members - 成员(编译产物 ctx.<var> 引用;结构语句里是裸变量引用,非字符串数组)。type:Shape[]
75
+ * @note members 在 .fai.js 里是裸变量引用(编译为 ctx.<var>),字符串数组形态的成员名经 keep() 反查兼容历史 IR。
76
+ * @example
77
+ * const part0 = cad.box(30, 20, 10, { centered: true })
78
+ * cad.group({ name: '底板组', members: [part0] })
79
+ */
80
+ export function group(params) {
81
+ const members = params.members ?? [];
82
+ if (members.length > 0)
83
+ keep(...members);
84
+ const memberNames = memberNamesOf(params, members);
85
+ const c = makeCompound(members);
86
+ // 挂最小 behavior(memberNames 供 ExecutionResult.compounds 结构输出;group 无约束)
87
+ ensureSlot(c).behavior = {
88
+ memberNames,
89
+ constraints: [],
90
+ joints: [],
91
+ solve: () => [],
92
+ solveDetailed: () => ({ transforms: [], dof: 0, converged: true, unsupported: [] }),
93
+ };
94
+ return c;
95
+ }
96
+ /**
97
+ * 装配:成员 + 约束。结构语句,无几何输出,成员用变量名引用、实体用 EntityRef / 拓扑引用。
98
+ * 求解内核复用 vendored brepjs solverAdapter.solveConstraints(链式拓扑调度 / DOF / converged /
99
+ * unsupported 诊断);输出为 per-member 终态变换(每成员一条,恒等位姿不输出)。
100
+ * @group 结构
101
+ * @inputs 1
102
+ * @async false
103
+ * @qual warn
104
+ * @name assembly
105
+ * @deprecated **`../3d_editor` 消费面**(原 `@deprecated` 措辞已于 2026-09-22 校正):该 op 为编辑器应用提供(成员以编辑器结构语句形态声明,服务于画布与时间线),不属 faijs 平台面,但**不是废弃项**——它服务真实负载。**变更其 API 形态必须同步更新 `../3d_editor`**(见 `docs/plans/2026-09-22-topology-identity-development-plan.md` §2)。faijs 平台面不提供等价 op(需要时须按平台需求另行设计,不得直接搬用本 op)。
106
+ * @returns CompoundShape + AssemblyBehavior(含 do_assemble / solve 方法)。
107
+ * @note 约束类型(a=参考、b=从动,移动 b 去贴合 a):`mate` 面对面贴合(法向反向+面中心重合,遗留 face_mate 的新名,求解降级为 concentric + 轴编码);`align` 同向对齐(法向同向+面中心重合);`coincident` 共面/共点/共线(保留面内 2 个平移 DOF);`concentric` 轴重合(孔轴配合,圆柱/圆锥面需 hint.axis,直边/圆边需 EdgeHint.axis);`distance` 定距(mm,带 value);`angle` 夹角(deg,带 value);`parallel`/`perpendicular` 平行/垂直(angle 0°/90° 语法糖);`fixed` 锚定部件(地基);`face_mate` 为遗留别名(规范化为 mate,新代码不再使用)。
108
+ * @note EntityRef 四种形态:`{ part, face: { topoRef } | { surfaceType?, center, normal } }`、`{ part, edge: { topoRef } | { axis: { origin, direction } } }`、`{ part, point: [x,y,z] }`、`{ part, faceIndex }`(1 起,仅调试简写)。
109
+ * @note 不收敛(实体类型不匹配/环/参考不可达)→ 抛错并带 unsupported 明细;成员名为空串 → 求解前抛错;mesh 快照缺 axis 的圆柱/圆锥面作轴实体 → E_TOPO_NOT_FOUND(绝不静默降级)。`mate`(中心重合)与 `coincident`(只共面)是两种不同语义,不互相映射。
110
+ * @note 早期文档/示例曾用 `fixedPartId`/`movingPartId`/`faceRowIndex`/`faceId`/`invalid`——这些键在代码中不存在。真实契约是 `fixedPartName`/`movingPartName` + `fixedFace`/`movingFace`(遗留 face_mate)。`faceId` 字段随 §6.2 移除,不再写入。
111
+ * @param params.name - 装配名。type:string
112
+ * @param params.members - 成员(裸变量引用)。type:Shape[]
113
+ * @param params.constraints - 约束数组(遗留 face_mate 形态或上述新形态 { type, a, b })。type:AssemblyConstraint[]
114
+ * @example
115
+ * let asm1 = cad.assembly({ name: '主轴组件', members: [part0, part1, part2], constraints: [ { type: 'fixed', part: 'part0' }, { type: 'mate', a: { part: 'part0', face: { topoRef: { kind: 'face', origin: 'part0', role: 'box:top', hint: { kind: 'face', surfaceType: 'plane' } } } }, b: { part: 'part1', face: { topoRef: { kind: 'face', origin: 'part1', role: 'box:bottom', hint: { kind: 'face', surfaceType: 'plane' } } } } }, { type: 'concentric', a: { part: 'part1', face: { topoRef: { kind: 'face', origin: 'part1', role: '', hint: { kind: 'face', surfaceType: 'cylinder' } } } }, b: { part: 'part2', face: { topoRef: { kind: 'face', origin: 'part2', role: 'cylinder:lateral', hint: { kind: 'face', surfaceType: 'cylinder' } } } } } ] })
116
+ * asm1.solve()
117
+ */
118
+ export function assembly(params) {
119
+ const members = params.members ?? [];
120
+ const constraints = params.constraints ?? [];
121
+ const joints = params.joints ?? [];
122
+ const drive = params.drive;
123
+ // P2-f1:约束参数运行期校验(keep() 之前,fail-fast;规则见 api/assembly/validate.ts V1–V6)
124
+ const memberNames = memberNamesOf(params, members);
125
+ validateConstraints(constraints, memberNames);
126
+ // P3:运动副构造期 fail-fast——parent/child ∈ members、child 唯一驱动、多 DOF 类型
127
+ // 在 assembly() 构造时暴露(buildJoint/buildKinematicTree 复用同一份校验实现)
128
+ if (joints.length > 0)
129
+ buildKinematicTree(memberNames, joints);
130
+ if (members.length > 0)
131
+ keep(...members);
132
+ const c = makeCompound(members);
133
+ const behavior = {
134
+ name: params.name,
135
+ memberNames,
136
+ constraints,
137
+ joints,
138
+ drive,
139
+ memberColors: params.memberColors,
140
+ solver: params.solver,
141
+ solve: () => solveTransforms(members, behavior),
142
+ solveDetailed: () => solveAssemblyAndKinematics(members, behavior.memberNames, behavior.constraints, behavior.joints ?? [], behavior.drive, { solver: behavior.solver, name: behavior.name }),
143
+ };
144
+ ensureSlot(c).behavior = behavior;
145
+ // solve / do_assemble 完全同义(方案 §5.5 D2:solve 为新名,do_assemble 保留为别名)
146
+ const solveAndRegister = () => {
147
+ // P6:只求解并登记待应用变换;应用与下游失效由引擎做(F2:库不查询/修改 DAG)
148
+ // P3:约束 + 运动副在库侧一次合并(solveAssemblyAndKinematics),transforms 与
149
+ // kinematics 一起登记(禁止引擎侧两次求解/两次登记)
150
+ const result = behavior.solveDetailed();
151
+ if (result.transforms.length > 0)
152
+ setPendingAssemblyTransforms(c, result.transforms);
153
+ if (result.kinematics)
154
+ setPendingAssemblyKinematics(c, result.kinematics);
155
+ };
156
+ c.do_assemble = solveAndRegister;
157
+ c.solve = solveAndRegister;
158
+ c.add_constraint = () => {
159
+ // Phase 1 semantics: constraints are read from the assembly statement's args.constraints;
160
+ // add_constraint is intentionally a no-op (kept for ABI uniformity).
161
+ };
162
+ return c;
163
+ }
164
+ //# sourceMappingURL=compound.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compound.js","sourceRoot":"","sources":["../../src/ops/compound.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * stdlib compound — group/assembly 库函数(compound Shape + AssemblyBehavior)\n *\n *\n * 从 src/ops/assemble.ts 迁出并改写为 stdlib 形态:\n * - `group(params)` → compound Shape(kind='compound',children 为成员 Shape 引用)\n * - `assembly(params)` → compound Shape + AssemblyBehavior(约束列表 + solve 方法)\n * - 装配求解(P1 起)委派 api/assembly/(brepjs solverAdapter 内核):\n * do_assemble/solve 触发求解 → 引擎应用\n * (mesh 顶点烘焙 + BREP 刚体变换 + 下游传播)。\n * P2-f5:旧装配算法与自有四元数实现已删除,求解全链路走 api/assembly。\n *\n * compound 自身无独立 mesh——几何由 children 承载,意义是结构(层级)。\n * do_assemble 编译为 `await ctx.<asm>.do_assemble()`:调用 compound 的求解方法,\n * 对约束定位的成员施加装配变换(mesh 顶点烘焙 + BREP 刚体变换 + 下游传播)。\n */\n\nimport type { Shape } from '@faicad/faijs/mesh/types'\nimport { compound as makeCompound, ensureSlot, type CompoundShape } from '@faicad/faijs/shape'\nimport { keep, nameOf, setPendingAssemblyTransforms, setPendingAssemblyKinematics, type AssemblyTransform } from '@faicad/faijs/runtime-state'\nimport { solveAssemblyAndKinematics, type AssemblySolveResult } from '@faicad/faijs/api/assembly/solve'\nimport { validateConstraints } from '@faicad/faijs/api/assembly/validate'\nimport { buildKinematicTree, type JointSpec } from '@faicad/faijs/api/assembly/joints'\nimport type { AssemblyConstraint } from '@faicad/faijs/api/assembly/types'\nimport type { SolverStyle } from '@faicad/faijs/api/assembly/solvers/types'\n\n// ── 参数类型(keep-syntax 设计 §2.5:成员保留由函数体 keep() 显式声明,不再靠类型标注) ──\n\n/** Parameters for the `group` stdlib function: an optional name and ordered members. */\nexport interface GroupParams {\n name?: string\n /** Compound members: read-only references, never mutated by group/assembly. */\n members?: Shape[]\n memberNames?: string[]\n}\n\n/** Parameters for the `assembly` stdlib function: group params plus assembly constraints. */\nexport interface AssemblyParams extends GroupParams {\n constraints?: AssemblyConstraint[]\n /** P3:运动副声明(可选;parent/child 必须是 members 里的名字)。 */\n joints?: JointSpec[]\n /** P3:驱动值覆盖(键 = child 成员名;值 = 主 DOF 数值或多 DOF 数组)。 */\n drive?: Record<string, number | number[]>\n /** cq-compat:成员颜色(sRGB 0..1),导出 STEP 时写入 XCAF。 */\n memberColors?: Record<string, [number, number, number]>\n /** P1:求解风格。'chain'(默认,vendored brepjs 解析链式)| 'global'(CadQuery 兼容全局最小二乘)。 */\n solver?: SolverStyle\n}\n\n// ── 约束类型(P1 起定义收口在 api/assembly/types,此处 re-export 保持既有导出面) ──\n\nexport type {\n AssemblyConstraint,\n FaceMateConstraint,\n FaceMateFace,\n EntityRef,\n FaceRef,\n EdgeRef,\n MateConstraint,\n AlignConstraint,\n CoincidentConstraint,\n ConcentricConstraint,\n DistanceConstraint,\n AngleConstraint,\n ParallelConstraint,\n PerpendicularConstraint,\n FixedConstraint,\n StructuralConstraint,\n AssemblyVec3,\n} from '@faicad/faijs/api/assembly/types'\nexport type { AssemblySolveResult } from '@faicad/faijs/api/assembly/solve'\n\n// ── 求解器 ──\n// P2-f5:旧装配算法与自有四元数实现已整体删除——旋转计算一律走\n// brepjs utils/quaternion.ts,输出经 api/assembly/pose.ts fromBrepjsQuat 重排。\n\n// 应用变换(mesh 顶点烘焙)下沉到引擎侧 src/mesh/rigid-transform.ts(E-b:\n// 引擎不得 import stdlib/compound;公共 API 经本 re-export 保持)。\nexport { applyTransform } from '@faicad/faijs/mesh/rigid-transform'\n\n// ── AssemblyBehavior ──\n\n/** Behavior attached to an assembly compound: its members, constraints, and solver. */\nexport interface AssemblyBehavior {\n name?: string\n memberNames: string[]\n constraints: AssemblyConstraint[]\n /** P3:运动副声明(无 joints 时为空数组)。 */\n joints?: JointSpec[]\n /** P3:驱动值覆盖(键 = child 成员名;缺省 undefined = 用 joint 存储值)。 */\n drive?: Record<string, number | number[]>\n /** cq-compat:成员颜色(sRGB 0..1)。 */\n memberColors?: Record<string, [number, number, number]>\n /** P1:求解风格。 */\n solver?: SolverStyle\n /** 只求解(P6):返回\"成员下标 → 变换\"列表。不改写入参、不传播;可重复调用(幂等)。 */\n solve(): AssemblyTransform[]\n /** 只求解并带诊断量(P1):transforms + dof/converged/unsupported(方案 P1⑤);P3 增 kinematics/warnings。 */\n solveDetailed(): AssemblySolveResult\n}\n\n/**\n * 纯求解(P6:求解 ≠ 传播):委派 api/assembly/solveAssembly(P1 起)。\n * 不修改任何输入、不触碰引擎状态——引擎负责应用变换并让下游失效重算(F2)。\n *\n * 约束形态(方案 §5):\n * - 遗留 face_mate:规范化为 mate 后降级为 brepjs concentric + 轴编码求解(§3.7.2);\n * - 新形态 mate/align/coincident/concentric/distance/angle/parallel/perpendicular/fixed;\n * - 面参数 `{ topoRef }` 执行期解析(BREP 现场/mesh 行快照),旧 `{ center, normal }`\n * 快照直接使用(兼容已持久化的历史脚本);\n * - 输出为 per-member 终态(L6 修复),锚定成员不输出变换。\n */\nfunction solveTransforms(members: Shape[], behavior: AssemblyBehavior): AssemblyTransform[] {\n return solveAssemblyAndKinematics(\n members,\n behavior.memberNames,\n behavior.constraints,\n behavior.joints ?? [],\n behavior.drive,\n { solver: behavior.solver, name: behavior.name },\n ).transforms\n}\n\n// ── group / assembly 库函数 ──\n\n/**\n * 成员名推导:显式 memberNames 兼容旧手工构造 IR;否则经 keep() 反查\n * (P3 起经 keep()/nameOfShapes 反查成员名——库不再访问执行上下文,F1)。\n */\nfunction memberNamesOf(params: { memberNames?: unknown }, members: Shape[]): string[] {\n if (Array.isArray(params.memberNames) && params.memberNames.length > 0) {\n return params.memberNames as string[]\n }\n return members.map((m) => {\n // 兼容字符串形态的 members(历史 IR 直传 partName):字符串本身就是名字\n if (typeof m === 'string') return m\n return String(nameOf(m) ?? '')\n })\n}\n\n/**\n * `cad.group({ name, members })` → compound Shape。\n * members 是成员 Shape(编译产物 ctx.<var> 引用),成员名经 keep() 反查。\n *\n * 函数体 keep 声明(keep-syntax 设计 §2.5):group 保留其成员且可见(R6)。\n */\n/**\n * 分组:零约束,保持当前布局。结构语句,无几何输出,成员用变量名引用。\n * @group 结构\n * @inputs 1\n * @async false\n * @qual ok\n * @name group\n * @deprecated **`../3d_editor` 消费面**(原 `@deprecated` 措辞已于 2026-09-22 校正):该 op 为编辑器应用提供(无几何输出,服务于编辑器画布与时间线),不属 faijs 平台面,但**不是废弃项**——它服务真实负载。**变更其 API 形态必须同步更新 `../3d_editor`**(见 `docs/plans/2026-09-22-topology-identity-development-plan.md` §2)。**平台侧需要几何复合体请用 `cad.compound`**(内核 `makeCompound`,持 OCCT 句柄,可变换/可导出)。\n * @returns CompoundShape 复合几何(kind='compound',children 为成员 Shape 引用)。\n * @param params.name - 组名。type:string\n * @param params.members - 成员(编译产物 ctx.<var> 引用;结构语句里是裸变量引用,非字符串数组)。type:Shape[]\n * @note members 在 .fai.js 里是裸变量引用(编译为 ctx.<var>),字符串数组形态的成员名经 keep() 反查兼容历史 IR。\n * @example\n * const part0 = cad.box(30, 20, 10, { centered: true })\n * cad.group({ name: '底板组', members: [part0] })\n */\nexport function group(params: GroupParams): CompoundShape {\n const members = (params.members as Shape[] | undefined) ?? []\n if (members.length > 0) keep(...members)\n const memberNames = memberNamesOf(params, members)\n const c = makeCompound(members)\n // 挂最小 behavior(memberNames 供 ExecutionResult.compounds 结构输出;group 无约束)\n ensureSlot(c).behavior = {\n memberNames,\n constraints: [],\n joints: [],\n solve: () => [],\n solveDetailed: () => ({ transforms: [], dof: 0, converged: true, unsupported: [] }),\n }\n return c\n}\n\n/**\n * 装配:成员 + 约束。结构语句,无几何输出,成员用变量名引用、实体用 EntityRef / 拓扑引用。\n * 求解内核复用 vendored brepjs solverAdapter.solveConstraints(链式拓扑调度 / DOF / converged /\n * unsupported 诊断);输出为 per-member 终态变换(每成员一条,恒等位姿不输出)。\n * @group 结构\n * @inputs 1\n * @async false\n * @qual warn\n * @name assembly\n * @deprecated **`../3d_editor` 消费面**(原 `@deprecated` 措辞已于 2026-09-22 校正):该 op 为编辑器应用提供(成员以编辑器结构语句形态声明,服务于画布与时间线),不属 faijs 平台面,但**不是废弃项**——它服务真实负载。**变更其 API 形态必须同步更新 `../3d_editor`**(见 `docs/plans/2026-09-22-topology-identity-development-plan.md` §2)。faijs 平台面不提供等价 op(需要时须按平台需求另行设计,不得直接搬用本 op)。\n * @returns CompoundShape + AssemblyBehavior(含 do_assemble / solve 方法)。\n * @note 约束类型(a=参考、b=从动,移动 b 去贴合 a):`mate` 面对面贴合(法向反向+面中心重合,遗留 face_mate 的新名,求解降级为 concentric + 轴编码);`align` 同向对齐(法向同向+面中心重合);`coincident` 共面/共点/共线(保留面内 2 个平移 DOF);`concentric` 轴重合(孔轴配合,圆柱/圆锥面需 hint.axis,直边/圆边需 EdgeHint.axis);`distance` 定距(mm,带 value);`angle` 夹角(deg,带 value);`parallel`/`perpendicular` 平行/垂直(angle 0°/90° 语法糖);`fixed` 锚定部件(地基);`face_mate` 为遗留别名(规范化为 mate,新代码不再使用)。\n * @note EntityRef 四种形态:`{ part, face: { topoRef } | { surfaceType?, center, normal } }`、`{ part, edge: { topoRef } | { axis: { origin, direction } } }`、`{ part, point: [x,y,z] }`、`{ part, faceIndex }`(1 起,仅调试简写)。\n * @note 不收敛(实体类型不匹配/环/参考不可达)→ 抛错并带 unsupported 明细;成员名为空串 → 求解前抛错;mesh 快照缺 axis 的圆柱/圆锥面作轴实体 → E_TOPO_NOT_FOUND(绝不静默降级)。`mate`(中心重合)与 `coincident`(只共面)是两种不同语义,不互相映射。\n * @note 早期文档/示例曾用 `fixedPartId`/`movingPartId`/`faceRowIndex`/`faceId`/`invalid`——这些键在代码中不存在。真实契约是 `fixedPartName`/`movingPartName` + `fixedFace`/`movingFace`(遗留 face_mate)。`faceId` 字段随 §6.2 移除,不再写入。\n * @param params.name - 装配名。type:string\n * @param params.members - 成员(裸变量引用)。type:Shape[]\n * @param params.constraints - 约束数组(遗留 face_mate 形态或上述新形态 { type, a, b })。type:AssemblyConstraint[]\n * @example\n * let asm1 = cad.assembly({ name: '主轴组件', members: [part0, part1, part2], constraints: [ { type: 'fixed', part: 'part0' }, { type: 'mate', a: { part: 'part0', face: { topoRef: { kind: 'face', origin: 'part0', role: 'box:top', hint: { kind: 'face', surfaceType: 'plane' } } } }, b: { part: 'part1', face: { topoRef: { kind: 'face', origin: 'part1', role: 'box:bottom', hint: { kind: 'face', surfaceType: 'plane' } } } } }, { type: 'concentric', a: { part: 'part1', face: { topoRef: { kind: 'face', origin: 'part1', role: '', hint: { kind: 'face', surfaceType: 'cylinder' } } } }, b: { part: 'part2', face: { topoRef: { kind: 'face', origin: 'part2', role: 'cylinder:lateral', hint: { kind: 'face', surfaceType: 'cylinder' } } } } } ] })\n * asm1.solve()\n */\nexport function assembly(params: AssemblyParams): CompoundShape {\n const members = (params.members as Shape[] | undefined) ?? []\n const constraints = (params.constraints as AssemblyConstraint[] | undefined) ?? []\n const joints = (params.joints as JointSpec[] | undefined) ?? []\n const drive = params.drive as Record<string, number | number[]> | undefined\n\n // P2-f1:约束参数运行期校验(keep() 之前,fail-fast;规则见 api/assembly/validate.ts V1–V6)\n const memberNames = memberNamesOf(params, members)\n validateConstraints(constraints, memberNames)\n // P3:运动副构造期 fail-fast——parent/child ∈ members、child 唯一驱动、多 DOF 类型\n // 在 assembly() 构造时暴露(buildJoint/buildKinematicTree 复用同一份校验实现)\n if (joints.length > 0) buildKinematicTree(memberNames, joints)\n\n if (members.length > 0) keep(...members)\n const c = makeCompound(members)\n const behavior: AssemblyBehavior = {\n name: params.name as string | undefined,\n memberNames,\n constraints,\n joints,\n drive,\n memberColors: params.memberColors,\n solver: params.solver,\n solve: () => solveTransforms(members, behavior),\n solveDetailed: () =>\n solveAssemblyAndKinematics(\n members,\n behavior.memberNames,\n behavior.constraints,\n behavior.joints ?? [],\n behavior.drive,\n { solver: behavior.solver, name: behavior.name },\n ),\n }\n ensureSlot(c).behavior = behavior\n // solve / do_assemble 完全同义(方案 §5.5 D2:solve 为新名,do_assemble 保留为别名)\n const solveAndRegister = (): void => {\n // P6:只求解并登记待应用变换;应用与下游失效由引擎做(F2:库不查询/修改 DAG)\n // P3:约束 + 运动副在库侧一次合并(solveAssemblyAndKinematics),transforms 与\n // kinematics 一起登记(禁止引擎侧两次求解/两次登记)\n const result = behavior.solveDetailed()\n if (result.transforms.length > 0) setPendingAssemblyTransforms(c, result.transforms)\n if (result.kinematics) setPendingAssemblyKinematics(c, result.kinematics)\n }\n ;(c as CompoundShape & { do_assemble?: () => void }).do_assemble = solveAndRegister\n ;(c as CompoundShape & { solve?: () => void }).solve = solveAndRegister\n // 统一成员调用 ABI:add_constraint 是 no-op(现状语义:约束由 assembly 语句 args.constraints 读取,\n // 编译产物机械发射 `ctx.<asm>.add_constraint({...})`,调用此方法不崩)\n ;(c as CompoundShape & { add_constraint?: () => void }).add_constraint = () => {\n // Phase 1 semantics: constraints are read from the assembly statement's args.constraints;\n // add_constraint is intentionally a no-op (kept for ABI uniformity).\n }\n return c\n}\n"]}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * stdlib copy — 深拷贝几何(方案 B:独立新对象,源不变)
3
+ *
4
+ *
5
+ * copy 是"共享读取"(克隆出新对象,源不变),与 drill/transform 的"独占改写"本质不同:
6
+ * - **copy 不消费其源**(从消费方排除,与 group/assembly 同级)
7
+ * - copy 输出是独立新对象 → 归"新名"类(allocate-id.ts 不保名)
8
+ * - **源显示**(part0=box; part1=copy(part0) → 画布显示 box 和副本两份)
9
+ *
10
+ * 双链路:
11
+ * - mesh 路径:深拷贝 positions/indices 到新数组
12
+ * - BREP 路径:kernel.copy(inputSolid) → solidToShape → fromBrep 登记
13
+ */
14
+ import type { Shape } from '@faicad/faijs/mesh/types';
15
+ /**
16
+ * `cad.copy(input)` → 深拷贝 Shape。
17
+ *
18
+ * 函数体 keep 声明(keep-syntax 设计 §2.5):copy 保留其源(可见)——
19
+ * keep(input) 使源变量保持终端(画布显示 box 和副本两份)。
20
+ *
21
+ * mesh 路径:positions/indices 复制到新数组(改副本不影响源)。
22
+ * BREP 路径:kernel.copy 产出独立 ShapeHandle。
23
+ */
24
+ /**
25
+ * 深拷贝几何为独立新对象(源不变,源与副本都显示)。
26
+ * @group 特征
27
+ * @inputs 1
28
+ * @async false
29
+ * @qual ok
30
+ * @name copy
31
+ * @deprecated **`../3d_editor` 消费面**(原 `@deprecated` 措辞已于 2026-09-22 校正):该 op 为编辑器应用提供(语义含编辑器画布显示——源与副本各显示一份),不属 faijs 平台面,但**不是废弃项**——它服务真实负载。**变更其 API 形态必须同步更新 `../3d_editor`**(见 `docs/plans/2026-09-22-topology-identity-development-plan.md` §2)。faijs 平台面不提供等价 op(需要时须按平台需求另行设计,不得直接搬用本 op)。
32
+ * @param input - 源几何。type:Shape required:true
33
+ * @returns Shape 源几何的深拷贝。copy 不消费其源(画布显示 box 和副本两份),改副本不影响源。
34
+ * @example
35
+ * const part1 = cad.copy(part0)
36
+ */
37
+ export declare const copy: ((input: Shape) => Promise<Shape>) & {
38
+ __faijs__dualOp?: import("@faicad/faijs/sdk").DualOpMeta;
39
+ };
40
+ //# sourceMappingURL=copy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copy.d.ts","sourceRoot":"","sources":["../../src/ops/copy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAA;AAoCrD;;;;;;;;GAQG;AACH;;;;;;;;;;;;IAYI;AACJ,eAAO,MAAM,IAAI;;CAgBf,CAAA"}