@faicad/sheetmetal 0.16.0 → 0.17.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.
- package/dist/allowanceFns.d.ts +1 -1
- package/dist/allowanceFns.d.ts.map +1 -1
- package/dist/allowanceFns.js +1 -1
- package/dist/allowanceFns.js.map +1 -1
- package/dist/api.d.ts +21 -20
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +20 -20
- package/dist/api.js.map +1 -1
- package/dist/authorFns.d.ts +2 -2
- package/dist/authorFns.d.ts.map +1 -1
- package/dist/authorFns.js +61 -51
- package/dist/authorFns.js.map +1 -1
- package/dist/bendTableFns.d.ts +1 -1
- package/dist/bendTableFns.d.ts.map +1 -1
- package/dist/bendTableFns.js +1 -1
- package/dist/bendTableFns.js.map +1 -1
- package/dist/contourFlangeFns.d.ts +5 -4
- package/dist/contourFlangeFns.d.ts.map +1 -1
- package/dist/contourFlangeFns.js +59 -44
- package/dist/contourFlangeFns.js.map +1 -1
- package/dist/cutoutFns.d.ts +5 -5
- package/dist/cutoutFns.d.ts.map +1 -1
- package/dist/cutoutFns.js +22 -14
- package/dist/cutoutFns.js.map +1 -1
- package/dist/dxfFns.d.ts +1 -1
- package/dist/dxfFns.d.ts.map +1 -1
- package/dist/dxfFns.js +1 -1
- package/dist/dxfFns.js.map +1 -1
- package/dist/facade.d.ts +43 -42
- package/dist/facade.d.ts.map +1 -1
- package/dist/facade.js +83 -83
- package/dist/facade.js.map +1 -1
- package/dist/featureTreeFns.d.ts +1 -1
- package/dist/featureTreeFns.d.ts.map +1 -1
- package/dist/featureTreeFns.js +1 -1
- package/dist/featureTreeFns.js.map +1 -1
- package/dist/foldFns.d.ts +3 -3
- package/dist/foldFns.d.ts.map +1 -1
- package/dist/foldFns.js +12 -12
- package/dist/foldFns.js.map +1 -1
- package/dist/foreignUnfoldFns.d.ts +2 -1
- package/dist/foreignUnfoldFns.d.ts.map +1 -1
- package/dist/foreignUnfoldFns.js +21 -10
- package/dist/foreignUnfoldFns.js.map +1 -1
- package/dist/formFns.d.ts +4 -4
- package/dist/formFns.d.ts.map +1 -1
- package/dist/formFns.js +91 -76
- package/dist/formFns.js.map +1 -1
- package/dist/geometryOps.d.ts +32 -0
- package/dist/geometryOps.d.ts.map +1 -0
- package/dist/geometryOps.js +83 -0
- package/dist/geometryOps.js.map +1 -0
- package/dist/hemFns.d.ts +2 -2
- package/dist/hemFns.d.ts.map +1 -1
- package/dist/hemFns.js +4 -4
- package/dist/hemFns.js.map +1 -1
- package/dist/internal.d.ts +2 -1
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +1 -1
- package/dist/internal.js.map +1 -1
- package/dist/jogFns.d.ts +2 -2
- package/dist/jogFns.d.ts.map +1 -1
- package/dist/jogFns.js +6 -6
- package/dist/jogFns.js.map +1 -1
- package/dist/loftedFlangeFns.d.ts +2 -2
- package/dist/loftedFlangeFns.d.ts.map +1 -1
- package/dist/loftedFlangeFns.js +35 -25
- package/dist/loftedFlangeFns.js.map +1 -1
- package/dist/miterFns.d.ts +3 -3
- package/dist/miterFns.d.ts.map +1 -1
- package/dist/miterFns.js +30 -19
- package/dist/miterFns.js.map +1 -1
- package/dist/nestFns.d.ts +1 -1
- package/dist/nestFns.d.ts.map +1 -1
- package/dist/nestFns.js +1 -1
- package/dist/nestFns.js.map +1 -1
- package/dist/polygonFns.d.ts +2 -2
- package/dist/polygonFns.d.ts.map +1 -1
- package/dist/polygonFns.js +1 -1
- package/dist/polygonFns.js.map +1 -1
- package/dist/reliefFns.d.ts +4 -4
- package/dist/reliefFns.d.ts.map +1 -1
- package/dist/reliefFns.js +39 -31
- package/dist/reliefFns.js.map +1 -1
- package/dist/reportFns.d.ts +1 -1
- package/dist/reportFns.d.ts.map +1 -1
- package/dist/reportFns.js +1 -1
- package/dist/reportFns.js.map +1 -1
- package/dist/tabFns.d.ts +3 -3
- package/dist/tabFns.d.ts.map +1 -1
- package/dist/tabFns.js +21 -13
- package/dist/tabFns.js.map +1 -1
- package/dist/types.d.ts +21 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/unfoldFns.d.ts +1 -1
- package/dist/unfoldFns.d.ts.map +1 -1
- package/dist/unfoldFns.js +2 -2
- package/dist/unfoldFns.js.map +1 -1
- package/dist/validateFns.d.ts.map +1 -1
- package/dist/validateFns.js +4 -6
- package/dist/validateFns.js.map +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"featureTreeFns.js","sourceRoot":"","sources":["../src/featureTreeFns.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Result, ok, err, validationError } from '@faicad/faijs/brepjs-compat';\nimport type { BendFeature, FlangeFeature, SheetMetalPart, SheetMetalWarning } from './types.js';\n\n/** Id of the root flat — the part's base flat, present as the root of every graph. */\nexport const ROOT_FLAT_ID = 'root';\n\n/** A flat region in the feature graph (the part's base plus every flange face). */\nexport interface FlatNode {\n id: string;\n isRoot: boolean;\n flange?: FlangeFeature | undefined;\n}\n\n/** A bend connecting two flats. `parent`/`child` are flat ids; `bend` is the recorded feature. */\nexport interface BendEdge {\n bend: BendFeature;\n parent: string;\n child: string;\n}\n\n/** Graph view of an authored part: flats = nodes, bends = edges. */\nexport interface FeatureGraph {\n nodes: Map<string, FlatNode>;\n edges: BendEdge[];\n}\n\n/** A bend that survives in the spanning tree, paired with its source/target flat. */\nexport interface TreeBend {\n bend: BendFeature;\n parent: string;\n child: string;\n}\n\n/** A non-tree edge that must be cut to flatten a closed profile. */\nexport interface SeamCut {\n bend: BendFeature;\n between: [string, string];\n}\n\n/** Result of a spanning-tree build over a feature graph: BFS-ordered tree bends, seam cuts, and the flat nodes. */\nexport interface FeatureTree {\n rootId: string;\n /** Tree edges in breadth-first order (parents precede their children). */\n bends: TreeBend[];\n seams: SeamCut[];\n nodes: Map<string, FlatNode>;\n warnings: SheetMetalWarning[];\n}\n\n/**\n * Build the feature graph for an authored part. Each flange contributes a flat\n * node `flange.id`; bends connect a parent flat to a child flat. A bend whose id\n * matches a flange id (the flange's own fold) is wired parent→flange; any other\n * bend is matched to a flange by id suffix `<flange>::<n>` or defaults to a\n * root-anchored edge so authored parts always produce a connected graph.\n *\n * @param part - the authored sheet-metal part to graph.\n * @returns a `Result<FeatureGraph>` — `ok` with `{ nodes, edges }` on success,\n * or `err` with a `validationError` for a non-positive thickness, duplicate\n * flange/bend ids, or bends that resolve to no flange flat.\n */\nexport function buildFeatureGraph(part: SheetMetalPart): Result<FeatureGraph> {\n if (!Number.isFinite(part.thickness) || part.thickness <= 0) {\n return err(validationError('INVALID_THICKNESS', `part.thickness must be positive, got ${part.thickness}`));\n }\n\n const nodes = new Map<string, FlatNode>();\n nodes.set(ROOT_FLAT_ID, { id: ROOT_FLAT_ID, isRoot: true });\n\n const flangeById = new Map<string, FlangeFeature>();\n for (const flange of part.flanges) {\n if (nodes.has(flange.id)) {\n return err(validationError('DUPLICATE_FLAT', `duplicate flange/flat id '${flange.id}'`));\n }\n nodes.set(flange.id, { id: flange.id, isRoot: false, flange });\n flangeById.set(flange.id, flange);\n }\n\n const edges: BendEdge[] = [];\n const seenBendIds = new Set<string>();\n for (const bend of part.bends) {\n if (seenBendIds.has(bend.id)) {\n return err(validationError('DUPLICATE_BEND', `duplicate bend id '${bend.id}'`));\n }\n seenBendIds.add(bend.id);\n\n // A contour-flange bend (`contour::<flange>::<n>`) is one arc of a multi-bend\n // contour flange. The contour flange records its own developed strip in\n // `part.contourFlanges` and lays out independently of the bend spanning tree\n // (its development is non-rectilinear, like a miter), so its bends never enter\n // the graph — they would resolve to no flange flat and break the tree.\n if (bend.id.startsWith('contour::')) continue;\n\n // Hem and jog sub-bends (`hem::<id>::<n>` / `jog::<id>::<n>`) are the curl/step\n // arcs of a recorded hem or jog. Like contour bends they record their own\n // developed strip (in `part.hems` / `part.jogs`) and lay out non-rectilinearly,\n // so they never enter the spanning tree.\n if (bend.id.startsWith('hem::') || bend.id.startsWith('jog::')) continue;\n\n // A seam bend (`seam::<parent>::<child>`) is an explicit edge between two\n // already-authored flats — the cycle-closing edge of a tube/box profile.\n if (bend.id.startsWith('seam::')) {\n // Format is `seam::<parent>::<child>`; flange ids are validated to exclude\n // `::`, so the last delimiter splits parent from child unambiguously.\n const withoutPrefix = bend.id.slice('seam::'.length);\n const sep = withoutPrefix.lastIndexOf('::');\n const parent = sep >= 0 ? withoutPrefix.slice(0, sep) : undefined;\n const child = sep >= 0 ? withoutPrefix.slice(sep + 2) : undefined;\n if (parent === undefined || child === undefined || !nodes.has(parent) || !nodes.has(child)) {\n return err(\n validationError('UNRESOLVED_SEAM', `seam bend '${bend.id}' references an unknown flat`)\n );\n }\n edges.push({ bend, parent, child });\n continue;\n }\n\n const child = resolveChildFlat(bend.id, nodes);\n if (child === undefined) {\n return err(\n validationError('UNRESOLVED_BEND', `bend '${bend.id}' does not correspond to any flange flat`)\n );\n }\n const flange = flangeById.get(child);\n const parent = resolveParentFlat(flange, nodes);\n edges.push({ bend, parent, child });\n }\n\n return ok({ nodes, edges });\n}\n\nfunction resolveChildFlat(bendId: string, nodes: Map<string, FlatNode>): string | undefined {\n if (nodes.has(bendId)) return bendId;\n const sep = bendId.indexOf('::');\n if (sep > 0) {\n const base = bendId.slice(0, sep);\n if (nodes.has(base)) return base;\n }\n return undefined;\n}\n\nfunction resolveParentFlat(flange: FlangeFeature | undefined, nodes: Map<string, FlatNode>): string {\n if (flange === undefined) return ROOT_FLAT_ID;\n const ref = flange.baseEdge;\n // Chained flanges name their parent flat directly; `face-0` is the base flat.\n if (ref.parentId !== undefined && ref.parentId !== 'face-0' && nodes.has(ref.parentId)) {\n return ref.parentId;\n }\n return nodes.has(`face-${ref.faceIndex}`) ? `face-${ref.faceIndex}` : ROOT_FLAT_ID;\n}\n\n/**\n * Spanning tree over the feature graph, rooted at the base flat. Tree edges are\n * returned BFS-ordered (every parent appears before its children); edges that\n * would close a cycle (box/closed profiles) become seam cuts with a warning.\n *\n * @param graph - the feature graph built by {@link buildFeatureGraph}.\n * @param rootId - the flat id to root the tree at; defaults to {@link ROOT_FLAT_ID}.\n * @returns a `Result<FeatureTree>` — `ok` with the BFS-ordered tree bends, seam\n * cuts, flat nodes, and warnings, or `err` with a `validationError` when the\n * root is unknown or some flat is unreachable from the root.\n */\nexport function buildFeatureTree(graph: FeatureGraph, rootId: string = ROOT_FLAT_ID): Result<FeatureTree> {\n if (!graph.nodes.has(rootId)) {\n return err(validationError('UNKNOWN_ROOT', `root flat '${rootId}' not present in graph`));\n }\n\n // Authored seam bends (`seam::…`) are explicitly the cycle-closing edges of a\n // closed profile. They must never enter the spanning tree, or the BFS can grab a\n // seam as a tree edge and demote a real authored bend to the seam cut — placing\n // its child flat off the wrong frame. Exclude them from BFS and record them as\n // seam cuts directly, so authored seams are always the non-tree edges.\n const seamEdges: BendEdge[] = [];\n const treeCandidates: BendEdge[] = [];\n for (const edge of graph.edges) {\n if (edge.bend.id.startsWith('seam::')) seamEdges.push(edge);\n else treeCandidates.push(edge);\n }\n\n const adjacency = new Map<string, BendEdge[]>();\n for (const id of graph.nodes.keys()) adjacency.set(id, []);\n for (const edge of treeCandidates) {\n adjacency.get(edge.parent)?.push(edge);\n adjacency.get(edge.child)?.push(edge);\n }\n\n const visited = new Set<string>([rootId]);\n const treeEdges = new Set<BendEdge>();\n const bends: TreeBend[] = [];\n const queue: string[] = [rootId];\n\n while (queue.length > 0) {\n const current = queue.shift();\n if (current === undefined) break;\n for (const edge of adjacency.get(current) ?? []) {\n if (treeEdges.has(edge)) continue;\n const next = edge.parent === current ? edge.child : edge.parent;\n if (visited.has(next)) continue;\n visited.add(next);\n treeEdges.add(edge);\n bends.push({ bend: edge.bend, parent: current, child: next });\n queue.push(next);\n }\n }\n\n const warnings: SheetMetalWarning[] = [];\n const seams: SeamCut[] = [];\n const recordSeam = (edge: BendEdge): void => {\n seams.push({ bend: edge.bend, between: [edge.parent, edge.child] });\n warnings.push({\n code: 'SEAM_CUT',\n message: `closed profile: bend '${edge.bend.id}' (${edge.parent}↔${edge.child}) becomes a seam cut`,\n featureId: edge.bend.id,\n });\n };\n for (const edge of seamEdges) recordSeam(edge);\n // A non-seam edge left out of the tree closes a cycle authored without a seam.\n for (const edge of treeCandidates) {\n if (treeEdges.has(edge)) continue;\n recordSeam(edge);\n }\n\n for (const node of graph.nodes.values()) {\n if (!visited.has(node.id)) {\n return err(\n validationError('DISCONNECTED_FLAT', `flat '${node.id}' is not reachable from root '${rootId}'`)\n );\n }\n }\n\n return ok({ rootId, bends, seams, nodes: graph.nodes, warnings });\n}\n\n/**\n * Convenience: graph + spanning tree in one call.\n *\n * @param part - the authored sheet-metal part to graph and tree.\n * @param rootId - the flat id to root the tree at; defaults to {@link ROOT_FLAT_ID}.\n * @returns a `Result<FeatureTree>` — `ok` with the feature tree, or the first\n * `err` produced by {@link buildFeatureGraph} or {@link buildFeatureTree}.\n */\nexport function featureTree(part: SheetMetalPart, rootId: string = ROOT_FLAT_ID): Result<FeatureTree> {\n const graph = buildFeatureGraph(part);\n if (!graph.ok) return graph;\n return buildFeatureTree(graph.value, rootId);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"featureTreeFns.js","sourceRoot":"","sources":["../src/featureTreeFns.ts"],"names":[],"mappings":"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","sourcesContent":["import {type Result, ok, err, validationError} from '@faicad/faijs/api';\nimport type { BendFeature, FlangeFeature, SheetMetalPart, SheetMetalWarning } from './types.js';\n\n/** Id of the root flat — the part's base flat, present as the root of every graph. */\nexport const ROOT_FLAT_ID = 'root';\n\n/** A flat region in the feature graph (the part's base plus every flange face). */\nexport interface FlatNode {\n id: string;\n isRoot: boolean;\n flange?: FlangeFeature | undefined;\n}\n\n/** A bend connecting two flats. `parent`/`child` are flat ids; `bend` is the recorded feature. */\nexport interface BendEdge {\n bend: BendFeature;\n parent: string;\n child: string;\n}\n\n/** Graph view of an authored part: flats = nodes, bends = edges. */\nexport interface FeatureGraph {\n nodes: Map<string, FlatNode>;\n edges: BendEdge[];\n}\n\n/** A bend that survives in the spanning tree, paired with its source/target flat. */\nexport interface TreeBend {\n bend: BendFeature;\n parent: string;\n child: string;\n}\n\n/** A non-tree edge that must be cut to flatten a closed profile. */\nexport interface SeamCut {\n bend: BendFeature;\n between: [string, string];\n}\n\n/** Result of a spanning-tree build over a feature graph: BFS-ordered tree bends, seam cuts, and the flat nodes. */\nexport interface FeatureTree {\n rootId: string;\n /** Tree edges in breadth-first order (parents precede their children). */\n bends: TreeBend[];\n seams: SeamCut[];\n nodes: Map<string, FlatNode>;\n warnings: SheetMetalWarning[];\n}\n\n/**\n * Build the feature graph for an authored part. Each flange contributes a flat\n * node `flange.id`; bends connect a parent flat to a child flat. A bend whose id\n * matches a flange id (the flange's own fold) is wired parent→flange; any other\n * bend is matched to a flange by id suffix `<flange>::<n>` or defaults to a\n * root-anchored edge so authored parts always produce a connected graph.\n *\n * @param part - the authored sheet-metal part to graph.\n * @returns a `Result<FeatureGraph>` — `ok` with `{ nodes, edges }` on success,\n * or `err` with a `validationError` for a non-positive thickness, duplicate\n * flange/bend ids, or bends that resolve to no flange flat.\n */\nexport function buildFeatureGraph(part: SheetMetalPart): Result<FeatureGraph> {\n if (!Number.isFinite(part.thickness) || part.thickness <= 0) {\n return err(validationError('INVALID_THICKNESS', `part.thickness must be positive, got ${part.thickness}`));\n }\n\n const nodes = new Map<string, FlatNode>();\n nodes.set(ROOT_FLAT_ID, { id: ROOT_FLAT_ID, isRoot: true });\n\n const flangeById = new Map<string, FlangeFeature>();\n for (const flange of part.flanges) {\n if (nodes.has(flange.id)) {\n return err(validationError('DUPLICATE_FLAT', `duplicate flange/flat id '${flange.id}'`));\n }\n nodes.set(flange.id, { id: flange.id, isRoot: false, flange });\n flangeById.set(flange.id, flange);\n }\n\n const edges: BendEdge[] = [];\n const seenBendIds = new Set<string>();\n for (const bend of part.bends) {\n if (seenBendIds.has(bend.id)) {\n return err(validationError('DUPLICATE_BEND', `duplicate bend id '${bend.id}'`));\n }\n seenBendIds.add(bend.id);\n\n // A contour-flange bend (`contour::<flange>::<n>`) is one arc of a multi-bend\n // contour flange. The contour flange records its own developed strip in\n // `part.contourFlanges` and lays out independently of the bend spanning tree\n // (its development is non-rectilinear, like a miter), so its bends never enter\n // the graph — they would resolve to no flange flat and break the tree.\n if (bend.id.startsWith('contour::')) continue;\n\n // Hem and jog sub-bends (`hem::<id>::<n>` / `jog::<id>::<n>`) are the curl/step\n // arcs of a recorded hem or jog. Like contour bends they record their own\n // developed strip (in `part.hems` / `part.jogs`) and lay out non-rectilinearly,\n // so they never enter the spanning tree.\n if (bend.id.startsWith('hem::') || bend.id.startsWith('jog::')) continue;\n\n // A seam bend (`seam::<parent>::<child>`) is an explicit edge between two\n // already-authored flats — the cycle-closing edge of a tube/box profile.\n if (bend.id.startsWith('seam::')) {\n // Format is `seam::<parent>::<child>`; flange ids are validated to exclude\n // `::`, so the last delimiter splits parent from child unambiguously.\n const withoutPrefix = bend.id.slice('seam::'.length);\n const sep = withoutPrefix.lastIndexOf('::');\n const parent = sep >= 0 ? withoutPrefix.slice(0, sep) : undefined;\n const child = sep >= 0 ? withoutPrefix.slice(sep + 2) : undefined;\n if (parent === undefined || child === undefined || !nodes.has(parent) || !nodes.has(child)) {\n return err(\n validationError('UNRESOLVED_SEAM', `seam bend '${bend.id}' references an unknown flat`)\n );\n }\n edges.push({ bend, parent, child });\n continue;\n }\n\n const child = resolveChildFlat(bend.id, nodes);\n if (child === undefined) {\n return err(\n validationError('UNRESOLVED_BEND', `bend '${bend.id}' does not correspond to any flange flat`)\n );\n }\n const flange = flangeById.get(child);\n const parent = resolveParentFlat(flange, nodes);\n edges.push({ bend, parent, child });\n }\n\n return ok({ nodes, edges });\n}\n\nfunction resolveChildFlat(bendId: string, nodes: Map<string, FlatNode>): string | undefined {\n if (nodes.has(bendId)) return bendId;\n const sep = bendId.indexOf('::');\n if (sep > 0) {\n const base = bendId.slice(0, sep);\n if (nodes.has(base)) return base;\n }\n return undefined;\n}\n\nfunction resolveParentFlat(flange: FlangeFeature | undefined, nodes: Map<string, FlatNode>): string {\n if (flange === undefined) return ROOT_FLAT_ID;\n const ref = flange.baseEdge;\n // Chained flanges name their parent flat directly; `face-0` is the base flat.\n if (ref.parentId !== undefined && ref.parentId !== 'face-0' && nodes.has(ref.parentId)) {\n return ref.parentId;\n }\n return nodes.has(`face-${ref.faceIndex}`) ? `face-${ref.faceIndex}` : ROOT_FLAT_ID;\n}\n\n/**\n * Spanning tree over the feature graph, rooted at the base flat. Tree edges are\n * returned BFS-ordered (every parent appears before its children); edges that\n * would close a cycle (box/closed profiles) become seam cuts with a warning.\n *\n * @param graph - the feature graph built by {@link buildFeatureGraph}.\n * @param rootId - the flat id to root the tree at; defaults to {@link ROOT_FLAT_ID}.\n * @returns a `Result<FeatureTree>` — `ok` with the BFS-ordered tree bends, seam\n * cuts, flat nodes, and warnings, or `err` with a `validationError` when the\n * root is unknown or some flat is unreachable from the root.\n */\nexport function buildFeatureTree(graph: FeatureGraph, rootId: string = ROOT_FLAT_ID): Result<FeatureTree> {\n if (!graph.nodes.has(rootId)) {\n return err(validationError('UNKNOWN_ROOT', `root flat '${rootId}' not present in graph`));\n }\n\n // Authored seam bends (`seam::…`) are explicitly the cycle-closing edges of a\n // closed profile. They must never enter the spanning tree, or the BFS can grab a\n // seam as a tree edge and demote a real authored bend to the seam cut — placing\n // its child flat off the wrong frame. Exclude them from BFS and record them as\n // seam cuts directly, so authored seams are always the non-tree edges.\n const seamEdges: BendEdge[] = [];\n const treeCandidates: BendEdge[] = [];\n for (const edge of graph.edges) {\n if (edge.bend.id.startsWith('seam::')) seamEdges.push(edge);\n else treeCandidates.push(edge);\n }\n\n const adjacency = new Map<string, BendEdge[]>();\n for (const id of graph.nodes.keys()) adjacency.set(id, []);\n for (const edge of treeCandidates) {\n adjacency.get(edge.parent)?.push(edge);\n adjacency.get(edge.child)?.push(edge);\n }\n\n const visited = new Set<string>([rootId]);\n const treeEdges = new Set<BendEdge>();\n const bends: TreeBend[] = [];\n const queue: string[] = [rootId];\n\n while (queue.length > 0) {\n const current = queue.shift();\n if (current === undefined) break;\n for (const edge of adjacency.get(current) ?? []) {\n if (treeEdges.has(edge)) continue;\n const next = edge.parent === current ? edge.child : edge.parent;\n if (visited.has(next)) continue;\n visited.add(next);\n treeEdges.add(edge);\n bends.push({ bend: edge.bend, parent: current, child: next });\n queue.push(next);\n }\n }\n\n const warnings: SheetMetalWarning[] = [];\n const seams: SeamCut[] = [];\n const recordSeam = (edge: BendEdge): void => {\n seams.push({ bend: edge.bend, between: [edge.parent, edge.child] });\n warnings.push({\n code: 'SEAM_CUT',\n message: `closed profile: bend '${edge.bend.id}' (${edge.parent}↔${edge.child}) becomes a seam cut`,\n featureId: edge.bend.id,\n });\n };\n for (const edge of seamEdges) recordSeam(edge);\n // A non-seam edge left out of the tree closes a cycle authored without a seam.\n for (const edge of treeCandidates) {\n if (treeEdges.has(edge)) continue;\n recordSeam(edge);\n }\n\n for (const node of graph.nodes.values()) {\n if (!visited.has(node.id)) {\n return err(\n validationError('DISCONNECTED_FLAT', `flat '${node.id}' is not reachable from root '${rootId}'`)\n );\n }\n }\n\n return ok({ rootId, bends, seams, nodes: graph.nodes, warnings });\n}\n\n/**\n * Convenience: graph + spanning tree in one call.\n *\n * @param part - the authored sheet-metal part to graph and tree.\n * @param rootId - the flat id to root the tree at; defaults to {@link ROOT_FLAT_ID}.\n * @returns a `Result<FeatureTree>` — `ok` with the feature tree, or the first\n * `err` produced by {@link buildFeatureGraph} or {@link buildFeatureTree}.\n */\nexport function featureTree(part: SheetMetalPart, rootId: string = ROOT_FLAT_ID): Result<FeatureTree> {\n const graph = buildFeatureGraph(part);\n if (!graph.ok) return graph;\n return buildFeatureTree(graph.value, rootId);\n}\n"]}
|
package/dist/foldFns.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type Result } from '@faicad/faijs/
|
|
1
|
+
import { type Result } from '@faicad/faijs/api';
|
|
2
2
|
import type { BendRule, FlatInput, FlatPattern, MaterialSpec, SheetMetalPart, SheetMetalWarning } from './types.js';
|
|
3
3
|
/** A folded part plus the warnings raised while folding (e.g. SEAM_CUT, MIN_RADIUS). */
|
|
4
4
|
export interface FoldResult {
|
|
@@ -19,13 +19,13 @@ export interface FoldResult {
|
|
|
19
19
|
* @param input - the flat pattern input to fold.
|
|
20
20
|
* @returns the folded sheet metal part, or an error.
|
|
21
21
|
*/
|
|
22
|
-
export declare function fold(input: FlatInput): Result<SheetMetalPart
|
|
22
|
+
export declare function fold(input: FlatInput): Promise<Result<SheetMetalPart>>;
|
|
23
23
|
/**
|
|
24
24
|
* {@link fold} that also surfaces the fold warnings alongside the part.
|
|
25
25
|
* @param input - the flat pattern input to fold.
|
|
26
26
|
* @returns the fold result with warnings, or an error.
|
|
27
27
|
*/
|
|
28
|
-
export declare function foldWithWarnings(input: FlatInput): Result<FoldResult
|
|
28
|
+
export declare function foldWithWarnings(input: FlatInput): Promise<Result<FoldResult>>;
|
|
29
29
|
/** How to resolve the bend rule for a bend line read out of a 2D flat pattern. */
|
|
30
30
|
export interface PatternToFlatInputOptions {
|
|
31
31
|
thickness: number;
|
package/dist/foldFns.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"foldFns.d.ts","sourceRoot":"","sources":["../src/foldFns.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"foldFns.d.ts","sourceRoot":"","sources":["../src/foldFns.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,MAAM,EAAgF,MAAM,mBAAmB,CAAC;AAC7H,OAAO,KAAK,EACV,QAAQ,EAER,SAAS,EACT,WAAW,EAIX,YAAY,EACZ,cAAc,EACd,iBAAiB,EAElB,MAAM,YAAY,CAAC;AAWpB,wFAAwF;AACxF,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,cAAc,CAAC;IACrB,QAAQ,EAAE,iBAAiB,EAAE,CAAC;CAC/B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,IAAI,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAI5E;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAyEpF;AAiBD,kFAAkF;AAClF,MAAM,WAAW,yBAAyB;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;OAKG;IACH,OAAO,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,QAAQ,CAAC;IACzC,QAAQ,CAAC,EAAE,YAAY,GAAG,SAAS,CAAC;CACrC;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,WAAW,EACpB,IAAI,EAAE,yBAAyB,GAC9B,MAAM,CAAC,SAAS,CAAC,CA4BnB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM,CAAC,SAAS,CAAC,CAwBvE"}
|
package/dist/foldFns.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ok, err, validationError, getEdges, curveStartPoint, curveEndPoint
|
|
1
|
+
import { ok, err, validationError, getEdges, curveStartPoint, curveEndPoint } from '@faicad/faijs/api';
|
|
2
2
|
import { authorPart } from './authorFns.js';
|
|
3
3
|
import { addBendRelief } from './reliefFns.js';
|
|
4
4
|
import { addCutout } from './cutoutFns.js';
|
|
@@ -22,8 +22,8 @@ import { validatePart } from './validateFns.js';
|
|
|
22
22
|
* @param input - the flat pattern input to fold.
|
|
23
23
|
* @returns the folded sheet metal part, or an error.
|
|
24
24
|
*/
|
|
25
|
-
export function fold(input) {
|
|
26
|
-
const result = foldWithWarnings(input);
|
|
25
|
+
export async function fold(input) {
|
|
26
|
+
const result = await foldWithWarnings(input);
|
|
27
27
|
if (!result.ok)
|
|
28
28
|
return result;
|
|
29
29
|
return ok(result.value.part);
|
|
@@ -33,14 +33,14 @@ export function fold(input) {
|
|
|
33
33
|
* @param input - the flat pattern input to fold.
|
|
34
34
|
* @returns the fold result with warnings, or an error.
|
|
35
35
|
*/
|
|
36
|
-
export function foldWithWarnings(input) {
|
|
36
|
+
export async function foldWithWarnings(input) {
|
|
37
37
|
const spec = {
|
|
38
38
|
thickness: input.thickness,
|
|
39
39
|
base: { length: input.baseLength, width: input.width },
|
|
40
40
|
flanges: input.regions.map(regionToFlange),
|
|
41
41
|
...(input.material !== undefined ? { material: input.material } : {}),
|
|
42
42
|
};
|
|
43
|
-
const authored = authorPart(spec);
|
|
43
|
+
const authored = await authorPart(spec);
|
|
44
44
|
if (!authored.ok)
|
|
45
45
|
return authored;
|
|
46
46
|
let part = authored.value;
|
|
@@ -50,7 +50,7 @@ export function foldWithWarnings(input) {
|
|
|
50
50
|
for (const region of input.regions) {
|
|
51
51
|
if (region.bendRelief === undefined)
|
|
52
52
|
continue;
|
|
53
|
-
const relieved = addBendRelief(part, region.id, region.bendRelief);
|
|
53
|
+
const relieved = await addBendRelief(part, region.id, region.bendRelief);
|
|
54
54
|
if (!relieved.ok)
|
|
55
55
|
return relieved;
|
|
56
56
|
part = relieved.value;
|
|
@@ -58,14 +58,14 @@ export function foldWithWarnings(input) {
|
|
|
58
58
|
// Re-apply recorded cutouts (in region-local coords) so a cutout'd part folds
|
|
59
59
|
// back into the same solid + recorded feature, exactly as `addCutout` produces.
|
|
60
60
|
for (const spec of input.baseCutouts ?? []) {
|
|
61
|
-
const cutResult = addCutout(part, { ...spec, region: ROOT_FLAT_ID });
|
|
61
|
+
const cutResult = await addCutout(part, { ...spec, region: ROOT_FLAT_ID });
|
|
62
62
|
if (!cutResult.ok)
|
|
63
63
|
return cutResult;
|
|
64
64
|
part = cutResult.value;
|
|
65
65
|
}
|
|
66
66
|
for (const region of input.regions) {
|
|
67
67
|
for (const spec of region.cutouts ?? []) {
|
|
68
|
-
const cutResult = addCutout(part, { ...spec, region: region.id });
|
|
68
|
+
const cutResult = await addCutout(part, { ...spec, region: region.id });
|
|
69
69
|
if (!cutResult.ok)
|
|
70
70
|
return cutResult;
|
|
71
71
|
part = cutResult.value;
|
|
@@ -74,28 +74,28 @@ export function foldWithWarnings(input) {
|
|
|
74
74
|
// Re-apply recorded tabs (additive protrusions) and form features so a tab'd /
|
|
75
75
|
// formed part folds back into the same solid + recorded features.
|
|
76
76
|
for (const spec of input.baseTabs ?? []) {
|
|
77
|
-
const tabbed = addTab(part, { ...spec, region: ROOT_FLAT_ID });
|
|
77
|
+
const tabbed = await addTab(part, { ...spec, region: ROOT_FLAT_ID });
|
|
78
78
|
if (!tabbed.ok)
|
|
79
79
|
return tabbed;
|
|
80
80
|
part = tabbed.value;
|
|
81
81
|
}
|
|
82
82
|
for (const region of input.regions) {
|
|
83
83
|
for (const spec of region.tabs ?? []) {
|
|
84
|
-
const tabbed = addTab(part, { ...spec, region: region.id });
|
|
84
|
+
const tabbed = await addTab(part, { ...spec, region: region.id });
|
|
85
85
|
if (!tabbed.ok)
|
|
86
86
|
return tabbed;
|
|
87
87
|
part = tabbed.value;
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
90
|
for (const spec of input.baseForms ?? []) {
|
|
91
|
-
const formed = addForm(part, { ...spec, region: ROOT_FLAT_ID });
|
|
91
|
+
const formed = await addForm(part, { ...spec, region: ROOT_FLAT_ID });
|
|
92
92
|
if (!formed.ok)
|
|
93
93
|
return formed;
|
|
94
94
|
part = formed.value;
|
|
95
95
|
}
|
|
96
96
|
for (const region of input.regions) {
|
|
97
97
|
for (const spec of region.forms ?? []) {
|
|
98
|
-
const formed = addForm(part, { ...spec, region: region.id });
|
|
98
|
+
const formed = await addForm(part, { ...spec, region: region.id });
|
|
99
99
|
if (!formed.ok)
|
|
100
100
|
return formed;
|
|
101
101
|
part = formed.value;
|
package/dist/foldFns.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"foldFns.js","sourceRoot":"","sources":["../src/foldFns.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type Result,\n type Vec3,\n ok,\n err,\n validationError,\n getEdges,\n curveStartPoint,\n curveEndPoint,\n} from '@faicad/faijs/brepjs-compat';\nimport type {\n BendRule,\n CutoutSpec,\n FlatInput,\n FlatPattern,\n FlatSide,\n FoldRegion,\n FormSpec,\n MaterialSpec,\n SheetMetalPart,\n SheetMetalWarning,\n TabSpec,\n} from './types.js';\nimport { authorPart, type AuthorSpec, type FlangeSpec } from './authorFns.js';\nimport { addBendRelief } from './reliefFns.js';\nimport { addCutout } from './cutoutFns.js';\nimport { addTab } from './tabFns.js';\nimport { addForm } from './formFns.js';\nimport { featureTree, ROOT_FLAT_ID } from './featureTreeFns.js';\nimport { developedLength } from './allowanceFns.js';\nimport { unfold, edgeBasis2, type Frame2 } from './unfoldFns.js';\nimport { validatePart } from './validateFns.js';\n\n/** A folded part plus the warnings raised while folding (e.g. SEAM_CUT, MIN_RADIUS). */\nexport interface FoldResult {\n part: SheetMetalPart;\n warnings: SheetMetalWarning[];\n}\n\n/**\n * Fold a flat pattern up into a 3D part. Each {@link FoldRegion} folds about its\n * fold line off its parent region, exactly inverting {@link unfold}: folding by an\n * angle is the same rigid construction the forward authoring path performs, so this\n * reuses {@link authorPart}'s bend geometry wholesale rather than re-deriving it.\n *\n * The result carries a fully-populated {@link SheetMetalPart} (valid solid + the\n * BendFeature/FlangeFeature tree consistent with `authorPart`), so\n * `unfold(fold(input))` round-trips. SEAM_CUT-style and min-radius warnings ride\n * inside the Ok payload.\n *\n * @param input - the flat pattern input to fold.\n * @returns the folded sheet metal part, or an error.\n */\nexport function fold(input: FlatInput): Result<SheetMetalPart> {\n const result = foldWithWarnings(input);\n if (!result.ok) return result;\n return ok(result.value.part);\n}\n\n/**\n * {@link fold} that also surfaces the fold warnings alongside the part.\n * @param input - the flat pattern input to fold.\n * @returns the fold result with warnings, or an error.\n */\nexport function foldWithWarnings(input: FlatInput): Result<FoldResult> {\n const spec: AuthorSpec = {\n thickness: input.thickness,\n base: { length: input.baseLength, width: input.width },\n flanges: input.regions.map(regionToFlange),\n ...(input.material !== undefined ? { material: input.material } : {}),\n };\n\n const authored = authorPart(spec);\n if (!authored.ok) return authored;\n let part = authored.value;\n\n // Re-apply any bend reliefs recorded on the regions, so fold reproduces a\n // relief'd part's solid + recorded feature (reliefs are cut after the solid is\n // built, exactly as the explicit `addBendRelief` API does).\n for (const region of input.regions) {\n if (region.bendRelief === undefined) continue;\n const relieved = addBendRelief(part, region.id, region.bendRelief);\n if (!relieved.ok) return relieved;\n part = relieved.value;\n }\n\n // Re-apply recorded cutouts (in region-local coords) so a cutout'd part folds\n // back into the same solid + recorded feature, exactly as `addCutout` produces.\n for (const spec of input.baseCutouts ?? []) {\n const cutResult = addCutout(part, { ...spec, region: ROOT_FLAT_ID });\n if (!cutResult.ok) return cutResult;\n part = cutResult.value;\n }\n for (const region of input.regions) {\n for (const spec of region.cutouts ?? []) {\n const cutResult = addCutout(part, { ...spec, region: region.id });\n if (!cutResult.ok) return cutResult;\n part = cutResult.value;\n }\n }\n\n // Re-apply recorded tabs (additive protrusions) and form features so a tab'd /\n // formed part folds back into the same solid + recorded features.\n for (const spec of input.baseTabs ?? []) {\n const tabbed = addTab(part, { ...spec, region: ROOT_FLAT_ID });\n if (!tabbed.ok) return tabbed;\n part = tabbed.value;\n }\n for (const region of input.regions) {\n for (const spec of region.tabs ?? []) {\n const tabbed = addTab(part, { ...spec, region: region.id });\n if (!tabbed.ok) return tabbed;\n part = tabbed.value;\n }\n }\n for (const spec of input.baseForms ?? []) {\n const formed = addForm(part, { ...spec, region: ROOT_FLAT_ID });\n if (!formed.ok) return formed;\n part = formed.value;\n }\n for (const region of input.regions) {\n for (const spec of region.forms ?? []) {\n const formed = addForm(part, { ...spec, region: region.id });\n if (!formed.ok) return formed;\n part = formed.value;\n }\n }\n\n // SEAM_CUT comes from the feature-tree walk; INVALID_SOLID / COLLISION / MIN_RADIUS\n // come from the canonical validator, so fold inherits the same checks (and message\n // text) as the rest of the package instead of re-deriving min-radius here.\n const warnings: SheetMetalWarning[] = [];\n const tree = featureTree(part);\n if (tree.ok) warnings.push(...tree.value.warnings);\n warnings.push(...validatePart(part));\n\n return ok({ part, warnings });\n}\n\nfunction regionToFlange(region: FoldRegion): FlangeSpec {\n return {\n id: region.id,\n length: region.length,\n angleDeg: region.angleDeg,\n rule: region.rule,\n direction: region.direction,\n ...(region.side !== undefined ? { side: region.side } : {}),\n ...(region.parent !== undefined ? { parent: region.parent } : {}),\n ...(region.offset !== undefined ? { offset: region.offset } : {}),\n ...(region.width !== undefined ? { width: region.width } : {}),\n ...(region.miter !== undefined ? { miter: region.miter } : {}),\n };\n}\n\n/** How to resolve the bend rule for a bend line read out of a 2D flat pattern. */\nexport interface PatternToFlatInputOptions {\n thickness: number;\n /**\n * Rule for bend line `i` (0-based, in {@link FlatPattern.bendLines} order). A flat\n * pattern is pure geometry and cannot encode K-factor/inner-radius, so the rule is\n * a required *input*; only the regions/sides/offsets/spans/lengths/angles are\n * recovered from the 2D geometry.\n */\n ruleFor: (bendIndex: number) => BendRule;\n material?: MaterialSpec | undefined;\n}\n\n/**\n * Reconstruct a {@link FlatInput} region-tree from the *2D flat-pattern geometry*\n * alone — `pattern.outline` (a closed 2D wire) and `pattern.bendLines` (each a 2D\n * segment + fold angle/direction). Nothing is read from a feature tree or a 3D\n * solid: the regions, sides, offsets, spans and flat lengths are all recovered by\n * reading real 2D coordinates back out of the wire/edges via the public morph\n * geometry readers (`getEdges`, `curveStartPoint`, `curveEndPoint`).\n *\n * This is the non-circular round-trip bridge: feeding `unfold(part).pattern` through\n * here and into {@link fold} exercises unfold's 2D placement, this parser, and the\n * forward fold geometry — a bug in any of them breaks the round-trip.\n *\n * Algorithm (rectilinear families — PR1 develops only axis-aligned rectangles):\n * every bend line is an axis-aligned segment lying on the shared edge between a\n * parent region and a child's developed strip. The developed strip width is\n * `developedLength(angle, thickness, ruleFor(i))` (the supplied rule). BFS outward\n * from the base region (the one anchored at the origin): a bend line on a known\n * region's edge spawns a child region whose far edge is the next outward bend line\n * (a grandchild) or the outline boundary; `length = far-extent − dev`, `span` =\n * bend-line length, `offset`/`side` are the bend line's position on the parent edge.\n *\n * @param pattern - the flat pattern to convert.\n * @param opts - options (thickness, ruleFor, material).\n * @returns the flat input, or an error.\n */\nexport function patternToFlatInput(\n pattern: FlatPattern,\n opts: PatternToFlatInputOptions\n): Result<FlatInput> {\n const { thickness, ruleFor, material } = opts;\n if (!Number.isFinite(thickness) || thickness <= 0) {\n return err(validationError('INVALID_THICKNESS', `thickness must be positive, got ${thickness}`));\n }\n\n const segsResult = parseBendLines(pattern, thickness, ruleFor);\n if (!segsResult.ok) return segsResult;\n const bends = segsResult.value;\n\n const outline = parseOutlineExtents(pattern);\n if (!outline.ok) return outline;\n const { xs, ys, contains } = outline.value;\n\n const base = baseRect(xs, ys, contains, bends);\n if (!base.ok) return base;\n const baseRectVal = base.value;\n\n const buildResult = buildRegions(baseRectVal, bends, contains);\n if (!buildResult.ok) return buildResult;\n\n return ok({\n thickness,\n baseLength: baseRectVal.x1 - baseRectVal.x0,\n width: baseRectVal.y1 - baseRectVal.y0,\n ...(material !== undefined ? { material } : {}),\n regions: buildResult.value,\n });\n}\n\n/**\n * Convert an authored {@link SheetMetalPart} into the {@link FlatInput} that folds\n * back into it, going strictly through the 2D flat pattern: `unfold(part)` produces\n * the developed wire + bend lines, and {@link patternToFlatInput} recovers the\n * region tree from that 2D geometry. Only the bend *rule* is read off the part (by\n * matching bend id), which a flat pattern legitimately cannot encode; every\n * geometric attribute is parsed from the wire/edges. This makes the round-trip\n * oracle non-circular — a bug in unfold's 2D placement or in the parser breaks it.\n *\n * Seam bends (closed profiles) are left unfolded by `unfold`, so the recovered part\n * is the open spanning-tree shape, not the re-closed box.\n *\n * @param part - the sheet metal part to recover a flat input from.\n * @returns the flat input, or an error.\n */\nexport function partToFlatInput(part: SheetMetalPart): Result<FlatInput> {\n const unfolded = unfold(part);\n if (!unfolded.ok) return unfolded;\n const pattern = unfolded.value.pattern;\n\n // The rule is allowed as an input (a flat pattern cannot encode K-factor). Match\n // each bend line back to its authored bend by id, in unfold's bend-line order\n // (which is the spanning-tree order featureTree/layoutTree emit), falling back to\n // a default rule if a bend can't be matched.\n const ruleByIndex = bendRulesInOrder(part);\n const fallback: BendRule = part.material?.defaultRule ?? { innerRadius: part.thickness, kFactor: 0.44 };\n\n const recovered = patternToFlatInput(pattern, {\n thickness: part.thickness,\n ruleFor: (i) => ruleByIndex[i] ?? fallback,\n ...(part.material !== undefined ? { material: part.material } : {}),\n });\n if (!recovered.ok) return recovered;\n\n const withCutouts = attachCutouts(part, recovered.value);\n if (!withCutouts.ok) return withCutouts;\n const withTabs = attachTabs(part, withCutouts.value);\n if (!withTabs.ok) return withTabs;\n return attachForms(part, withTabs.value);\n}\n\n/**\n * Re-attach a part's recorded cutouts onto a recovered {@link FlatInput}. Cutouts\n * ride as interior loops, so {@link patternToFlatInput} (which reads only the outer\n * outline) cannot recover them; we carry the region-local specs across instead.\n * The recovered region for the i-th feature-tree bend is `b${i}` (the parser's id\n * scheme), and the unfold emits bend lines in that same BFS order, so a flange's\n * recovered region id is its position in `featureTree(part).bends`. A cutout whose\n * region can't be mapped is failed loudly rather than dropped: silently shedding it\n * would change the refolded volume with no diagnostic, a correctness violation.\n */\nfunction attachCutouts(part: SheetMetalPart, input: FlatInput): Result<FlatInput> {\n if (part.cutouts === undefined || part.cutouts.length === 0) return ok(input);\n\n const recoveredIdByFlange = new Map<string, string>();\n const tree = featureTree(part);\n if (tree.ok) {\n tree.value.bends.forEach((tb, i) => recoveredIdByFlange.set(tb.child, `b${i}`));\n }\n\n const baseCutouts: CutoutSpec[] = [];\n const byRegion = new Map<string, CutoutSpec[]>();\n for (const c of part.cutouts) {\n if (c.region === ROOT_FLAT_ID) {\n baseCutouts.push(c.spec);\n continue;\n }\n const recoveredId = recoveredIdByFlange.get(c.region);\n if (recoveredId === undefined) {\n return err(\n validationError(\n 'CUTOUT_REGION_UNMAPPED',\n `partToFlatInput: cutout on region '${c.region}' has no recovered flat region; round-trip would drop it`\n )\n );\n }\n const list = byRegion.get(recoveredId) ?? [];\n list.push(c.spec);\n byRegion.set(recoveredId, list);\n }\n\n const regions = input.regions.map((r) => {\n const specs = byRegion.get(r.id);\n return specs === undefined ? r : { ...r, cutouts: specs };\n });\n\n return ok({\n ...input,\n regions,\n ...(baseCutouts.length > 0 ? { baseCutouts } : {}),\n });\n}\n\n/**\n * Re-attach a part's recorded tabs onto a recovered {@link FlatInput}, mirroring\n * {@link attachCutouts}. A tab carries its region-local {@link TabSpec}, so it\n * replays through the recorded-feature path exactly as cutouts/forms do — the spec,\n * not the outline, drives the re-fuse. (The tab does extend the outer outline, but\n * the outline parser only needs to recover the base/flange rectangles, which it does\n * from the bend lines and the unprotruded edges; see {@link partToFlatInput}.) An\n * unmappable region fails loudly rather than silently dropping the tab — silently\n * shedding it would change the refolded volume with no diagnostic.\n */\nfunction attachTabs(part: SheetMetalPart, input: FlatInput): Result<FlatInput> {\n if (part.tabs === undefined || part.tabs.length === 0) return ok(input);\n\n const recoveredIdByFlange = new Map<string, string>();\n const tree = featureTree(part);\n if (tree.ok) {\n tree.value.bends.forEach((tb, i) => recoveredIdByFlange.set(tb.child, `b${i}`));\n }\n\n const baseTabs: TabSpec[] = [];\n const byRegion = new Map<string, TabSpec[]>();\n for (const t of part.tabs) {\n if (t.region === ROOT_FLAT_ID) {\n baseTabs.push(t.spec);\n continue;\n }\n const recoveredId = recoveredIdByFlange.get(t.region);\n if (recoveredId === undefined) {\n return err(\n validationError(\n 'TAB_REGION_UNMAPPED',\n `partToFlatInput: tab on region '${t.region}' has no recovered flat region; round-trip would drop it`\n )\n );\n }\n const list = byRegion.get(recoveredId) ?? [];\n list.push(t.spec);\n byRegion.set(recoveredId, list);\n }\n\n const regions = input.regions.map((r) => {\n const specs = byRegion.get(r.id);\n return specs === undefined ? r : { ...r, tabs: specs };\n });\n\n return ok({\n ...input,\n regions,\n ...(baseTabs.length > 0 ? { baseTabs } : {}),\n });\n}\n\n/**\n * Re-attach a part's recorded form features (louvers / embosses) onto a recovered\n * {@link FlatInput}, mirroring {@link attachCutouts}. Forms are net-material-neutral\n * (they don't change the outer outline), so they round-trip cleanly through the\n * outline oracle; only their region-local specs need carrying across. An unmappable\n * region fails loudly rather than silently dropping the form.\n */\nfunction attachForms(part: SheetMetalPart, input: FlatInput): Result<FlatInput> {\n if (part.forms === undefined || part.forms.length === 0) return ok(input);\n\n const recoveredIdByFlange = new Map<string, string>();\n const tree = featureTree(part);\n if (tree.ok) {\n tree.value.bends.forEach((tb, i) => recoveredIdByFlange.set(tb.child, `b${i}`));\n }\n\n const baseForms: FormSpec[] = [];\n const byRegion = new Map<string, FormSpec[]>();\n for (const f of part.forms) {\n if (f.region === ROOT_FLAT_ID) {\n baseForms.push(f.spec);\n continue;\n }\n const recoveredId = recoveredIdByFlange.get(f.region);\n if (recoveredId === undefined) {\n return err(\n validationError(\n 'FORM_REGION_UNMAPPED',\n `partToFlatInput: form on region '${f.region}' has no recovered flat region; round-trip would drop it`\n )\n );\n }\n const list = byRegion.get(recoveredId) ?? [];\n list.push(f.spec);\n byRegion.set(recoveredId, list);\n }\n\n const regions = input.regions.map((r) => {\n const specs = byRegion.get(r.id);\n return specs === undefined ? r : { ...r, forms: specs };\n });\n\n return ok({\n ...input,\n regions,\n ...(baseForms.length > 0 ? { baseForms } : {}),\n });\n}\n\n/**\n * Bend rules in {@link FlatPattern.bendLines} order. `unfold` emits bend lines in\n * the layout walk's order, which is the feature tree's BFS (spanning-tree) order;\n * the same walk drives the rules here so index `i` lines up with bend line `i`.\n */\nfunction bendRulesInOrder(part: SheetMetalPart): BendRule[] {\n const tree = featureTree(part);\n if (!tree.ok) return part.flanges.map((f) => f.rule);\n const ruleById = new Map<string, BendRule>();\n for (const f of part.flanges) ruleById.set(f.id, f.rule);\n for (const b of part.bends) if (!ruleById.has(b.id)) ruleById.set(b.id, b.rule);\n const rules: BendRule[] = [];\n for (const tb of tree.value.bends) {\n rules.push(ruleById.get(tb.child) ?? tb.bend.rule);\n }\n return rules;\n}\n\nconst EPS = 1e-6;\n\ntype Pt2 = [number, number];\n\n/** A bend line parsed from the 2D pattern: an axis-aligned segment + fold metadata. */\ninterface BendSeg {\n index: number;\n /** Orientation of the segment line. */\n axis: 'h' | 'v';\n /** Fixed coordinate of the line (x for vertical, y for horizontal). */\n fixed: number;\n /** Segment span on the free axis: `[lo, hi]`. */\n lo: number;\n hi: number;\n span: number;\n angleDeg: number;\n direction: 'up' | 'down';\n /** The supplied rule (a flat pattern cannot encode K-factor, so it's an input). */\n rule: BendRule;\n /** Developed strip width for this bend (from the supplied rule). */\n dev: number;\n}\n\nfunction parseBendLines(\n pattern: FlatPattern,\n thickness: number,\n ruleFor: (i: number) => BendRule\n): Result<BendSeg[]> {\n const out: BendSeg[] = [];\n for (let i = 0; i < pattern.bendLines.length; i += 1) {\n const bl = pattern.bendLines[i];\n if (bl === undefined) continue;\n const a = curveStartPoint(bl.line);\n const b = curveEndPoint(bl.line);\n const seg = axisAlignedSeg(a, b);\n if (seg === undefined) {\n return err(\n validationError('NON_AXIS_BEND', `bend line ${i} is not axis-aligned: (${a[0]},${a[1]})→(${b[0]},${b[1]})`)\n );\n }\n const rule = ruleFor(i);\n const devResult = developedLength(bl.angleDeg, thickness, rule);\n if (!devResult.ok) return devResult;\n out.push({\n index: i,\n axis: seg.axis,\n fixed: seg.fixed,\n lo: seg.lo,\n hi: seg.hi,\n span: seg.hi - seg.lo,\n angleDeg: bl.angleDeg,\n direction: bl.direction,\n rule,\n dev: devResult.value,\n });\n }\n return ok(out);\n}\n\nfunction axisAlignedSeg(a: Vec3, b: Vec3): { axis: 'h' | 'v'; fixed: number; lo: number; hi: number } | undefined {\n if (Math.abs(a[0] - b[0]) < EPS) {\n return { axis: 'v', fixed: (a[0] + b[0]) / 2, lo: Math.min(a[1], b[1]), hi: Math.max(a[1], b[1]) };\n }\n if (Math.abs(a[1] - b[1]) < EPS) {\n return { axis: 'h', fixed: (a[1] + b[1]) / 2, lo: Math.min(a[0], b[0]), hi: Math.max(a[0], b[0]) };\n }\n return undefined;\n}\n\ninterface OutlineExtents {\n /** Sorted unique x-coordinates of every outline vertex. */\n xs: number[];\n /** Sorted unique y-coordinates of every outline vertex. */\n ys: number[];\n /** True if the point lies strictly inside the filled (developed) region. */\n contains: (x: number, y: number) => boolean;\n}\n\n/**\n * Read the outline wire's vertices back out via `getEdges` + curve endpoint readers\n * and build a point-in-region test over the axis-aligned arrangement they induce.\n * The developed pattern is a simply-connected rectilinear polygon, so a winding-free\n * cell test (is this cell's centre inside the polygon) suffices.\n */\nfunction parseOutlineExtents(pattern: FlatPattern): Result<OutlineExtents> {\n const edges = getEdges(pattern.outline);\n if (edges.length < 3) {\n return err(validationError('OUTLINE_TOO_SMALL', `outline has ${edges.length} edges, need ≥ 3`));\n }\n const segs: { a: Pt2; b: Pt2 }[] = [];\n const xsRaw: number[] = [];\n const ysRaw: number[] = [];\n for (const e of edges) {\n const s = curveStartPoint(e);\n const t = curveEndPoint(e);\n segs.push({ a: [s[0], s[1]], b: [t[0], t[1]] });\n xsRaw.push(s[0], t[0]);\n ysRaw.push(s[1], t[1]);\n }\n const poly = orderedLoop(segs);\n if (poly === undefined) {\n return err(validationError('OUTLINE_NOT_CLOSED', 'outline edges do not form a single closed loop'));\n }\n const xs = uniqueSorted(xsRaw);\n const ys = uniqueSorted(ysRaw);\n const contains = (x: number, y: number): boolean => pointInPolygon(poly, x, y);\n return ok({ xs, ys, contains });\n}\n\n/** Chain segments into one ordered vertex loop, or undefined if they don't close. */\nfunction orderedLoop(segs: { a: Pt2; b: Pt2 }[]): Pt2[] | undefined {\n if (segs.length === 0) return undefined;\n const key = (p: Pt2): string => `${round(p[0])}|${round(p[1])}`;\n const from = new Map<string, Pt2>();\n // Two segments sharing a start-vertex key means the loop isn't a simple chain\n // (floating-point drift can also collapse two near vertices into one bucket);\n // bail rather than silently overwrite and trace a wrong polygon.\n for (const s of segs) {\n const k = key(s.a);\n if (from.has(k)) return undefined;\n from.set(k, s.b);\n }\n const start = segs[0]?.a;\n if (start === undefined) return undefined;\n const loop: Pt2[] = [start];\n let cur = from.get(key(start));\n let guard = 0;\n while (cur !== undefined && key(cur) !== key(start) && guard < segs.length + 2) {\n loop.push(cur);\n cur = from.get(key(cur));\n guard += 1;\n }\n if (cur === undefined || key(cur) !== key(start)) return undefined;\n return loop;\n}\n\nfunction round(n: number): number {\n return Math.round(n / EPS) * EPS;\n}\n\n/** Standard ray-cast point-in-polygon for the (axis-aligned) outline loop. */\nfunction pointInPolygon(poly: Pt2[], x: number, y: number): boolean {\n let inside = false;\n for (let i = 0, j = poly.length - 1; i < poly.length; j = i, i += 1) {\n const pi = poly[i];\n const pj = poly[j];\n if (pi === undefined || pj === undefined) continue;\n const intersect =\n pi[1] > y !== pj[1] > y &&\n x < ((pj[0] - pi[0]) * (y - pi[1])) / (pj[1] - pi[1]) + pi[0];\n if (intersect) inside = !inside;\n }\n return inside;\n}\n\ninterface Rect {\n x0: number;\n y0: number;\n x1: number;\n y1: number;\n}\n\n/**\n * Base region: the rectangle anchored at the origin, `[0, baseLength] × [0, width]`\n * (the unfold layout fixes the base frame there). Each base edge is bounded by the\n * bend line lying on it (a tray folds off all four edges) or, when no flange folds\n * off that edge, by the outline boundary. The extents are therefore the nearest\n * base-bounding bend line — a bend line perpendicular to the run that crosses the\n * origin row/column — clamped to the outline reach.\n */\nfunction baseRect(\n xs: number[],\n ys: number[],\n contains: (x: number, y: number) => boolean,\n bends: BendSeg[]\n): Result<Rect> {\n if (xs.length < 2 || ys.length < 2) {\n return err(validationError('BASE_NOT_FOUND', 'cannot locate base region at origin'));\n }\n // Probe halfway between the origin and the first positive x grid line — a\n // scale-invariant point inside the base's undivided +X span (the base is one\n // rectangle in X, so the first gridline > 0 is its right edge). Avoids assuming\n // any absolute unit and stays correct when xmin/ymin flanges add negative coords.\n const xFirstPositive = xs.find((v) => v > EPS);\n if (xFirstPositive === undefined) {\n return err(validationError('BASE_NOT_FOUND', 'no positive x extent to locate the base region'));\n }\n const xProbeBase = xFirstPositive / 2;\n const yProbe = firstFilledCellMid(ys.filter((v) => v > -EPS), (mid) => contains(xProbeBase, mid));\n if (yProbe === undefined) {\n return err(validationError('BASE_NOT_FOUND', 'origin cell is not inside the developed region'));\n }\n const x0 = 0;\n const y0 = 0;\n // +X base edge: nearest vertical bend line right of origin crossing the base row,\n // else the outline reach.\n const xBendBound = nearestBend(bends, 'v', yProbe, x0, 1);\n const x1 = xBendBound ?? marchOutline(x0, 1, (c) => contains(c, yProbe));\n const xProbe = (x0 + x1) / 2;\n const yBendBound = nearestBend(bends, 'h', xProbe, y0, 1);\n const y1 = yBendBound ?? marchOutline(y0, 1, (c) => contains(xProbe, c));\n if (x1 <= x0 + EPS || y1 <= y0 + EPS) {\n return err(validationError('BASE_NOT_FOUND', 'base region has zero extent'));\n }\n return ok({ x0, y0, x1, y1 });\n}\n\n/**\n * Nearest bend line of the given orientation, on the `dir` side of `from` along its\n * perpendicular axis, whose span covers the base `cross` coordinate — i.e. a bend\n * line lying on the base's far edge in that direction. Returns its fixed coordinate.\n */\nfunction nearestBend(\n bends: BendSeg[],\n axis: 'h' | 'v',\n cross: number,\n from: number,\n dir: 1 | -1\n): number | undefined {\n let best: number | undefined;\n for (const b of bends) {\n if (b.axis !== axis) continue;\n if (cross < b.lo - EPS || cross > b.hi + EPS) continue;\n const beyond = dir > 0 ? b.fixed > from + EPS : b.fixed < from - EPS;\n if (!beyond) continue;\n if (best === undefined || Math.abs(b.fixed - from) < Math.abs(best - from)) best = b.fixed;\n }\n return best;\n}\n\n/** First arrangement cell whose midpoint passes `probe`; locates an interior coord. */\nfunction firstFilledCellMid(coords: number[], probe: (mid: number) => boolean): number | undefined {\n for (let j = 0; j + 1 < coords.length; j += 1) {\n const lo = coords[j];\n const hi = coords[j + 1];\n if (lo === undefined || hi === undefined) continue;\n const mid = (lo + hi) / 2;\n if (probe(mid)) return mid;\n }\n return undefined;\n}\n\n/** March from `c0` in `dir` until the probe leaves the region; bisect to the boundary. */\nfunction marchOutline(c0: number, dir: 1 | -1, probe: (c: number) => boolean): number {\n let inside = c0 + dir * EPS * 4;\n let step = 1;\n let guard = 0;\n while (probe(inside + dir * step) && guard < 100000) {\n inside += dir * step;\n step *= 2;\n guard += 1;\n }\n let lo = inside;\n let hi = inside + dir * step;\n for (let i = 0; i < 60; i += 1) {\n const m = (lo + hi) / 2;\n if (probe(m)) lo = m;\n else hi = m;\n }\n return lo;\n}\n\n/**\n * BFS outward from the base, attributing each bend line to the region whose local\n * edge it lies on (the parent) and spawning the child region beyond it. Each region\n * carries its 2D frame; a bend line collinear with one of the parent's four local\n * edges, within that edge's span, folds a child whose far edge is the nearest\n * outward grandchild bend line or the outline boundary. `side`/`offset` are reported\n * in the parent's local frame so the re-fold reproduces the authored attachment.\n */\nfunction buildRegions(\n base: Rect,\n bends: BendSeg[],\n contains: (x: number, y: number) => boolean\n): Result<FoldRegion[]> {\n const regions: FoldRegion[] = [];\n const used = new Set<number>();\n const baseFrame: Frame2 = {\n origin: [base.x0, base.y0],\n u: [1, 0],\n v: [0, 1],\n uLen: base.x1 - base.x0,\n vLen: base.y1 - base.y0,\n };\n const queue: { frame: Frame2; id: string | undefined }[] = [{ frame: baseFrame, id: undefined }];\n const idForBend = (b: BendSeg): string => `b${b.index}`;\n\n let guard = 0;\n while (queue.length > 0 && guard < bends.length + 4) {\n guard += 1;\n const node = queue.shift();\n if (node === undefined) break;\n for (const b of bends) {\n if (used.has(b.index)) continue;\n const attached = bendOnFrameEdge(b, node.frame);\n if (attached === undefined) continue;\n used.add(b.index);\n\n const far = farExtent(b, attached.outSign, bends, contains);\n const length = far - b.dev;\n if (length <= EPS) {\n return err(\n validationError('BAD_FLANGE_LENGTH', `recovered flange length for bend ${b.index} is non-positive (${length})`)\n );\n }\n\n const id = idForBend(b);\n const region: FoldRegion = {\n id,\n length,\n angleDeg: b.angleDeg,\n direction: b.direction,\n rule: b.rule,\n side: attached.side,\n offset: attached.offset,\n width: b.span,\n ...(node.id !== undefined ? { parent: node.id } : {}),\n };\n regions.push(region);\n queue.push({ frame: childFrame(attached, b, length), id });\n }\n }\n\n if (used.size !== bends.length) {\n return err(\n validationError('UNATTACHED_BEND', `${bends.length - used.size} bend line(s) could not be attached to a region`)\n );\n }\n\n return ok(regions);\n}\n\ninterface BendAttachment {\n side: FlatSide;\n offset: number;\n /** Edge basis of the parent's local edge `side` (mirrors unfold `edgeBasis2`). */\n along: Pt2;\n out: Pt2;\n edgeOrigin: Pt2;\n /** Sign of `out` on the bend's perpendicular axis, so `farExtent` marches outward. */\n outSign: 1 | -1;\n}\n\n/**\n * If bend `b` lies on one of `frame`'s four local edges (within that edge's span),\n * return the parent-local `side`, the `offset` along that edge, and the edge basis.\n * The bend line is collinear with the edge `edgeOrigin + along·t`, `t ∈ [0, edgeLen]`;\n * the offset is the projection of the bend's near endpoint onto `along`.\n */\nfunction bendOnFrameEdge(b: BendSeg, frame: Frame2): BendAttachment | undefined {\n const segMid = bendMidpoint(b);\n const segDir: Pt2 = b.axis === 'v' ? [0, 1] : [1, 0];\n for (const side of ['xmax', 'xmin', 'ymax', 'ymin'] as const) {\n const basis = edgeBasis2(frame, side);\n // Edge must be parallel to the bend (along ∥ segDir) and the bend must sit on it.\n if (Math.abs(cross2(basis.along, segDir)) > EPS) continue;\n const rel: Pt2 = [segMid[0] - basis.edgeOrigin[0], segMid[1] - basis.edgeOrigin[1]];\n const perp = Math.abs(dot2(rel, basis.out));\n if (perp > EPS) continue;\n const t = dot2(rel, basis.along);\n const edgeLen = edgeLengthOf(frame, side);\n const half = b.span / 2;\n if (t < half - EPS || t > edgeLen - half + EPS) continue;\n const offset = t - half;\n // Outward sign on the bend's perpendicular axis (X for a vertical bend line,\n // Y for a horizontal one), so `farExtent` marches the right way.\n const outComp = b.axis === 'v' ? basis.out[0] : basis.out[1];\n const outSign: 1 | -1 = outComp >= 0 ? 1 : -1;\n return { side, offset: Math.max(0, offset), along: basis.along, out: basis.out, edgeOrigin: basis.edgeOrigin, outSign };\n }\n return undefined;\n}\n\n/**\n * Child region frame, mirroring unfold's `placeChild`: origin past the developed\n * strip (`edgeOrigin + along·offset + out·dev`), u along the bend axis (span), v\n * outward (length). This keeps recovered frames identical to the layout's so a\n * grandchild attaches to the right local edge.\n */\nfunction childFrame(attached: BendAttachment, b: BendSeg, length: number): Frame2 {\n const stripFar: Pt2 = [\n attached.edgeOrigin[0] + attached.along[0] * attached.offset + attached.out[0] * b.dev,\n attached.edgeOrigin[1] + attached.along[1] * attached.offset + attached.out[1] * b.dev,\n ];\n return { origin: stripFar, u: attached.along, v: attached.out, uLen: b.span, vLen: length };\n}\n\nfunction edgeLengthOf(f: Frame2, side: FlatSide): number {\n return side === 'xmax' || side === 'xmin' ? f.vLen : f.uLen;\n}\n\nfunction bendMidpoint(b: BendSeg): Pt2 {\n const mid = (b.lo + b.hi) / 2;\n return b.axis === 'v' ? [b.fixed, mid] : [mid, b.fixed];\n}\n\nfunction cross2(a: Pt2, b: Pt2): number {\n return a[0] * b[1] - a[1] * b[0];\n}\nfunction dot2(a: Pt2, b: Pt2): number {\n return a[0] * b[0] + a[1] * b[1];\n}\n\n/**\n * Far perpendicular extent (strip + flat) of a child region from its bend line: the\n * nearest grandchild bend line beyond `b` (parallel, overlapping the span, same\n * outward side) or, failing that, the outline boundary, measured as a distance from\n * the bend line outward. Because bend lines are axis-aligned, the outward direction\n * is along the bend's perpendicular axis with `outSign` (from the edge basis).\n */\nfunction farExtent(\n b: BendSeg,\n outSign: 1 | -1,\n bends: BendSeg[],\n contains: (x: number, y: number) => boolean\n): number {\n let nearest: number | undefined;\n for (const g of bends) {\n if (g.index === b.index) continue;\n if (g.axis !== b.axis) continue;\n const overlaps = g.lo < b.hi - EPS && b.lo < g.hi - EPS;\n if (!overlaps) continue;\n const beyond = outSign > 0 ? g.fixed > b.fixed + EPS : g.fixed < b.fixed - EPS;\n if (!beyond) continue;\n if (nearest === undefined || Math.abs(g.fixed - b.fixed) < Math.abs(nearest - b.fixed)) {\n nearest = g.fixed;\n }\n }\n const boundary = nearest ?? outlineFar(b, outSign, contains);\n return Math.abs(boundary - b.fixed);\n}\n\n/**\n * March perpendicular outward from the bend line until the region stops being filled\n * (the outline boundary), probing at the span midpoint, then bisect to the boundary.\n */\nfunction outlineFar(\n b: BendSeg,\n outSign: 1 | -1,\n contains: (x: number, y: number) => boolean\n): number {\n const mid = (b.lo + b.hi) / 2;\n const probe = (perp: number): boolean =>\n b.axis === 'v' ? contains(perp, mid) : contains(mid, perp);\n return marchOutline(b.fixed, outSign, probe);\n}\n\nfunction uniqueSorted(values: number[]): number[] {\n const sorted = [...values].sort((a, b) => a - b);\n const out: number[] = [];\n for (const v of sorted) {\n const last = out[out.length - 1];\n if (last === undefined || Math.abs(v - last) > EPS) out.push(v);\n }\n return out;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"foldFns.js","sourceRoot":"","sources":["../src/foldFns.ts"],"names":[],"mappings":"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","sourcesContent":["import {type Result, type Vec3, ok, err, validationError, getEdges, curveStartPoint, curveEndPoint} from '@faicad/faijs/api';\nimport type {\n BendRule,\n CutoutSpec,\n FlatInput,\n FlatPattern,\n FlatSide,\n FoldRegion,\n FormSpec,\n MaterialSpec,\n SheetMetalPart,\n SheetMetalWarning,\n TabSpec,\n} from './types.js';\nimport { authorPart, type AuthorSpec, type FlangeSpec } from './authorFns.js';\nimport { addBendRelief } from './reliefFns.js';\nimport { addCutout } from './cutoutFns.js';\nimport { addTab } from './tabFns.js';\nimport { addForm } from './formFns.js';\nimport { featureTree, ROOT_FLAT_ID } from './featureTreeFns.js';\nimport { developedLength } from './allowanceFns.js';\nimport { unfold, edgeBasis2, type Frame2 } from './unfoldFns.js';\nimport { validatePart } from './validateFns.js';\n\n/** A folded part plus the warnings raised while folding (e.g. SEAM_CUT, MIN_RADIUS). */\nexport interface FoldResult {\n part: SheetMetalPart;\n warnings: SheetMetalWarning[];\n}\n\n/**\n * Fold a flat pattern up into a 3D part. Each {@link FoldRegion} folds about its\n * fold line off its parent region, exactly inverting {@link unfold}: folding by an\n * angle is the same rigid construction the forward authoring path performs, so this\n * reuses {@link authorPart}'s bend geometry wholesale rather than re-deriving it.\n *\n * The result carries a fully-populated {@link SheetMetalPart} (valid solid + the\n * BendFeature/FlangeFeature tree consistent with `authorPart`), so\n * `unfold(fold(input))` round-trips. SEAM_CUT-style and min-radius warnings ride\n * inside the Ok payload.\n *\n * @param input - the flat pattern input to fold.\n * @returns the folded sheet metal part, or an error.\n */\nexport async function fold(input: FlatInput): Promise<Result<SheetMetalPart>> {\n const result = await foldWithWarnings(input);\n if (!result.ok) return result;\n return ok(result.value.part);\n}\n\n/**\n * {@link fold} that also surfaces the fold warnings alongside the part.\n * @param input - the flat pattern input to fold.\n * @returns the fold result with warnings, or an error.\n */\nexport async function foldWithWarnings(input: FlatInput): Promise<Result<FoldResult>> {\n const spec: AuthorSpec = {\n thickness: input.thickness,\n base: { length: input.baseLength, width: input.width },\n flanges: input.regions.map(regionToFlange),\n ...(input.material !== undefined ? { material: input.material } : {}),\n };\n\n const authored = await authorPart(spec);\n if (!authored.ok) return authored;\n let part = authored.value;\n\n // Re-apply any bend reliefs recorded on the regions, so fold reproduces a\n // relief'd part's solid + recorded feature (reliefs are cut after the solid is\n // built, exactly as the explicit `addBendRelief` API does).\n for (const region of input.regions) {\n if (region.bendRelief === undefined) continue;\n const relieved = await addBendRelief(part, region.id, region.bendRelief);\n if (!relieved.ok) return relieved;\n part = relieved.value;\n }\n\n // Re-apply recorded cutouts (in region-local coords) so a cutout'd part folds\n // back into the same solid + recorded feature, exactly as `addCutout` produces.\n for (const spec of input.baseCutouts ?? []) {\n const cutResult = await addCutout(part, { ...spec, region: ROOT_FLAT_ID });\n if (!cutResult.ok) return cutResult;\n part = cutResult.value;\n }\n for (const region of input.regions) {\n for (const spec of region.cutouts ?? []) {\n const cutResult = await addCutout(part, { ...spec, region: region.id });\n if (!cutResult.ok) return cutResult;\n part = cutResult.value;\n }\n }\n\n // Re-apply recorded tabs (additive protrusions) and form features so a tab'd /\n // formed part folds back into the same solid + recorded features.\n for (const spec of input.baseTabs ?? []) {\n const tabbed = await addTab(part, { ...spec, region: ROOT_FLAT_ID });\n if (!tabbed.ok) return tabbed;\n part = tabbed.value;\n }\n for (const region of input.regions) {\n for (const spec of region.tabs ?? []) {\n const tabbed = await addTab(part, { ...spec, region: region.id });\n if (!tabbed.ok) return tabbed;\n part = tabbed.value;\n }\n }\n for (const spec of input.baseForms ?? []) {\n const formed = await addForm(part, { ...spec, region: ROOT_FLAT_ID });\n if (!formed.ok) return formed;\n part = formed.value;\n }\n for (const region of input.regions) {\n for (const spec of region.forms ?? []) {\n const formed = await addForm(part, { ...spec, region: region.id });\n if (!formed.ok) return formed;\n part = formed.value;\n }\n }\n\n // SEAM_CUT comes from the feature-tree walk; INVALID_SOLID / COLLISION / MIN_RADIUS\n // come from the canonical validator, so fold inherits the same checks (and message\n // text) as the rest of the package instead of re-deriving min-radius here.\n const warnings: SheetMetalWarning[] = [];\n const tree = featureTree(part);\n if (tree.ok) warnings.push(...tree.value.warnings);\n warnings.push(...validatePart(part));\n\n return ok({ part, warnings });\n}\n\nfunction regionToFlange(region: FoldRegion): FlangeSpec {\n return {\n id: region.id,\n length: region.length,\n angleDeg: region.angleDeg,\n rule: region.rule,\n direction: region.direction,\n ...(region.side !== undefined ? { side: region.side } : {}),\n ...(region.parent !== undefined ? { parent: region.parent } : {}),\n ...(region.offset !== undefined ? { offset: region.offset } : {}),\n ...(region.width !== undefined ? { width: region.width } : {}),\n ...(region.miter !== undefined ? { miter: region.miter } : {}),\n };\n}\n\n/** How to resolve the bend rule for a bend line read out of a 2D flat pattern. */\nexport interface PatternToFlatInputOptions {\n thickness: number;\n /**\n * Rule for bend line `i` (0-based, in {@link FlatPattern.bendLines} order). A flat\n * pattern is pure geometry and cannot encode K-factor/inner-radius, so the rule is\n * a required *input*; only the regions/sides/offsets/spans/lengths/angles are\n * recovered from the 2D geometry.\n */\n ruleFor: (bendIndex: number) => BendRule;\n material?: MaterialSpec | undefined;\n}\n\n/**\n * Reconstruct a {@link FlatInput} region-tree from the *2D flat-pattern geometry*\n * alone — `pattern.outline` (a closed 2D wire) and `pattern.bendLines` (each a 2D\n * segment + fold angle/direction). Nothing is read from a feature tree or a 3D\n * solid: the regions, sides, offsets, spans and flat lengths are all recovered by\n * reading real 2D coordinates back out of the wire/edges via the public morph\n * geometry readers (`getEdges`, `curveStartPoint`, `curveEndPoint`).\n *\n * This is the non-circular round-trip bridge: feeding `unfold(part).pattern` through\n * here and into {@link fold} exercises unfold's 2D placement, this parser, and the\n * forward fold geometry — a bug in any of them breaks the round-trip.\n *\n * Algorithm (rectilinear families — PR1 develops only axis-aligned rectangles):\n * every bend line is an axis-aligned segment lying on the shared edge between a\n * parent region and a child's developed strip. The developed strip width is\n * `developedLength(angle, thickness, ruleFor(i))` (the supplied rule). BFS outward\n * from the base region (the one anchored at the origin): a bend line on a known\n * region's edge spawns a child region whose far edge is the next outward bend line\n * (a grandchild) or the outline boundary; `length = far-extent − dev`, `span` =\n * bend-line length, `offset`/`side` are the bend line's position on the parent edge.\n *\n * @param pattern - the flat pattern to convert.\n * @param opts - options (thickness, ruleFor, material).\n * @returns the flat input, or an error.\n */\nexport function patternToFlatInput(\n pattern: FlatPattern,\n opts: PatternToFlatInputOptions\n): Result<FlatInput> {\n const { thickness, ruleFor, material } = opts;\n if (!Number.isFinite(thickness) || thickness <= 0) {\n return err(validationError('INVALID_THICKNESS', `thickness must be positive, got ${thickness}`));\n }\n\n const segsResult = parseBendLines(pattern, thickness, ruleFor);\n if (!segsResult.ok) return segsResult;\n const bends = segsResult.value;\n\n const outline = parseOutlineExtents(pattern);\n if (!outline.ok) return outline;\n const { xs, ys, contains } = outline.value;\n\n const base = baseRect(xs, ys, contains, bends);\n if (!base.ok) return base;\n const baseRectVal = base.value;\n\n const buildResult = buildRegions(baseRectVal, bends, contains);\n if (!buildResult.ok) return buildResult;\n\n return ok({\n thickness,\n baseLength: baseRectVal.x1 - baseRectVal.x0,\n width: baseRectVal.y1 - baseRectVal.y0,\n ...(material !== undefined ? { material } : {}),\n regions: buildResult.value,\n });\n}\n\n/**\n * Convert an authored {@link SheetMetalPart} into the {@link FlatInput} that folds\n * back into it, going strictly through the 2D flat pattern: `unfold(part)` produces\n * the developed wire + bend lines, and {@link patternToFlatInput} recovers the\n * region tree from that 2D geometry. Only the bend *rule* is read off the part (by\n * matching bend id), which a flat pattern legitimately cannot encode; every\n * geometric attribute is parsed from the wire/edges. This makes the round-trip\n * oracle non-circular — a bug in unfold's 2D placement or in the parser breaks it.\n *\n * Seam bends (closed profiles) are left unfolded by `unfold`, so the recovered part\n * is the open spanning-tree shape, not the re-closed box.\n *\n * @param part - the sheet metal part to recover a flat input from.\n * @returns the flat input, or an error.\n */\nexport function partToFlatInput(part: SheetMetalPart): Result<FlatInput> {\n const unfolded = unfold(part);\n if (!unfolded.ok) return unfolded;\n const pattern = unfolded.value.pattern;\n\n // The rule is allowed as an input (a flat pattern cannot encode K-factor). Match\n // each bend line back to its authored bend by id, in unfold's bend-line order\n // (which is the spanning-tree order featureTree/layoutTree emit), falling back to\n // a default rule if a bend can't be matched.\n const ruleByIndex = bendRulesInOrder(part);\n const fallback: BendRule = part.material?.defaultRule ?? { innerRadius: part.thickness, kFactor: 0.44 };\n\n const recovered = patternToFlatInput(pattern, {\n thickness: part.thickness,\n ruleFor: (i) => ruleByIndex[i] ?? fallback,\n ...(part.material !== undefined ? { material: part.material } : {}),\n });\n if (!recovered.ok) return recovered;\n\n const withCutouts = attachCutouts(part, recovered.value);\n if (!withCutouts.ok) return withCutouts;\n const withTabs = attachTabs(part, withCutouts.value);\n if (!withTabs.ok) return withTabs;\n return attachForms(part, withTabs.value);\n}\n\n/**\n * Re-attach a part's recorded cutouts onto a recovered {@link FlatInput}. Cutouts\n * ride as interior loops, so {@link patternToFlatInput} (which reads only the outer\n * outline) cannot recover them; we carry the region-local specs across instead.\n * The recovered region for the i-th feature-tree bend is `b${i}` (the parser's id\n * scheme), and the unfold emits bend lines in that same BFS order, so a flange's\n * recovered region id is its position in `featureTree(part).bends`. A cutout whose\n * region can't be mapped is failed loudly rather than dropped: silently shedding it\n * would change the refolded volume with no diagnostic, a correctness violation.\n */\nfunction attachCutouts(part: SheetMetalPart, input: FlatInput): Result<FlatInput> {\n if (part.cutouts === undefined || part.cutouts.length === 0) return ok(input);\n\n const recoveredIdByFlange = new Map<string, string>();\n const tree = featureTree(part);\n if (tree.ok) {\n tree.value.bends.forEach((tb, i) => recoveredIdByFlange.set(tb.child, `b${i}`));\n }\n\n const baseCutouts: CutoutSpec[] = [];\n const byRegion = new Map<string, CutoutSpec[]>();\n for (const c of part.cutouts) {\n if (c.region === ROOT_FLAT_ID) {\n baseCutouts.push(c.spec);\n continue;\n }\n const recoveredId = recoveredIdByFlange.get(c.region);\n if (recoveredId === undefined) {\n return err(\n validationError(\n 'CUTOUT_REGION_UNMAPPED',\n `partToFlatInput: cutout on region '${c.region}' has no recovered flat region; round-trip would drop it`\n )\n );\n }\n const list = byRegion.get(recoveredId) ?? [];\n list.push(c.spec);\n byRegion.set(recoveredId, list);\n }\n\n const regions = input.regions.map((r) => {\n const specs = byRegion.get(r.id);\n return specs === undefined ? r : { ...r, cutouts: specs };\n });\n\n return ok({\n ...input,\n regions,\n ...(baseCutouts.length > 0 ? { baseCutouts } : {}),\n });\n}\n\n/**\n * Re-attach a part's recorded tabs onto a recovered {@link FlatInput}, mirroring\n * {@link attachCutouts}. A tab carries its region-local {@link TabSpec}, so it\n * replays through the recorded-feature path exactly as cutouts/forms do — the spec,\n * not the outline, drives the re-fuse. (The tab does extend the outer outline, but\n * the outline parser only needs to recover the base/flange rectangles, which it does\n * from the bend lines and the unprotruded edges; see {@link partToFlatInput}.) An\n * unmappable region fails loudly rather than silently dropping the tab — silently\n * shedding it would change the refolded volume with no diagnostic.\n */\nfunction attachTabs(part: SheetMetalPart, input: FlatInput): Result<FlatInput> {\n if (part.tabs === undefined || part.tabs.length === 0) return ok(input);\n\n const recoveredIdByFlange = new Map<string, string>();\n const tree = featureTree(part);\n if (tree.ok) {\n tree.value.bends.forEach((tb, i) => recoveredIdByFlange.set(tb.child, `b${i}`));\n }\n\n const baseTabs: TabSpec[] = [];\n const byRegion = new Map<string, TabSpec[]>();\n for (const t of part.tabs) {\n if (t.region === ROOT_FLAT_ID) {\n baseTabs.push(t.spec);\n continue;\n }\n const recoveredId = recoveredIdByFlange.get(t.region);\n if (recoveredId === undefined) {\n return err(\n validationError(\n 'TAB_REGION_UNMAPPED',\n `partToFlatInput: tab on region '${t.region}' has no recovered flat region; round-trip would drop it`\n )\n );\n }\n const list = byRegion.get(recoveredId) ?? [];\n list.push(t.spec);\n byRegion.set(recoveredId, list);\n }\n\n const regions = input.regions.map((r) => {\n const specs = byRegion.get(r.id);\n return specs === undefined ? r : { ...r, tabs: specs };\n });\n\n return ok({\n ...input,\n regions,\n ...(baseTabs.length > 0 ? { baseTabs } : {}),\n });\n}\n\n/**\n * Re-attach a part's recorded form features (louvers / embosses) onto a recovered\n * {@link FlatInput}, mirroring {@link attachCutouts}. Forms are net-material-neutral\n * (they don't change the outer outline), so they round-trip cleanly through the\n * outline oracle; only their region-local specs need carrying across. An unmappable\n * region fails loudly rather than silently dropping the form.\n */\nfunction attachForms(part: SheetMetalPart, input: FlatInput): Result<FlatInput> {\n if (part.forms === undefined || part.forms.length === 0) return ok(input);\n\n const recoveredIdByFlange = new Map<string, string>();\n const tree = featureTree(part);\n if (tree.ok) {\n tree.value.bends.forEach((tb, i) => recoveredIdByFlange.set(tb.child, `b${i}`));\n }\n\n const baseForms: FormSpec[] = [];\n const byRegion = new Map<string, FormSpec[]>();\n for (const f of part.forms) {\n if (f.region === ROOT_FLAT_ID) {\n baseForms.push(f.spec);\n continue;\n }\n const recoveredId = recoveredIdByFlange.get(f.region);\n if (recoveredId === undefined) {\n return err(\n validationError(\n 'FORM_REGION_UNMAPPED',\n `partToFlatInput: form on region '${f.region}' has no recovered flat region; round-trip would drop it`\n )\n );\n }\n const list = byRegion.get(recoveredId) ?? [];\n list.push(f.spec);\n byRegion.set(recoveredId, list);\n }\n\n const regions = input.regions.map((r) => {\n const specs = byRegion.get(r.id);\n return specs === undefined ? r : { ...r, forms: specs };\n });\n\n return ok({\n ...input,\n regions,\n ...(baseForms.length > 0 ? { baseForms } : {}),\n });\n}\n\n/**\n * Bend rules in {@link FlatPattern.bendLines} order. `unfold` emits bend lines in\n * the layout walk's order, which is the feature tree's BFS (spanning-tree) order;\n * the same walk drives the rules here so index `i` lines up with bend line `i`.\n */\nfunction bendRulesInOrder(part: SheetMetalPart): BendRule[] {\n const tree = featureTree(part);\n if (!tree.ok) return part.flanges.map((f) => f.rule);\n const ruleById = new Map<string, BendRule>();\n for (const f of part.flanges) ruleById.set(f.id, f.rule);\n for (const b of part.bends) if (!ruleById.has(b.id)) ruleById.set(b.id, b.rule);\n const rules: BendRule[] = [];\n for (const tb of tree.value.bends) {\n rules.push(ruleById.get(tb.child) ?? tb.bend.rule);\n }\n return rules;\n}\n\nconst EPS = 1e-6;\n\ntype Pt2 = [number, number];\n\n/** A bend line parsed from the 2D pattern: an axis-aligned segment + fold metadata. */\ninterface BendSeg {\n index: number;\n /** Orientation of the segment line. */\n axis: 'h' | 'v';\n /** Fixed coordinate of the line (x for vertical, y for horizontal). */\n fixed: number;\n /** Segment span on the free axis: `[lo, hi]`. */\n lo: number;\n hi: number;\n span: number;\n angleDeg: number;\n direction: 'up' | 'down';\n /** The supplied rule (a flat pattern cannot encode K-factor, so it's an input). */\n rule: BendRule;\n /** Developed strip width for this bend (from the supplied rule). */\n dev: number;\n}\n\nfunction parseBendLines(\n pattern: FlatPattern,\n thickness: number,\n ruleFor: (i: number) => BendRule\n): Result<BendSeg[]> {\n const out: BendSeg[] = [];\n for (let i = 0; i < pattern.bendLines.length; i += 1) {\n const bl = pattern.bendLines[i];\n if (bl === undefined) continue;\n const a = curveStartPoint(bl.line);\n const b = curveEndPoint(bl.line);\n const seg = axisAlignedSeg(a, b);\n if (seg === undefined) {\n return err(\n validationError('NON_AXIS_BEND', `bend line ${i} is not axis-aligned: (${a[0]},${a[1]})→(${b[0]},${b[1]})`)\n );\n }\n const rule = ruleFor(i);\n const devResult = developedLength(bl.angleDeg, thickness, rule);\n if (!devResult.ok) return devResult;\n out.push({\n index: i,\n axis: seg.axis,\n fixed: seg.fixed,\n lo: seg.lo,\n hi: seg.hi,\n span: seg.hi - seg.lo,\n angleDeg: bl.angleDeg,\n direction: bl.direction,\n rule,\n dev: devResult.value,\n });\n }\n return ok(out);\n}\n\nfunction axisAlignedSeg(a: Vec3, b: Vec3): { axis: 'h' | 'v'; fixed: number; lo: number; hi: number } | undefined {\n if (Math.abs(a[0] - b[0]) < EPS) {\n return { axis: 'v', fixed: (a[0] + b[0]) / 2, lo: Math.min(a[1], b[1]), hi: Math.max(a[1], b[1]) };\n }\n if (Math.abs(a[1] - b[1]) < EPS) {\n return { axis: 'h', fixed: (a[1] + b[1]) / 2, lo: Math.min(a[0], b[0]), hi: Math.max(a[0], b[0]) };\n }\n return undefined;\n}\n\ninterface OutlineExtents {\n /** Sorted unique x-coordinates of every outline vertex. */\n xs: number[];\n /** Sorted unique y-coordinates of every outline vertex. */\n ys: number[];\n /** True if the point lies strictly inside the filled (developed) region. */\n contains: (x: number, y: number) => boolean;\n}\n\n/**\n * Read the outline wire's vertices back out via `getEdges` + curve endpoint readers\n * and build a point-in-region test over the axis-aligned arrangement they induce.\n * The developed pattern is a simply-connected rectilinear polygon, so a winding-free\n * cell test (is this cell's centre inside the polygon) suffices.\n */\nfunction parseOutlineExtents(pattern: FlatPattern): Result<OutlineExtents> {\n const edges = getEdges(pattern.outline);\n if (edges.length < 3) {\n return err(validationError('OUTLINE_TOO_SMALL', `outline has ${edges.length} edges, need ≥ 3`));\n }\n const segs: { a: Pt2; b: Pt2 }[] = [];\n const xsRaw: number[] = [];\n const ysRaw: number[] = [];\n for (const e of edges) {\n const s = curveStartPoint(e);\n const t = curveEndPoint(e);\n segs.push({ a: [s[0], s[1]], b: [t[0], t[1]] });\n xsRaw.push(s[0], t[0]);\n ysRaw.push(s[1], t[1]);\n }\n const poly = orderedLoop(segs);\n if (poly === undefined) {\n return err(validationError('OUTLINE_NOT_CLOSED', 'outline edges do not form a single closed loop'));\n }\n const xs = uniqueSorted(xsRaw);\n const ys = uniqueSorted(ysRaw);\n const contains = (x: number, y: number): boolean => pointInPolygon(poly, x, y);\n return ok({ xs, ys, contains });\n}\n\n/** Chain segments into one ordered vertex loop, or undefined if they don't close. */\nfunction orderedLoop(segs: { a: Pt2; b: Pt2 }[]): Pt2[] | undefined {\n if (segs.length === 0) return undefined;\n const key = (p: Pt2): string => `${round(p[0])}|${round(p[1])}`;\n const from = new Map<string, Pt2>();\n // Two segments sharing a start-vertex key means the loop isn't a simple chain\n // (floating-point drift can also collapse two near vertices into one bucket);\n // bail rather than silently overwrite and trace a wrong polygon.\n for (const s of segs) {\n const k = key(s.a);\n if (from.has(k)) return undefined;\n from.set(k, s.b);\n }\n const start = segs[0]?.a;\n if (start === undefined) return undefined;\n const loop: Pt2[] = [start];\n let cur = from.get(key(start));\n let guard = 0;\n while (cur !== undefined && key(cur) !== key(start) && guard < segs.length + 2) {\n loop.push(cur);\n cur = from.get(key(cur));\n guard += 1;\n }\n if (cur === undefined || key(cur) !== key(start)) return undefined;\n return loop;\n}\n\nfunction round(n: number): number {\n return Math.round(n / EPS) * EPS;\n}\n\n/** Standard ray-cast point-in-polygon for the (axis-aligned) outline loop. */\nfunction pointInPolygon(poly: Pt2[], x: number, y: number): boolean {\n let inside = false;\n for (let i = 0, j = poly.length - 1; i < poly.length; j = i, i += 1) {\n const pi = poly[i];\n const pj = poly[j];\n if (pi === undefined || pj === undefined) continue;\n const intersect =\n pi[1] > y !== pj[1] > y &&\n x < ((pj[0] - pi[0]) * (y - pi[1])) / (pj[1] - pi[1]) + pi[0];\n if (intersect) inside = !inside;\n }\n return inside;\n}\n\ninterface Rect {\n x0: number;\n y0: number;\n x1: number;\n y1: number;\n}\n\n/**\n * Base region: the rectangle anchored at the origin, `[0, baseLength] × [0, width]`\n * (the unfold layout fixes the base frame there). Each base edge is bounded by the\n * bend line lying on it (a tray folds off all four edges) or, when no flange folds\n * off that edge, by the outline boundary. The extents are therefore the nearest\n * base-bounding bend line — a bend line perpendicular to the run that crosses the\n * origin row/column — clamped to the outline reach.\n */\nfunction baseRect(\n xs: number[],\n ys: number[],\n contains: (x: number, y: number) => boolean,\n bends: BendSeg[]\n): Result<Rect> {\n if (xs.length < 2 || ys.length < 2) {\n return err(validationError('BASE_NOT_FOUND', 'cannot locate base region at origin'));\n }\n // Probe halfway between the origin and the first positive x grid line — a\n // scale-invariant point inside the base's undivided +X span (the base is one\n // rectangle in X, so the first gridline > 0 is its right edge). Avoids assuming\n // any absolute unit and stays correct when xmin/ymin flanges add negative coords.\n const xFirstPositive = xs.find((v) => v > EPS);\n if (xFirstPositive === undefined) {\n return err(validationError('BASE_NOT_FOUND', 'no positive x extent to locate the base region'));\n }\n const xProbeBase = xFirstPositive / 2;\n const yProbe = firstFilledCellMid(ys.filter((v) => v > -EPS), (mid) => contains(xProbeBase, mid));\n if (yProbe === undefined) {\n return err(validationError('BASE_NOT_FOUND', 'origin cell is not inside the developed region'));\n }\n const x0 = 0;\n const y0 = 0;\n // +X base edge: nearest vertical bend line right of origin crossing the base row,\n // else the outline reach.\n const xBendBound = nearestBend(bends, 'v', yProbe, x0, 1);\n const x1 = xBendBound ?? marchOutline(x0, 1, (c) => contains(c, yProbe));\n const xProbe = (x0 + x1) / 2;\n const yBendBound = nearestBend(bends, 'h', xProbe, y0, 1);\n const y1 = yBendBound ?? marchOutline(y0, 1, (c) => contains(xProbe, c));\n if (x1 <= x0 + EPS || y1 <= y0 + EPS) {\n return err(validationError('BASE_NOT_FOUND', 'base region has zero extent'));\n }\n return ok({ x0, y0, x1, y1 });\n}\n\n/**\n * Nearest bend line of the given orientation, on the `dir` side of `from` along its\n * perpendicular axis, whose span covers the base `cross` coordinate — i.e. a bend\n * line lying on the base's far edge in that direction. Returns its fixed coordinate.\n */\nfunction nearestBend(\n bends: BendSeg[],\n axis: 'h' | 'v',\n cross: number,\n from: number,\n dir: 1 | -1\n): number | undefined {\n let best: number | undefined;\n for (const b of bends) {\n if (b.axis !== axis) continue;\n if (cross < b.lo - EPS || cross > b.hi + EPS) continue;\n const beyond = dir > 0 ? b.fixed > from + EPS : b.fixed < from - EPS;\n if (!beyond) continue;\n if (best === undefined || Math.abs(b.fixed - from) < Math.abs(best - from)) best = b.fixed;\n }\n return best;\n}\n\n/** First arrangement cell whose midpoint passes `probe`; locates an interior coord. */\nfunction firstFilledCellMid(coords: number[], probe: (mid: number) => boolean): number | undefined {\n for (let j = 0; j + 1 < coords.length; j += 1) {\n const lo = coords[j];\n const hi = coords[j + 1];\n if (lo === undefined || hi === undefined) continue;\n const mid = (lo + hi) / 2;\n if (probe(mid)) return mid;\n }\n return undefined;\n}\n\n/** March from `c0` in `dir` until the probe leaves the region; bisect to the boundary. */\nfunction marchOutline(c0: number, dir: 1 | -1, probe: (c: number) => boolean): number {\n let inside = c0 + dir * EPS * 4;\n let step = 1;\n let guard = 0;\n while (probe(inside + dir * step) && guard < 100000) {\n inside += dir * step;\n step *= 2;\n guard += 1;\n }\n let lo = inside;\n let hi = inside + dir * step;\n for (let i = 0; i < 60; i += 1) {\n const m = (lo + hi) / 2;\n if (probe(m)) lo = m;\n else hi = m;\n }\n return lo;\n}\n\n/**\n * BFS outward from the base, attributing each bend line to the region whose local\n * edge it lies on (the parent) and spawning the child region beyond it. Each region\n * carries its 2D frame; a bend line collinear with one of the parent's four local\n * edges, within that edge's span, folds a child whose far edge is the nearest\n * outward grandchild bend line or the outline boundary. `side`/`offset` are reported\n * in the parent's local frame so the re-fold reproduces the authored attachment.\n */\nfunction buildRegions(\n base: Rect,\n bends: BendSeg[],\n contains: (x: number, y: number) => boolean\n): Result<FoldRegion[]> {\n const regions: FoldRegion[] = [];\n const used = new Set<number>();\n const baseFrame: Frame2 = {\n origin: [base.x0, base.y0],\n u: [1, 0],\n v: [0, 1],\n uLen: base.x1 - base.x0,\n vLen: base.y1 - base.y0,\n };\n const queue: { frame: Frame2; id: string | undefined }[] = [{ frame: baseFrame, id: undefined }];\n const idForBend = (b: BendSeg): string => `b${b.index}`;\n\n let guard = 0;\n while (queue.length > 0 && guard < bends.length + 4) {\n guard += 1;\n const node = queue.shift();\n if (node === undefined) break;\n for (const b of bends) {\n if (used.has(b.index)) continue;\n const attached = bendOnFrameEdge(b, node.frame);\n if (attached === undefined) continue;\n used.add(b.index);\n\n const far = farExtent(b, attached.outSign, bends, contains);\n const length = far - b.dev;\n if (length <= EPS) {\n return err(\n validationError('BAD_FLANGE_LENGTH', `recovered flange length for bend ${b.index} is non-positive (${length})`)\n );\n }\n\n const id = idForBend(b);\n const region: FoldRegion = {\n id,\n length,\n angleDeg: b.angleDeg,\n direction: b.direction,\n rule: b.rule,\n side: attached.side,\n offset: attached.offset,\n width: b.span,\n ...(node.id !== undefined ? { parent: node.id } : {}),\n };\n regions.push(region);\n queue.push({ frame: childFrame(attached, b, length), id });\n }\n }\n\n if (used.size !== bends.length) {\n return err(\n validationError('UNATTACHED_BEND', `${bends.length - used.size} bend line(s) could not be attached to a region`)\n );\n }\n\n return ok(regions);\n}\n\ninterface BendAttachment {\n side: FlatSide;\n offset: number;\n /** Edge basis of the parent's local edge `side` (mirrors unfold `edgeBasis2`). */\n along: Pt2;\n out: Pt2;\n edgeOrigin: Pt2;\n /** Sign of `out` on the bend's perpendicular axis, so `farExtent` marches outward. */\n outSign: 1 | -1;\n}\n\n/**\n * If bend `b` lies on one of `frame`'s four local edges (within that edge's span),\n * return the parent-local `side`, the `offset` along that edge, and the edge basis.\n * The bend line is collinear with the edge `edgeOrigin + along·t`, `t ∈ [0, edgeLen]`;\n * the offset is the projection of the bend's near endpoint onto `along`.\n */\nfunction bendOnFrameEdge(b: BendSeg, frame: Frame2): BendAttachment | undefined {\n const segMid = bendMidpoint(b);\n const segDir: Pt2 = b.axis === 'v' ? [0, 1] : [1, 0];\n for (const side of ['xmax', 'xmin', 'ymax', 'ymin'] as const) {\n const basis = edgeBasis2(frame, side);\n // Edge must be parallel to the bend (along ∥ segDir) and the bend must sit on it.\n if (Math.abs(cross2(basis.along, segDir)) > EPS) continue;\n const rel: Pt2 = [segMid[0] - basis.edgeOrigin[0], segMid[1] - basis.edgeOrigin[1]];\n const perp = Math.abs(dot2(rel, basis.out));\n if (perp > EPS) continue;\n const t = dot2(rel, basis.along);\n const edgeLen = edgeLengthOf(frame, side);\n const half = b.span / 2;\n if (t < half - EPS || t > edgeLen - half + EPS) continue;\n const offset = t - half;\n // Outward sign on the bend's perpendicular axis (X for a vertical bend line,\n // Y for a horizontal one), so `farExtent` marches the right way.\n const outComp = b.axis === 'v' ? basis.out[0] : basis.out[1];\n const outSign: 1 | -1 = outComp >= 0 ? 1 : -1;\n return { side, offset: Math.max(0, offset), along: basis.along, out: basis.out, edgeOrigin: basis.edgeOrigin, outSign };\n }\n return undefined;\n}\n\n/**\n * Child region frame, mirroring unfold's `placeChild`: origin past the developed\n * strip (`edgeOrigin + along·offset + out·dev`), u along the bend axis (span), v\n * outward (length). This keeps recovered frames identical to the layout's so a\n * grandchild attaches to the right local edge.\n */\nfunction childFrame(attached: BendAttachment, b: BendSeg, length: number): Frame2 {\n const stripFar: Pt2 = [\n attached.edgeOrigin[0] + attached.along[0] * attached.offset + attached.out[0] * b.dev,\n attached.edgeOrigin[1] + attached.along[1] * attached.offset + attached.out[1] * b.dev,\n ];\n return { origin: stripFar, u: attached.along, v: attached.out, uLen: b.span, vLen: length };\n}\n\nfunction edgeLengthOf(f: Frame2, side: FlatSide): number {\n return side === 'xmax' || side === 'xmin' ? f.vLen : f.uLen;\n}\n\nfunction bendMidpoint(b: BendSeg): Pt2 {\n const mid = (b.lo + b.hi) / 2;\n return b.axis === 'v' ? [b.fixed, mid] : [mid, b.fixed];\n}\n\nfunction cross2(a: Pt2, b: Pt2): number {\n return a[0] * b[1] - a[1] * b[0];\n}\nfunction dot2(a: Pt2, b: Pt2): number {\n return a[0] * b[0] + a[1] * b[1];\n}\n\n/**\n * Far perpendicular extent (strip + flat) of a child region from its bend line: the\n * nearest grandchild bend line beyond `b` (parallel, overlapping the span, same\n * outward side) or, failing that, the outline boundary, measured as a distance from\n * the bend line outward. Because bend lines are axis-aligned, the outward direction\n * is along the bend's perpendicular axis with `outSign` (from the edge basis).\n */\nfunction farExtent(\n b: BendSeg,\n outSign: 1 | -1,\n bends: BendSeg[],\n contains: (x: number, y: number) => boolean\n): number {\n let nearest: number | undefined;\n for (const g of bends) {\n if (g.index === b.index) continue;\n if (g.axis !== b.axis) continue;\n const overlaps = g.lo < b.hi - EPS && b.lo < g.hi - EPS;\n if (!overlaps) continue;\n const beyond = outSign > 0 ? g.fixed > b.fixed + EPS : g.fixed < b.fixed - EPS;\n if (!beyond) continue;\n if (nearest === undefined || Math.abs(g.fixed - b.fixed) < Math.abs(nearest - b.fixed)) {\n nearest = g.fixed;\n }\n }\n const boundary = nearest ?? outlineFar(b, outSign, contains);\n return Math.abs(boundary - b.fixed);\n}\n\n/**\n * March perpendicular outward from the bend line until the region stops being filled\n * (the outline boundary), probing at the span midpoint, then bisect to the boundary.\n */\nfunction outlineFar(\n b: BendSeg,\n outSign: 1 | -1,\n contains: (x: number, y: number) => boolean\n): number {\n const mid = (b.lo + b.hi) / 2;\n const probe = (perp: number): boolean =>\n b.axis === 'v' ? contains(perp, mid) : contains(mid, perp);\n return marchOutline(b.fixed, outSign, probe);\n}\n\nfunction uniqueSorted(values: number[]): number[] {\n const sorted = [...values].sort((a, b) => a - b);\n const out: number[] = [];\n for (const v of sorted) {\n const last = out[out.length - 1];\n if (last === undefined || Math.abs(v - last) > EPS) out.push(v);\n }\n return out;\n}\n"]}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import type { Solid, Face } from './types.js';
|
|
2
|
+
import { type Result, type Vec3 } from '@faicad/faijs/api';
|
|
2
3
|
import type { UnfoldResult } from './types.js';
|
|
3
4
|
/** A fitted cylinder recovered numerically from a face's sampled points + normals. */
|
|
4
5
|
export interface FittedCylinder {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"foreignUnfoldFns.d.ts","sourceRoot":"","sources":["../src/foreignUnfoldFns.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"foreignUnfoldFns.d.ts","sourceRoot":"","sources":["../src/foreignUnfoldFns.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAC,KAAK,MAAM,EAAE,KAAK,IAAI,EAAmN,MAAM,mBAAmB,CAAC;AAC3Q,OAAO,KAAK,EACV,YAAY,EAIb,MAAM,YAAY,CAAC;AAUpB,sFAAsF;AACtF,MAAM,WAAW,cAAc;IAC7B,gCAAgC;IAChC,UAAU,EAAE,IAAI,CAAC;IACjB,2BAA2B;IAC3B,OAAO,EAAE,IAAI,CAAC;IACd,8EAA8E;IAC9E,MAAM,EAAE,MAAM,CAAC;IACf,mEAAmE;IACnE,SAAS,EAAE,MAAM,CAAC;IAClB,wFAAwF;IACxF,QAAQ,EAAE,MAAM,CAAC;CAClB;AA6BD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,cAAc,GAAG,IAAI,CA8C7D;AA8JD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,KAAK,EACZ,IAAI,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,GACtC,MAAM,CAAC,YAAY,CAAC,CAyDtB"}
|
package/dist/foreignUnfoldFns.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getBounds } from './geometryOps.js';
|
|
2
|
+
import { ok, err, validationError, getFaces, getSurfaceType, pointOnSurface, normalAt, faceCenter, sharedEdges, measureArea, isValid, vecAdd, vecSub, vecScale, vecDot, vecCross, vecLength, vecNormalize, line, wireLoop } from '@faicad/faijs/api';
|
|
2
3
|
import { developedLength } from './allowanceFns.js';
|
|
3
4
|
/** Default neutral-axis K-factor for a purely geometric unfold (mid-surface). */
|
|
4
5
|
const DEFAULT_FOREIGN_K = 0.5;
|
|
@@ -46,7 +47,10 @@ function sampleFace(face, n) {
|
|
|
46
47
|
*/
|
|
47
48
|
export function fitCylinder(face) {
|
|
48
49
|
const surf = getSurfaceType(face);
|
|
49
|
-
|
|
50
|
+
// OCCT keeps exact cylinders as 'cylinder', but applyMatrix (gp_GTrsf) and
|
|
51
|
+
// boolean ops (intersect/cut) can re-parameterise them to 'bspline' — the
|
|
52
|
+
// numeric fit below works on either; other types fail the residual check.
|
|
53
|
+
if (!surf.ok || (surf.value !== 'cylinder' && surf.value !== 'bspline'))
|
|
50
54
|
return null;
|
|
51
55
|
const samples = sampleFace(face, 6);
|
|
52
56
|
if (samples.length < 4)
|
|
@@ -262,10 +266,17 @@ export function unfoldForeignSolid(solid, opts) {
|
|
|
262
266
|
warnings.push({ code: 'UNSUPPORTED_FACE', message: 'failed to read a face surface type; skipping' });
|
|
263
267
|
continue;
|
|
264
268
|
}
|
|
265
|
-
if (t.value === '
|
|
269
|
+
if (t.value === 'plane') {
|
|
266
270
|
planarFaces.push(face);
|
|
267
|
-
|
|
271
|
+
}
|
|
272
|
+
else if (t.value === 'cylinder') {
|
|
273
|
+
cylFaces.push(face);
|
|
274
|
+
}
|
|
275
|
+
else if (fitCylinder(face) !== null) {
|
|
276
|
+
// A numerically-fittable bspline/other surface IS a cylindrical bend
|
|
277
|
+
// (OCCT re-parameterises exact cylinders through transforms/booleans).
|
|
268
278
|
cylFaces.push(face);
|
|
279
|
+
}
|
|
269
280
|
else {
|
|
270
281
|
warnings.push({
|
|
271
282
|
code: 'UNSUPPORTED_FACE',
|
|
@@ -375,12 +386,12 @@ function pairFlats(planar, thickness, warnings) {
|
|
|
375
386
|
const areaA = measureArea(fa);
|
|
376
387
|
const areaB = measureArea(fb);
|
|
377
388
|
let area;
|
|
378
|
-
if (areaA
|
|
379
|
-
area = (areaA
|
|
380
|
-
else if (areaA
|
|
381
|
-
area = areaA
|
|
382
|
-
else if (areaB
|
|
383
|
-
area = areaB
|
|
389
|
+
if (Number.isFinite(areaA) && Number.isFinite(areaB))
|
|
390
|
+
area = (areaA + areaB) / 2;
|
|
391
|
+
else if (Number.isFinite(areaA))
|
|
392
|
+
area = areaA;
|
|
393
|
+
else if (Number.isFinite(areaB))
|
|
394
|
+
area = areaB;
|
|
384
395
|
else {
|
|
385
396
|
// Neither face area is measurable: fall back to the panel's bounding-box
|
|
386
397
|
// footprint so developedArea isn't silently zero, and flag the estimate.
|