@faicad/sheetmetal 0.16.1 → 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
package/dist/bendTableFns.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bendTableFns.js","sourceRoot":"","sources":["../src/bendTableFns.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Result, ok, err, validationError } from '@faicad/faijs/brepjs-compat';\nimport type { BendRule, SheetMetalWarning } from './types.js';\n\nconst DEG_TO_RAD = Math.PI / 180;\n\n/**\n * One row of a shop bend table: the tabulated value for a single\n * (thickness, innerRadius, bend-angle) operating point. `value` is a bend\n * allowance (`kind: 'allowance'`) or a bend deduction (`kind: 'deduction'`),\n * per the owning {@link BendTable}.\n */\nexport interface BendTableRow {\n /** Material thickness the row was measured at. */\n thickness: number;\n /** Inner bend radius the row was measured at. */\n radius: number;\n /** Swept bend angle in degrees (90° = a right-angle bend). */\n angleDeg: number;\n /** Bend allowance or bend deduction, per the table's {@link BendTable.kind}. */\n value: number;\n}\n\n/**\n * A named shop bend table: empirical bend-allowance or bend-deduction values\n * measured per (thickness, radius, angle). When a {@link BendRule} references a\n * table by id, {@link resolveBendAllowance} interpolates the table instead of\n * applying the K-factor formula, so the developed length matches the shop's\n * actual press-brake results.\n *\n * `kind` selects how a row's `value` is interpreted: an `'allowance'` table\n * tabulates the developed arc length directly; a `'deduction'` table tabulates\n * the bend deduction, which is converted to an allowance on lookup (see\n * {@link resolveBendAllowance} for the OSSB conversion).\n */\nexport interface BendTable {\n id: string;\n kind: 'allowance' | 'deduction';\n rows: BendTableRow[];\n}\n\n/**\n * The live bend-table registry, explicit as a shared resource object (§7.3):\n * no hidden module-level mutable state. `registerBendTable`,\n * {@link getBendTable} and the built-in resource all read/write the same\n * `byId` map, so hosts can inspect or snapshot the registry directly.\n */\nexport const bendTables: { readonly byId: Map<string, BendTable> } = {\n byId: new Map<string, BendTable>(),\n};\n\n/**\n * Register (or replace) a bend table under its id, so a {@link BendRule} with a\n * matching `bendTableRef` resolves against it. Returns the registered table.\n *\n * @param table - the bend table to register.\n * @returns a {@link Result} carrying the stored (copied) table on success, or a\n * validation error when the id, kind, or any row is invalid.\n */\nexport function registerBendTable(table: BendTable): Result<BendTable> {\n if (typeof table.id !== 'string' || table.id.length === 0) {\n return err(validationError('INVALID_TABLE_ID', `bend table id must be a non-empty string, got ${String(table.id)}`));\n }\n if (table.kind !== 'allowance' && table.kind !== 'deduction') {\n return err(validationError('INVALID_TABLE_KIND', `bend table '${table.id}' kind must be 'allowance' or 'deduction', got ${String(table.kind)}`));\n }\n if (!Array.isArray(table.rows) || table.rows.length === 0) {\n return err(validationError('EMPTY_TABLE', `bend table '${table.id}' must have at least one row`));\n }\n for (const row of table.rows) {\n if (\n !Number.isFinite(row.thickness) ||\n row.thickness <= 0 ||\n !Number.isFinite(row.radius) ||\n row.radius < 0 ||\n !Number.isFinite(row.angleDeg) ||\n !Number.isFinite(row.value) ||\n row.value < 0\n ) {\n return err(\n validationError(\n 'INVALID_TABLE_ROW',\n `bend table '${table.id}' has an invalid row: ${JSON.stringify(row)} (thickness>0, radius≥0, finite angle, value≥0 required)`\n )\n );\n }\n }\n const stored = { id: table.id, kind: table.kind, rows: table.rows.map((r) => ({ ...r })) };\n bendTables.byId.set(table.id, stored);\n return ok(stored);\n}\n\n/**\n * Look up a registered bend table by id (registers the starter tables on first use).\n *\n * @param id - the bend table id to look up.\n * @returns the registered {@link BendTable}, or `undefined` when no table is\n * registered under `id`.\n */\nexport function getBendTable(id: string): BendTable | undefined {\n ensureStarterTables();\n return bendTables.byId.get(id);\n}\n\n/**\n * Linear interpolation of `value` over `angleDeg` within a set of rows that\n * already share a (thickness, radius) operating point. Clamps to the nearest\n * endpoint outside the tabulated angle span and records a clamp via `clamped`.\n */\nfunction interpAngle(rows: BendTableRow[], angleDeg: number): { value: number; clamped: boolean } {\n const sorted = [...rows].sort((a, b) => a.angleDeg - b.angleDeg);\n const first = sorted[0];\n const last = sorted[sorted.length - 1];\n if (first === undefined || last === undefined) return { value: 0, clamped: true };\n if (angleDeg <= first.angleDeg) {\n return { value: first.value, clamped: angleDeg < first.angleDeg };\n }\n if (angleDeg >= last.angleDeg) {\n return { value: last.value, clamped: angleDeg > last.angleDeg };\n }\n for (let i = 0; i + 1 < sorted.length; i++) {\n const lo = sorted[i];\n const hi = sorted[i + 1];\n if (lo === undefined || hi === undefined) continue;\n if (angleDeg >= lo.angleDeg && angleDeg <= hi.angleDeg) {\n const span = hi.angleDeg - lo.angleDeg;\n if (span === 0) return { value: lo.value, clamped: false };\n const t = (angleDeg - lo.angleDeg) / span;\n return { value: lo.value + t * (hi.value - lo.value), clamped: false };\n }\n }\n return { value: last.value, clamped: true };\n}\n\n/** Distinct sorted values of a numeric key across the table rows. */\nfunction distinct(rows: BendTableRow[], key: 'thickness' | 'radius'): number[] {\n return [...new Set(rows.map((r) => r[key]))].sort((a, b) => a - b);\n}\n\n/** Bracketing pair `[lo, hi]` of a query value within sorted breakpoints, clamping to ends. */\nfunction bracket(values: number[], q: number): { lo: number; hi: number; clamped: boolean } {\n const first = values[0];\n const last = values[values.length - 1];\n if (first === undefined || last === undefined) return { lo: q, hi: q, clamped: true };\n if (q <= first) return { lo: first, hi: first, clamped: q < first };\n if (q >= last) return { lo: last, hi: last, clamped: q > last };\n for (let i = 0; i + 1 < values.length; i++) {\n const lo = values[i];\n const hi = values[i + 1];\n if (lo === undefined || hi === undefined) continue;\n if (q >= lo && q <= hi) return { lo, hi, clamped: false };\n }\n return { lo: last, hi: last, clamped: true };\n}\n\n/**\n * Angle-interpolated value at a (thickness, radius) breakpoint. Prefers rows at\n * the exact breakpoint; if the grid is sparse (a diagonal R-per-gauge table has\n * no row at every t×r corner) it falls back to the rows at the nearest\n * tabulated radius for that thickness, then the nearest thickness, flagging the\n * substitution as clamped. Returns undefined only when the table is empty.\n */\nfunction valueAt(table: BendTable, thickness: number, radius: number, angleDeg: number): { value: number; clamped: boolean } | undefined {\n const exact = table.rows.filter((r) => r.thickness === thickness && r.radius === radius);\n if (exact.length > 0) return interpAngle(exact, angleDeg);\n\n const atThickness = table.rows.filter((r) => r.thickness === thickness);\n if (atThickness.length > 0) {\n const nearestR = nearest(distinct(atThickness, 'radius'), radius);\n const rows = atThickness.filter((r) => r.radius === nearestR);\n if (rows.length > 0) {\n // Sparse-grid substitution (a diagonal one-radius-per-gauge table has no row\n // at this corner) is an internal resolution, NOT a query clamp — genuine\n // out-of-range thickness/radius is already flagged by `bracket` in interpTable,\n // and out-of-range angle by interpAngle. Don't over-warn on in-range interior\n // queries; only propagate the angle clamp.\n const a = interpAngle(rows, angleDeg);\n return { value: a.value, clamped: a.clamped };\n }\n }\n\n const nearestT = nearest(distinct(table.rows, 'thickness'), thickness);\n const atNearestT = table.rows.filter((r) => r.thickness === nearestT);\n if (atNearestT.length === 0) return undefined;\n const nearestR = nearest(distinct(atNearestT, 'radius'), radius);\n const rows = atNearestT.filter((r) => r.radius === nearestR);\n if (rows.length === 0) return undefined;\n const a = interpAngle(rows, angleDeg);\n return { value: a.value, clamped: a.clamped };\n}\n\n/** Nearest value in a set of breakpoints to a query. */\nfunction nearest(values: number[], q: number): number | undefined {\n let best: number | undefined;\n let bestDist = Infinity;\n for (const v of values) {\n const d = Math.abs(v - q);\n if (d < bestDist) {\n bestDist = d;\n best = v;\n }\n }\n return best;\n}\n\n/**\n * Bilinear-in-(thickness, radius) + linear-in-angle interpolation of a bend\n * table at the query operating point. Brackets the query thickness and radius\n * to the nearest tabulated breakpoints (clamping outside the table extents),\n * interpolates angle within each corner, then blends the corners. Sparse grids\n * (a diagonal one-radius-per-gauge table) resolve each corner by nearest-radius\n * substitution inside {@link valueAt}. Returns the raw tabulated quantity (an\n * allowance or a deduction per the table kind).\n */\nfunction interpTable(table: BendTable, thickness: number, radius: number, angleDeg: number): { value: number; clamped: boolean } | undefined {\n const thicknesses = distinct(table.rows, 'thickness');\n const radii = distinct(table.rows, 'radius');\n const tB = bracket(thicknesses, thickness);\n const rB = bracket(radii, radius);\n\n const c00 = valueAt(table, tB.lo, rB.lo, angleDeg);\n const c01 = valueAt(table, tB.lo, rB.hi, angleDeg);\n const c10 = valueAt(table, tB.hi, rB.lo, angleDeg);\n const c11 = valueAt(table, tB.hi, rB.hi, angleDeg);\n if (c00 === undefined || c01 === undefined || c10 === undefined || c11 === undefined) {\n return undefined;\n }\n\n const ft = tB.hi === tB.lo ? 0 : (thickness - tB.lo) / (tB.hi - tB.lo);\n const fr = rB.hi === rB.lo ? 0 : (radius - rB.lo) / (rB.hi - rB.lo);\n\n const lo = c00.value + fr * (c01.value - c00.value);\n const hi = c10.value + fr * (c11.value - c10.value);\n const value = lo + ft * (hi - lo);\n const clamped = tB.clamped || rB.clamped || c00.clamped || c01.clamped || c10.clamped || c11.clamped;\n return { value, clamped };\n}\n\n/**\n * Outside setback OSSB = (R + T)·tan(θ/2) for swept bend angle θ — the run from\n * the bend's tangent point to the apex of the two outside faces. (90° → tan45° →\n * OSSB = R + T.)\n */\nfunction ossb(radius: number, thickness: number, angleDeg: number): number {\n return (radius + thickness) * Math.tan((DEG_TO_RAD * Math.abs(angleDeg)) / 2);\n}\n\n/** Bend allowance from a bend deduction: BD = 2·OSSB − BA ⇒ BA = 2·OSSB − BD. */\nfunction allowanceFromDeduction(deduction: number, radius: number, thickness: number, angleDeg: number): number {\n return 2 * ossb(radius, thickness, angleDeg) - deduction;\n}\n\n/**\n * The single source of truth for a bend's developed (neutral-axis) length.\n *\n * Precedence:\n * 1. `rule.bendTableRef` — look up the table and interpolate it (linear in\n * angle, bilinear across thickness × radius), converting a deduction table\n * to an allowance via {@link allowanceFromDeduction}. Outside the table\n * extents the lookup clamps to the nearest breakpoint and reports a\n * `MIN_RADIUS`-class warning through `onWarning` rather than extrapolating.\n * 2. `rule.allowance` — an explicit per-bend override, returned verbatim.\n * 3. The K-factor formula BA = (π/180)·|angle|·(R + K·T).\n *\n * The returned value is in the same units and sense the rest of the package's\n * `developedLength` consumes (a strip width along the developed pattern).\n *\n * @param rule - the bend rule driving the lookup (bend table ref, explicit\n * allowance, or K-factor).\n * @param angleDeg - the bend angle in degrees.\n * @param thickness - the sheet thickness.\n * @param onWarning - optional callback invoked with a {@link SheetMetalWarning}\n * when a table lookup clamped to the nearest breakpoint outside the tabulated range.\n * @returns a {@link Result} carrying the resolved bend allowance on success, or a\n * validation error for an unknown table / non-positive input / failed lookup.\n */\nexport function resolveBendAllowance(\n rule: BendRule,\n angleDeg: number,\n thickness: number,\n onWarning?: (warning: SheetMetalWarning) => void\n): Result<number> {\n if (rule.bendTableRef !== undefined) {\n if (!Number.isFinite(angleDeg)) {\n return err(validationError('INVALID_ANGLE', `angleDeg must be finite, got ${angleDeg}`));\n }\n if (!Number.isFinite(thickness) || thickness <= 0) {\n return err(validationError('INVALID_THICKNESS', `thickness must be a finite, positive number, got ${thickness}`));\n }\n if (!Number.isFinite(rule.innerRadius) || rule.innerRadius < 0) {\n return err(validationError('INVALID_RADIUS', `innerRadius must be a finite, non-negative number, got ${rule.innerRadius}`));\n }\n const table = getBendTable(rule.bendTableRef);\n if (table === undefined) {\n return err(validationError('UNKNOWN_BEND_TABLE', `no bend table registered under id '${rule.bendTableRef}'`));\n }\n const angle = Math.abs(angleDeg);\n const interp = interpTable(table, thickness, rule.innerRadius, angle);\n if (interp === undefined) {\n return err(\n validationError('TABLE_LOOKUP_FAILED', `bend table '${table.id}' has no rows bracketing (t=${thickness}, r=${rule.innerRadius})`)\n );\n }\n const ba = table.kind === 'deduction' ? allowanceFromDeduction(interp.value, rule.innerRadius, thickness, angle) : interp.value;\n if (!Number.isFinite(ba) || ba < 0) {\n return err(\n validationError(\n 'INVALID_TABLE_ALLOWANCE',\n `bend table '${table.id}' produced a non-positive allowance ${ba} at (t=${thickness}, r=${rule.innerRadius}, θ=${angle})`\n )\n );\n }\n if (interp.clamped && onWarning !== undefined) {\n onWarning({\n code: 'TABLE_CLAMP',\n message: `bend table '${table.id}' query (t=${thickness}, r=${rule.innerRadius}, θ=${angle}) is outside the tabulated range; clamped to the nearest entry`,\n });\n }\n return ok(ba);\n }\n return fallbackAllowance(rule, angleDeg, thickness);\n}\n\n/** Explicit-allowance override, then the K-factor formula (the pre-table behaviour). */\nfunction fallbackAllowance(rule: BendRule, angleDeg: number, thickness: number): Result<number> {\n if (rule.allowance !== undefined) {\n if (!Number.isFinite(rule.allowance) || rule.allowance < 0) {\n return err(\n validationError('INVALID_ALLOWANCE', `allowance override must be a finite, non-negative number, got ${rule.allowance}`)\n );\n }\n return ok(rule.allowance);\n }\n if (!Number.isFinite(angleDeg)) {\n return err(validationError('INVALID_ANGLE', `angleDeg must be finite, got ${angleDeg}`));\n }\n if (!Number.isFinite(thickness) || thickness <= 0) {\n return err(validationError('INVALID_THICKNESS', `thickness must be a finite, positive number, got ${thickness}`));\n }\n if (!Number.isFinite(rule.innerRadius) || rule.innerRadius < 0) {\n return err(validationError('INVALID_RADIUS', `innerRadius must be a finite, non-negative number, got ${rule.innerRadius}`));\n }\n if (!Number.isFinite(rule.kFactor) || rule.kFactor < 0 || rule.kFactor > 1) {\n return err(validationError('INVALID_K_FACTOR', `kFactor must be in [0, 1], got ${rule.kFactor}`));\n }\n const neutralRadius = rule.innerRadius + rule.kFactor * thickness;\n return ok(DEG_TO_RAD * Math.abs(angleDeg) * neutralRadius);\n}\n\n/**\n * Starter shop bend tables, auto-registered on first table access. The values\n * are published 90°-equivalent air-bend allowances scaled across the standard\n * {30, 60, 90, 120}° set by the linear angle ratio, at a single canonical inner\n * radius per gauge.\n *\n * Sources: SheetMetal.Me air-bend / bend-allowance charts and Machinery's\n * Handbook (29th ed.) sheet-metal bend-allowance tables for mild steel and\n * 5052-H32 aluminium. The 90° allowances are the published mid-range air-bend\n * figures; the other angles are the proportional neutral-axis arc lengths\n * (allowance scales ~linearly with the swept angle at a fixed radius).\n */\nconst STARTER_TABLES: readonly BendTable[] = [\n {\n id: 'steel-airbend',\n kind: 'allowance',\n rows: angleSet([\n { thickness: 0.91, radius: 1.0, ba90: 2.36 },\n { thickness: 1.52, radius: 1.5, ba90: 3.63 },\n { thickness: 1.9, radius: 2.0, ba90: 4.62 },\n { thickness: 2.66, radius: 3.0, ba90: 6.59 },\n ]),\n },\n {\n id: 'aluminum-airbend',\n kind: 'allowance',\n rows: angleSet([\n { thickness: 0.81, radius: 1.0, ba90: 2.27 },\n { thickness: 1.29, radius: 1.5, ba90: 3.44 },\n { thickness: 1.63, radius: 2.0, ba90: 4.49 },\n { thickness: 2.59, radius: 3.0, ba90: 6.51 },\n ]),\n },\n];\n\n/** Expand a per-gauge 90° allowance into the {30, 60, 90, 120}° rows by the angle ratio. */\nfunction angleSet(seeds: { thickness: number; radius: number; ba90: number }[]): BendTableRow[] {\n const angles = [30, 60, 90, 120];\n const rows: BendTableRow[] = [];\n for (const seed of seeds) {\n for (const angleDeg of angles) {\n rows.push({ thickness: seed.thickness, radius: seed.radius, angleDeg, value: (seed.ba90 * angleDeg) / 90 });\n }\n }\n return rows;\n}\n\nlet starterTablesRegistered = false;\n\n/**\n * Register the starter tables exactly once. Done lazily (not at module load) so\n * the package keeps `sideEffects: false` — importing the package never mutates\n * the registry; the tables materialise on the first {@link getBendTable} call.\n */\nfunction ensureStarterTables(): void {\n if (starterTablesRegistered) return;\n starterTablesRegistered = true;\n for (const table of STARTER_TABLES) {\n // Never clobber a table a caller registered under a starter id before first access.\n if (bendTables.byId.has(table.id)) continue;\n bendTables.byId.set(table.id, { id: table.id, kind: table.kind, rows: table.rows.map((r) => ({ ...r })) });\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"bendTableFns.js","sourceRoot":"","sources":["../src/bendTableFns.ts"],"names":[],"mappings":"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","sourcesContent":["import {type Result, ok, err, validationError} from '@faicad/faijs/api';\nimport type { BendRule, SheetMetalWarning } from './types.js';\n\nconst DEG_TO_RAD = Math.PI / 180;\n\n/**\n * One row of a shop bend table: the tabulated value for a single\n * (thickness, innerRadius, bend-angle) operating point. `value` is a bend\n * allowance (`kind: 'allowance'`) or a bend deduction (`kind: 'deduction'`),\n * per the owning {@link BendTable}.\n */\nexport interface BendTableRow {\n /** Material thickness the row was measured at. */\n thickness: number;\n /** Inner bend radius the row was measured at. */\n radius: number;\n /** Swept bend angle in degrees (90° = a right-angle bend). */\n angleDeg: number;\n /** Bend allowance or bend deduction, per the table's {@link BendTable.kind}. */\n value: number;\n}\n\n/**\n * A named shop bend table: empirical bend-allowance or bend-deduction values\n * measured per (thickness, radius, angle). When a {@link BendRule} references a\n * table by id, {@link resolveBendAllowance} interpolates the table instead of\n * applying the K-factor formula, so the developed length matches the shop's\n * actual press-brake results.\n *\n * `kind` selects how a row's `value` is interpreted: an `'allowance'` table\n * tabulates the developed arc length directly; a `'deduction'` table tabulates\n * the bend deduction, which is converted to an allowance on lookup (see\n * {@link resolveBendAllowance} for the OSSB conversion).\n */\nexport interface BendTable {\n id: string;\n kind: 'allowance' | 'deduction';\n rows: BendTableRow[];\n}\n\n/**\n * The live bend-table registry, explicit as a shared resource object (§7.3):\n * no hidden module-level mutable state. `registerBendTable`,\n * {@link getBendTable} and the built-in resource all read/write the same\n * `byId` map, so hosts can inspect or snapshot the registry directly.\n */\nexport const bendTables: { readonly byId: Map<string, BendTable> } = {\n byId: new Map<string, BendTable>(),\n};\n\n/**\n * Register (or replace) a bend table under its id, so a {@link BendRule} with a\n * matching `bendTableRef` resolves against it. Returns the registered table.\n *\n * @param table - the bend table to register.\n * @returns a {@link Result} carrying the stored (copied) table on success, or a\n * validation error when the id, kind, or any row is invalid.\n */\nexport function registerBendTable(table: BendTable): Result<BendTable> {\n if (typeof table.id !== 'string' || table.id.length === 0) {\n return err(validationError('INVALID_TABLE_ID', `bend table id must be a non-empty string, got ${String(table.id)}`));\n }\n if (table.kind !== 'allowance' && table.kind !== 'deduction') {\n return err(validationError('INVALID_TABLE_KIND', `bend table '${table.id}' kind must be 'allowance' or 'deduction', got ${String(table.kind)}`));\n }\n if (!Array.isArray(table.rows) || table.rows.length === 0) {\n return err(validationError('EMPTY_TABLE', `bend table '${table.id}' must have at least one row`));\n }\n for (const row of table.rows) {\n if (\n !Number.isFinite(row.thickness) ||\n row.thickness <= 0 ||\n !Number.isFinite(row.radius) ||\n row.radius < 0 ||\n !Number.isFinite(row.angleDeg) ||\n !Number.isFinite(row.value) ||\n row.value < 0\n ) {\n return err(\n validationError(\n 'INVALID_TABLE_ROW',\n `bend table '${table.id}' has an invalid row: ${JSON.stringify(row)} (thickness>0, radius≥0, finite angle, value≥0 required)`\n )\n );\n }\n }\n const stored = { id: table.id, kind: table.kind, rows: table.rows.map((r) => ({ ...r })) };\n bendTables.byId.set(table.id, stored);\n return ok(stored);\n}\n\n/**\n * Look up a registered bend table by id (registers the starter tables on first use).\n *\n * @param id - the bend table id to look up.\n * @returns the registered {@link BendTable}, or `undefined` when no table is\n * registered under `id`.\n */\nexport function getBendTable(id: string): BendTable | undefined {\n ensureStarterTables();\n return bendTables.byId.get(id);\n}\n\n/**\n * Linear interpolation of `value` over `angleDeg` within a set of rows that\n * already share a (thickness, radius) operating point. Clamps to the nearest\n * endpoint outside the tabulated angle span and records a clamp via `clamped`.\n */\nfunction interpAngle(rows: BendTableRow[], angleDeg: number): { value: number; clamped: boolean } {\n const sorted = [...rows].sort((a, b) => a.angleDeg - b.angleDeg);\n const first = sorted[0];\n const last = sorted[sorted.length - 1];\n if (first === undefined || last === undefined) return { value: 0, clamped: true };\n if (angleDeg <= first.angleDeg) {\n return { value: first.value, clamped: angleDeg < first.angleDeg };\n }\n if (angleDeg >= last.angleDeg) {\n return { value: last.value, clamped: angleDeg > last.angleDeg };\n }\n for (let i = 0; i + 1 < sorted.length; i++) {\n const lo = sorted[i];\n const hi = sorted[i + 1];\n if (lo === undefined || hi === undefined) continue;\n if (angleDeg >= lo.angleDeg && angleDeg <= hi.angleDeg) {\n const span = hi.angleDeg - lo.angleDeg;\n if (span === 0) return { value: lo.value, clamped: false };\n const t = (angleDeg - lo.angleDeg) / span;\n return { value: lo.value + t * (hi.value - lo.value), clamped: false };\n }\n }\n return { value: last.value, clamped: true };\n}\n\n/** Distinct sorted values of a numeric key across the table rows. */\nfunction distinct(rows: BendTableRow[], key: 'thickness' | 'radius'): number[] {\n return [...new Set(rows.map((r) => r[key]))].sort((a, b) => a - b);\n}\n\n/** Bracketing pair `[lo, hi]` of a query value within sorted breakpoints, clamping to ends. */\nfunction bracket(values: number[], q: number): { lo: number; hi: number; clamped: boolean } {\n const first = values[0];\n const last = values[values.length - 1];\n if (first === undefined || last === undefined) return { lo: q, hi: q, clamped: true };\n if (q <= first) return { lo: first, hi: first, clamped: q < first };\n if (q >= last) return { lo: last, hi: last, clamped: q > last };\n for (let i = 0; i + 1 < values.length; i++) {\n const lo = values[i];\n const hi = values[i + 1];\n if (lo === undefined || hi === undefined) continue;\n if (q >= lo && q <= hi) return { lo, hi, clamped: false };\n }\n return { lo: last, hi: last, clamped: true };\n}\n\n/**\n * Angle-interpolated value at a (thickness, radius) breakpoint. Prefers rows at\n * the exact breakpoint; if the grid is sparse (a diagonal R-per-gauge table has\n * no row at every t×r corner) it falls back to the rows at the nearest\n * tabulated radius for that thickness, then the nearest thickness, flagging the\n * substitution as clamped. Returns undefined only when the table is empty.\n */\nfunction valueAt(table: BendTable, thickness: number, radius: number, angleDeg: number): { value: number; clamped: boolean } | undefined {\n const exact = table.rows.filter((r) => r.thickness === thickness && r.radius === radius);\n if (exact.length > 0) return interpAngle(exact, angleDeg);\n\n const atThickness = table.rows.filter((r) => r.thickness === thickness);\n if (atThickness.length > 0) {\n const nearestR = nearest(distinct(atThickness, 'radius'), radius);\n const rows = atThickness.filter((r) => r.radius === nearestR);\n if (rows.length > 0) {\n // Sparse-grid substitution (a diagonal one-radius-per-gauge table has no row\n // at this corner) is an internal resolution, NOT a query clamp — genuine\n // out-of-range thickness/radius is already flagged by `bracket` in interpTable,\n // and out-of-range angle by interpAngle. Don't over-warn on in-range interior\n // queries; only propagate the angle clamp.\n const a = interpAngle(rows, angleDeg);\n return { value: a.value, clamped: a.clamped };\n }\n }\n\n const nearestT = nearest(distinct(table.rows, 'thickness'), thickness);\n const atNearestT = table.rows.filter((r) => r.thickness === nearestT);\n if (atNearestT.length === 0) return undefined;\n const nearestR = nearest(distinct(atNearestT, 'radius'), radius);\n const rows = atNearestT.filter((r) => r.radius === nearestR);\n if (rows.length === 0) return undefined;\n const a = interpAngle(rows, angleDeg);\n return { value: a.value, clamped: a.clamped };\n}\n\n/** Nearest value in a set of breakpoints to a query. */\nfunction nearest(values: number[], q: number): number | undefined {\n let best: number | undefined;\n let bestDist = Infinity;\n for (const v of values) {\n const d = Math.abs(v - q);\n if (d < bestDist) {\n bestDist = d;\n best = v;\n }\n }\n return best;\n}\n\n/**\n * Bilinear-in-(thickness, radius) + linear-in-angle interpolation of a bend\n * table at the query operating point. Brackets the query thickness and radius\n * to the nearest tabulated breakpoints (clamping outside the table extents),\n * interpolates angle within each corner, then blends the corners. Sparse grids\n * (a diagonal one-radius-per-gauge table) resolve each corner by nearest-radius\n * substitution inside {@link valueAt}. Returns the raw tabulated quantity (an\n * allowance or a deduction per the table kind).\n */\nfunction interpTable(table: BendTable, thickness: number, radius: number, angleDeg: number): { value: number; clamped: boolean } | undefined {\n const thicknesses = distinct(table.rows, 'thickness');\n const radii = distinct(table.rows, 'radius');\n const tB = bracket(thicknesses, thickness);\n const rB = bracket(radii, radius);\n\n const c00 = valueAt(table, tB.lo, rB.lo, angleDeg);\n const c01 = valueAt(table, tB.lo, rB.hi, angleDeg);\n const c10 = valueAt(table, tB.hi, rB.lo, angleDeg);\n const c11 = valueAt(table, tB.hi, rB.hi, angleDeg);\n if (c00 === undefined || c01 === undefined || c10 === undefined || c11 === undefined) {\n return undefined;\n }\n\n const ft = tB.hi === tB.lo ? 0 : (thickness - tB.lo) / (tB.hi - tB.lo);\n const fr = rB.hi === rB.lo ? 0 : (radius - rB.lo) / (rB.hi - rB.lo);\n\n const lo = c00.value + fr * (c01.value - c00.value);\n const hi = c10.value + fr * (c11.value - c10.value);\n const value = lo + ft * (hi - lo);\n const clamped = tB.clamped || rB.clamped || c00.clamped || c01.clamped || c10.clamped || c11.clamped;\n return { value, clamped };\n}\n\n/**\n * Outside setback OSSB = (R + T)·tan(θ/2) for swept bend angle θ — the run from\n * the bend's tangent point to the apex of the two outside faces. (90° → tan45° →\n * OSSB = R + T.)\n */\nfunction ossb(radius: number, thickness: number, angleDeg: number): number {\n return (radius + thickness) * Math.tan((DEG_TO_RAD * Math.abs(angleDeg)) / 2);\n}\n\n/** Bend allowance from a bend deduction: BD = 2·OSSB − BA ⇒ BA = 2·OSSB − BD. */\nfunction allowanceFromDeduction(deduction: number, radius: number, thickness: number, angleDeg: number): number {\n return 2 * ossb(radius, thickness, angleDeg) - deduction;\n}\n\n/**\n * The single source of truth for a bend's developed (neutral-axis) length.\n *\n * Precedence:\n * 1. `rule.bendTableRef` — look up the table and interpolate it (linear in\n * angle, bilinear across thickness × radius), converting a deduction table\n * to an allowance via {@link allowanceFromDeduction}. Outside the table\n * extents the lookup clamps to the nearest breakpoint and reports a\n * `MIN_RADIUS`-class warning through `onWarning` rather than extrapolating.\n * 2. `rule.allowance` — an explicit per-bend override, returned verbatim.\n * 3. The K-factor formula BA = (π/180)·|angle|·(R + K·T).\n *\n * The returned value is in the same units and sense the rest of the package's\n * `developedLength` consumes (a strip width along the developed pattern).\n *\n * @param rule - the bend rule driving the lookup (bend table ref, explicit\n * allowance, or K-factor).\n * @param angleDeg - the bend angle in degrees.\n * @param thickness - the sheet thickness.\n * @param onWarning - optional callback invoked with a {@link SheetMetalWarning}\n * when a table lookup clamped to the nearest breakpoint outside the tabulated range.\n * @returns a {@link Result} carrying the resolved bend allowance on success, or a\n * validation error for an unknown table / non-positive input / failed lookup.\n */\nexport function resolveBendAllowance(\n rule: BendRule,\n angleDeg: number,\n thickness: number,\n onWarning?: (warning: SheetMetalWarning) => void\n): Result<number> {\n if (rule.bendTableRef !== undefined) {\n if (!Number.isFinite(angleDeg)) {\n return err(validationError('INVALID_ANGLE', `angleDeg must be finite, got ${angleDeg}`));\n }\n if (!Number.isFinite(thickness) || thickness <= 0) {\n return err(validationError('INVALID_THICKNESS', `thickness must be a finite, positive number, got ${thickness}`));\n }\n if (!Number.isFinite(rule.innerRadius) || rule.innerRadius < 0) {\n return err(validationError('INVALID_RADIUS', `innerRadius must be a finite, non-negative number, got ${rule.innerRadius}`));\n }\n const table = getBendTable(rule.bendTableRef);\n if (table === undefined) {\n return err(validationError('UNKNOWN_BEND_TABLE', `no bend table registered under id '${rule.bendTableRef}'`));\n }\n const angle = Math.abs(angleDeg);\n const interp = interpTable(table, thickness, rule.innerRadius, angle);\n if (interp === undefined) {\n return err(\n validationError('TABLE_LOOKUP_FAILED', `bend table '${table.id}' has no rows bracketing (t=${thickness}, r=${rule.innerRadius})`)\n );\n }\n const ba = table.kind === 'deduction' ? allowanceFromDeduction(interp.value, rule.innerRadius, thickness, angle) : interp.value;\n if (!Number.isFinite(ba) || ba < 0) {\n return err(\n validationError(\n 'INVALID_TABLE_ALLOWANCE',\n `bend table '${table.id}' produced a non-positive allowance ${ba} at (t=${thickness}, r=${rule.innerRadius}, θ=${angle})`\n )\n );\n }\n if (interp.clamped && onWarning !== undefined) {\n onWarning({\n code: 'TABLE_CLAMP',\n message: `bend table '${table.id}' query (t=${thickness}, r=${rule.innerRadius}, θ=${angle}) is outside the tabulated range; clamped to the nearest entry`,\n });\n }\n return ok(ba);\n }\n return fallbackAllowance(rule, angleDeg, thickness);\n}\n\n/** Explicit-allowance override, then the K-factor formula (the pre-table behaviour). */\nfunction fallbackAllowance(rule: BendRule, angleDeg: number, thickness: number): Result<number> {\n if (rule.allowance !== undefined) {\n if (!Number.isFinite(rule.allowance) || rule.allowance < 0) {\n return err(\n validationError('INVALID_ALLOWANCE', `allowance override must be a finite, non-negative number, got ${rule.allowance}`)\n );\n }\n return ok(rule.allowance);\n }\n if (!Number.isFinite(angleDeg)) {\n return err(validationError('INVALID_ANGLE', `angleDeg must be finite, got ${angleDeg}`));\n }\n if (!Number.isFinite(thickness) || thickness <= 0) {\n return err(validationError('INVALID_THICKNESS', `thickness must be a finite, positive number, got ${thickness}`));\n }\n if (!Number.isFinite(rule.innerRadius) || rule.innerRadius < 0) {\n return err(validationError('INVALID_RADIUS', `innerRadius must be a finite, non-negative number, got ${rule.innerRadius}`));\n }\n if (!Number.isFinite(rule.kFactor) || rule.kFactor < 0 || rule.kFactor > 1) {\n return err(validationError('INVALID_K_FACTOR', `kFactor must be in [0, 1], got ${rule.kFactor}`));\n }\n const neutralRadius = rule.innerRadius + rule.kFactor * thickness;\n return ok(DEG_TO_RAD * Math.abs(angleDeg) * neutralRadius);\n}\n\n/**\n * Starter shop bend tables, auto-registered on first table access. The values\n * are published 90°-equivalent air-bend allowances scaled across the standard\n * {30, 60, 90, 120}° set by the linear angle ratio, at a single canonical inner\n * radius per gauge.\n *\n * Sources: SheetMetal.Me air-bend / bend-allowance charts and Machinery's\n * Handbook (29th ed.) sheet-metal bend-allowance tables for mild steel and\n * 5052-H32 aluminium. The 90° allowances are the published mid-range air-bend\n * figures; the other angles are the proportional neutral-axis arc lengths\n * (allowance scales ~linearly with the swept angle at a fixed radius).\n */\nconst STARTER_TABLES: readonly BendTable[] = [\n {\n id: 'steel-airbend',\n kind: 'allowance',\n rows: angleSet([\n { thickness: 0.91, radius: 1.0, ba90: 2.36 },\n { thickness: 1.52, radius: 1.5, ba90: 3.63 },\n { thickness: 1.9, radius: 2.0, ba90: 4.62 },\n { thickness: 2.66, radius: 3.0, ba90: 6.59 },\n ]),\n },\n {\n id: 'aluminum-airbend',\n kind: 'allowance',\n rows: angleSet([\n { thickness: 0.81, radius: 1.0, ba90: 2.27 },\n { thickness: 1.29, radius: 1.5, ba90: 3.44 },\n { thickness: 1.63, radius: 2.0, ba90: 4.49 },\n { thickness: 2.59, radius: 3.0, ba90: 6.51 },\n ]),\n },\n];\n\n/** Expand a per-gauge 90° allowance into the {30, 60, 90, 120}° rows by the angle ratio. */\nfunction angleSet(seeds: { thickness: number; radius: number; ba90: number }[]): BendTableRow[] {\n const angles = [30, 60, 90, 120];\n const rows: BendTableRow[] = [];\n for (const seed of seeds) {\n for (const angleDeg of angles) {\n rows.push({ thickness: seed.thickness, radius: seed.radius, angleDeg, value: (seed.ba90 * angleDeg) / 90 });\n }\n }\n return rows;\n}\n\nlet starterTablesRegistered = false;\n\n/**\n * Register the starter tables exactly once. Done lazily (not at module load) so\n * the package keeps `sideEffects: false` — importing the package never mutates\n * the registry; the tables materialise on the first {@link getBendTable} call.\n */\nfunction ensureStarterTables(): void {\n if (starterTablesRegistered) return;\n starterTablesRegistered = true;\n for (const table of STARTER_TABLES) {\n // Never clobber a table a caller registered under a starter id before first access.\n if (bendTables.byId.has(table.id)) continue;\n bendTables.byId.set(table.id, { id: table.id, kind: table.kind, rows: table.rows.map((r) => ({ ...r })) });\n }\n}\n"]}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import type { Solid } from './types.js';
|
|
2
|
+
import { type Result, type Vec3 } from '@faicad/faijs/api';
|
|
2
3
|
import type { ContourFlangeSpec, FlatSide, ProfileSegment, SheetMetalPart } from './types.js';
|
|
3
4
|
/**
|
|
4
5
|
* The local frame of one contour-flange segment: the contact origin plus the
|
|
@@ -28,7 +29,7 @@ export interface SegmentFrame {
|
|
|
28
29
|
* @returns a `Result<SheetMetalPart>` — `ok` with the part plus the fused solid and the recorded
|
|
29
30
|
* {@link ContourFlangeFeature}, or `err` with a `validationError` on invalid input
|
|
30
31
|
*/
|
|
31
|
-
export declare function authorContourFlange(part: SheetMetalPart, spec: ContourFlangeSpec): Result<SheetMetalPart
|
|
32
|
+
export declare function authorContourFlange(part: SheetMetalPart, spec: ContourFlangeSpec): Promise<Result<SheetMetalPart>>;
|
|
32
33
|
/**
|
|
33
34
|
* Result of building one contour-flange segment: the fused solid and the next
|
|
34
35
|
* segment's chained frame.
|
|
@@ -56,7 +57,7 @@ export interface BuiltArc extends BuiltSegment {
|
|
|
56
57
|
* @returns a `Result<BuiltSegment>` — `ok` with the fused solid and the next segment's
|
|
57
58
|
* frame, or `err` when the boolean fuse fails
|
|
58
59
|
*/
|
|
59
|
-
export declare function buildLineLeg(base: Solid, frame: SegmentFrame, span: number, thickness: number, legLength: number): Result<BuiltSegment
|
|
60
|
+
export declare function buildLineLeg(base: Solid, frame: SegmentFrame, span: number, thickness: number, legLength: number): Promise<Result<BuiltSegment>>;
|
|
60
61
|
/**
|
|
61
62
|
* Add one cylindrical bend turning the running direction by `angleDeg`. Mirrors
|
|
62
63
|
* {@link authorPart}'s bend patch: a hollow tube (outer R+T, inner R) intersected
|
|
@@ -73,7 +74,7 @@ export declare function buildLineLeg(base: Solid, frame: SegmentFrame, span: num
|
|
|
73
74
|
*/
|
|
74
75
|
export declare function buildArcBend(base: Solid, frame: SegmentFrame, span: number, thickness: number, seg: Extract<ProfileSegment, {
|
|
75
76
|
kind: 'arc';
|
|
76
|
-
}>): Result<BuiltArc
|
|
77
|
+
}>): Promise<Result<BuiltArc>>;
|
|
77
78
|
/**
|
|
78
79
|
* One of the four straight edges of a flat region, resolved into the start line a
|
|
79
80
|
* profile is chained from: edge direction, outward normal, start point and length.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contourFlangeFns.d.ts","sourceRoot":"","sources":["../src/contourFlangeFns.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"contourFlangeFns.d.ts","sourceRoot":"","sources":["../src/contourFlangeFns.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAc,MAAM,YAAY,CAAC;AAEpD,OAAO,EAAC,KAAK,MAAM,EAAE,KAAK,IAAI,EAAqI,MAAM,mBAAmB,CAAC;AAC7L,OAAO,KAAK,EAIV,iBAAiB,EACjB,QAAQ,EACR,cAAc,EACd,cAAc,EACf,MAAM,YAAY,CAAC;AAIpB;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,2EAA2E;IAC3E,MAAM,EAAE,IAAI,CAAC;IACb,sDAAsD;IACtD,GAAG,EAAE,IAAI,CAAC;IACV,mDAAmD;IACnD,CAAC,EAAE,IAAI,CAAC;IACR,mEAAmE;IACnE,IAAI,EAAE,IAAI,CAAC;CACZ;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,cAAc,EACpB,IAAI,EAAE,iBAAiB,GACtB,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAuGjC;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,KAAK,CAAC;IACb,KAAK,EAAE,YAAY,CAAC;CACrB;AAED;;;GAGG;AACH,MAAM,WAAW,QAAS,SAAQ,YAAY;IAC5C,UAAU,EAAE,IAAI,CAAC;CAClB;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,YAAY,CAChC,IAAI,EAAE,KAAK,EACX,KAAK,EAAE,YAAY,EACnB,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAc/B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,YAAY,CAChC,IAAI,EAAE,KAAK,EACX,KAAK,EAAE,YAAY,EACnB,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,OAAO,CAAC,cAAc,EAAE;IAAE,IAAI,EAAE,KAAK,CAAA;CAAE,CAAC,GAC5C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAkD3B;AAgCD;;;GAGG;AACH,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,IAAI,CAAC;IACV,GAAG,EAAE,IAAI,CAAC;IACV,KAAK,EAAE,IAAI,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,QAAQ,GAAG,QAAQ,CA8CvE;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CACxB,KAAK,EAAE;IAAE,MAAM,EAAE,IAAI,CAAC;IAAC,CAAC,EAAE,IAAI,CAAC;IAAC,CAAC,EAAE,IAAI,CAAC;IAAC,CAAC,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAC9E,IAAI,EAAE,QAAQ,GACb,QAAQ,CAwCV;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,YAAY,CAOzF"}
|
package/dist/contourFlangeFns.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { cylinder, translate } from './geometryOps.js';
|
|
2
|
+
import { ok, err, kernelError, validationError, box, fuse, cut, intersect, rotate, vecAdd, vecScale, vecSub, vecDot, vecCross, vecNormalize } from '@faicad/faijs/api';
|
|
2
3
|
import { normalizeSolid } from './internal.js';
|
|
3
4
|
import { developedLength } from './allowanceFns.js';
|
|
4
5
|
/**
|
|
@@ -15,7 +16,7 @@ import { developedLength } from './allowanceFns.js';
|
|
|
15
16
|
* @returns a `Result<SheetMetalPart>` — `ok` with the part plus the fused solid and the recorded
|
|
16
17
|
* {@link ContourFlangeFeature}, or `err` with a `validationError` on invalid input
|
|
17
18
|
*/
|
|
18
|
-
export function authorContourFlange(part, spec) {
|
|
19
|
+
export async function authorContourFlange(part, spec) {
|
|
19
20
|
if (part.solid === undefined) {
|
|
20
21
|
return err(validationError('NO_SOLID', `part has no solid to attach contour flange '${spec.id}'`));
|
|
21
22
|
}
|
|
@@ -64,7 +65,7 @@ export function authorContourFlange(part, spec) {
|
|
|
64
65
|
if (!Number.isFinite(seg.length) || seg.length <= 0) {
|
|
65
66
|
return err(validationError('INVALID_SEGMENT_LENGTH', `contour flange '${spec.id}' line segment ${i} length must be positive`));
|
|
66
67
|
}
|
|
67
|
-
const built = buildLineLeg(solid, frame, span, thickness, seg.length);
|
|
68
|
+
const built = await buildLineLeg(solid, frame, span, thickness, seg.length);
|
|
68
69
|
if (!built.ok)
|
|
69
70
|
return built;
|
|
70
71
|
solid = built.value.solid;
|
|
@@ -74,7 +75,7 @@ export function authorContourFlange(part, spec) {
|
|
|
74
75
|
}
|
|
75
76
|
else {
|
|
76
77
|
const rule = spec.rule ?? { innerRadius: seg.radius, kFactor: 0.44 };
|
|
77
|
-
const built = buildArcBend(solid, frame, span, thickness, seg);
|
|
78
|
+
const built = await buildArcBend(solid, frame, span, thickness, seg);
|
|
78
79
|
if (!built.ok)
|
|
79
80
|
return built;
|
|
80
81
|
solid = built.value.solid;
|
|
@@ -124,17 +125,20 @@ export function authorContourFlange(part, spec) {
|
|
|
124
125
|
* @returns a `Result<BuiltSegment>` — `ok` with the fused solid and the next segment's
|
|
125
126
|
* frame, or `err` when the boolean fuse fails
|
|
126
127
|
*/
|
|
127
|
-
export function buildLineLeg(base, frame, span, thickness, legLength) {
|
|
128
|
+
export async function buildLineLeg(base, frame, span, thickness, legLength) {
|
|
128
129
|
// Canonical box (legLength × span × thickness) at the origin, mapped onto the
|
|
129
130
|
// current segment frame: +X→run, +Y→axis, +Z→n.
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
131
|
+
try {
|
|
132
|
+
const place = frameTransform(frame.run, frame.axis, frame.n, frame.origin);
|
|
133
|
+
const canon = (await box({ width: legLength, depth: span, height: thickness }));
|
|
134
|
+
const placed = await place.solid(canon);
|
|
135
|
+
const fused = (await fuse(base, placed));
|
|
136
|
+
const nextOrigin = vecAdd(frame.origin, vecScale(frame.run, legLength));
|
|
137
|
+
return ok({ solid: fused, frame: { ...frame, origin: nextOrigin } });
|
|
138
|
+
}
|
|
139
|
+
catch (e) {
|
|
140
|
+
return err(kernelError('FUSE_FAILED', `contour line leg: ${e instanceof Error ? e.message : String(e)}`));
|
|
141
|
+
}
|
|
138
142
|
}
|
|
139
143
|
/**
|
|
140
144
|
* Add one cylindrical bend turning the running direction by `angleDeg`. Mirrors
|
|
@@ -150,7 +154,7 @@ export function buildLineLeg(base, frame, span, thickness, legLength) {
|
|
|
150
154
|
* @returns a `Result<BuiltArc>` — `ok` with the fused solid, the rotated next frame and the
|
|
151
155
|
* world-space bend axis origin, or `err` with a `validationError` on invalid geometry
|
|
152
156
|
*/
|
|
153
|
-
export function buildArcBend(base, frame, span, thickness, seg) {
|
|
157
|
+
export async function buildArcBend(base, frame, span, thickness, seg) {
|
|
154
158
|
const r = seg.radius;
|
|
155
159
|
if (!Number.isFinite(r) || r < 0) {
|
|
156
160
|
return err(validationError('INVALID_RADIUS', `contour arc radius must be non-negative, got ${r}`));
|
|
@@ -165,13 +169,17 @@ export function buildArcBend(base, frame, span, thickness, seg) {
|
|
|
165
169
|
const canonAxisZ = sign > 0 ? thickness + r : -r;
|
|
166
170
|
const canonOrigin = [0, 0, canonAxisZ];
|
|
167
171
|
const place = frameTransform(frame.run, frame.axis, frame.n, frame.origin);
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
172
|
+
let fused;
|
|
173
|
+
try {
|
|
174
|
+
const patch = await buildBendPatch(canonOrigin, seg.angleDeg, r, span, thickness, seg.direction);
|
|
175
|
+
if (!patch.ok)
|
|
176
|
+
return patch;
|
|
177
|
+
const placed = await place.solid(patch.value);
|
|
178
|
+
fused = (await fuse(base, placed));
|
|
179
|
+
}
|
|
180
|
+
catch (e) {
|
|
181
|
+
return err(kernelError('FUSE_FAILED', `contour arc bend: ${e instanceof Error ? e.message : String(e)}`));
|
|
182
|
+
}
|
|
175
183
|
// Fold run/normal by ∓θ about the axis (authorPart: rotate −sign·θ about +Y).
|
|
176
184
|
const theta = (seg.angleDeg * Math.PI) / 180;
|
|
177
185
|
const a = -sign * theta;
|
|
@@ -189,7 +197,7 @@ export function buildArcBend(base, frame, span, thickness, seg) {
|
|
|
189
197
|
const nextN = place.vector(nC);
|
|
190
198
|
const axisOrigin = place.point(canonOrigin);
|
|
191
199
|
return ok({
|
|
192
|
-
solid: fused
|
|
200
|
+
solid: fused,
|
|
193
201
|
frame: { origin: nextOrigin, run: nextRun, n: nextN, axis: frame.axis },
|
|
194
202
|
axisOrigin,
|
|
195
203
|
});
|
|
@@ -208,9 +216,9 @@ function frameTransform(runT, axisT, nT, origin) {
|
|
|
208
216
|
const aa = matrixToAxisAngle(m);
|
|
209
217
|
const applyR = (v) => vecAdd(vecAdd(vecScale(runT, v[0]), vecScale(axisT, v[1])), vecScale(nT, v[2]));
|
|
210
218
|
return {
|
|
211
|
-
solid: (s) => {
|
|
212
|
-
const rotated = aa.angleDeg === 0 ? s : rotate(s, aa.angleDeg, { at: [0, 0, 0], axis: aa.axis });
|
|
213
|
-
return translate(rotated, origin);
|
|
219
|
+
solid: async (s) => {
|
|
220
|
+
const rotated = aa.angleDeg === 0 ? s : await rotate(s, aa.angleDeg, { at: [0, 0, 0], axis: aa.axis });
|
|
221
|
+
return (await translate(rotated, origin));
|
|
214
222
|
},
|
|
215
223
|
point: (p) => vecAdd(applyR(p), origin),
|
|
216
224
|
vector: applyR,
|
|
@@ -335,30 +343,37 @@ export function initialSegmentFrame(edge, n, offset) {
|
|
|
335
343
|
};
|
|
336
344
|
}
|
|
337
345
|
/** Cylindrical bend patch (hollow tube ∩ fold wedge), mirroring authorFns. */
|
|
338
|
-
function buildBendPatch(axisOrigin, thetaDeg, r, width, thickness, direction) {
|
|
346
|
+
async function buildBendPatch(axisOrigin, thetaDeg, r, width, thickness, direction) {
|
|
339
347
|
const outerR = r + thickness;
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
+
try {
|
|
349
|
+
const outer = await cylinder(outerR, width, { at: axisOrigin, axis: [0, 1, 0] });
|
|
350
|
+
let tube = outer;
|
|
351
|
+
if (r > 1e-9) {
|
|
352
|
+
const inner = await cylinder(r, width, { at: axisOrigin, axis: [0, 1, 0] });
|
|
353
|
+
tube = (await cut(outer, inner));
|
|
354
|
+
}
|
|
355
|
+
const wedge = await buildWedge(axisOrigin, thetaDeg, outerR, width, direction);
|
|
356
|
+
if (!wedge.ok)
|
|
357
|
+
return wedge;
|
|
358
|
+
return ok((await intersect(tube, wedge.value)));
|
|
359
|
+
}
|
|
360
|
+
catch (e) {
|
|
361
|
+
return err(kernelError('BEND_PATCH_FAILED', `contour bend patch: ${e instanceof Error ? e.message : String(e)}`));
|
|
348
362
|
}
|
|
349
|
-
const wedge = buildWedge(axisOrigin, thetaDeg, outerR, width, direction);
|
|
350
|
-
if (!wedge.ok)
|
|
351
|
-
return wedge;
|
|
352
|
-
return intersect(tube, wedge.value);
|
|
353
363
|
}
|
|
354
|
-
function buildWedge(axisOrigin, thetaDeg, outerR, width, direction) {
|
|
364
|
+
async function buildWedge(axisOrigin, thetaDeg, outerR, width, direction) {
|
|
355
365
|
const span = outerR * 2 + 2;
|
|
356
366
|
const margin = 1;
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
367
|
+
try {
|
|
368
|
+
const blockA = (await box({ width: span, depth: width + 2 * margin, height: 2 * span }));
|
|
369
|
+
const halfA = (await translate(blockA, [axisOrigin[0], axisOrigin[1] - margin, axisOrigin[2] - span]));
|
|
370
|
+
const sign = direction === 'up' ? 1 : -1;
|
|
371
|
+
const halfB = await rotate(halfA, sign * (180 - thetaDeg), { at: axisOrigin, axis: [0, 1, 0] });
|
|
372
|
+
return ok((await intersect(halfA, halfB)));
|
|
373
|
+
}
|
|
374
|
+
catch (e) {
|
|
375
|
+
return err(kernelError('WEDGE_FAILED', `contour wedge: ${e instanceof Error ? e.message : String(e)}`));
|
|
376
|
+
}
|
|
362
377
|
}
|
|
363
378
|
/** Axis-angle of a 3×3 rotation matrix (row-major). */
|
|
364
379
|
function matrixToAxisAngle(m) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contourFlangeFns.js","sourceRoot":"","sources":["../src/contourFlangeFns.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type Result,\n type Vec3,\n type Solid,\n type ValidSolid,\n ok,\n err,\n validationError,\n box,\n cylinder,\n fuse,\n cut,\n intersect,\n rotate,\n translate,\n vecAdd,\n vecScale,\n vecSub,\n vecDot,\n vecCross,\n vecNormalize,\n} from '@faicad/faijs/brepjs-compat';\nimport type {\n BendFeature,\n BendRule,\n ContourFlangeFeature,\n ContourFlangeSpec,\n FlatSide,\n ProfileSegment,\n SheetMetalPart,\n} from './types.js';\nimport { normalizeSolid } from './internal.js';\nimport { developedLength } from './allowanceFns.js';\n\n/**\n * The local frame of one contour-flange segment: the contact origin plus the\n * segment's run, normal and shared bend-axis directions.\n */\nexport interface SegmentFrame {\n /** Origin of the −normal (bottom) surface at the start of this segment. */\n origin: Vec3;\n /** Outward run direction (the segment's local +X). */\n run: Vec3;\n /** Top-surface normal (+Z), n = bendAxis × run. */\n n: Vec3;\n /** Bend axis along the base edge (+Y), shared by every segment. */\n axis: Vec3;\n}\n\n/**\n * Author a contour flange: an OPEN 2D profile (alternating line/arc segments) swept\n * along one straight edge of the base flat. Each arc is a cylindrical bend, each\n * line a flat leg; consecutive segments chain frame-to-frame exactly as\n * {@link authorPart} chains flanges, building one connected multi-bend cross-section\n * (a return, a hat, a J). The recorded {@link ContourFlangeFeature} carries each\n * segment's EXACT developed length (lines: `length`; arcs: the canonical\n * {@link developedLength}) so the unfold lays the strip out straight with no error.\n * Construction stays on the public, OCCT-WASM-safe API.\n * @param part the sheet-metal part the contour flange is added to (must already carry a solid)\n * @param spec the contour-flange specification: profile segments, side, offset, width and optional bend rule\n * @returns a `Result<SheetMetalPart>` — `ok` with the part plus the fused solid and the recorded\n * {@link ContourFlangeFeature}, or `err` with a `validationError` on invalid input\n */\nexport function authorContourFlange(\n part: SheetMetalPart,\n spec: ContourFlangeSpec\n): Result<SheetMetalPart> {\n if (part.solid === undefined) {\n return err(validationError('NO_SOLID', `part has no solid to attach contour flange '${spec.id}'`));\n }\n if (spec.id === '' || spec.id.includes('::')) {\n return err(\n validationError('INVALID_CONTOUR_ID', `contour flange id must be non-empty and must not contain '::', got '${spec.id}'`)\n );\n }\n for (const existing of part.contourFlanges ?? []) {\n if (existing.id === spec.id) {\n return err(validationError('DUPLICATE_CONTOUR', `duplicate contour flange id '${spec.id}'`));\n }\n }\n if (spec.profile.length === 0) {\n return err(validationError('EMPTY_PROFILE', `contour flange '${spec.id}' profile is empty`));\n }\n\n const thickness = part.thickness;\n const edge = baseEdge(part, spec.side);\n const offset = spec.offset ?? 0;\n const span = spec.width ?? edge.length;\n if (!Number.isFinite(offset) || offset < -1e-9) {\n return err(validationError('INVALID_OFFSET', `contour flange '${spec.id}' offset must be non-negative`));\n }\n if (!Number.isFinite(span) || span <= 0) {\n return err(validationError('INVALID_CONTOUR_WIDTH', `contour flange '${spec.id}' width must be positive`));\n }\n if (offset + span > edge.length + 1e-6) {\n return err(\n validationError('CONTOUR_OUT_OF_BOUNDS', `contour flange '${spec.id}' [${offset}, ${offset + span}] exceeds base edge length ${edge.length}`)\n );\n }\n\n // The profile is swept across `span` along the base edge starting at `offset`.\n const stripStart = vecAdd(edge.start, vecScale(edge.dir, offset));\n let frame: SegmentFrame = {\n origin: stripStart,\n run: edge.out,\n n: [0, 0, 1],\n axis: edge.dir,\n };\n\n let solid: Solid = part.solid;\n const bends: BendFeature[] = [];\n const segments: ContourFlangeFeature['segments'] = [];\n let devTotal = 0;\n let arcIndex = 0;\n\n for (let i = 0; i < spec.profile.length; i += 1) {\n const seg = spec.profile[i];\n if (seg === undefined) continue;\n if (seg.kind === 'line') {\n if (!Number.isFinite(seg.length) || seg.length <= 0) {\n return err(validationError('INVALID_SEGMENT_LENGTH', `contour flange '${spec.id}' line segment ${i} length must be positive`));\n }\n const built = buildLineLeg(solid, frame, span, thickness, seg.length);\n if (!built.ok) return built;\n solid = built.value.solid;\n frame = built.value.frame;\n segments.push({ kind: 'line', dev: seg.length });\n devTotal += seg.length;\n } else {\n const rule: BendRule = spec.rule ?? { innerRadius: seg.radius, kFactor: 0.44 };\n const built = buildArcBend(solid, frame, span, thickness, seg);\n if (!built.ok) return built;\n solid = built.value.solid;\n frame = built.value.frame;\n\n const devResult = developedLength(seg.angleDeg, thickness, { ...rule, innerRadius: seg.radius });\n if (!devResult.ok) return devResult;\n const dev = devResult.value;\n\n const bendId = `contour::${spec.id}::${arcIndex}`;\n arcIndex += 1;\n bends.push({\n id: bendId,\n axisOrigin: [built.value.axisOrigin[0], built.value.axisOrigin[1], built.value.axisOrigin[2]],\n axisDir: [edge.dir[0], edge.dir[1], edge.dir[2]],\n angleDeg: seg.angleDeg,\n direction: seg.direction,\n rule: { ...rule, innerRadius: seg.radius },\n });\n segments.push({ kind: 'arc', dev, angleDeg: seg.angleDeg, direction: seg.direction, bendId });\n devTotal += dev;\n }\n }\n\n const feature: ContourFlangeFeature = {\n id: spec.id,\n side: spec.side,\n offset,\n span,\n developedLength: devTotal,\n segments,\n };\n\n return ok({\n ...part,\n solid: normalizeSolid(solid),\n bends: [...part.bends, ...bends],\n contourFlanges: [...(part.contourFlanges ?? []), feature],\n });\n}\n\n/**\n * Result of building one contour-flange segment: the fused solid and the next\n * segment's chained frame.\n */\nexport interface BuiltSegment {\n solid: Solid;\n frame: SegmentFrame;\n}\n\n/**\n * Result of building a cylindrical bend: {@link BuiltSegment} plus the world-space\n * origin of the bend axis.\n */\nexport interface BuiltArc extends BuiltSegment {\n axisOrigin: Vec3;\n}\n\n/**\n * Add one straight leg of `legLength` extending from `frame.origin` along\n * `frame.run`, full thickness along `frame.n`, across `span` along `frame.axis`.\n * The next segment's frame starts at the leg's far end.\n * @param base the solid the new leg is fused onto\n * @param frame the current segment frame the leg is built in\n * @param span the flange width along the bend axis\n * @param thickness the sheet thickness\n * @param legLength the straight-run length of the leg\n * @returns a `Result<BuiltSegment>` — `ok` with the fused solid and the next segment's\n * frame, or `err` when the boolean fuse fails\n */\nexport function buildLineLeg(\n base: Solid,\n frame: SegmentFrame,\n span: number,\n thickness: number,\n legLength: number\n): Result<BuiltSegment> {\n // Canonical box (legLength × span × thickness) at the origin, mapped onto the\n // current segment frame: +X→run, +Y→axis, +Z→n.\n const place = frameTransform(frame.run, frame.axis, frame.n, frame.origin);\n const canon = box(legLength, span, thickness);\n const placed = place.solid(canon);\n const fused = fuse(base, placed);\n if (!fused.ok) return fused;\n\n const nextOrigin = vecAdd(frame.origin, vecScale(frame.run, legLength));\n return ok({ solid: fused.value, frame: { ...frame, origin: nextOrigin } });\n}\n\n/**\n * Add one cylindrical bend turning the running direction by `angleDeg`. Mirrors\n * {@link authorPart}'s bend patch: a hollow tube (outer R+T, inner R) intersected\n * with the fold wedge, in a canonical frame mapped onto the current segment frame.\n * The returned frame's run/normal are rotated by the fold so the next leg continues\n * tangentially.\n * @param base the solid the bend is fused onto\n * @param frame the current segment frame the bend turns from\n * @param span the flange width along the bend axis\n * @param thickness the sheet thickness\n * @param seg the arc profile segment: radius, angle and fold direction\n * @returns a `Result<BuiltArc>` — `ok` with the fused solid, the rotated next frame and the\n * world-space bend axis origin, or `err` with a `validationError` on invalid geometry\n */\nexport function buildArcBend(\n base: Solid,\n frame: SegmentFrame,\n span: number,\n thickness: number,\n seg: Extract<ProfileSegment, { kind: 'arc' }>\n): Result<BuiltArc> {\n const r = seg.radius;\n if (!Number.isFinite(r) || r < 0) {\n return err(validationError('INVALID_RADIUS', `contour arc radius must be non-negative, got ${r}`));\n }\n if (!Number.isFinite(seg.angleDeg) || seg.angleDeg <= 0 || seg.angleDeg > 180) {\n return err(validationError('INVALID_ARC_ANGLE', `contour arc angleDeg must be in (0, 180], got ${seg.angleDeg}`));\n }\n\n const sign = seg.direction === 'up' ? 1 : -1;\n // Canonical assembly (authorPart convention): bend axis +Y, run +X, top +Z, with\n // the bend-axis centre line at z = T+r (up) / −r (down). The current segment frame\n // maps +X→run, +Y→axis, +Z→n.\n const canonAxisZ = sign > 0 ? thickness + r : -r;\n const canonOrigin: Vec3 = [0, 0, canonAxisZ];\n const place = frameTransform(frame.run, frame.axis, frame.n, frame.origin);\n\n const patch = buildBendPatch(canonOrigin, seg.angleDeg, r, span, thickness, seg.direction);\n if (!patch.ok) return patch;\n const placed = place.solid(patch.value);\n const fused = fuse(base, placed);\n if (!fused.ok) return fused;\n\n // Fold run/normal by ∓θ about the axis (authorPart: rotate −sign·θ about +Y).\n const theta = (seg.angleDeg * Math.PI) / 180;\n const a = -sign * theta;\n const ca = Math.cos(a);\n const sa = Math.sin(a);\n // Canonical run +X folds to [ca, 0, −sa]; normal +Z to [sa, 0, ca].\n const runC: Vec3 = [ca, 0, -sa];\n const nC: Vec3 = [sa, 0, ca];\n // The post-bend exit point in canonical coords: the near-bottom corner [0,0,0]\n // rotated about the pivot [0,0,axisZ].\n const dz = -canonAxisZ;\n const cornerC: Vec3 = [dz * sa, 0, canonAxisZ + dz * ca];\n\n const nextOrigin = place.point(cornerC);\n const nextRun = place.vector(runC);\n const nextN = place.vector(nC);\n const axisOrigin = place.point(canonOrigin);\n\n return ok({\n solid: fused.value,\n frame: { origin: nextOrigin, run: nextRun, n: nextN, axis: frame.axis },\n axisOrigin,\n });\n}\n\ninterface PlacedTransform {\n solid: (s: Solid) => Solid;\n point: (p: Vec3) => Vec3;\n vector: (v: Vec3) => Vec3;\n}\n\n/**\n * Rigid map of a canonical assembly (run +X, axis +Y, normal +Z, contact at the\n * origin) onto a world frame: align +X→`runT`, +Y→`axisT`, +Z→`nT`, then translate\n * the origin to `origin`.\n */\nfunction frameTransform(runT: Vec3, axisT: Vec3, nT: Vec3, origin: Vec3): PlacedTransform {\n const m: number[] = [\n runT[0], axisT[0], nT[0],\n runT[1], axisT[1], nT[1],\n runT[2], axisT[2], nT[2],\n ];\n const aa = matrixToAxisAngle(m);\n const applyR = (v: Vec3): Vec3 =>\n vecAdd(vecAdd(vecScale(runT, v[0]), vecScale(axisT, v[1])), vecScale(nT, v[2]));\n return {\n solid: (s: Solid) => {\n const rotated = aa.angleDeg === 0 ? s : rotate(s, aa.angleDeg, { at: [0, 0, 0], axis: aa.axis });\n return translate(rotated, origin);\n },\n point: (p: Vec3) => vecAdd(applyR(p), origin),\n vector: applyR,\n };\n}\n\n/**\n * One of the four straight edges of a flat region, resolved into the start line a\n * profile is chained from: edge direction, outward normal, start point and length.\n */\nexport interface BaseEdge {\n dir: Vec3;\n out: Vec3;\n start: Vec3;\n length: number;\n}\n\n/**\n * Resolve one of the four edges of the base flat (the contour-flange root).\n * @param part the sheet-metal part whose base flat edge is resolved\n * @param side which of the four base-flat edges to resolve (`'xmax'`/`'xmin'`/`'ymax'`/`'ymin'`)\n * @returns the resolved {@link BaseEdge} — edge direction, outward normal, start point and length\n */\nexport function baseEdge(part: SheetMetalPart, side: FlatSide): BaseEdge {\n const o: Vec3 = [0, 0, 0];\n const u: Vec3 = [1, 0, 0];\n const v: Vec3 = [0, 1, 0];\n const n: Vec3 = [0, 0, 1];\n const uLen = part.baseLength;\n const vLen = part.width;\n\n const uTop = vecAdd(o, vecScale(u, uLen));\n const vTop = vecAdd(o, vecScale(v, vLen));\n const uvTop = vecAdd(uTop, vecScale(v, vLen));\n\n let out: Vec3;\n let length: number;\n let a: Vec3;\n let b: Vec3;\n switch (side) {\n case 'xmax':\n out = u;\n length = vLen;\n a = uTop;\n b = uvTop;\n break;\n case 'xmin':\n out = vecScale(u, -1);\n length = vLen;\n a = o;\n b = vTop;\n break;\n case 'ymax':\n out = v;\n length = uLen;\n a = vTop;\n b = uvTop;\n break;\n case 'ymin':\n out = vecScale(v, -1);\n length = uLen;\n a = o;\n b = uTop;\n break;\n }\n const dir = vecNormalize(vecCross(n, out));\n const toB = vecSub(b, a);\n const start = vecDot(toB, dir) >= 0 ? a : b;\n return { dir, out, start, length };\n}\n\n/**\n * Resolve one of the four edges of an arbitrary flat region (its world top-surface\n * frame), the region-aware generalization of {@link baseEdge}: the base is the\n * special case where `origin = 0`, `u = +X`, `v = +Y`, `n = +Z`. Used by hems and\n * jogs to chain their profile off a named flange (or the base) edge.\n * @param frame the region's world top-surface frame (origin, u/v/n axes and extents)\n * @param side which of the four region edges to resolve\n * @returns the resolved {@link BaseEdge} — edge direction, outward normal, start point and length\n */\nexport function regionEdge(\n frame: { origin: Vec3; u: Vec3; v: Vec3; n: Vec3; uLen: number; vLen: number },\n side: FlatSide\n): BaseEdge {\n const o = frame.origin;\n const uTop = vecAdd(o, vecScale(frame.u, frame.uLen));\n const vTop = vecAdd(o, vecScale(frame.v, frame.vLen));\n const uvTop = vecAdd(uTop, vecScale(frame.v, frame.vLen));\n\n let out: Vec3;\n let length: number;\n let a: Vec3;\n let b: Vec3;\n switch (side) {\n case 'xmax':\n out = frame.u;\n length = frame.vLen;\n a = uTop;\n b = uvTop;\n break;\n case 'xmin':\n out = vecScale(frame.u, -1);\n length = frame.vLen;\n a = o;\n b = vTop;\n break;\n case 'ymax':\n out = frame.v;\n length = frame.uLen;\n a = vTop;\n b = uvTop;\n break;\n case 'ymin':\n out = vecScale(frame.v, -1);\n length = frame.uLen;\n a = o;\n b = uTop;\n break;\n }\n const dir = vecNormalize(vecCross(frame.n, out));\n const toB = vecSub(b, a);\n const start = vecDot(toB, dir) >= 0 ? a : b;\n return { dir, out, start, length };\n}\n\n/**\n * The starting {@link SegmentFrame} for a profile chained off `edge` at `offset`\n * along it: contact at the edge, run pointing outward, normal = the region normal,\n * bend axis along the edge. Shared by the contour-flange, hem and jog builders.\n * @param edge the resolved region edge the profile starts from\n * @param n the region normal, used as the frame's +Z\n * @param offset the start position along the edge, measured from `edge.start`\n * @returns the {@link SegmentFrame} with contact at the edge at `offset`, run pointing\n * outward and axis along the edge\n */\nexport function initialSegmentFrame(edge: BaseEdge, n: Vec3, offset: number): SegmentFrame {\n return {\n origin: vecAdd(edge.start, vecScale(edge.dir, offset)),\n run: edge.out,\n n,\n axis: edge.dir,\n };\n}\n\n/** Cylindrical bend patch (hollow tube ∩ fold wedge), mirroring authorFns. */\nfunction buildBendPatch(\n axisOrigin: Vec3,\n thetaDeg: number,\n r: number,\n width: number,\n thickness: number,\n direction: 'up' | 'down'\n): Result<ValidSolid> {\n const outerR = r + thickness;\n const outer = cylinder(outerR, width, { at: axisOrigin, axis: [0, 1, 0] });\n let tube: Solid = outer;\n if (r > 1e-9) {\n const inner = cylinder(r, width, { at: axisOrigin, axis: [0, 1, 0] });\n const carved = cut(outer, inner);\n if (!carved.ok) return carved;\n tube = carved.value;\n }\n const wedge = buildWedge(axisOrigin, thetaDeg, outerR, width, direction);\n if (!wedge.ok) return wedge;\n return intersect(tube, wedge.value) as Result<ValidSolid>;\n}\n\nfunction buildWedge(\n axisOrigin: Vec3,\n thetaDeg: number,\n outerR: number,\n width: number,\n direction: 'up' | 'down'\n): Result<Solid> {\n const span = outerR * 2 + 2;\n const margin = 1;\n const blockA = box(span, width + 2 * margin, 2 * span);\n const halfA: Solid = translate(blockA, [axisOrigin[0], axisOrigin[1] - margin, axisOrigin[2] - span]);\n const sign = direction === 'up' ? 1 : -1;\n const halfB = rotate(halfA, sign * (180 - thetaDeg), { at: axisOrigin, axis: [0, 1, 0] });\n return intersect(halfA, halfB);\n}\n\n/** Axis-angle of a 3×3 rotation matrix (row-major). */\nfunction matrixToAxisAngle(m: number[]): { axis: Vec3; angleDeg: number } {\n const m00 = m[0] ?? 0;\n const m01 = m[1] ?? 0;\n const m02 = m[2] ?? 0;\n const m10 = m[3] ?? 0;\n const m11 = m[4] ?? 0;\n const m12 = m[5] ?? 0;\n const m20 = m[6] ?? 0;\n const m21 = m[7] ?? 0;\n const m22 = m[8] ?? 0;\n\n const trace = m00 + m11 + m22;\n const cos = Math.max(-1, Math.min(1, (trace - 1) / 2));\n const angle = Math.acos(cos);\n const angleDeg = (angle * 180) / Math.PI;\n if (angle < 1e-9) return { axis: [0, 0, 1], angleDeg: 0 };\n\n if (Math.PI - angle < 1e-6) {\n const xx = (m00 + 1) / 2;\n const yy = (m11 + 1) / 2;\n const zz = (m22 + 1) / 2;\n let axis: Vec3;\n if (xx >= yy && xx >= zz) {\n const x = Math.sqrt(Math.max(xx, 0));\n axis = [x, (m01 + m10) / (4 * x), (m02 + m20) / (4 * x)];\n } else if (yy >= zz) {\n const y = Math.sqrt(Math.max(yy, 0));\n axis = [(m01 + m10) / (4 * y), y, (m12 + m21) / (4 * y)];\n } else {\n const z = Math.sqrt(Math.max(zz, 0));\n axis = [(m02 + m20) / (4 * z), (m12 + m21) / (4 * z), z];\n }\n return { axis: vecNormalize(axis), angleDeg: 180 };\n }\n\n const denom = 2 * Math.sin(angle);\n const axis: Vec3 = [(m21 - m12) / denom, (m02 - m20) / denom, (m10 - m01) / denom];\n return { axis: vecNormalize(axis), angleDeg };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"contourFlangeFns.js","sourceRoot":"","sources":["../src/contourFlangeFns.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Solid, ValidSolid } from './types.js';\nimport { cylinder, translate } from './geometryOps.js';\nimport {type Result, type Vec3, ok, err, kernelError, validationError, box, fuse, cut, intersect, rotate, vecAdd, vecScale, vecSub, vecDot, vecCross, vecNormalize} from '@faicad/faijs/api';\nimport type {\n BendFeature,\n BendRule,\n ContourFlangeFeature,\n ContourFlangeSpec,\n FlatSide,\n ProfileSegment,\n SheetMetalPart,\n} from './types.js';\nimport { normalizeSolid } from './internal.js';\nimport { developedLength } from './allowanceFns.js';\n\n/**\n * The local frame of one contour-flange segment: the contact origin plus the\n * segment's run, normal and shared bend-axis directions.\n */\nexport interface SegmentFrame {\n /** Origin of the −normal (bottom) surface at the start of this segment. */\n origin: Vec3;\n /** Outward run direction (the segment's local +X). */\n run: Vec3;\n /** Top-surface normal (+Z), n = bendAxis × run. */\n n: Vec3;\n /** Bend axis along the base edge (+Y), shared by every segment. */\n axis: Vec3;\n}\n\n/**\n * Author a contour flange: an OPEN 2D profile (alternating line/arc segments) swept\n * along one straight edge of the base flat. Each arc is a cylindrical bend, each\n * line a flat leg; consecutive segments chain frame-to-frame exactly as\n * {@link authorPart} chains flanges, building one connected multi-bend cross-section\n * (a return, a hat, a J). The recorded {@link ContourFlangeFeature} carries each\n * segment's EXACT developed length (lines: `length`; arcs: the canonical\n * {@link developedLength}) so the unfold lays the strip out straight with no error.\n * Construction stays on the public, OCCT-WASM-safe API.\n * @param part the sheet-metal part the contour flange is added to (must already carry a solid)\n * @param spec the contour-flange specification: profile segments, side, offset, width and optional bend rule\n * @returns a `Result<SheetMetalPart>` — `ok` with the part plus the fused solid and the recorded\n * {@link ContourFlangeFeature}, or `err` with a `validationError` on invalid input\n */\nexport async function authorContourFlange(\n part: SheetMetalPart,\n spec: ContourFlangeSpec\n): Promise<Result<SheetMetalPart>> {\n if (part.solid === undefined) {\n return err(validationError('NO_SOLID', `part has no solid to attach contour flange '${spec.id}'`));\n }\n if (spec.id === '' || spec.id.includes('::')) {\n return err(\n validationError('INVALID_CONTOUR_ID', `contour flange id must be non-empty and must not contain '::', got '${spec.id}'`)\n );\n }\n for (const existing of part.contourFlanges ?? []) {\n if (existing.id === spec.id) {\n return err(validationError('DUPLICATE_CONTOUR', `duplicate contour flange id '${spec.id}'`));\n }\n }\n if (spec.profile.length === 0) {\n return err(validationError('EMPTY_PROFILE', `contour flange '${spec.id}' profile is empty`));\n }\n\n const thickness = part.thickness;\n const edge = baseEdge(part, spec.side);\n const offset = spec.offset ?? 0;\n const span = spec.width ?? edge.length;\n if (!Number.isFinite(offset) || offset < -1e-9) {\n return err(validationError('INVALID_OFFSET', `contour flange '${spec.id}' offset must be non-negative`));\n }\n if (!Number.isFinite(span) || span <= 0) {\n return err(validationError('INVALID_CONTOUR_WIDTH', `contour flange '${spec.id}' width must be positive`));\n }\n if (offset + span > edge.length + 1e-6) {\n return err(\n validationError('CONTOUR_OUT_OF_BOUNDS', `contour flange '${spec.id}' [${offset}, ${offset + span}] exceeds base edge length ${edge.length}`)\n );\n }\n\n // The profile is swept across `span` along the base edge starting at `offset`.\n const stripStart = vecAdd(edge.start, vecScale(edge.dir, offset));\n let frame: SegmentFrame = {\n origin: stripStart,\n run: edge.out,\n n: [0, 0, 1],\n axis: edge.dir,\n };\n\n let solid: Solid = part.solid;\n const bends: BendFeature[] = [];\n const segments: ContourFlangeFeature['segments'] = [];\n let devTotal = 0;\n let arcIndex = 0;\n\n for (let i = 0; i < spec.profile.length; i += 1) {\n const seg = spec.profile[i];\n if (seg === undefined) continue;\n if (seg.kind === 'line') {\n if (!Number.isFinite(seg.length) || seg.length <= 0) {\n return err(validationError('INVALID_SEGMENT_LENGTH', `contour flange '${spec.id}' line segment ${i} length must be positive`));\n }\n const built = await buildLineLeg(solid, frame, span, thickness, seg.length);\n if (!built.ok) return built;\n solid = built.value.solid;\n frame = built.value.frame;\n segments.push({ kind: 'line', dev: seg.length });\n devTotal += seg.length;\n } else {\n const rule: BendRule = spec.rule ?? { innerRadius: seg.radius, kFactor: 0.44 };\n const built = await buildArcBend(solid, frame, span, thickness, seg);\n if (!built.ok) return built;\n solid = built.value.solid;\n frame = built.value.frame;\n\n const devResult = developedLength(seg.angleDeg, thickness, { ...rule, innerRadius: seg.radius });\n if (!devResult.ok) return devResult;\n const dev = devResult.value;\n\n const bendId = `contour::${spec.id}::${arcIndex}`;\n arcIndex += 1;\n bends.push({\n id: bendId,\n axisOrigin: [built.value.axisOrigin[0], built.value.axisOrigin[1], built.value.axisOrigin[2]],\n axisDir: [edge.dir[0], edge.dir[1], edge.dir[2]],\n angleDeg: seg.angleDeg,\n direction: seg.direction,\n rule: { ...rule, innerRadius: seg.radius },\n });\n segments.push({ kind: 'arc', dev, angleDeg: seg.angleDeg, direction: seg.direction, bendId });\n devTotal += dev;\n }\n }\n\n const feature: ContourFlangeFeature = {\n id: spec.id,\n side: spec.side,\n offset,\n span,\n developedLength: devTotal,\n segments,\n };\n\n return ok({\n ...part,\n solid: normalizeSolid(solid),\n bends: [...part.bends, ...bends],\n contourFlanges: [...(part.contourFlanges ?? []), feature],\n });\n}\n\n/**\n * Result of building one contour-flange segment: the fused solid and the next\n * segment's chained frame.\n */\nexport interface BuiltSegment {\n solid: Solid;\n frame: SegmentFrame;\n}\n\n/**\n * Result of building a cylindrical bend: {@link BuiltSegment} plus the world-space\n * origin of the bend axis.\n */\nexport interface BuiltArc extends BuiltSegment {\n axisOrigin: Vec3;\n}\n\n/**\n * Add one straight leg of `legLength` extending from `frame.origin` along\n * `frame.run`, full thickness along `frame.n`, across `span` along `frame.axis`.\n * The next segment's frame starts at the leg's far end.\n * @param base the solid the new leg is fused onto\n * @param frame the current segment frame the leg is built in\n * @param span the flange width along the bend axis\n * @param thickness the sheet thickness\n * @param legLength the straight-run length of the leg\n * @returns a `Result<BuiltSegment>` — `ok` with the fused solid and the next segment's\n * frame, or `err` when the boolean fuse fails\n */\nexport async function buildLineLeg(\n base: Solid,\n frame: SegmentFrame,\n span: number,\n thickness: number,\n legLength: number\n): Promise<Result<BuiltSegment>> {\n // Canonical box (legLength × span × thickness) at the origin, mapped onto the\n // current segment frame: +X→run, +Y→axis, +Z→n.\n try {\n const place = frameTransform(frame.run, frame.axis, frame.n, frame.origin);\n const canon = (await box({ width: legLength, depth: span, height: thickness })) as Solid;\n const placed = await place.solid(canon);\n const fused = (await fuse(base, placed)) as Solid;\n\n const nextOrigin = vecAdd(frame.origin, vecScale(frame.run, legLength));\n return ok({ solid: fused, frame: { ...frame, origin: nextOrigin } });\n } catch (e) {\n return err(kernelError('FUSE_FAILED', `contour line leg: ${e instanceof Error ? e.message : String(e)}`));\n }\n}\n\n/**\n * Add one cylindrical bend turning the running direction by `angleDeg`. Mirrors\n * {@link authorPart}'s bend patch: a hollow tube (outer R+T, inner R) intersected\n * with the fold wedge, in a canonical frame mapped onto the current segment frame.\n * The returned frame's run/normal are rotated by the fold so the next leg continues\n * tangentially.\n * @param base the solid the bend is fused onto\n * @param frame the current segment frame the bend turns from\n * @param span the flange width along the bend axis\n * @param thickness the sheet thickness\n * @param seg the arc profile segment: radius, angle and fold direction\n * @returns a `Result<BuiltArc>` — `ok` with the fused solid, the rotated next frame and the\n * world-space bend axis origin, or `err` with a `validationError` on invalid geometry\n */\nexport async function buildArcBend(\n base: Solid,\n frame: SegmentFrame,\n span: number,\n thickness: number,\n seg: Extract<ProfileSegment, { kind: 'arc' }>\n): Promise<Result<BuiltArc>> {\n const r = seg.radius;\n if (!Number.isFinite(r) || r < 0) {\n return err(validationError('INVALID_RADIUS', `contour arc radius must be non-negative, got ${r}`));\n }\n if (!Number.isFinite(seg.angleDeg) || seg.angleDeg <= 0 || seg.angleDeg > 180) {\n return err(validationError('INVALID_ARC_ANGLE', `contour arc angleDeg must be in (0, 180], got ${seg.angleDeg}`));\n }\n\n const sign = seg.direction === 'up' ? 1 : -1;\n // Canonical assembly (authorPart convention): bend axis +Y, run +X, top +Z, with\n // the bend-axis centre line at z = T+r (up) / −r (down). The current segment frame\n // maps +X→run, +Y→axis, +Z→n.\n const canonAxisZ = sign > 0 ? thickness + r : -r;\n const canonOrigin: Vec3 = [0, 0, canonAxisZ];\n const place = frameTransform(frame.run, frame.axis, frame.n, frame.origin);\n\n let fused: Solid;\n try {\n const patch = await buildBendPatch(canonOrigin, seg.angleDeg, r, span, thickness, seg.direction);\n if (!patch.ok) return patch;\n const placed = await place.solid(patch.value);\n fused = (await fuse(base, placed)) as Solid;\n } catch (e) {\n return err(kernelError('FUSE_FAILED', `contour arc bend: ${e instanceof Error ? e.message : String(e)}`));\n }\n\n // Fold run/normal by ∓θ about the axis (authorPart: rotate −sign·θ about +Y).\n const theta = (seg.angleDeg * Math.PI) / 180;\n const a = -sign * theta;\n const ca = Math.cos(a);\n const sa = Math.sin(a);\n // Canonical run +X folds to [ca, 0, −sa]; normal +Z to [sa, 0, ca].\n const runC: Vec3 = [ca, 0, -sa];\n const nC: Vec3 = [sa, 0, ca];\n // The post-bend exit point in canonical coords: the near-bottom corner [0,0,0]\n // rotated about the pivot [0,0,axisZ].\n const dz = -canonAxisZ;\n const cornerC: Vec3 = [dz * sa, 0, canonAxisZ + dz * ca];\n\n const nextOrigin = place.point(cornerC);\n const nextRun = place.vector(runC);\n const nextN = place.vector(nC);\n const axisOrigin = place.point(canonOrigin);\n\n return ok({\n solid: fused,\n frame: { origin: nextOrigin, run: nextRun, n: nextN, axis: frame.axis },\n axisOrigin,\n });\n}\n\ninterface PlacedTransform {\n solid: (s: Solid) => Promise<Solid>;\n point: (p: Vec3) => Vec3;\n vector: (v: Vec3) => Vec3;\n}\n\n/**\n * Rigid map of a canonical assembly (run +X, axis +Y, normal +Z, contact at the\n * origin) onto a world frame: align +X→`runT`, +Y→`axisT`, +Z→`nT`, then translate\n * the origin to `origin`.\n */\nfunction frameTransform(runT: Vec3, axisT: Vec3, nT: Vec3, origin: Vec3): PlacedTransform {\n const m: number[] = [\n runT[0], axisT[0], nT[0],\n runT[1], axisT[1], nT[1],\n runT[2], axisT[2], nT[2],\n ];\n const aa = matrixToAxisAngle(m);\n const applyR = (v: Vec3): Vec3 =>\n vecAdd(vecAdd(vecScale(runT, v[0]), vecScale(axisT, v[1])), vecScale(nT, v[2]));\n return {\n solid: async (s: Solid): Promise<Solid> => {\n const rotated = aa.angleDeg === 0 ? s : await rotate(s, aa.angleDeg, { at: [0, 0, 0], axis: aa.axis });\n return (await translate(rotated, origin)) as Solid;\n },\n point: (p: Vec3) => vecAdd(applyR(p), origin),\n vector: applyR,\n };\n}\n\n/**\n * One of the four straight edges of a flat region, resolved into the start line a\n * profile is chained from: edge direction, outward normal, start point and length.\n */\nexport interface BaseEdge {\n dir: Vec3;\n out: Vec3;\n start: Vec3;\n length: number;\n}\n\n/**\n * Resolve one of the four edges of the base flat (the contour-flange root).\n * @param part the sheet-metal part whose base flat edge is resolved\n * @param side which of the four base-flat edges to resolve (`'xmax'`/`'xmin'`/`'ymax'`/`'ymin'`)\n * @returns the resolved {@link BaseEdge} — edge direction, outward normal, start point and length\n */\nexport function baseEdge(part: SheetMetalPart, side: FlatSide): BaseEdge {\n const o: Vec3 = [0, 0, 0];\n const u: Vec3 = [1, 0, 0];\n const v: Vec3 = [0, 1, 0];\n const n: Vec3 = [0, 0, 1];\n const uLen = part.baseLength;\n const vLen = part.width;\n\n const uTop = vecAdd(o, vecScale(u, uLen));\n const vTop = vecAdd(o, vecScale(v, vLen));\n const uvTop = vecAdd(uTop, vecScale(v, vLen));\n\n let out: Vec3;\n let length: number;\n let a: Vec3;\n let b: Vec3;\n switch (side) {\n case 'xmax':\n out = u;\n length = vLen;\n a = uTop;\n b = uvTop;\n break;\n case 'xmin':\n out = vecScale(u, -1);\n length = vLen;\n a = o;\n b = vTop;\n break;\n case 'ymax':\n out = v;\n length = uLen;\n a = vTop;\n b = uvTop;\n break;\n case 'ymin':\n out = vecScale(v, -1);\n length = uLen;\n a = o;\n b = uTop;\n break;\n }\n const dir = vecNormalize(vecCross(n, out));\n const toB = vecSub(b, a);\n const start = vecDot(toB, dir) >= 0 ? a : b;\n return { dir, out, start, length };\n}\n\n/**\n * Resolve one of the four edges of an arbitrary flat region (its world top-surface\n * frame), the region-aware generalization of {@link baseEdge}: the base is the\n * special case where `origin = 0`, `u = +X`, `v = +Y`, `n = +Z`. Used by hems and\n * jogs to chain their profile off a named flange (or the base) edge.\n * @param frame the region's world top-surface frame (origin, u/v/n axes and extents)\n * @param side which of the four region edges to resolve\n * @returns the resolved {@link BaseEdge} — edge direction, outward normal, start point and length\n */\nexport function regionEdge(\n frame: { origin: Vec3; u: Vec3; v: Vec3; n: Vec3; uLen: number; vLen: number },\n side: FlatSide\n): BaseEdge {\n const o = frame.origin;\n const uTop = vecAdd(o, vecScale(frame.u, frame.uLen));\n const vTop = vecAdd(o, vecScale(frame.v, frame.vLen));\n const uvTop = vecAdd(uTop, vecScale(frame.v, frame.vLen));\n\n let out: Vec3;\n let length: number;\n let a: Vec3;\n let b: Vec3;\n switch (side) {\n case 'xmax':\n out = frame.u;\n length = frame.vLen;\n a = uTop;\n b = uvTop;\n break;\n case 'xmin':\n out = vecScale(frame.u, -1);\n length = frame.vLen;\n a = o;\n b = vTop;\n break;\n case 'ymax':\n out = frame.v;\n length = frame.uLen;\n a = vTop;\n b = uvTop;\n break;\n case 'ymin':\n out = vecScale(frame.v, -1);\n length = frame.uLen;\n a = o;\n b = uTop;\n break;\n }\n const dir = vecNormalize(vecCross(frame.n, out));\n const toB = vecSub(b, a);\n const start = vecDot(toB, dir) >= 0 ? a : b;\n return { dir, out, start, length };\n}\n\n/**\n * The starting {@link SegmentFrame} for a profile chained off `edge` at `offset`\n * along it: contact at the edge, run pointing outward, normal = the region normal,\n * bend axis along the edge. Shared by the contour-flange, hem and jog builders.\n * @param edge the resolved region edge the profile starts from\n * @param n the region normal, used as the frame's +Z\n * @param offset the start position along the edge, measured from `edge.start`\n * @returns the {@link SegmentFrame} with contact at the edge at `offset`, run pointing\n * outward and axis along the edge\n */\nexport function initialSegmentFrame(edge: BaseEdge, n: Vec3, offset: number): SegmentFrame {\n return {\n origin: vecAdd(edge.start, vecScale(edge.dir, offset)),\n run: edge.out,\n n,\n axis: edge.dir,\n };\n}\n\n/** Cylindrical bend patch (hollow tube ∩ fold wedge), mirroring authorFns. */\nasync function buildBendPatch(\n axisOrigin: Vec3,\n thetaDeg: number,\n r: number,\n width: number,\n thickness: number,\n direction: 'up' | 'down'\n): Promise<Result<ValidSolid>> {\n const outerR = r + thickness;\n try {\n const outer = await cylinder(outerR, width, { at: axisOrigin, axis: [0, 1, 0] });\n let tube: Solid = outer as Solid;\n if (r > 1e-9) {\n const inner = await cylinder(r, width, { at: axisOrigin, axis: [0, 1, 0] });\n tube = (await cut(outer, inner)) as Solid;\n }\n const wedge = await buildWedge(axisOrigin, thetaDeg, outerR, width, direction);\n if (!wedge.ok) return wedge;\n return ok((await intersect(tube, wedge.value)) as ValidSolid);\n } catch (e) {\n return err(kernelError('BEND_PATCH_FAILED', `contour bend patch: ${e instanceof Error ? e.message : String(e)}`));\n }\n}\n\nasync function buildWedge(\n axisOrigin: Vec3,\n thetaDeg: number,\n outerR: number,\n width: number,\n direction: 'up' | 'down'\n): Promise<Result<Solid>> {\n const span = outerR * 2 + 2;\n const margin = 1;\n try {\n const blockA = (await box({ width: span, depth: width + 2 * margin, height: 2 * span })) as Solid;\n const halfA: Solid = (await translate(blockA, [axisOrigin[0], axisOrigin[1] - margin, axisOrigin[2] - span])) as Solid;\n const sign = direction === 'up' ? 1 : -1;\n const halfB = await rotate(halfA, sign * (180 - thetaDeg), { at: axisOrigin, axis: [0, 1, 0] });\n return ok((await intersect(halfA, halfB)) as Solid);\n } catch (e) {\n return err(kernelError('WEDGE_FAILED', `contour wedge: ${e instanceof Error ? e.message : String(e)}`));\n }\n}\n\n/** Axis-angle of a 3×3 rotation matrix (row-major). */\nfunction matrixToAxisAngle(m: number[]): { axis: Vec3; angleDeg: number } {\n const m00 = m[0] ?? 0;\n const m01 = m[1] ?? 0;\n const m02 = m[2] ?? 0;\n const m10 = m[3] ?? 0;\n const m11 = m[4] ?? 0;\n const m12 = m[5] ?? 0;\n const m20 = m[6] ?? 0;\n const m21 = m[7] ?? 0;\n const m22 = m[8] ?? 0;\n\n const trace = m00 + m11 + m22;\n const cos = Math.max(-1, Math.min(1, (trace - 1) / 2));\n const angle = Math.acos(cos);\n const angleDeg = (angle * 180) / Math.PI;\n if (angle < 1e-9) return { axis: [0, 0, 1], angleDeg: 0 };\n\n if (Math.PI - angle < 1e-6) {\n const xx = (m00 + 1) / 2;\n const yy = (m11 + 1) / 2;\n const zz = (m22 + 1) / 2;\n let axis: Vec3;\n if (xx >= yy && xx >= zz) {\n const x = Math.sqrt(Math.max(xx, 0));\n axis = [x, (m01 + m10) / (4 * x), (m02 + m20) / (4 * x)];\n } else if (yy >= zz) {\n const y = Math.sqrt(Math.max(yy, 0));\n axis = [(m01 + m10) / (4 * y), y, (m12 + m21) / (4 * y)];\n } else {\n const z = Math.sqrt(Math.max(zz, 0));\n axis = [(m02 + m20) / (4 * z), (m12 + m21) / (4 * z), z];\n }\n return { axis: vecNormalize(axis), angleDeg: 180 };\n }\n\n const denom = 2 * Math.sin(angle);\n const axis: Vec3 = [(m21 - m12) / denom, (m02 - m20) / denom, (m10 - m01) / denom];\n return { axis: vecNormalize(axis), angleDeg };\n}\n"]}
|
package/dist/cutoutFns.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 { CutoutSpec, SheetMetalPart } from './types.js';
|
|
3
3
|
import { type FlatFrame } from './authorFns.js';
|
|
4
4
|
import { type Frame2 } from './unfoldFns.js';
|
|
@@ -17,7 +17,7 @@ type Pt2 = [number, number];
|
|
|
17
17
|
* @param spec - the cutout specification (kind, region, geometry).
|
|
18
18
|
* @returns the updated part with the cutout feature recorded, or an error.
|
|
19
19
|
*/
|
|
20
|
-
export declare function addCutout(part: SheetMetalPart, spec: CutoutSpec): Result<SheetMetalPart
|
|
20
|
+
export declare function addCutout(part: SheetMetalPart, spec: CutoutSpec): Promise<Result<SheetMetalPart>>;
|
|
21
21
|
/**
|
|
22
22
|
* Punch a circular hole of `diameter` centred at region-local `(x, y)`.
|
|
23
23
|
* @param part - the sheet metal part to cut.
|
|
@@ -27,7 +27,7 @@ export declare function addCutout(part: SheetMetalPart, spec: CutoutSpec): Resul
|
|
|
27
27
|
* @param diameter - the hole diameter.
|
|
28
28
|
* @returns the updated part with the hole feature recorded, or an error.
|
|
29
29
|
*/
|
|
30
|
-
export declare function addHole(part: SheetMetalPart, region: string, x: number, y: number, diameter: number): Result<SheetMetalPart
|
|
30
|
+
export declare function addHole(part: SheetMetalPart, region: string, x: number, y: number, diameter: number): Promise<Result<SheetMetalPart>>;
|
|
31
31
|
/**
|
|
32
32
|
* Punch a slot centred at `(x, y)`: `length` along the slot axis by `width` across.
|
|
33
33
|
* @param part - the sheet metal part to cut.
|
|
@@ -42,7 +42,7 @@ export declare function addSlot(part: SheetMetalPart, region: string, opts: {
|
|
|
42
42
|
width: number;
|
|
43
43
|
angleDeg?: number;
|
|
44
44
|
round?: boolean;
|
|
45
|
-
}): Result<SheetMetalPart
|
|
45
|
+
}): Promise<Result<SheetMetalPart>>;
|
|
46
46
|
/**
|
|
47
47
|
* Punch an arbitrary polygon cutout from its region-local `points` (≥ 3).
|
|
48
48
|
* @param part - the sheet metal part to cut.
|
|
@@ -50,7 +50,7 @@ export declare function addSlot(part: SheetMetalPart, region: string, opts: {
|
|
|
50
50
|
* @param points - the polygon vertices in region-local coordinates (≥ 3).
|
|
51
51
|
* @returns the updated part with the polygon cutout feature recorded, or an error.
|
|
52
52
|
*/
|
|
53
|
-
export declare function addPolygonCutout(part: SheetMetalPart, region: string, points: [number, number][]): Result<SheetMetalPart
|
|
53
|
+
export declare function addPolygonCutout(part: SheetMetalPart, region: string, points: [number, number][]): Promise<Result<SheetMetalPart>>;
|
|
54
54
|
/**
|
|
55
55
|
* `'base'` is an alias for the base region; everything else passes through.
|
|
56
56
|
* @param region - the region name to resolve.
|
package/dist/cutoutFns.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cutoutFns.d.ts","sourceRoot":"","sources":["../src/cutoutFns.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cutoutFns.d.ts","sourceRoot":"","sources":["../src/cutoutFns.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,KAAK,MAAM,EAA2I,MAAM,mBAAmB,CAAC;AACxL,OAAO,KAAK,EAAE,UAAU,EAAiB,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5E,OAAO,EAAe,KAAK,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,EAAc,KAAK,MAAM,EAAE,MAAM,gBAAgB,CAAC;AASzD,KAAK,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE5B;;;;;;;;;;;;;GAaG;AACH,wBAAsB,SAAS,CAAC,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAyDvG;AAED;;;;;;;;GAQG;AACH,wBAAsB,OAAO,CAC3B,IAAI,EAAE,cAAc,EACpB,MAAM,EAAE,MAAM,EACd,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAEjC;AAED;;;;;;GAMG;AACH,wBAAsB,OAAO,CAC3B,IAAI,EAAE,cAAc,EACpB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GAChG,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAEjC;AAED;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,cAAc,EACpB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,GACzB,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAEjC;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,cAAc,EACpB,MAAM,EAAE,MAAM,GACb,MAAM,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,SAAS,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,CAc7D;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,GAAG,MAAM,CAEhG;AAsED,qDAAqD;AACrD,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAkED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,MAAM,GAAG,GAAG,CAKlD"}
|