@faicad/faijs 0.13.1 → 0.13.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.
- package/dist/api/edge-ref.d.ts +3 -2
- package/dist/api/edge-ref.d.ts.map +1 -1
- package/dist/api/edge-ref.js +3 -2
- package/dist/api/edge-ref.js.map +1 -1
- package/dist/api/internal/compat-op.d.ts +2 -0
- package/dist/api/internal/compat-op.d.ts.map +1 -1
- package/dist/api/internal/compat-op.js +8 -1
- package/dist/api/internal/compat-op.js.map +1 -1
- package/dist/browser.d.ts +0 -2
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +2 -2
- package/dist/browser.js.map +1 -1
- package/dist/fcstd/attachment.d.ts +65 -0
- package/dist/fcstd/attachment.d.ts.map +1 -0
- package/dist/fcstd/attachment.js +87 -0
- package/dist/fcstd/attachment.js.map +1 -0
- package/dist/fcstd/build-fai-zip.d.ts +11 -0
- package/dist/fcstd/build-fai-zip.d.ts.map +1 -1
- package/dist/fcstd/build-fai-zip.js +9 -1
- package/dist/fcstd/build-fai-zip.js.map +1 -1
- package/dist/fcstd/cli.d.ts +3 -0
- package/dist/fcstd/cli.d.ts.map +1 -0
- package/dist/fcstd/cli.js +37 -0
- package/dist/fcstd/cli.js.map +1 -0
- package/dist/fcstd/codegen.d.ts +14 -1
- package/dist/fcstd/codegen.d.ts.map +1 -1
- package/dist/fcstd/codegen.js +11 -2
- package/dist/fcstd/codegen.js.map +1 -1
- package/dist/fcstd/container.d.ts +16 -1
- package/dist/fcstd/container.d.ts.map +1 -1
- package/dist/fcstd/container.js +12 -1
- package/dist/fcstd/container.js.map +1 -1
- package/dist/fcstd/contour.d.ts +9 -1
- package/dist/fcstd/contour.d.ts.map +1 -1
- package/dist/fcstd/contour.js +12 -1
- package/dist/fcstd/contour.js.map +1 -1
- package/dist/fcstd/convert.d.ts +47 -2
- package/dist/fcstd/convert.d.ts.map +1 -1
- package/dist/fcstd/convert.js +82 -13
- package/dist/fcstd/convert.js.map +1 -1
- package/dist/fcstd/document.d.ts +8 -1
- package/dist/fcstd/document.d.ts.map +1 -1
- package/dist/fcstd/document.js +4 -1
- package/dist/fcstd/document.js.map +1 -1
- package/dist/fcstd/expressions.d.ts +14 -1
- package/dist/fcstd/expressions.d.ts.map +1 -1
- package/dist/fcstd/expressions.js +11 -1
- package/dist/fcstd/expressions.js.map +1 -1
- package/dist/fcstd/external-geo.d.ts +15 -1
- package/dist/fcstd/external-geo.d.ts.map +1 -1
- package/dist/fcstd/external-geo.js +8 -1
- package/dist/fcstd/external-geo.js.map +1 -1
- package/dist/fcstd/feature-translate.d.ts +65 -3
- package/dist/fcstd/feature-translate.d.ts.map +1 -1
- package/dist/fcstd/feature-translate.js +82 -4
- package/dist/fcstd/feature-translate.js.map +1 -1
- package/dist/fcstd/index.d.ts +23 -0
- package/dist/fcstd/index.d.ts.map +1 -0
- package/dist/fcstd/index.js +19 -0
- package/dist/fcstd/index.js.map +1 -0
- package/dist/fcstd/placement.d.ts +49 -6
- package/dist/fcstd/placement.d.ts.map +1 -1
- package/dist/fcstd/placement.js +46 -6
- package/dist/fcstd/placement.js.map +1 -1
- package/dist/fcstd/planegcs-backend.d.ts +16 -1
- package/dist/fcstd/planegcs-backend.d.ts.map +1 -1
- package/dist/fcstd/planegcs-backend.js +16 -1
- package/dist/fcstd/planegcs-backend.js.map +1 -1
- package/dist/fcstd/sketch-parse.d.ts +43 -0
- package/dist/fcstd/sketch-parse.d.ts.map +1 -1
- package/dist/fcstd/sketch-parse.js +26 -0
- package/dist/fcstd/sketch-parse.js.map +1 -1
- package/dist/fcstd/sketch-solver.d.ts +20 -2
- package/dist/fcstd/sketch-solver.d.ts.map +1 -1
- package/dist/fcstd/sketch-solver.js +6 -1
- package/dist/fcstd/sketch-solver.js.map +1 -1
- package/dist/fcstd/sketch-verify.d.ts +19 -1
- package/dist/fcstd/sketch-verify.d.ts.map +1 -1
- package/dist/fcstd/sketch-verify.js +14 -1
- package/dist/fcstd/sketch-verify.js.map +1 -1
- package/dist/fcstd/unpack.d.ts +21 -2
- package/dist/fcstd/unpack.d.ts.map +1 -1
- package/dist/fcstd/unpack.js +11 -2
- package/dist/fcstd/unpack.js.map +1 -1
- package/dist/fcstd-convert.d.ts +30 -0
- package/dist/fcstd-convert.d.ts.map +1 -0
- package/dist/fcstd-convert.js +27 -0
- package/dist/fcstd-convert.js.map +1 -0
- package/dist/weapp.d.ts +22 -0
- package/dist/weapp.d.ts.map +1 -0
- package/dist/weapp.js +23 -0
- package/dist/weapp.js.map +1 -0
- package/package.json +18 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-fai-zip.js","sourceRoot":"","sources":["../../src/fcstd/build-fai-zip.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,IAAI,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"build-fai-zip.js","sourceRoot":"","sources":["../../src/fcstd/build-fai-zip.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * M2.2/M2.3/M2.4 — .fai.zip builder.\n *\n * freecad/ shadow: byte-exact copy of every source ZIP member except\n * Document.xml / GuiDocument.xml (kept too — nothing is dropped), verified by\n * sha256 equality (V1). Baked geometry comes from the ZIP's .brp members\n * directly (M2.3 — no FreeCAD runtime involved). Unit normalization (D7/M2.4):\n * FCStd internal storage is mm, matching faijs; the units field records this.\n */\nimport { zipSync, strToU8 } from 'fflate';\nimport { createHash } from 'node:crypto';\nimport { isOk } from '../api/result.js';\nimport type { FcstdArchive } from './unpack.js';\nimport { memberText } from './unpack.js';\nimport { parseDocumentXml, type FcstdDocument } from './document.js';\nimport {\n buildManifest,\n initialDisposition,\n type FaiMapping,\n type ObjectMappingEntry,\n} from './container.js';\n\n/** Build output: the .fai.zip bytes, the serialized manifest, the per-object mapping and the shadow hash table. */\nexport interface FaiZipResult {\n /** the produced .fai.zip archive bytes */\n zip: Uint8Array;\n /** serialized manifest.json content */\n manifest: unknown;\n mapping: FaiMapping;\n /** sha256 verification table for the freecad/ shadow (V1) */\n shadowHashes: Record<string, { source: string; shadow: string }>;\n}\n\nfunction sha256(bytes: Uint8Array): string {\n return createHash('sha256').update(bytes).digest('hex');\n}\n\nconst FREECAD_SHADOW_PREFIX = 'freecad/';\n\n/**\n * Build the .fai.zip container: byte-exact freecad/ shadow of every source\n * member, baked .brp-derived assets, mapping ledger and manifest.\n * Returns `{ error }` when Document.xml is missing or unparseable.\n * @param source unpacked FCStd archive (ZIP members + metadata)\n * @param sourceFileName original FCStd file name recorded in the manifest\n * @returns the built archive or an error message\n */\nexport function buildFaiZip(\n source: FcstdArchive,\n sourceFileName: string,\n): { result?: FaiZipResult; error?: string } {\n const xml = memberText(source, 'Document.xml');\n if (xml === undefined) return { error: 'Document.xml missing from source archive' };\n const parsed = parseDocumentXml(xml);\n if (!isOk(parsed)) return { error: parsed.error.message };\n const doc: FcstdDocument = parsed.value;\n\n const out: Record<string, Uint8Array | string> = {};\n const shadowHashes: Record<string, { source: string; shadow: string }> = {};\n\n // M2.2 — byte-exact freecad/ shadow of ALL members (including Document.xml)\n for (const [path, bytes] of source.members) {\n const shadowPath = FREECAD_SHADOW_PREFIX + path;\n out[shadowPath] = bytes;\n const h = sha256(bytes);\n shadowHashes[path] = { source: h, shadow: h }; // same bytes → same hash\n }\n\n // M2.3 — baked assets: copy .brp members as-is into assets/\n const brpOwners = new Map<string, string[]>();\n for (const obj of doc.objects) {\n const shapeProp = obj.properties.get('Shape');\n if (!shapeProp) continue;\n // brp file names appear as <File ...> inside the Part::PropertyPartShape\n const fileEl = shapeProp.children[0]?.attributes['file'];\n void fileEl; // file attribute lives on the wrapping element in some schemas\n const files: string[] = [];\n collectBrpRefs(shapeProp.valueXml ?? '', files);\n if (files.length) brpOwners.set(obj.name, files);\n }\n\n const mapping: FaiMapping = { objects: [] };\n const usedAssets = new Set<string>();\n for (const obj of doc.objects) {\n const entry: ObjectMappingEntry = {\n name: obj.name,\n type: obj.type,\n ...initialDisposition(obj),\n artifacts: [],\n };\n // attach baked .brp-derived assets where the object owns shape members\n const brps = brpOwners.get(obj.name) ?? [];\n for (const brp of brps) {\n const bytes = source.members.get(brp);\n if (!bytes) continue;\n const assetPath = `assets/${brp}`;\n out[assetPath] = bytes;\n entry.artifacts.push(assetPath);\n usedAssets.add(brp);\n }\n mapping.objects.push(entry);\n }\n\n // M2.4 — units: FCStd stores mm internally; faijs contract is mm. No\n // scaling is applied; manifest.units records the normalized unit (D7).\n // fflate requires Uint8Array values — strings must go through strToU8.\n out['manifest.json'] = strToU8(JSON.stringify(buildManifest(doc, sourceFileName, readProgramVersion(doc)), null, 2));\n out['mapping.json'] = strToU8(JSON.stringify(mapping, null, 2));\n\n const zip = zipSync(out as Record<string, Uint8Array>, { level: 6 });\n return { result: { zip, manifest: out['manifest.json'], mapping, shadowHashes } };\n}\n\nfunction readProgramVersion(doc: FcstdDocument): string {\n // ProgramVersion is an attribute of <Document> captured in meta? xmldom:\n // meta holds child property elements only, so fall back to a sane default.\n return doc.meta.get('ProgramVersion')?.valueText ?? 'unknown';\n}\n\n/** Extract .brp file references from a serialized property value. */\nfunction collectBrpRefs(xml: string, out: string[]): void {\n const re = /file=\"([^\"]+\\.brp)\"/g;\n let m: RegExpExecArray | null;\n while ((m = re.exec(xml)) !== null) {\n const name = m[1]!.replace(/^.*[/\\\\]/, '');\n if (!out.includes(name)) out.push(name);\n }\n}\n\n/** Re-export strToU8 for callers that need to embed text members. */\nexport { strToU8 };\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/fcstd/cli.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* fcstd CLI — batch driver entry: .FCStd → .fai.zip with a machine contract.
|
|
4
|
+
*
|
|
5
|
+
* Exit codes (plan §5.2):
|
|
6
|
+
* 0 = converted; mapping final check passed (only translated /
|
|
7
|
+
* python-baked / preserved-only dispositions)
|
|
8
|
+
* 2 = translation gaps (non-Python baked) — NO zip written
|
|
9
|
+
* 1 = internal error (read/unpack/parse/codegen/container failure)
|
|
10
|
+
*
|
|
11
|
+
* stdout: exactly one JSON line (the summary). Human chatter is forbidden on
|
|
12
|
+
* stdout; diagnostics go to stderr (which must stay empty on success).
|
|
13
|
+
*
|
|
14
|
+
* Run (published): faijs-fcstd-convert <in.FCStd> [out.fai.zip]
|
|
15
|
+
* Run (in-repo): npm run fcstd:convert -w @faicad/faijs -- <in.FCStd> [out.fai.zip]
|
|
16
|
+
* With no <out>, acts as a dry audit (no file written).
|
|
17
|
+
*/
|
|
18
|
+
import { writeFileSync } from 'node:fs';
|
|
19
|
+
import { convertFcstdFile } from './convert.js';
|
|
20
|
+
const [input, output] = process.argv.slice(2);
|
|
21
|
+
if (!input) {
|
|
22
|
+
console.error('usage: faijs-fcstd-convert <in.FCStd> [out.fai.zip]');
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
const summary = await convertFcstdFile(input);
|
|
26
|
+
if (summary.ok && output && summary.zip) {
|
|
27
|
+
writeFileSync(output, summary.zip);
|
|
28
|
+
}
|
|
29
|
+
// stdout contract: ONE json line, no binary payload — zip bytes are stripped
|
|
30
|
+
// before serialization (they are written to <out> above, never printed).
|
|
31
|
+
const { zip: _zip, ...report } = summary;
|
|
32
|
+
void _zip;
|
|
33
|
+
console.log(JSON.stringify(report));
|
|
34
|
+
if (!summary.ok) {
|
|
35
|
+
process.exit(summary.gaps.length > 0 ? 2 : 1);
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/fcstd/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEhD,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC9C,IAAI,CAAC,KAAK,EAAE,CAAC;IACX,OAAO,CAAC,KAAK,CAAC,qDAAqD,CAAC,CAAC;IACrE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,OAAO,GAAG,MAAM,gBAAgB,CAAC,KAAK,CAAC,CAAC;AAC9C,IAAI,OAAO,CAAC,EAAE,IAAI,MAAM,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACxC,aAAa,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;AACrC,CAAC;AACD,6EAA6E;AAC7E,yEAAyE;AACzE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,MAAM,EAAE,GAAG,OAAO,CAAC;AACzC,KAAK,IAAI,CAAC;AACV,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;AAEpC,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;IAChB,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAChD,CAAC","sourcesContent":["#!/usr/bin/env node\n/**\n * fcstd CLI — batch driver entry: .FCStd → .fai.zip with a machine contract.\n *\n * Exit codes (plan §5.2):\n * 0 = converted; mapping final check passed (only translated /\n * python-baked / preserved-only dispositions)\n * 2 = translation gaps (non-Python baked) — NO zip written\n * 1 = internal error (read/unpack/parse/codegen/container failure)\n *\n * stdout: exactly one JSON line (the summary). Human chatter is forbidden on\n * stdout; diagnostics go to stderr (which must stay empty on success).\n *\n * Run (published): faijs-fcstd-convert <in.FCStd> [out.fai.zip]\n * Run (in-repo): npm run fcstd:convert -w @faicad/faijs -- <in.FCStd> [out.fai.zip]\n * With no <out>, acts as a dry audit (no file written).\n */\nimport { writeFileSync } from 'node:fs';\nimport { convertFcstdFile } from './convert.js';\n\nconst [input, output] = process.argv.slice(2);\nif (!input) {\n console.error('usage: faijs-fcstd-convert <in.FCStd> [out.fai.zip]');\n process.exit(1);\n}\n\nconst summary = await convertFcstdFile(input);\nif (summary.ok && output && summary.zip) {\n writeFileSync(output, summary.zip);\n}\n// stdout contract: ONE json line, no binary payload — zip bytes are stripped\n// before serialization (they are written to <out> above, never printed).\nconst { zip: _zip, ...report } = summary;\nvoid _zip;\nconsole.log(JSON.stringify(report));\n\nif (!summary.ok) {\n process.exit(summary.gaps.length > 0 ? 2 : 1);\n}\n"]}
|
package/dist/fcstd/codegen.d.ts
CHANGED
|
@@ -11,8 +11,11 @@ import type { FcstdDocument } from './document.js';
|
|
|
11
11
|
import type { CadCall } from './feature-translate.js';
|
|
12
12
|
import type { Contour } from './contour.js';
|
|
13
13
|
import { type Placement } from './placement.js';
|
|
14
|
+
/** Per-object codegen outcome: what was emitted for one FCStd object. */
|
|
14
15
|
export interface GenObjectResult {
|
|
16
|
+
/** FCStd object name */
|
|
15
17
|
name: string;
|
|
18
|
+
/** FCStd type id */
|
|
16
19
|
type: string;
|
|
17
20
|
/** variable name bound in generated code (partN) or undefined when baked */
|
|
18
21
|
variable?: string;
|
|
@@ -26,6 +29,7 @@ export interface GenObjectResult {
|
|
|
26
29
|
loopCount?: number;
|
|
27
30
|
};
|
|
28
31
|
}
|
|
32
|
+
/** Full codegen output: lowered calls, per-object ledger and generated script(s). */
|
|
29
33
|
export interface GenResult {
|
|
30
34
|
/** ordered translated calls (dependency order) */
|
|
31
35
|
calls: CadCall[];
|
|
@@ -46,6 +50,13 @@ export interface GenResult {
|
|
|
46
50
|
* M5.1/M5.2 — translate every object in dependency order and lower to JS.
|
|
47
51
|
* `sketchVerdict` supplies the M3 outcome per sketch object name; sketches
|
|
48
52
|
* whose contour feeds a Pad/Pocket appear as inputs.
|
|
53
|
+
*
|
|
54
|
+
* @param doc parsed FCStd object graph to translate
|
|
55
|
+
* @param sketchVerdict per-sketch M3 verdict keyed by object name
|
|
56
|
+
* @param sketchContours solved contours per L0 sketch, keyed by object name
|
|
57
|
+
* @param baseName source base name used in generated file headers/labels
|
|
58
|
+
* @param placements per-object Placement used to re-orient placed geometry; missing → identity
|
|
59
|
+
* @returns the lowered call plan, per-object dispositions and generated code
|
|
49
60
|
*/
|
|
50
61
|
export declare function generateModel(doc: FcstdDocument, sketchVerdict: Map<string, {
|
|
51
62
|
level: 'L0' | 'L1' | 'L2';
|
|
@@ -53,5 +64,7 @@ export declare function generateModel(doc: FcstdDocument, sketchVerdict: Map<str
|
|
|
53
64
|
loopCount?: number;
|
|
54
65
|
}>, sketchContours: Map<string, Contour[]>, baseName: string,
|
|
55
66
|
/** M8.3: per-object Placement (sketches + features); missing → identity */
|
|
56
|
-
placements?: Map<string, Placement
|
|
67
|
+
placements?: Map<string, Placement>,
|
|
68
|
+
/** H7: objects whose Shape is a ZIP .brp member (pure-Shape carriers → shape-asset). */
|
|
69
|
+
shapeCarriers?: ReadonlySet<string>): GenResult;
|
|
57
70
|
//# sourceMappingURL=codegen.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codegen.d.ts","sourceRoot":"","sources":["../../src/fcstd/codegen.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,KAAK,EAAE,OAAO,EAAoB,MAAM,wBAAwB,CAAC;AAExE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,KAAK,SAAS,EAA0C,MAAM,gBAAgB,CAAC;AAExF,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,OAAO,EAAE,CAAC;IACjB,WAAW,EAAE,YAAY,GAAG,OAAO,GAAG,gBAAgB,CAAC;IACvD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oDAAoD;IACpD,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7E;AAED,MAAM,WAAW,SAAS;IACxB,kDAAkD;IAClD,KAAK,EAAE,OAAO,EAAE,CAAC;IACjB,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,+EAA+E;IAC/E,IAAI,EAAE,MAAM,CAAC;IACb;wFACoF;IACpF,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACtD,kFAAkF;IAClF,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAqDD
|
|
1
|
+
{"version":3,"file":"codegen.d.ts","sourceRoot":"","sources":["../../src/fcstd/codegen.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,KAAK,EAAE,OAAO,EAAoB,MAAM,wBAAwB,CAAC;AAExE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,KAAK,SAAS,EAA0C,MAAM,gBAAgB,CAAC;AAExF,yEAAyE;AACzE,MAAM,WAAW,eAAe;IAC9B,wBAAwB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,oBAAoB;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,OAAO,EAAE,CAAC;IACjB,WAAW,EAAE,YAAY,GAAG,OAAO,GAAG,gBAAgB,CAAC;IACvD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oDAAoD;IACpD,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7E;AAED,qFAAqF;AACrF,MAAM,WAAW,SAAS;IACxB,kDAAkD;IAClD,KAAK,EAAE,OAAO,EAAE,CAAC;IACjB,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,+EAA+E;IAC/E,IAAI,EAAE,MAAM,CAAC;IACb;wFACoF;IACpF,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACtD,kFAAkF;IAClF,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAqDD;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,aAAa,EAClB,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,EAC9F,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,EACtC,QAAQ,EAAE,MAAM;AAChB,2EAA2E;AAC3E,UAAU,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC;AACnC,wFAAwF;AACxF,aAAa,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,GAClC,SAAS,CA6UX"}
|
package/dist/fcstd/codegen.js
CHANGED
|
@@ -50,10 +50,19 @@ function bodyFeatureNames(obj) {
|
|
|
50
50
|
* M5.1/M5.2 — translate every object in dependency order and lower to JS.
|
|
51
51
|
* `sketchVerdict` supplies the M3 outcome per sketch object name; sketches
|
|
52
52
|
* whose contour feeds a Pad/Pocket appear as inputs.
|
|
53
|
+
*
|
|
54
|
+
* @param doc parsed FCStd object graph to translate
|
|
55
|
+
* @param sketchVerdict per-sketch M3 verdict keyed by object name
|
|
56
|
+
* @param sketchContours solved contours per L0 sketch, keyed by object name
|
|
57
|
+
* @param baseName source base name used in generated file headers/labels
|
|
58
|
+
* @param placements per-object Placement used to re-orient placed geometry; missing → identity
|
|
59
|
+
* @returns the lowered call plan, per-object dispositions and generated code
|
|
53
60
|
*/
|
|
54
61
|
export function generateModel(doc, sketchVerdict, sketchContours, baseName,
|
|
55
62
|
/** M8.3: per-object Placement (sketches + features); missing → identity */
|
|
56
|
-
placements
|
|
63
|
+
placements,
|
|
64
|
+
/** H7: objects whose Shape is a ZIP .brp member (pure-Shape carriers → shape-asset). */
|
|
65
|
+
shapeCarriers) {
|
|
57
66
|
const byName = new Map(doc.objects.map((o) => [o.name, o]));
|
|
58
67
|
const nodes = new Map();
|
|
59
68
|
for (const obj of doc.objects) {
|
|
@@ -156,7 +165,7 @@ placements) {
|
|
|
156
165
|
const verdict = translateObject(obj, (dep) => {
|
|
157
166
|
const v = variables.get(dep);
|
|
158
167
|
return v !== undefined ? v : undefined;
|
|
159
|
-
}, doc.objects);
|
|
168
|
+
}, doc.objects, shapeCarriers);
|
|
160
169
|
node.verdict = verdict;
|
|
161
170
|
if (verdict.kind === 'translated') {
|
|
162
171
|
// rename output vars to partN sequence
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codegen.js","sourceRoot":"","sources":["../../src/fcstd/codegen.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * M5 — code generation: object graph + M4 call plans → model/*.fai.js.\n *\n * M5.1 topological order: Body.Group order wins where present; otherwise\n * PropertyLink dependency order. Cycles / missing deps → baked (no fallback\n * heuristics — explicit downgrade per plan §12).\n * M5.2 lowering: params → JS constants; calls → `const partN = await cad.x(...)`;\n * statement ids sN. Sketch contours enter as blueprint literals.\n */\nimport type { FcstdDocument } from './document.js';\nimport type { CadCall, TranslateVerdict } from './feature-translate.js';\nimport { translateObject, isJsExpr, jsExpr } from './feature-translate.js';\nimport type { Contour } from './contour.js';\nimport { type Placement, isIdentityPlacement, quatToEulerXYZDeg } from './placement.js';\n\nexport interface GenObjectResult {\n name: string;\n type: string;\n /** variable name bound in generated code (partN) or undefined when baked */\n variable?: string;\n calls: CadCall[];\n disposition: 'translated' | 'baked' | 'preserved-only';\n reason?: string;\n /** M3 sketch verdict when the object is a sketch */\n sketch?: { level: 'L0' | 'L1' | 'L2'; reason?: string; loopCount?: number };\n}\n\nexport interface GenResult {\n /** ordered translated calls (dependency order) */\n calls: CadCall[];\n objects: GenObjectResult[];\n /** generated .fai.js source (single-file mode or the main/aggregate script) */\n code: string;\n /** M10.3: multi-file mode — one script per Body with translated geometry.\n * Empty in single-file mode. Paths are container-relative (model/<Name>.fai.js). */\n files: { path: string; code: string; body: string }[];\n /** M10.3: variable in main.fai.js holding the grouped result (multi-file mode) */\n rootVar?: string;\n}\n\ninterface Node {\n name: string;\n obj: ReturnType<FcstdDocument['objects'][number]['properties']['get']> extends never ? never : FcstdDocument['objects'][number];\n deps: Set<string>;\n verdict?: TranslateVerdict;\n variable?: string;\n}\n\n/** Extract link dependencies relevant for ordering. */\nfunction depsOf(obj: FcstdDocument['objects'][number]): string[] {\n const out: string[] = [];\n const linkProps = ['Base', 'Tool', 'Profile', 'BaseFeature', 'Originals'];\n for (const p of linkProps) {\n const el = obj.properties.get(p)?.children[0];\n const v = el?.attributes['value'];\n if (v) out.push(v);\n }\n const shapes = obj.properties.get('Shapes')?.children[0];\n if (shapes) {\n for (const link of shapes.children) {\n const v = link.attributes['value'];\n if (v) out.push(v);\n }\n }\n return out;\n}\n\n/**\n * GOTCHA (PadTest V6 failure): a `PartDesign::Body`'s feature list lives in\n * DIFFERENT properties depending on the FreeCAD version —\n * - modern (0.19+): `Model` (App::PropertyLinkList), ordered\n * - legacy: `Group` (App::PropertyLinkList)\n * The Tip is `Body.Tip`. Reading only `Group` on a modern document yields an\n * empty list → no same-Body chaining → features degrade to a loose\n * `cad.group` of overlapping siblings (PadTest rebuilt volume ≈ 5.2× the Tip's,\n * bboxDiag ≈ 2×). Prefer `Model`, fall back to `Group`.\n */\nfunction bodyFeatureNames(obj: FcstdDocument['objects'][number]): string[] {\n for (const prop of ['Model', 'Group']) {\n const list = obj.properties.get(prop)?.children[0];\n if (!list) continue;\n const names: string[] = [];\n for (const link of list.children) {\n const v = link.attributes['value'];\n if (v) names.push(v);\n }\n if (names.length > 0) return names;\n }\n return [];\n}\n\n/**\n * M5.1/M5.2 — translate every object in dependency order and lower to JS.\n * `sketchVerdict` supplies the M3 outcome per sketch object name; sketches\n * whose contour feeds a Pad/Pocket appear as inputs.\n */\nexport function generateModel(\n doc: FcstdDocument,\n sketchVerdict: Map<string, { level: 'L0' | 'L1' | 'L2'; reason?: string; loopCount?: number }>,\n sketchContours: Map<string, Contour[]>,\n baseName: string,\n /** M8.3: per-object Placement (sketches + features); missing → identity */\n placements?: Map<string, Placement>,\n): GenResult {\n const byName = new Map(doc.objects.map((o) => [o.name, o]));\n const nodes = new Map<string, Node>();\n for (const obj of doc.objects) {\n nodes.set(obj.name, { name: obj.name, obj, deps: new Set(depsOf(obj)) });\n }\n\n // Kahn topological sort; objects with unbuilt deps fall back to insertion\n // order iteration until progress stalls (remaining are baked with reason).\n // M10.1: iteration order is Body.Group sequence FIRST (features of a Body\n // process in Group order so the D-C chain follows PartDesign semantics),\n // then leftover objects in document order.\n const groupSeq: string[] = [];\n for (const obj of doc.objects) {\n if (obj.type !== 'PartDesign::Body') continue;\n for (const m of bodyFeatureNames(obj)) {\n if (byName.has(m) && !groupSeq.includes(m)) groupSeq.push(m);\n }\n }\n const iterationOrder = [\n ...groupSeq,\n ...doc.objects.map((o) => o.name).filter((n) => !groupSeq.includes(n)),\n ];\n const order: string[] = [];\n const built = new Set<string>();\n let progress = true;\n while (progress) {\n progress = false;\n for (const name of iterationOrder) {\n const node = nodes.get(name)!;\n if (built.has(node.name)) continue;\n if ([...node.deps].every((d) => built.has(d) || !byName.has(d))) {\n built.add(node.name);\n order.push(node.name);\n progress = true;\n }\n }\n }\n\n const variables = new Map<string, string>();\n const results: GenObjectResult[] = [];\n const calls: CadCall[] = [];\n let partCounter = 0;\n const newVar = (): string => `part${partCounter++}`;\n\n // D-C (M9.4): same-Body features fuse cumulatively in Body.Group order —\n // the first translated feature is the base, every later additive feature\n // (Pad/…) unions with the chain, every subtractive one (Pocket/Cut)\n // subtracts. cad.group is NOT used inside a Body (that is assembly\n // semantics); cross-Body grouping stays in lower()'s root handling (M10).\n const memberToBody = new Map<string, string>();\n for (const obj of doc.objects) {\n if (obj.type !== 'PartDesign::Body') continue;\n for (const m of bodyFeatureNames(obj)) {\n if (!memberToBody.has(m)) memberToBody.set(m, obj.name);\n }\n }\n const chainVar = new Map<string, string>(); // body name → accumulated var\n\n for (const name of order) {\n const node = nodes.get(name)!;\n const obj = node.obj;\n\n if (obj.type === 'Sketcher::SketchObject') {\n const verdict = sketchVerdict.get(name);\n const contours = sketchContours.get(name);\n const usable =\n !!verdict &&\n verdict.level !== 'L2' &&\n (verdict.loopCount ?? 0) > 0 &&\n !!contours &&\n contours.length > 0;\n if (usable) {\n // M6 wiring: emit a real `cad.sketch({contours})` creator so the\n // solved contour becomes a face variable the Pad/Pocket/Extrusion/\n // Revolution features below can consume.\n const v = newVar();\n variables.set(name, v);\n const sketchCall: CadCall = {\n out: v, op: 'cad.sketch', source: name, inputs: [], params: { contours },\n };\n calls.push(sketchCall);\n results.push({\n name, type: obj.type, variable: v, calls: [sketchCall], disposition: 'translated',\n sketch: verdict,\n });\n } else {\n results.push({\n name, type: obj.type, calls: [], disposition: 'baked',\n reason: verdict?.reason ?? (contours ? 'sketch-not-solved' : 'sketch-no-contours'), sketch: verdict,\n });\n }\n continue;\n }\n\n if (obj.type === 'App::Origin' || obj.type === 'App::Plane' || obj.type === 'App::Line') {\n results.push({ name, type: obj.type, calls: [], disposition: 'preserved-only', reason: 'datum' });\n continue;\n }\n\n // Sketches are now real face variables (see the Sketcher::SketchObject\n // branch above), so every dependency that resolves to one flows through.\n const verdict = translateObject(obj, (dep) => {\n const v = variables.get(dep);\n return v !== undefined ? v : undefined;\n }, doc.objects);\n node.verdict = verdict;\n if (verdict.kind === 'translated') {\n // rename output vars to partN sequence\n for (const call of verdict.calls) {\n const v = newVar();\n variables.set(call.out, v);\n // remap inputs that were intermediate (Pocket_cut) or named outputs\n call.inputs = call.inputs.map((i) => variables.get(i) ?? i);\n call.out = v;\n calls.push(call);\n }\n // M8.3: features build in sketch-local coordinates (cad.sketch lays the\n // face on local XY; extrude runs along local +Z). Re-orient the final\n // solid by the PROFILE SKETCH's Placement: rotate_euler then translate,\n // so the result lands where FreeCAD puts it. Identity placements emit\n // nothing.\n // GOTCHA (PadTest V6, relErr 3.20%): a PartDesign feature's geometry is\n // built in the SKETCH frame, but FreeCAD may store a DIFFERENT Placement\n // on the feature object itself (Pad001: sketch P=(10,0,0)\n // Q=(0,.7071,0,.7071) vs feature P=0 Q=(0,.7071,.7071,0)) — re-orienting\n // by the feature's own frame drops the sketch origin offset and rotates\n // the extrude axis into the wrong direction (−3.20% volume, centroid\n // off 1.67). The sketch's Placement is the authoritative frame for the\n // built geometry; fall back to the feature's own for sketchless features.\n const lastVar = verdict.calls.at(-1)?.out;\n const sketchLink = obj.properties.get('Sketch')?.children[0]?.attributes['value'];\n const pl = (sketchLink ? placements?.get(sketchLink) : undefined) ?? placements?.get(name);\n if (lastVar && pl && !isIdentityPlacement(pl)) {\n let cur = lastVar;\n const euler = quatToEulerXYZDeg(pl.q);\n const isRotation = Math.abs(euler[0]) > 1e-9 || Math.abs(euler[1]) > 1e-9 || Math.abs(euler[2]) > 1e-9;\n if (isRotation) {\n const rv = newVar();\n variables.set(cur, rv); // map old name → rotated var for consumers\n calls.push({ out: rv, op: 'cad.rotate_euler', source: name, inputs: [cur], params: { anglesDeg: euler } });\n cur = rv;\n }\n const needsTranslate = Math.abs(pl.p[0]) > 1e-9 || Math.abs(pl.p[1]) > 1e-9 || Math.abs(pl.p[2]) > 1e-9;\n if (needsTranslate) {\n const tv = newVar();\n variables.set(cur, tv);\n calls.push({ out: tv, op: 'cad.translate', source: name, inputs: [cur], params: { offset: [...pl.p] } });\n cur = tv;\n }\n // the object's variable is now the fully placed result\n variables.set(name, cur);\n }\n // M9.4 (D-C): fold the feature into its Body's chain — AFTER the placement\n // step so the chain accumulates the PLACED feature shape. Pocket/Cut\n // subtract from the chain; everything else unions onto it. The first\n // feature in the Body's feature list (Model/Group) order becomes the\n // chain base — no cad.group inside a Body; consumers (M10) read chainVar.\n // GOTCHA (PadTest V6): folding the UNPLACED feature var (the old order)\n // left the chain head in sketch-local space while each feature's Placement\n // was applied to a separate, unused variable → the exported body spanned\n // both the local and the placed copies (~2× bboxDiag, ~5× volume).\n const body = memberToBody.get(name);\n const isSubtractive = obj.type === 'PartDesign::Pocket' || obj.type === 'Part::Cut';\n if (body) {\n const prev = chainVar.get(body);\n // UpToLast/UpToFirst: FreeCAD's \"up to\" support is the Body's ACCUMULATED\n // shape, NOT only the immediate BaseFeature link — retarget the kernel\n // ref at the chain head (prev). GOTCHA (PadTest V6): truncating against\n // the immediate BaseFeature (a small Pad001 disc) left an 8.06% volume\n // deficit vs the Tip; against the accumulated chain it drops to 3.20%\n // (bbox already exact at delta 0).\n if (prev) {\n for (const c of verdict.calls) {\n if (c.op === 'cad.extrude' && c.params.baseFeature !== undefined) {\n // GOTCHA (PadTest V6 residual): the up-to extrude builds its\n // prism in the SKETCH-LOCAL frame, but the chain head (prev)\n // lives in the PLACED (global) frame. FreeCAD's boolean runs in\n // one frame — so transform prev back into the sketch frame\n // first: local = R^-1(global - p). Feeding the placed chain var\n // directly silently truncates at the wrong face (Pad002 truth\n // AddShape 48199 vs rebuilt deficit ~9108 mm^3 → 3.2% total).\n const needsInverse =\n pl !== undefined && !isIdentityPlacement(pl);\n if (needsInverse && pl) {\n const invQ: [number, number, number, number] = [\n -pl.q[0]!, -pl.q[1]!, -pl.q[2]!, pl.q[3]!,\n ];\n const invEuler = quatToEulerXYZDeg(invQ);\n const tv = newVar();\n const tvCall: CadCall = {\n out: tv, op: 'cad.translate', source: name,\n inputs: [prev], params: { offset: [-pl.p[0]!, -pl.p[1]!, -pl.p[2]!] },\n };\n const rv = newVar();\n const rvCall: CadCall = {\n out: rv, op: 'cad.rotate_euler', source: name,\n inputs: [tv], params: { anglesDeg: invEuler },\n };\n // insert BEFORE the extrude call: faijs is a statement\n // language — `baseFeature: partN` referencing a later\n // statement is E_REFERENCE (parser rejects forward refs).\n const at = calls.indexOf(c);\n calls.splice(at < 0 ? calls.length : at, 0, tvCall, rvCall);\n c.params.baseFeature = jsExpr(rv);\n } else {\n c.params.baseFeature = jsExpr(prev);\n }\n }\n }\n }\n const featureVar = variables.get(name) ?? verdict.calls.at(-1)!.out;\n if (!prev) {\n chainVar.set(body, featureVar); // base feature\n } else if (isSubtractive && verdict.calls.at(-1)!.op === 'cad.subtract' && verdict.calls.at(-1)!.inputs.includes(prev)) {\n // Pocket already subtracted from the chain var itself (BaseFeature\n // resolved to the chain) — its output IS the new chain head; no\n // extra subtract (would cut twice).\n chainVar.set(body, featureVar);\n } else if (isSubtractive) {\n const nv = newVar();\n calls.push({ out: nv, op: 'cad.subtract', source: name, inputs: [prev, featureVar], params: {} });\n chainVar.set(body, nv);\n } else {\n const nv = newVar();\n calls.push({ out: nv, op: 'cad.union', source: name, inputs: [prev, featureVar], params: {} });\n chainVar.set(body, nv);\n }\n }\n results.push({ name, type: obj.type, variable: verdict.calls.at(-1)?.out, calls: verdict.calls, disposition: 'translated', reason: verdict.reason });\n } else if (verdict.kind === 'baked') {\n results.push({ name, type: obj.type, calls: [], disposition: 'baked', reason: verdict.reason });\n } else {\n results.push({ name, type: obj.type, calls: [], disposition: 'preserved-only', reason: verdict.reason });\n }\n }\n\n // also mark unreachable (cycle) objects as baked\n for (const obj of doc.objects) {\n if (!results.some((r) => r.name === obj.name)) {\n results.push({ name: obj.name, type: obj.type, calls: [], disposition: 'baked', reason: 'dependency-cycle' });\n }\n }\n\n // M10.3/M10.5 — split by Body: calls whose source object belongs to a Body\n // (including the chain union/subtract calls emitted for it) go to\n // model/<BodyName>.fai.js; everything else (loose Part features) stays in\n // main.fai.js. When no Body has geometry, everything lands in main (the\n // single-file shape). Aggregate entry groups per-file roots via cad.group.\n const callBody = new Map<string, string>();\n for (const r of results) {\n const b = memberToBody.get(r.name);\n if (b) for (const c of r.calls) callBody.set(c.out, b);\n }\n const bodiesWithGeo = new Set<string>();\n for (const b of new Set(memberToBody.values())) {\n if (chainVar.has(b)) bodiesWithGeo.add(b);\n }\n const files: GenResult['files'] = [];\n let code: string;\n let rootVar: string | undefined;\n if (bodiesWithGeo.size > 0) {\n const mainCalls: CadCall[] = [];\n const perBody = new Map<string, CadCall[]>();\n // M10c partition in DEPENDENCY ORDER: `calls` is already topologically\n // sorted, so ONE forward pass assigns each call — to its own source's Body\n // when known (`callBody`), else to the Body its first body-owned input went\n // to. GOTCHA (PadTest V6): the previous implementation re-assigned such\n // calls by APPENDING them to the end of the Body file, which broke\n // dependency order — a Body file ended up referencing a variable declared\n // further down (`let` TDZ ReferenceError at run time: `part8` used `part6`).\n // Filtering `calls` in place preserves the topological order.\n const assigned = new Map<string, string>(); // call.out → Body file name\n for (const c of calls) {\n const own = callBody.get(c.out);\n const viaInput = c.inputs.map((inp) => assigned.get(inp)).find((b) => b !== undefined);\n const b = own !== undefined && bodiesWithGeo.has(own) ? own : viaInput;\n if (b !== undefined && bodiesWithGeo.has(b)) {\n if (!perBody.has(b)) perBody.set(b, []);\n perBody.get(b)!.push(c);\n assigned.set(c.out, b);\n } else {\n mainCalls.push(c);\n }\n }\n for (const b of bodiesWithGeo) {\n const bodyCalls = perBody.get(b) ?? [];\n // terminal: alias the chain head to <Body>_out so the aggregate entry\n // has a stable, name-independent reference to each Body's result.\n const head = chainVar.get(b)!;\n const withTerminal = [\n ...bodyCalls,\n { out: `${b}_out`, op: 'identity', source: b, inputs: [head], params: {} } as CadCall,\n ];\n files.push({ path: `model/${b}.fai.js`, code: lowerBody(withTerminal, `${baseName}/${b}`, b), body: b });\n }\n // main.fai.js: aggregate the per-Body terminals via cad.group. M10c:\n // cross-file references close through the standard relative-import\n // contract (module-registry D6) — each Body module's terminal alias\n // `<Body>_out` is its live shape, so a named import binds it.\n const lines: string[] = [];\n lines.push(`// Generated by faijs FCStd port — ${baseName} (aggregate entry)`);\n lines.push(`// Units: mm (faijs contract; FCStd internal units are mm)`);\n const members = [...bodiesWithGeo].map((b) => `${b}_out`);\n // Always import the per-Body terminals: the aggregate entry references\n // `<Body>_out` in BOTH the cad.group (multi-Body) and the single-Body alias\n // path, so a missing import is a SEC_FREE_IDENT parse error (GOTCHA: the\n // single-Body branch previously emitted `let part_out = <Body>_out;` with\n // no import). `mainCalls` may still be empty here.\n if (members.length >= 1) {\n for (const b of bodiesWithGeo) {\n lines.push(`import { ${b}_out } from './${b}.fai.js'; // module ${b}`);\n }\n }\n for (const c of mainCalls) {\n const id = `s${lines.length - 2}`;\n lines.push(`let ${c.out} = ${c.op}(${renderArgs(c)}); // ${id} ${c.source}`);\n }\n if (members.length > 1) {\n rootVar = 'part_out';\n lines.push(`let part_out = cad.group({ members: [${members.join(', ')}] });`);\n } else if (members.length === 1) {\n // single Body: the imported terminal IS the result — alias keeps a\n // stable root name for executors\n rootVar = members[0];\n lines.push(`let part_out = ${rootVar}; // single-Body aggregate`);\n rootVar = 'part_out';\n }\n code = lines.join('\\n') + '\\n';\n } else {\n code = lower(calls, baseName);\n }\n return { calls, objects: results, code, files, rootVar };\n}\n\n/** M10.3 — lower one Body's calls; the last entry is the terminal alias\n * `<Body>_out` (plain JS assignment — faijs has no identity op). */\nfunction lowerBody(calls: CadCall[], label: string, body: string): string {\n const lines: string[] = [];\n lines.push(`// Generated by faijs FCStd port — ${label}`);\n lines.push(`// Units: mm (faijs contract; FCStd internal units are mm)`);\n for (const call of calls) {\n if (call.op === 'identity') {\n // terminal alias: `let <Body>_out = <chain head>;`\n lines.push(`let ${call.out} = ${call.inputs[0]}; // s? ${body} terminal`);\n continue;\n }\n const id = `s${lines.length - 2}`;\n lines.push(`let ${call.out} = ${call.op}(${renderArgs(call)}); // ${id} ${call.source}`);\n }\n return lines.join('\\n') + '\\n';\n}\n\n/** M5.2 — lower the call plan to .fai.js source. faijs syntax: top-level\n * statement flow with `let partN = cad.x(...)`; no wrapper function. */\nfunction lower(calls: CadCall[], baseName: string): string {\n const lines: string[] = [];\n lines.push(`// Generated by faijs FCStd port — ${baseName}`);\n lines.push(`// Units: mm (faijs contract; FCStd internal units are mm)`);\n for (const call of calls) {\n const id = `s${lines.length - 2}`; // statement id sN\n const args = renderArgs(call);\n lines.push(`let ${call.out} = ${call.op}(${args}); // ${id} ${call.source}`);\n }\n // final shape: union of root calls that nobody consumes; faijs scripts\n // end with the output-producing statement (no return, per fixtures).\n const consumed = new Set(calls.flatMap((c) => c.inputs));\n const roots = calls.filter((c) => !consumed.has(c.out)).map((c) => c.out);\n if (roots.length > 1) {\n lines.push(`let part_out = cad.group({ members: [${roots.join(', ')}] });`);\n } else if (roots.length === 0) {\n lines.push(`// no translated geometry (all baked)`);\n }\n return lines.join('\\n') + '\\n';\n}\n\n/**\n * M5.2 — render one IR value as JS. Plain values JSON-encode (byte-identical to\n * the pre-JsExpr output); a `JsExpr` marker renders verbatim, and a container\n * holding one renders element-wise so the expression survives into the source.\n */\nfunction renderValue(v: unknown): string {\n if (isJsExpr(v)) return v.__jsExpr;\n if (Array.isArray(v)) {\n if (v.some(isJsExpr)) return `[${v.map(renderValue).join(', ')}]`;\n return JSON.stringify(v);\n }\n if (v && typeof v === 'object') {\n const entries = Object.entries(v as Record<string, unknown>);\n if (entries.some(([, val]) => containsJsExpr(val))) {\n return `{ ${entries.map(([k, val]) => `${k}: ${renderValue(val)}`).join(', ')} }`;\n }\n return JSON.stringify(v);\n }\n return JSON.stringify(v);\n}\n\n/** True when a value is or (recursively) contains a `JsExpr` marker. */\nfunction containsJsExpr(v: unknown): boolean {\n if (isJsExpr(v)) return true;\n if (Array.isArray(v)) return v.some(containsJsExpr);\n if (v && typeof v === 'object') return Object.values(v as Record<string, unknown>).some(containsJsExpr);\n return false;\n}\n\nfunction renderArgs(call: CadCall): string {\n const positional: string[] = [\n ...call.inputs.map((i) => i),\n ...(call.literals ?? []).map((l) => renderValue(l)),\n ].filter((s) => s.length > 0); // M7.1: drop empty entries so we never emit `(, `\n const named: string[] = [];\n for (const [k, v] of Object.entries(call.params ?? {})) {\n if (v === undefined) continue;\n named.push(`${k}: ${renderValue(v)}`);\n }\n const namedBlock = named.length ? `{ ${named.join(', ')} }` : '';\n // M7.1: no leading comma when there are no positional args — a call with only\n // named params must render as `cad.sketch({ ... })`, never `cad.sketch(, {...})`.\n const rest = namedBlock ? (positional.length ? `, ${namedBlock}` : namedBlock) : '';\n return `${positional.join(', ')}${rest}`;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"codegen.js","sourceRoot":"","sources":["../../src/fcstd/codegen.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * M5 — code generation: object graph + M4 call plans → model/*.fai.js.\n *\n * M5.1 topological order: Body.Group order wins where present; otherwise\n * PropertyLink dependency order. Cycles / missing deps → baked (no fallback\n * heuristics — explicit downgrade per plan §12).\n * M5.2 lowering: params → JS constants; calls → `const partN = await cad.x(...)`;\n * statement ids sN. Sketch contours enter as blueprint literals.\n */\nimport type { FcstdDocument } from './document.js';\nimport type { CadCall, TranslateVerdict } from './feature-translate.js';\nimport { translateObject, isJsExpr, jsExpr } from './feature-translate.js';\nimport type { Contour } from './contour.js';\nimport { type Placement, isIdentityPlacement, quatToEulerXYZDeg } from './placement.js';\n\n/** Per-object codegen outcome: what was emitted for one FCStd object. */\nexport interface GenObjectResult {\n /** FCStd object name */\n name: string;\n /** FCStd type id */\n type: string;\n /** variable name bound in generated code (partN) or undefined when baked */\n variable?: string;\n calls: CadCall[];\n disposition: 'translated' | 'baked' | 'preserved-only';\n reason?: string;\n /** M3 sketch verdict when the object is a sketch */\n sketch?: { level: 'L0' | 'L1' | 'L2'; reason?: string; loopCount?: number };\n}\n\n/** Full codegen output: lowered calls, per-object ledger and generated script(s). */\nexport interface GenResult {\n /** ordered translated calls (dependency order) */\n calls: CadCall[];\n objects: GenObjectResult[];\n /** generated .fai.js source (single-file mode or the main/aggregate script) */\n code: string;\n /** M10.3: multi-file mode — one script per Body with translated geometry.\n * Empty in single-file mode. Paths are container-relative (model/<Name>.fai.js). */\n files: { path: string; code: string; body: string }[];\n /** M10.3: variable in main.fai.js holding the grouped result (multi-file mode) */\n rootVar?: string;\n}\n\ninterface Node {\n name: string;\n obj: ReturnType<FcstdDocument['objects'][number]['properties']['get']> extends never ? never : FcstdDocument['objects'][number];\n deps: Set<string>;\n verdict?: TranslateVerdict;\n variable?: string;\n}\n\n/** Extract link dependencies relevant for ordering. */\nfunction depsOf(obj: FcstdDocument['objects'][number]): string[] {\n const out: string[] = [];\n const linkProps = ['Base', 'Tool', 'Profile', 'BaseFeature', 'Originals'];\n for (const p of linkProps) {\n const el = obj.properties.get(p)?.children[0];\n const v = el?.attributes['value'];\n if (v) out.push(v);\n }\n const shapes = obj.properties.get('Shapes')?.children[0];\n if (shapes) {\n for (const link of shapes.children) {\n const v = link.attributes['value'];\n if (v) out.push(v);\n }\n }\n return out;\n}\n\n/**\n * GOTCHA (PadTest V6 failure): a `PartDesign::Body`'s feature list lives in\n * DIFFERENT properties depending on the FreeCAD version —\n * - modern (0.19+): `Model` (App::PropertyLinkList), ordered\n * - legacy: `Group` (App::PropertyLinkList)\n * The Tip is `Body.Tip`. Reading only `Group` on a modern document yields an\n * empty list → no same-Body chaining → features degrade to a loose\n * `cad.group` of overlapping siblings (PadTest rebuilt volume ≈ 5.2× the Tip's,\n * bboxDiag ≈ 2×). Prefer `Model`, fall back to `Group`.\n */\nfunction bodyFeatureNames(obj: FcstdDocument['objects'][number]): string[] {\n for (const prop of ['Model', 'Group']) {\n const list = obj.properties.get(prop)?.children[0];\n if (!list) continue;\n const names: string[] = [];\n for (const link of list.children) {\n const v = link.attributes['value'];\n if (v) names.push(v);\n }\n if (names.length > 0) return names;\n }\n return [];\n}\n\n/**\n * M5.1/M5.2 — translate every object in dependency order and lower to JS.\n * `sketchVerdict` supplies the M3 outcome per sketch object name; sketches\n * whose contour feeds a Pad/Pocket appear as inputs.\n *\n * @param doc parsed FCStd object graph to translate\n * @param sketchVerdict per-sketch M3 verdict keyed by object name\n * @param sketchContours solved contours per L0 sketch, keyed by object name\n * @param baseName source base name used in generated file headers/labels\n * @param placements per-object Placement used to re-orient placed geometry; missing → identity\n * @returns the lowered call plan, per-object dispositions and generated code\n */\nexport function generateModel(\n doc: FcstdDocument,\n sketchVerdict: Map<string, { level: 'L0' | 'L1' | 'L2'; reason?: string; loopCount?: number }>,\n sketchContours: Map<string, Contour[]>,\n baseName: string,\n /** M8.3: per-object Placement (sketches + features); missing → identity */\n placements?: Map<string, Placement>,\n /** H7: objects whose Shape is a ZIP .brp member (pure-Shape carriers → shape-asset). */\n shapeCarriers?: ReadonlySet<string>,\n): GenResult {\n const byName = new Map(doc.objects.map((o) => [o.name, o]));\n const nodes = new Map<string, Node>();\n for (const obj of doc.objects) {\n nodes.set(obj.name, { name: obj.name, obj, deps: new Set(depsOf(obj)) });\n }\n\n // Kahn topological sort; objects with unbuilt deps fall back to insertion\n // order iteration until progress stalls (remaining are baked with reason).\n // M10.1: iteration order is Body.Group sequence FIRST (features of a Body\n // process in Group order so the D-C chain follows PartDesign semantics),\n // then leftover objects in document order.\n const groupSeq: string[] = [];\n for (const obj of doc.objects) {\n if (obj.type !== 'PartDesign::Body') continue;\n for (const m of bodyFeatureNames(obj)) {\n if (byName.has(m) && !groupSeq.includes(m)) groupSeq.push(m);\n }\n }\n const iterationOrder = [\n ...groupSeq,\n ...doc.objects.map((o) => o.name).filter((n) => !groupSeq.includes(n)),\n ];\n const order: string[] = [];\n const built = new Set<string>();\n let progress = true;\n while (progress) {\n progress = false;\n for (const name of iterationOrder) {\n const node = nodes.get(name)!;\n if (built.has(node.name)) continue;\n if ([...node.deps].every((d) => built.has(d) || !byName.has(d))) {\n built.add(node.name);\n order.push(node.name);\n progress = true;\n }\n }\n }\n\n const variables = new Map<string, string>();\n const results: GenObjectResult[] = [];\n const calls: CadCall[] = [];\n let partCounter = 0;\n const newVar = (): string => `part${partCounter++}`;\n\n // D-C (M9.4): same-Body features fuse cumulatively in Body.Group order —\n // the first translated feature is the base, every later additive feature\n // (Pad/…) unions with the chain, every subtractive one (Pocket/Cut)\n // subtracts. cad.group is NOT used inside a Body (that is assembly\n // semantics); cross-Body grouping stays in lower()'s root handling (M10).\n const memberToBody = new Map<string, string>();\n for (const obj of doc.objects) {\n if (obj.type !== 'PartDesign::Body') continue;\n for (const m of bodyFeatureNames(obj)) {\n if (!memberToBody.has(m)) memberToBody.set(m, obj.name);\n }\n }\n const chainVar = new Map<string, string>(); // body name → accumulated var\n\n for (const name of order) {\n const node = nodes.get(name)!;\n const obj = node.obj;\n\n if (obj.type === 'Sketcher::SketchObject') {\n const verdict = sketchVerdict.get(name);\n const contours = sketchContours.get(name);\n const usable =\n !!verdict &&\n verdict.level !== 'L2' &&\n (verdict.loopCount ?? 0) > 0 &&\n !!contours &&\n contours.length > 0;\n if (usable) {\n // M6 wiring: emit a real `cad.sketch({contours})` creator so the\n // solved contour becomes a face variable the Pad/Pocket/Extrusion/\n // Revolution features below can consume.\n const v = newVar();\n variables.set(name, v);\n const sketchCall: CadCall = {\n out: v, op: 'cad.sketch', source: name, inputs: [], params: { contours },\n };\n calls.push(sketchCall);\n results.push({\n name, type: obj.type, variable: v, calls: [sketchCall], disposition: 'translated',\n sketch: verdict,\n });\n } else {\n results.push({\n name, type: obj.type, calls: [], disposition: 'baked',\n reason: verdict?.reason ?? (contours ? 'sketch-not-solved' : 'sketch-no-contours'), sketch: verdict,\n });\n }\n continue;\n }\n\n if (obj.type === 'App::Origin' || obj.type === 'App::Plane' || obj.type === 'App::Line') {\n results.push({ name, type: obj.type, calls: [], disposition: 'preserved-only', reason: 'datum' });\n continue;\n }\n\n // Sketches are now real face variables (see the Sketcher::SketchObject\n // branch above), so every dependency that resolves to one flows through.\n const verdict = translateObject(obj, (dep) => {\n const v = variables.get(dep);\n return v !== undefined ? v : undefined;\n }, doc.objects, shapeCarriers);\n node.verdict = verdict;\n if (verdict.kind === 'translated') {\n // rename output vars to partN sequence\n for (const call of verdict.calls) {\n const v = newVar();\n variables.set(call.out, v);\n // remap inputs that were intermediate (Pocket_cut) or named outputs\n call.inputs = call.inputs.map((i) => variables.get(i) ?? i);\n call.out = v;\n calls.push(call);\n }\n // M8.3: features build in sketch-local coordinates (cad.sketch lays the\n // face on local XY; extrude runs along local +Z). Re-orient the final\n // solid by the PROFILE SKETCH's Placement: rotate_euler then translate,\n // so the result lands where FreeCAD puts it. Identity placements emit\n // nothing.\n // GOTCHA (PadTest V6, relErr 3.20%): a PartDesign feature's geometry is\n // built in the SKETCH frame, but FreeCAD may store a DIFFERENT Placement\n // on the feature object itself (Pad001: sketch P=(10,0,0)\n // Q=(0,.7071,0,.7071) vs feature P=0 Q=(0,.7071,.7071,0)) — re-orienting\n // by the feature's own frame drops the sketch origin offset and rotates\n // the extrude axis into the wrong direction (−3.20% volume, centroid\n // off 1.67). The sketch's Placement is the authoritative frame for the\n // built geometry; fall back to the feature's own for sketchless features.\n const lastVar = verdict.calls.at(-1)?.out;\n const sketchLink = obj.properties.get('Sketch')?.children[0]?.attributes['value'];\n const pl = (sketchLink ? placements?.get(sketchLink) : undefined) ?? placements?.get(name);\n if (lastVar && pl && !isIdentityPlacement(pl)) {\n let cur = lastVar;\n const euler = quatToEulerXYZDeg(pl.q);\n const isRotation = Math.abs(euler[0]) > 1e-9 || Math.abs(euler[1]) > 1e-9 || Math.abs(euler[2]) > 1e-9;\n if (isRotation) {\n const rv = newVar();\n variables.set(cur, rv); // map old name → rotated var for consumers\n calls.push({ out: rv, op: 'cad.rotate_euler', source: name, inputs: [cur], params: { anglesDeg: euler } });\n cur = rv;\n }\n const needsTranslate = Math.abs(pl.p[0]) > 1e-9 || Math.abs(pl.p[1]) > 1e-9 || Math.abs(pl.p[2]) > 1e-9;\n if (needsTranslate) {\n const tv = newVar();\n variables.set(cur, tv);\n calls.push({ out: tv, op: 'cad.translate', source: name, inputs: [cur], params: { offset: [...pl.p] } });\n cur = tv;\n }\n // the object's variable is now the fully placed result\n variables.set(name, cur);\n }\n // M9.4 (D-C): fold the feature into its Body's chain — AFTER the placement\n // step so the chain accumulates the PLACED feature shape. Pocket/Cut\n // subtract from the chain; everything else unions onto it. The first\n // feature in the Body's feature list (Model/Group) order becomes the\n // chain base — no cad.group inside a Body; consumers (M10) read chainVar.\n // GOTCHA (PadTest V6): folding the UNPLACED feature var (the old order)\n // left the chain head in sketch-local space while each feature's Placement\n // was applied to a separate, unused variable → the exported body spanned\n // both the local and the placed copies (~2× bboxDiag, ~5× volume).\n const body = memberToBody.get(name);\n const isSubtractive = obj.type === 'PartDesign::Pocket' || obj.type === 'Part::Cut';\n if (body) {\n const prev = chainVar.get(body);\n // UpToLast/UpToFirst: FreeCAD's \"up to\" support is the Body's ACCUMULATED\n // shape, NOT only the immediate BaseFeature link — retarget the kernel\n // ref at the chain head (prev). GOTCHA (PadTest V6): truncating against\n // the immediate BaseFeature (a small Pad001 disc) left an 8.06% volume\n // deficit vs the Tip; against the accumulated chain it drops to 3.20%\n // (bbox already exact at delta 0).\n if (prev) {\n for (const c of verdict.calls) {\n if (c.op === 'cad.extrude' && c.params.baseFeature !== undefined) {\n // GOTCHA (PadTest V6 residual): the up-to extrude builds its\n // prism in the SKETCH-LOCAL frame, but the chain head (prev)\n // lives in the PLACED (global) frame. FreeCAD's boolean runs in\n // one frame — so transform prev back into the sketch frame\n // first: local = R^-1(global - p). Feeding the placed chain var\n // directly silently truncates at the wrong face (Pad002 truth\n // AddShape 48199 vs rebuilt deficit ~9108 mm^3 → 3.2% total).\n const needsInverse =\n pl !== undefined && !isIdentityPlacement(pl);\n if (needsInverse && pl) {\n const invQ: [number, number, number, number] = [\n -pl.q[0]!, -pl.q[1]!, -pl.q[2]!, pl.q[3]!,\n ];\n const invEuler = quatToEulerXYZDeg(invQ);\n const tv = newVar();\n const tvCall: CadCall = {\n out: tv, op: 'cad.translate', source: name,\n inputs: [prev], params: { offset: [-pl.p[0]!, -pl.p[1]!, -pl.p[2]!] },\n };\n const rv = newVar();\n const rvCall: CadCall = {\n out: rv, op: 'cad.rotate_euler', source: name,\n inputs: [tv], params: { anglesDeg: invEuler },\n };\n // insert BEFORE the extrude call: faijs is a statement\n // language — `baseFeature: partN` referencing a later\n // statement is E_REFERENCE (parser rejects forward refs).\n const at = calls.indexOf(c);\n calls.splice(at < 0 ? calls.length : at, 0, tvCall, rvCall);\n c.params.baseFeature = jsExpr(rv);\n } else {\n c.params.baseFeature = jsExpr(prev);\n }\n }\n }\n }\n const featureVar = variables.get(name) ?? verdict.calls.at(-1)!.out;\n if (!prev) {\n chainVar.set(body, featureVar); // base feature\n } else if (isSubtractive && verdict.calls.at(-1)!.op === 'cad.subtract' && verdict.calls.at(-1)!.inputs.includes(prev)) {\n // Pocket already subtracted from the chain var itself (BaseFeature\n // resolved to the chain) — its output IS the new chain head; no\n // extra subtract (would cut twice).\n chainVar.set(body, featureVar);\n } else if (isSubtractive) {\n const nv = newVar();\n calls.push({ out: nv, op: 'cad.subtract', source: name, inputs: [prev, featureVar], params: {} });\n chainVar.set(body, nv);\n } else {\n const nv = newVar();\n calls.push({ out: nv, op: 'cad.union', source: name, inputs: [prev, featureVar], params: {} });\n chainVar.set(body, nv);\n }\n }\n results.push({ name, type: obj.type, variable: verdict.calls.at(-1)?.out, calls: verdict.calls, disposition: 'translated', reason: verdict.reason });\n } else if (verdict.kind === 'baked') {\n results.push({ name, type: obj.type, calls: [], disposition: 'baked', reason: verdict.reason });\n } else {\n results.push({ name, type: obj.type, calls: [], disposition: 'preserved-only', reason: verdict.reason });\n }\n }\n\n // also mark unreachable (cycle) objects as baked\n for (const obj of doc.objects) {\n if (!results.some((r) => r.name === obj.name)) {\n results.push({ name: obj.name, type: obj.type, calls: [], disposition: 'baked', reason: 'dependency-cycle' });\n }\n }\n\n // M10.3/M10.5 — split by Body: calls whose source object belongs to a Body\n // (including the chain union/subtract calls emitted for it) go to\n // model/<BodyName>.fai.js; everything else (loose Part features) stays in\n // main.fai.js. When no Body has geometry, everything lands in main (the\n // single-file shape). Aggregate entry groups per-file roots via cad.group.\n const callBody = new Map<string, string>();\n for (const r of results) {\n const b = memberToBody.get(r.name);\n if (b) for (const c of r.calls) callBody.set(c.out, b);\n }\n const bodiesWithGeo = new Set<string>();\n for (const b of new Set(memberToBody.values())) {\n if (chainVar.has(b)) bodiesWithGeo.add(b);\n }\n const files: GenResult['files'] = [];\n let code: string;\n let rootVar: string | undefined;\n if (bodiesWithGeo.size > 0) {\n const mainCalls: CadCall[] = [];\n const perBody = new Map<string, CadCall[]>();\n // M10c partition in DEPENDENCY ORDER: `calls` is already topologically\n // sorted, so ONE forward pass assigns each call — to its own source's Body\n // when known (`callBody`), else to the Body its first body-owned input went\n // to. GOTCHA (PadTest V6): the previous implementation re-assigned such\n // calls by APPENDING them to the end of the Body file, which broke\n // dependency order — a Body file ended up referencing a variable declared\n // further down (`let` TDZ ReferenceError at run time: `part8` used `part6`).\n // Filtering `calls` in place preserves the topological order.\n const assigned = new Map<string, string>(); // call.out → Body file name\n for (const c of calls) {\n const own = callBody.get(c.out);\n const viaInput = c.inputs.map((inp) => assigned.get(inp)).find((b) => b !== undefined);\n const b = own !== undefined && bodiesWithGeo.has(own) ? own : viaInput;\n if (b !== undefined && bodiesWithGeo.has(b)) {\n if (!perBody.has(b)) perBody.set(b, []);\n perBody.get(b)!.push(c);\n assigned.set(c.out, b);\n } else {\n mainCalls.push(c);\n }\n }\n for (const b of bodiesWithGeo) {\n const bodyCalls = perBody.get(b) ?? [];\n // terminal: alias the chain head to <Body>_out so the aggregate entry\n // has a stable, name-independent reference to each Body's result.\n const head = chainVar.get(b)!;\n const withTerminal = [\n ...bodyCalls,\n { out: `${b}_out`, op: 'identity', source: b, inputs: [head], params: {} } as CadCall,\n ];\n files.push({ path: `model/${b}.fai.js`, code: lowerBody(withTerminal, `${baseName}/${b}`, b), body: b });\n }\n // main.fai.js: aggregate the per-Body terminals via cad.group. M10c:\n // cross-file references close through the standard relative-import\n // contract (module-registry D6) — each Body module's terminal alias\n // `<Body>_out` is its live shape, so a named import binds it.\n const lines: string[] = [];\n lines.push(`// Generated by faijs FCStd port — ${baseName} (aggregate entry)`);\n lines.push(`// Units: mm (faijs contract; FCStd internal units are mm)`);\n const members = [...bodiesWithGeo].map((b) => `${b}_out`);\n // Always import the per-Body terminals: the aggregate entry references\n // `<Body>_out` in BOTH the cad.group (multi-Body) and the single-Body alias\n // path, so a missing import is a SEC_FREE_IDENT parse error (GOTCHA: the\n // single-Body branch previously emitted `let part_out = <Body>_out;` with\n // no import). `mainCalls` may still be empty here.\n if (members.length >= 1) {\n for (const b of bodiesWithGeo) {\n lines.push(`import { ${b}_out } from './${b}.fai.js'; // module ${b}`);\n }\n }\n for (const c of mainCalls) {\n const id = `s${lines.length - 2}`;\n lines.push(`let ${c.out} = ${c.op}(${renderArgs(c)}); // ${id} ${c.source}`);\n }\n if (members.length > 1) {\n rootVar = 'part_out';\n lines.push(`let part_out = cad.group({ members: [${members.join(', ')}] });`);\n } else if (members.length === 1) {\n // single Body: the imported terminal IS the result — alias keeps a\n // stable root name for executors\n rootVar = members[0];\n lines.push(`let part_out = ${rootVar}; // single-Body aggregate`);\n rootVar = 'part_out';\n }\n code = lines.join('\\n') + '\\n';\n } else {\n code = lower(calls, baseName);\n }\n return { calls, objects: results, code, files, rootVar };\n}\n\n/** M10.3 — lower one Body's calls; the last entry is the terminal alias\n * `<Body>_out` (plain JS assignment — faijs has no identity op). */\nfunction lowerBody(calls: CadCall[], label: string, body: string): string {\n const lines: string[] = [];\n lines.push(`// Generated by faijs FCStd port — ${label}`);\n lines.push(`// Units: mm (faijs contract; FCStd internal units are mm)`);\n for (const call of calls) {\n if (call.op === 'identity') {\n // terminal alias: `let <Body>_out = <chain head>;`\n lines.push(`let ${call.out} = ${call.inputs[0]}; // s? ${body} terminal`);\n continue;\n }\n const id = `s${lines.length - 2}`;\n lines.push(`let ${call.out} = ${call.op}(${renderArgs(call)}); // ${id} ${call.source}`);\n }\n return lines.join('\\n') + '\\n';\n}\n\n/** M5.2 — lower the call plan to .fai.js source. faijs syntax: top-level\n * statement flow with `let partN = cad.x(...)`; no wrapper function. */\nfunction lower(calls: CadCall[], baseName: string): string {\n const lines: string[] = [];\n lines.push(`// Generated by faijs FCStd port — ${baseName}`);\n lines.push(`// Units: mm (faijs contract; FCStd internal units are mm)`);\n for (const call of calls) {\n const id = `s${lines.length - 2}`; // statement id sN\n const args = renderArgs(call);\n lines.push(`let ${call.out} = ${call.op}(${args}); // ${id} ${call.source}`);\n }\n // final shape: union of root calls that nobody consumes; faijs scripts\n // end with the output-producing statement (no return, per fixtures).\n const consumed = new Set(calls.flatMap((c) => c.inputs));\n const roots = calls.filter((c) => !consumed.has(c.out)).map((c) => c.out);\n if (roots.length > 1) {\n lines.push(`let part_out = cad.group({ members: [${roots.join(', ')}] });`);\n } else if (roots.length === 0) {\n lines.push(`// no translated geometry (all baked)`);\n }\n return lines.join('\\n') + '\\n';\n}\n\n/**\n * M5.2 — render one IR value as JS. Plain values JSON-encode (byte-identical to\n * the pre-JsExpr output); a `JsExpr` marker renders verbatim, and a container\n * holding one renders element-wise so the expression survives into the source.\n */\nfunction renderValue(v: unknown): string {\n if (isJsExpr(v)) return v.__jsExpr;\n if (Array.isArray(v)) {\n if (v.some(isJsExpr)) return `[${v.map(renderValue).join(', ')}]`;\n return JSON.stringify(v);\n }\n if (v && typeof v === 'object') {\n const entries = Object.entries(v as Record<string, unknown>);\n if (entries.some(([, val]) => containsJsExpr(val))) {\n return `{ ${entries.map(([k, val]) => `${k}: ${renderValue(val)}`).join(', ')} }`;\n }\n return JSON.stringify(v);\n }\n return JSON.stringify(v);\n}\n\n/** True when a value is or (recursively) contains a `JsExpr` marker. */\nfunction containsJsExpr(v: unknown): boolean {\n if (isJsExpr(v)) return true;\n if (Array.isArray(v)) return v.some(containsJsExpr);\n if (v && typeof v === 'object') return Object.values(v as Record<string, unknown>).some(containsJsExpr);\n return false;\n}\n\nfunction renderArgs(call: CadCall): string {\n const positional: string[] = [\n ...call.inputs.map((i) => i),\n ...(call.literals ?? []).map((l) => renderValue(l)),\n ].filter((s) => s.length > 0); // M7.1: drop empty entries so we never emit `(, `\n const named: string[] = [];\n for (const [k, v] of Object.entries(call.params ?? {})) {\n if (v === undefined) continue;\n named.push(`${k}: ${renderValue(v)}`);\n }\n const namedBlock = named.length ? `{ ${named.join(', ')} }` : '';\n // M7.1: no leading comma when there are no positional args — a call with only\n // named params must render as `cad.sketch({ ... })`, never `cad.sketch(, {...})`.\n const rest = namedBlock ? (positional.length ? `, ${namedBlock}` : namedBlock) : '';\n return `${positional.join(', ')}${rest}`;\n}\n"]}
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* freecad/* — byte-exact shadow of the source ZIP members
|
|
10
10
|
*/
|
|
11
11
|
import type { FcstdDocument, FcstdObject } from './document.js';
|
|
12
|
+
/** manifest.json schema: source provenance, units and entry point for the .fai.zip container. */
|
|
12
13
|
export interface FaiManifest {
|
|
13
14
|
/** container format version */
|
|
14
15
|
format: 1;
|
|
@@ -31,6 +32,7 @@ export interface FaiManifest {
|
|
|
31
32
|
* disposition: translated | baked | preserved-only (V3 zero-silent-loss).
|
|
32
33
|
*/
|
|
33
34
|
export type ObjectDisposition = 'translated' | 'baked' | 'preserved-only';
|
|
35
|
+
/** One mapping.json entry: a single object's fidelity disposition, reason and produced artifacts. */
|
|
34
36
|
export interface ObjectMappingEntry {
|
|
35
37
|
/** FCStd object name */
|
|
36
38
|
name: string;
|
|
@@ -48,11 +50,24 @@ export interface ObjectMappingEntry {
|
|
|
48
50
|
gcs?: unknown;
|
|
49
51
|
};
|
|
50
52
|
}
|
|
53
|
+
/** mapping.json schema: the per-object fidelity ledger (zero silent loss, V3). */
|
|
51
54
|
export interface FaiMapping {
|
|
55
|
+
/** one entry per <ObjectData> object */
|
|
52
56
|
objects: ObjectMappingEntry[];
|
|
53
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* Assemble the container manifest.json from the parsed document.
|
|
60
|
+
* @param doc parsed FCStd document (SchemaVersion read from meta)
|
|
61
|
+
* @param sourceFile original FCStd file name (not full path)
|
|
62
|
+
* @param programVersion FreeCAD program version that wrote the document
|
|
63
|
+
* @returns the manifest with format 1, mm units and the BREP-chain entry point
|
|
64
|
+
*/
|
|
54
65
|
export declare function buildManifest(doc: FcstdDocument, sourceFile: string, programVersion: string): FaiManifest;
|
|
55
|
-
/**
|
|
66
|
+
/**
|
|
67
|
+
* Default disposition for an object type before feature translation (M4).
|
|
68
|
+
* @param obj the FCStd object to classify
|
|
69
|
+
* @returns `baked` for sketches and non-datum objects, `preserved-only` for datum types
|
|
70
|
+
*/
|
|
56
71
|
export declare function initialDisposition(obj: FcstdObject): {
|
|
57
72
|
disposition: ObjectDisposition;
|
|
58
73
|
reason?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"container.d.ts","sourceRoot":"","sources":["../../src/fcstd/container.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEhE,MAAM,WAAW,WAAW;IAC1B,+BAA+B;IAC/B,MAAM,EAAE,CAAC,CAAC;IACV,MAAM,EAAE;QACN,+CAA+C;QAC/C,IAAI,EAAE,MAAM,CAAC;QACb,cAAc,EAAE,MAAM,CAAC;QACvB,aAAa,EAAE,MAAM,CAAC;KACvB,CAAC;IACF,sEAAsE;IACtE,KAAK,EAAE,IAAI,CAAC;IACZ;gEAC4D;IAC5D,YAAY,EAAE,IAAI,CAAC;IACnB,iCAAiC;IACjC,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG,YAAY,GAAG,OAAO,GAAG,gBAAgB,CAAC;AAE1E,MAAM,WAAW,kBAAkB;IACjC,wBAAwB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,iBAAiB,CAAC;IAC/B,sEAAsE;IACtE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mDAAmD;IACnD,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,oCAAoC;IACpC,MAAM,CAAC,EAAE;QACP,KAAK,EAAE,QAAQ,GAAG,eAAe,GAAG,OAAO,CAAC;QAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,6DAA6D;QAC7D,GAAG,CAAC,EAAE,OAAO,CAAC;KACf,CAAC;CACH;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,kBAAkB,EAAE,CAAC;CAC/B;AAED,wBAAgB,aAAa,CAC3B,GAAG,EAAE,aAAa,EAClB,UAAU,EAAE,MAAM,EAClB,cAAc,EAAE,MAAM,GACrB,WAAW,CAYb;AAED
|
|
1
|
+
{"version":3,"file":"container.d.ts","sourceRoot":"","sources":["../../src/fcstd/container.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEhE,iGAAiG;AACjG,MAAM,WAAW,WAAW;IAC1B,+BAA+B;IAC/B,MAAM,EAAE,CAAC,CAAC;IACV,MAAM,EAAE;QACN,+CAA+C;QAC/C,IAAI,EAAE,MAAM,CAAC;QACb,cAAc,EAAE,MAAM,CAAC;QACvB,aAAa,EAAE,MAAM,CAAC;KACvB,CAAC;IACF,sEAAsE;IACtE,KAAK,EAAE,IAAI,CAAC;IACZ;gEAC4D;IAC5D,YAAY,EAAE,IAAI,CAAC;IACnB,iCAAiC;IACjC,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG,YAAY,GAAG,OAAO,GAAG,gBAAgB,CAAC;AAE1E,qGAAqG;AACrG,MAAM,WAAW,kBAAkB;IACjC,wBAAwB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,iBAAiB,CAAC;IAC/B,sEAAsE;IACtE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mDAAmD;IACnD,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,oCAAoC;IACpC,MAAM,CAAC,EAAE;QACP,KAAK,EAAE,QAAQ,GAAG,eAAe,GAAG,OAAO,CAAC;QAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,6DAA6D;QAC7D,GAAG,CAAC,EAAE,OAAO,CAAC;KACf,CAAC;CACH;AAED,kFAAkF;AAClF,MAAM,WAAW,UAAU;IACzB,wCAAwC;IACxC,OAAO,EAAE,kBAAkB,EAAE,CAAC;CAC/B;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,aAAa,EAClB,UAAU,EAAE,MAAM,EAClB,cAAc,EAAE,MAAM,GACrB,WAAW,CAYb;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,WAAW,GAAG;IAAE,WAAW,EAAE,iBAAiB,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CASxG"}
|
package/dist/fcstd/container.js
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Assemble the container manifest.json from the parsed document.
|
|
3
|
+
* @param doc parsed FCStd document (SchemaVersion read from meta)
|
|
4
|
+
* @param sourceFile original FCStd file name (not full path)
|
|
5
|
+
* @param programVersion FreeCAD program version that wrote the document
|
|
6
|
+
* @returns the manifest with format 1, mm units and the BREP-chain entry point
|
|
7
|
+
*/
|
|
1
8
|
export function buildManifest(doc, sourceFile, programVersion) {
|
|
2
9
|
return {
|
|
3
10
|
format: 1,
|
|
@@ -11,7 +18,11 @@ export function buildManifest(doc, sourceFile, programVersion) {
|
|
|
11
18
|
entry: 'model/main.fai.js',
|
|
12
19
|
};
|
|
13
20
|
}
|
|
14
|
-
/**
|
|
21
|
+
/**
|
|
22
|
+
* Default disposition for an object type before feature translation (M4).
|
|
23
|
+
* @param obj the FCStd object to classify
|
|
24
|
+
* @returns `baked` for sketches and non-datum objects, `preserved-only` for datum types
|
|
25
|
+
*/
|
|
15
26
|
export function initialDisposition(obj) {
|
|
16
27
|
if (obj.type === 'Sketcher::SketchObject') {
|
|
17
28
|
return { disposition: 'baked', reason: 'pending-sketch-channel' };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"container.js","sourceRoot":"","sources":["../../src/fcstd/container.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"container.js","sourceRoot":"","sources":["../../src/fcstd/container.ts"],"names":[],"mappings":"AA8DA;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAC3B,GAAkB,EAClB,UAAkB,EAClB,cAAsB;IAEtB,OAAO;QACL,MAAM,EAAE,CAAC;QACT,MAAM,EAAE;YACN,IAAI,EAAE,UAAU;YAChB,cAAc;YACd,aAAa,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,eAAe,CAAC,EAAE,SAAS,IAAI,CAAC,CAAC;SACrE;QACD,KAAK,EAAE,IAAI;QACX,YAAY,EAAE,IAAI;QAClB,KAAK,EAAE,mBAAmB;KAC3B,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,GAAgB;IACjD,IAAI,GAAG,CAAC,IAAI,KAAK,wBAAwB,EAAE,CAAC;QAC1C,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,wBAAwB,EAAE,CAAC;IACpE,CAAC;IACD,IAAI,GAAG,CAAC,IAAI,KAAK,aAAa,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,IAAI,GAAG,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;QACxF,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;IAC5D,CAAC;IACD,sEAAsE;IACtE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,6BAA6B,EAAE,CAAC;AACzE,CAAC","sourcesContent":["/**\n * M2.1 — .fai.zip container schemas (manifest.json / mapping.json).\n *\n * Container layout (plan §2.1, 前文 A §6):\n * manifest.json — container manifest, entry point, units\n * mapping.json — per-object fidelity ledger; zero silent loss (R7)\n * model/*.fai.js — translated model scripts\n * assets/*.step — baked geometry fallback set\n * freecad/* — byte-exact shadow of the source ZIP members\n */\nimport type { FcstdDocument, FcstdObject } from './document.js';\n\n/** manifest.json schema: source provenance, units and entry point for the .fai.zip container. */\nexport interface FaiManifest {\n /** container format version */\n format: 1;\n source: {\n /** original FCStd file name (not full path) */\n file: string;\n programVersion: string;\n schemaVersion: number;\n };\n /** unit normalization applied to all coordinates (D7); always \"mm\" */\n units: 'mm';\n /** D-A: FCStd port output is BREP-chain-only (sketch/extrude/... are brep\n * impls without mesh); execution must use `--mode brep`. */\n requiresBrep: true;\n /** entry script inside model/ */\n entry: string;\n}\n\n/**\n * Per-object fidelity ledger. Every <ObjectData> object must have exactly one\n * disposition: translated | baked | preserved-only (V3 zero-silent-loss).\n */\nexport type ObjectDisposition = 'translated' | 'baked' | 'preserved-only';\n\n/** One mapping.json entry: a single object's fidelity disposition, reason and produced artifacts. */\nexport interface ObjectMappingEntry {\n /** FCStd object name */\n name: string;\n type: string;\n disposition: ObjectDisposition;\n /** why not translated (required when disposition !== 'translated') */\n reason?: string;\n /** produced artifacts, container-relative paths */\n artifacts: string[];\n /** M3 sketch fidelity level (D3) */\n sketch?: {\n level: 'solved' | 'initial-value' | 'baked';\n reason?: string;\n /** GCS primitives for future editable-sketch upgrade (D1) */\n gcs?: unknown;\n };\n}\n\n/** mapping.json schema: the per-object fidelity ledger (zero silent loss, V3). */\nexport interface FaiMapping {\n /** one entry per <ObjectData> object */\n objects: ObjectMappingEntry[];\n}\n\n/**\n * Assemble the container manifest.json from the parsed document.\n * @param doc parsed FCStd document (SchemaVersion read from meta)\n * @param sourceFile original FCStd file name (not full path)\n * @param programVersion FreeCAD program version that wrote the document\n * @returns the manifest with format 1, mm units and the BREP-chain entry point\n */\nexport function buildManifest(\n doc: FcstdDocument,\n sourceFile: string,\n programVersion: string,\n): FaiManifest {\n return {\n format: 1,\n source: {\n file: sourceFile,\n programVersion,\n schemaVersion: Number(doc.meta.get('SchemaVersion')?.valueText ?? 4),\n },\n units: 'mm',\n requiresBrep: true,\n entry: 'model/main.fai.js',\n };\n}\n\n/**\n * Default disposition for an object type before feature translation (M4).\n * @param obj the FCStd object to classify\n * @returns `baked` for sketches and non-datum objects, `preserved-only` for datum types\n */\nexport function initialDisposition(obj: FcstdObject): { disposition: ObjectDisposition; reason?: string } {\n if (obj.type === 'Sketcher::SketchObject') {\n return { disposition: 'baked', reason: 'pending-sketch-channel' };\n }\n if (obj.type === 'App::Origin' || obj.type === 'App::Plane' || obj.type === 'App::Line') {\n return { disposition: 'preserved-only', reason: 'datum' };\n }\n // M2 stage: everything non-datum is baked from the ZIP's .brp members\n return { disposition: 'baked', reason: 'feature-translation-pending' };\n}\n"]}
|
package/dist/fcstd/contour.d.ts
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* segments sharing endpoints (tolerance-based), keep closed loops.
|
|
8
8
|
*/
|
|
9
9
|
import type { SketchGeom } from './sketch-parse.js';
|
|
10
|
+
/** One segment of a 2D contour: either a straight line or a circular arc (planar, sketch-local coordinates). */
|
|
10
11
|
export type ContourSeg = {
|
|
11
12
|
kind: 'line';
|
|
12
13
|
x1: number;
|
|
@@ -26,10 +27,17 @@ export type ContourSeg = {
|
|
|
26
27
|
x2: number;
|
|
27
28
|
y2: number;
|
|
28
29
|
};
|
|
30
|
+
/** A chained run of segments; `closed` when the chain's ends meet (R6: pure data, no OCCT dependency). */
|
|
29
31
|
export interface Contour {
|
|
32
|
+
/** chained segments in traversal order */
|
|
30
33
|
segments: ContourSeg[];
|
|
34
|
+
/** true when the chain's endpoints meet within JOIN_TOL */
|
|
31
35
|
closed: boolean;
|
|
32
36
|
}
|
|
33
|
-
/**
|
|
37
|
+
/**
|
|
38
|
+
* Extract closed contours (chains of segments whose endpoints meet).
|
|
39
|
+
* @param geoms solved sketch geometry to chain (non-construction segments only)
|
|
40
|
+
* @returns closed loops plus self-closed circles (open chains are dropped)
|
|
41
|
+
*/
|
|
34
42
|
export declare function extractContours(geoms: SketchGeom[]): Contour[];
|
|
35
43
|
//# sourceMappingURL=contour.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contour.d.ts","sourceRoot":"","sources":["../../src/fcstd/contour.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD,MAAM,MAAM,UAAU,GAClB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAChE;IACE,IAAI,EAAE,KAAK,CAAC;IACZ,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,OAAO,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;CACZ,CAAC;AAEN,MAAM,WAAW,OAAO;IACtB,QAAQ,EAAE,UAAU,EAAE,CAAC;IACvB,MAAM,EAAE,OAAO,CAAC;CACjB;AA2BD
|
|
1
|
+
{"version":3,"file":"contour.d.ts","sourceRoot":"","sources":["../../src/fcstd/contour.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD,gHAAgH;AAChH,MAAM,MAAM,UAAU,GAClB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAChE;IACE,IAAI,EAAE,KAAK,CAAC;IACZ,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,OAAO,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;CACZ,CAAC;AAEN,0GAA0G;AAC1G,MAAM,WAAW,OAAO;IACtB,0CAA0C;IAC1C,QAAQ,EAAE,UAAU,EAAE,CAAC;IACvB,2DAA2D;IAC3D,MAAM,EAAE,OAAO,CAAC;CACjB;AA2BD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,OAAO,EAAE,CA8D9D"}
|
package/dist/fcstd/contour.js
CHANGED
|
@@ -21,7 +21,11 @@ function segEnds(g) {
|
|
|
21
21
|
return undefined; // circles are closed on their own; points don't join
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
|
-
/**
|
|
24
|
+
/**
|
|
25
|
+
* Extract closed contours (chains of segments whose endpoints meet).
|
|
26
|
+
* @param geoms solved sketch geometry to chain (non-construction segments only)
|
|
27
|
+
* @returns closed loops plus self-closed circles (open chains are dropped)
|
|
28
|
+
*/
|
|
25
29
|
export function extractContours(geoms) {
|
|
26
30
|
const pool = [];
|
|
27
31
|
for (const g of geoms) {
|
|
@@ -41,6 +45,11 @@ export function extractContours(geoms) {
|
|
|
41
45
|
let extended = true;
|
|
42
46
|
while (extended) {
|
|
43
47
|
extended = false;
|
|
48
|
+
// GOTCHA (ballend corpus, 2026-09-20): restart the scan from the pool
|
|
49
|
+
// start after EVERY match. Scanning on with the drifted tail let a
|
|
50
|
+
// later-indexed segment touching the new tail steal the chain before
|
|
51
|
+
// the correct earlier-indexed continuation was reached, breaking a
|
|
52
|
+
// perfectly closed loop (extractContours returned 0).
|
|
44
53
|
for (const cand of pool) {
|
|
45
54
|
if (cand.used)
|
|
46
55
|
continue;
|
|
@@ -49,12 +58,14 @@ export function extractContours(geoms) {
|
|
|
49
58
|
segments.push(cand.seg);
|
|
50
59
|
tail = cand.b;
|
|
51
60
|
extended = true;
|
|
61
|
+
break;
|
|
52
62
|
}
|
|
53
63
|
else if (near(tail, cand.b)) {
|
|
54
64
|
cand.used = true;
|
|
55
65
|
segments.push(reverseSeg(cand.seg));
|
|
56
66
|
tail = cand.a;
|
|
57
67
|
extended = true;
|
|
68
|
+
break;
|
|
58
69
|
}
|
|
59
70
|
}
|
|
60
71
|
}
|