@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/hemFns.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hemFns.js","sourceRoot":"","sources":["../src/hemFns.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Result, type Solid, ok, err, validationError } from '@faicad/faijs/brepjs-compat';\nimport type {\n BendFeature,\n BendRule,\n HemFeature,\n HemSpec,\n SheetMetalPart,\n} from './types.js';\nimport { normalizeSolid } from './internal.js';\nimport { developedLength } from './allowanceFns.js';\nimport { worldFrames } from './authorFns.js';\nimport { ROOT_FLAT_ID } from './featureTreeFns.js';\nimport {\n type SegmentFrame,\n buildLineLeg,\n buildArcBend,\n regionEdge,\n initialSegmentFrame,\n} from './contourFlangeFns.js';\n\n/**\n * A small clearance baked into a CLOSED hem's curl radius. A true closed hem folds\n * the return flat against the parent with zero gap; modelling that exactly makes the\n * curl's inner cylinder coincide with the parent face, so the boolean fuse produces\n * a self-touching (non-manifold) solid. Inflating the inner radius by this HAIR\n * leaves a sub-thickness air gap that keeps the fused solid valid while still\n * reading as a closed hem. Documented so a reader understands the gap is intentional.\n */\nconst CLOSED_HEM_HAIR = 0.05;\n\n/** Sub-arc cap (deg): the bend-patch wedge degenerates at ≥180°, so curls split. */\nconst MAX_SUBARC_DEG = 120;\n\ninterface HemPlan {\n /** Total curl angle in degrees (≈180 for closed/open, >180 teardrop, ~270 rolled). */\n curlDeg: number;\n /** Inner bend radius used for the curl. */\n radius: number;\n /** Flat return-leg length past the curl (0 for rolled). */\n returnLength: number;\n}\n\n/**\n * Author a hem: fold a region edge back ~180°+ onto its parent flat, then run a\n * short return leg. Built on the contour-flange segment chainer — the curl is one\n * or more ≤120° sub-arcs (each a recorded `hem::<id>::<n>` bend) followed by a flat\n * return — so the development is EXACT: Σ curl bend allowances (via the table-aware\n * {@link developedLength}) + the return length, laid out straight past the edge.\n * Four `type`s set the curl/gap geometry (see {@link HemSpec}). Construction stays\n * on the public, OCCT-WASM-safe API; the result is guarded to a valid single solid.\n *\n * @param part - the sheet metal part to attach a hem to.\n * @param spec - the hem specification.\n * @returns the updated part with the hem feature recorded, or an error.\n */\nexport function hem(part: SheetMetalPart, spec: HemSpec): Result<SheetMetalPart> {\n if (part.solid === undefined) {\n return err(validationError('NO_SOLID', `part has no solid to attach hem '${hemId(spec)}'`));\n }\n const id = hemId(spec);\n if (id.includes('::')) {\n return err(validationError('INVALID_HEM_ID', `hem id must not contain '::', got '${id}'`));\n }\n for (const existing of part.hems ?? []) {\n if (existing.id === id) {\n return err(validationError('DUPLICATE_HEM', `duplicate hem id '${id}'`));\n }\n }\n\n const thickness = part.thickness;\n const planResult = planHem(spec, thickness);\n if (!planResult.ok) return planResult;\n const plan = planResult.value;\n\n const framesResult = worldFrames(part);\n if (!framesResult.ok) return framesResult;\n const regionId = resolveRegion(spec.region);\n const regionFrame = framesResult.value.get(regionId);\n if (regionFrame === undefined) {\n return err(validationError('UNKNOWN_REGION', `hem '${id}' references unknown region '${spec.region}'`));\n }\n\n const edge = regionEdge(regionFrame, 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', `hem '${id}' offset must be non-negative`));\n }\n if (!Number.isFinite(span) || span <= 0) {\n return err(validationError('INVALID_HEM_WIDTH', `hem '${id}' width must be positive`));\n }\n if (offset + span > edge.length + 1e-6) {\n return err(\n validationError('HEM_OUT_OF_BOUNDS', `hem '${id}' [${offset}, ${offset + span}] exceeds region edge length ${edge.length}`)\n );\n }\n\n const rule: BendRule = spec.rule ?? { innerRadius: plan.radius, kFactor: 0.44 };\n const subAngles = splitAngle(plan.curlDeg);\n\n // The curl is split into ≤120° sub-arcs only because the bend-patch wedge\n // degenerates at ≥180°; the DEVELOPMENT is one physical curl. Resolve the full\n // curl angle's allowance as a single table/formula query, then apportion it to\n // the sub-arcs by angle. Querying each sub-arc separately would over-count a\n // table sparse in angle (each sub-angle clamps up to the nearest tabulated row).\n const fullDevResult = developedLength(plan.curlDeg, thickness, { ...rule, innerRadius: plan.radius });\n if (!fullDevResult.ok) return fullDevResult;\n const devPerDeg = plan.curlDeg > 0 ? fullDevResult.value / plan.curlDeg : 0;\n\n let frame: SegmentFrame = initialSegmentFrame(edge, regionFrame.n, offset);\n let solid: Solid = part.solid;\n const bends: BendFeature[] = [];\n const segments: HemFeature['segments'] = [];\n const subBends: string[] = [];\n let devTotal = 0;\n\n for (let i = 0; i < subAngles.length; i += 1) {\n const subDeg = subAngles[i];\n if (subDeg === undefined) continue;\n const built = buildArcBend(solid, frame, span, thickness, {\n kind: 'arc',\n radius: plan.radius,\n angleDeg: subDeg,\n direction: 'up',\n });\n if (!built.ok) return built;\n solid = built.value.solid;\n frame = built.value.frame;\n\n const dev = devPerDeg * subDeg;\n\n const bendId = `hem::${id}::${i}`;\n subBends.push(bendId);\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: subDeg,\n direction: 'up',\n rule: { ...rule, innerRadius: plan.radius },\n });\n segments.push({ kind: 'arc', dev, angleDeg: subDeg, direction: 'up', bendId });\n devTotal += dev;\n }\n\n if (plan.returnLength > 0) {\n const built = buildLineLeg(solid, frame, span, thickness, plan.returnLength);\n if (!built.ok) return built;\n solid = built.value.solid;\n segments.push({ kind: 'line', dev: plan.returnLength });\n devTotal += plan.returnLength;\n }\n\n const feature: HemFeature = {\n id,\n type: spec.type,\n region: regionId,\n side: spec.side,\n offset,\n span,\n returnLength: plan.returnLength,\n developedLength: devTotal,\n subBends,\n segments,\n };\n\n return ok({\n ...part,\n solid: normalizeSolid(solid),\n bends: [...part.bends, ...bends],\n hems: [...(part.hems ?? []), feature],\n });\n}\n\n/** The hem's id: an explicit `spec.id`, else a deterministic region/side/type key. */\nfunction hemId(spec: HemSpec): string {\n return spec.id ?? `hem-${spec.region}-${spec.side}-${spec.type}`;\n}\n\nfunction resolveRegion(region: string): string {\n return region === 'base' || region === 'face-0' ? ROOT_FLAT_ID : region;\n}\n\n/**\n * Resolve a {@link HemSpec} into its curl angle, radius and return length. The\n * radius defaults to one thickness (the tightest practical hem). A closed hem\n * inflates the radius by {@link CLOSED_HEM_HAIR} so the fused solid stays valid;\n * an open hem widens the radius to span the requested gap; teardrop/rolled set a\n * larger curl angle.\n */\nfunction planHem(spec: HemSpec, thickness: number): Result<HemPlan> {\n if (!Number.isFinite(thickness) || thickness <= 0) {\n return err(validationError('INVALID_THICKNESS', `hem thickness must be positive, got ${thickness}`));\n }\n if (spec.radius !== undefined && (!Number.isFinite(spec.radius) || spec.radius < 0)) {\n return err(validationError('INVALID_HEM_RADIUS', `hem radius must be non-negative, got ${spec.radius}`));\n }\n // Inner-radius default differs by type: a closed hem folds essentially flat\n // (radius ≈ 0, just the HAIR clearance) so it is actually closed; teardrop/rolled\n // default to one thickness. Open derives its radius from the requested gap below.\n const baseRadius = spec.radius ?? thickness;\n\n switch (spec.type) {\n case 'closed': {\n const returnLength = spec.length ?? 0;\n if (!Number.isFinite(returnLength) || returnLength <= 0) {\n return err(\n validationError('INVALID_HEM_LENGTH', `closed hem requires a positive return length, got ${spec.length}`)\n );\n }\n if (returnLength < thickness) {\n return err(\n validationError('HEM_LENGTH_TOO_SHORT', `closed hem return length ${returnLength} must be ≥ thickness ${thickness}`)\n );\n }\n // Default to a tight (≈0) radius so the return folds flat against the parent\n // (an actually-closed hem); the HAIR keeps the coincident-face fuse valid.\n return ok({ curlDeg: 180, radius: (spec.radius ?? 0) + CLOSED_HEM_HAIR, returnLength });\n }\n case 'open': {\n const returnLength = spec.length ?? 0;\n if (!Number.isFinite(returnLength) || returnLength <= 0) {\n return err(\n validationError('INVALID_HEM_LENGTH', `open hem requires a positive return length, got ${spec.length}`)\n );\n }\n // `gap` is the physical clear distance between the return and the parent. A\n // 180° fold at inner radius r lands the return 2r away, so the radius is gap/2.\n const gap = spec.gap ?? thickness;\n if (!Number.isFinite(gap) || gap <= 0) {\n return err(validationError('INVALID_HEM_GAP', `open hem gap must be positive, got ${gap}`));\n }\n return ok({ curlDeg: 180, radius: gap / 2, returnLength });\n }\n case 'teardrop': {\n const returnLength = spec.length ?? 0;\n if (!Number.isFinite(returnLength) || returnLength <= 0) {\n return err(\n validationError('INVALID_HEM_LENGTH', `teardrop hem requires a positive return length, got ${spec.length}`)\n );\n }\n return ok({ curlDeg: 210, radius: baseRadius, returnLength });\n }\n case 'rolled':\n // A full circular roll (curled / safe edge): no flat return.\n return ok({ curlDeg: 270, radius: baseRadius, returnLength: 0 });\n default:\n return spec.type satisfies never;\n }\n}\n\n/** Split a curl angle into ≤{@link MAX_SUBARC_DEG} equal sub-arcs (the wedge cap). */\nfunction splitAngle(totalDeg: number): number[] {\n const n = Math.max(1, Math.ceil(totalDeg / MAX_SUBARC_DEG));\n const per = totalDeg / n;\n return Array.from({ length: n }, () => per);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"hemFns.js","sourceRoot":"","sources":["../src/hemFns.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Solid } from './types.js';\nimport {type Result, ok, err, validationError} from '@faicad/faijs/api';\nimport type {\n BendFeature,\n BendRule,\n HemFeature,\n HemSpec,\n SheetMetalPart,\n} from './types.js';\nimport { normalizeSolid } from './internal.js';\nimport { developedLength } from './allowanceFns.js';\nimport { worldFrames } from './authorFns.js';\nimport { ROOT_FLAT_ID } from './featureTreeFns.js';\nimport {\n type SegmentFrame,\n buildLineLeg,\n buildArcBend,\n regionEdge,\n initialSegmentFrame,\n} from './contourFlangeFns.js';\n\n/**\n * A small clearance baked into a CLOSED hem's curl radius. A true closed hem folds\n * the return flat against the parent with zero gap; modelling that exactly makes the\n * curl's inner cylinder coincide with the parent face, so the boolean fuse produces\n * a self-touching (non-manifold) solid. Inflating the inner radius by this HAIR\n * leaves a sub-thickness air gap that keeps the fused solid valid while still\n * reading as a closed hem. Documented so a reader understands the gap is intentional.\n */\nconst CLOSED_HEM_HAIR = 0.05;\n\n/** Sub-arc cap (deg): the bend-patch wedge degenerates at ≥180°, so curls split. */\nconst MAX_SUBARC_DEG = 120;\n\ninterface HemPlan {\n /** Total curl angle in degrees (≈180 for closed/open, >180 teardrop, ~270 rolled). */\n curlDeg: number;\n /** Inner bend radius used for the curl. */\n radius: number;\n /** Flat return-leg length past the curl (0 for rolled). */\n returnLength: number;\n}\n\n/**\n * Author a hem: fold a region edge back ~180°+ onto its parent flat, then run a\n * short return leg. Built on the contour-flange segment chainer — the curl is one\n * or more ≤120° sub-arcs (each a recorded `hem::<id>::<n>` bend) followed by a flat\n * return — so the development is EXACT: Σ curl bend allowances (via the table-aware\n * {@link developedLength}) + the return length, laid out straight past the edge.\n * Four `type`s set the curl/gap geometry (see {@link HemSpec}). Construction stays\n * on the public, OCCT-WASM-safe API; the result is guarded to a valid single solid.\n *\n * @param part - the sheet metal part to attach a hem to.\n * @param spec - the hem specification.\n * @returns the updated part with the hem feature recorded, or an error.\n */\nexport async function hem(part: SheetMetalPart, spec: HemSpec): Promise<Result<SheetMetalPart>> {\n if (part.solid === undefined) {\n return err(validationError('NO_SOLID', `part has no solid to attach hem '${hemId(spec)}'`));\n }\n const id = hemId(spec);\n if (id.includes('::')) {\n return err(validationError('INVALID_HEM_ID', `hem id must not contain '::', got '${id}'`));\n }\n for (const existing of part.hems ?? []) {\n if (existing.id === id) {\n return err(validationError('DUPLICATE_HEM', `duplicate hem id '${id}'`));\n }\n }\n\n const thickness = part.thickness;\n const planResult = planHem(spec, thickness);\n if (!planResult.ok) return planResult;\n const plan = planResult.value;\n\n const framesResult = worldFrames(part);\n if (!framesResult.ok) return framesResult;\n const regionId = resolveRegion(spec.region);\n const regionFrame = framesResult.value.get(regionId);\n if (regionFrame === undefined) {\n return err(validationError('UNKNOWN_REGION', `hem '${id}' references unknown region '${spec.region}'`));\n }\n\n const edge = regionEdge(regionFrame, 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', `hem '${id}' offset must be non-negative`));\n }\n if (!Number.isFinite(span) || span <= 0) {\n return err(validationError('INVALID_HEM_WIDTH', `hem '${id}' width must be positive`));\n }\n if (offset + span > edge.length + 1e-6) {\n return err(\n validationError('HEM_OUT_OF_BOUNDS', `hem '${id}' [${offset}, ${offset + span}] exceeds region edge length ${edge.length}`)\n );\n }\n\n const rule: BendRule = spec.rule ?? { innerRadius: plan.radius, kFactor: 0.44 };\n const subAngles = splitAngle(plan.curlDeg);\n\n // The curl is split into ≤120° sub-arcs only because the bend-patch wedge\n // degenerates at ≥180°; the DEVELOPMENT is one physical curl. Resolve the full\n // curl angle's allowance as a single table/formula query, then apportion it to\n // the sub-arcs by angle. Querying each sub-arc separately would over-count a\n // table sparse in angle (each sub-angle clamps up to the nearest tabulated row).\n const fullDevResult = developedLength(plan.curlDeg, thickness, { ...rule, innerRadius: plan.radius });\n if (!fullDevResult.ok) return fullDevResult;\n const devPerDeg = plan.curlDeg > 0 ? fullDevResult.value / plan.curlDeg : 0;\n\n let frame: SegmentFrame = initialSegmentFrame(edge, regionFrame.n, offset);\n let solid: Solid = part.solid;\n const bends: BendFeature[] = [];\n const segments: HemFeature['segments'] = [];\n const subBends: string[] = [];\n let devTotal = 0;\n\n for (let i = 0; i < subAngles.length; i += 1) {\n const subDeg = subAngles[i];\n if (subDeg === undefined) continue;\n const built = await buildArcBend(solid, frame, span, thickness, {\n kind: 'arc',\n radius: plan.radius,\n angleDeg: subDeg,\n direction: 'up',\n });\n if (!built.ok) return built;\n solid = built.value.solid;\n frame = built.value.frame;\n\n const dev = devPerDeg * subDeg;\n\n const bendId = `hem::${id}::${i}`;\n subBends.push(bendId);\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: subDeg,\n direction: 'up',\n rule: { ...rule, innerRadius: plan.radius },\n });\n segments.push({ kind: 'arc', dev, angleDeg: subDeg, direction: 'up', bendId });\n devTotal += dev;\n }\n\n if (plan.returnLength > 0) {\n const built = await buildLineLeg(solid, frame, span, thickness, plan.returnLength);\n if (!built.ok) return built;\n solid = built.value.solid;\n segments.push({ kind: 'line', dev: plan.returnLength });\n devTotal += plan.returnLength;\n }\n\n const feature: HemFeature = {\n id,\n type: spec.type,\n region: regionId,\n side: spec.side,\n offset,\n span,\n returnLength: plan.returnLength,\n developedLength: devTotal,\n subBends,\n segments,\n };\n\n return ok({\n ...part,\n solid: normalizeSolid(solid),\n bends: [...part.bends, ...bends],\n hems: [...(part.hems ?? []), feature],\n });\n}\n\n/** The hem's id: an explicit `spec.id`, else a deterministic region/side/type key. */\nfunction hemId(spec: HemSpec): string {\n return spec.id ?? `hem-${spec.region}-${spec.side}-${spec.type}`;\n}\n\nfunction resolveRegion(region: string): string {\n return region === 'base' || region === 'face-0' ? ROOT_FLAT_ID : region;\n}\n\n/**\n * Resolve a {@link HemSpec} into its curl angle, radius and return length. The\n * radius defaults to one thickness (the tightest practical hem). A closed hem\n * inflates the radius by {@link CLOSED_HEM_HAIR} so the fused solid stays valid;\n * an open hem widens the radius to span the requested gap; teardrop/rolled set a\n * larger curl angle.\n */\nfunction planHem(spec: HemSpec, thickness: number): Result<HemPlan> {\n if (!Number.isFinite(thickness) || thickness <= 0) {\n return err(validationError('INVALID_THICKNESS', `hem thickness must be positive, got ${thickness}`));\n }\n if (spec.radius !== undefined && (!Number.isFinite(spec.radius) || spec.radius < 0)) {\n return err(validationError('INVALID_HEM_RADIUS', `hem radius must be non-negative, got ${spec.radius}`));\n }\n // Inner-radius default differs by type: a closed hem folds essentially flat\n // (radius ≈ 0, just the HAIR clearance) so it is actually closed; teardrop/rolled\n // default to one thickness. Open derives its radius from the requested gap below.\n const baseRadius = spec.radius ?? thickness;\n\n switch (spec.type) {\n case 'closed': {\n const returnLength = spec.length ?? 0;\n if (!Number.isFinite(returnLength) || returnLength <= 0) {\n return err(\n validationError('INVALID_HEM_LENGTH', `closed hem requires a positive return length, got ${spec.length}`)\n );\n }\n if (returnLength < thickness) {\n return err(\n validationError('HEM_LENGTH_TOO_SHORT', `closed hem return length ${returnLength} must be ≥ thickness ${thickness}`)\n );\n }\n // Default to a tight (≈0) radius so the return folds flat against the parent\n // (an actually-closed hem); the HAIR keeps the coincident-face fuse valid.\n return ok({ curlDeg: 180, radius: (spec.radius ?? 0) + CLOSED_HEM_HAIR, returnLength });\n }\n case 'open': {\n const returnLength = spec.length ?? 0;\n if (!Number.isFinite(returnLength) || returnLength <= 0) {\n return err(\n validationError('INVALID_HEM_LENGTH', `open hem requires a positive return length, got ${spec.length}`)\n );\n }\n // `gap` is the physical clear distance between the return and the parent. A\n // 180° fold at inner radius r lands the return 2r away, so the radius is gap/2.\n const gap = spec.gap ?? thickness;\n if (!Number.isFinite(gap) || gap <= 0) {\n return err(validationError('INVALID_HEM_GAP', `open hem gap must be positive, got ${gap}`));\n }\n return ok({ curlDeg: 180, radius: gap / 2, returnLength });\n }\n case 'teardrop': {\n const returnLength = spec.length ?? 0;\n if (!Number.isFinite(returnLength) || returnLength <= 0) {\n return err(\n validationError('INVALID_HEM_LENGTH', `teardrop hem requires a positive return length, got ${spec.length}`)\n );\n }\n return ok({ curlDeg: 210, radius: baseRadius, returnLength });\n }\n case 'rolled':\n // A full circular roll (curled / safe edge): no flat return.\n return ok({ curlDeg: 270, radius: baseRadius, returnLength: 0 });\n default:\n return spec.type satisfies never;\n }\n}\n\n/** Split a curl angle into ≤{@link MAX_SUBARC_DEG} equal sub-arcs (the wedge cap). */\nfunction splitAngle(totalDeg: number): number[] {\n const n = Math.max(1, Math.ceil(totalDeg / MAX_SUBARC_DEG));\n const per = totalDeg / n;\n return Array.from({ length: n }, () => per);\n}\n"]}
|
package/dist/internal.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { Solid } from './types.js';
|
|
2
|
+
import { type Vec3 } from '@faicad/faijs/api';
|
|
2
3
|
import type { FlatSide } from './types.js';
|
|
3
4
|
/**
|
|
4
5
|
* OCCT boolean fuse returns a compound wrapping the unioned solid. Extract the
|
package/dist/internal.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,
|
|
1
|
+
{"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAC,KAAK,IAAI,EAAqB,MAAM,mBAAmB,CAAC;AAChE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,CAKlD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,IAAI,GAAG,QAAQ,GAAG,SAAS,CAInE"}
|
package/dist/internal.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isSolid, getSolids } from '@faicad/faijs/
|
|
1
|
+
import { isSolid, getSolids } from '@faicad/faijs/api';
|
|
2
2
|
/**
|
|
3
3
|
* OCCT boolean fuse returns a compound wrapping the unioned solid. Extract the
|
|
4
4
|
* single solid so a part's cached shape is a true `Solid` (clean STEP/GLB
|
package/dist/internal.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"internal.js","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"internal.js","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AACA,OAAO,EAAY,OAAO,EAAE,SAAS,EAAC,MAAM,mBAAmB,CAAC;AAGhE;;;;;;;;;GASG;AACH,MAAM,UAAU,cAAc,CAAC,KAAY;IACzC,IAAI,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACjC,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;IAChC,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACzD,OAAO,IAAI,IAAI,KAAK,CAAC;AACvB,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,eAAe,CAAC,OAAa;IAC3C,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG;QAAE,OAAO,MAAM,CAAC;IAC9C,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG;QAAE,OAAO,MAAM,CAAC;IAC9C,OAAO,SAAS,CAAC;AACnB,CAAC","sourcesContent":["import type { Solid } from './types.js';\nimport {type Vec3, isSolid, getSolids} from '@faicad/faijs/api';\nimport type { FlatSide } from './types.js';\n\n/**\n * OCCT boolean fuse returns a compound wrapping the unioned solid. Extract the\n * single solid so a part's cached shape is a true `Solid` (clean STEP/GLB\n * export); fall back to the compound if the union produced multiple bodies.\n *\n * @param shape - The shape returned by the fuse boolean operation (a `Solid` or\n * a compound wrapping one).\n * @returns The single `Solid` when the compound wraps exactly one solid,\n * otherwise the input `shape` unchanged.\n */\nexport function normalizeSolid(shape: Solid): Solid {\n if (isSolid(shape)) return shape;\n const solids = getSolids(shape);\n const only = solids.length === 1 ? solids[0] : undefined;\n return only ?? shape;\n}\n\n/**\n * Fallback develop side for a hand-built flange whose `baseEdge.side` is omitted:\n * derive it from the recorded bend axis. An axis along +Y (|axisDir.y|>0.5) is an\n * east flange that develops in +X (`xmax`); an axis along +X is a north flange\n * developing in +Y (`ymax`). This preserves the original axis-only unfold\n * heuristic for external fixtures predating the explicit `side` field; parts from\n * {@link authorPart} always set `side`, so this only kicks in for the legacy path.\n *\n * @param axisDir - The recorded bend axis as a `Vec3`.\n * @returns The develop side (`'xmax'` for a +Y axis, `'ymax'` for a +X axis),\n * or `undefined` when the axis does not point along +Y or +X.\n */\nexport function sideFromAxisDir(axisDir: Vec3): FlatSide | undefined {\n if (Math.abs(axisDir[1]) > 0.5) return 'xmax';\n if (Math.abs(axisDir[0]) > 0.5) return 'ymax';\n return undefined;\n}\n"]}
|
package/dist/jogFns.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 { JogSpec, SheetMetalPart } from './types.js';
|
|
3
3
|
/**
|
|
4
4
|
* Author a jog (joggle): two opposite bends (`+θ` then `−θ`) that step a flat by
|
|
@@ -14,5 +14,5 @@ import type { JogSpec, SheetMetalPart } from './types.js';
|
|
|
14
14
|
* @param spec - the jog specification.
|
|
15
15
|
* @returns the updated part with the jog feature recorded, or an error.
|
|
16
16
|
*/
|
|
17
|
-
export declare function jog(part: SheetMetalPart, spec: JogSpec): Result<SheetMetalPart
|
|
17
|
+
export declare function jog(part: SheetMetalPart, spec: JogSpec): Promise<Result<SheetMetalPart>>;
|
|
18
18
|
//# sourceMappingURL=jogFns.d.ts.map
|
package/dist/jogFns.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jogFns.d.ts","sourceRoot":"","sources":["../src/jogFns.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"jogFns.d.ts","sourceRoot":"","sources":["../src/jogFns.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,KAAK,MAAM,EAA2B,MAAM,mBAAmB,CAAC;AACxE,OAAO,KAAK,EAIV,OAAO,EACP,cAAc,EACf,MAAM,YAAY,CAAC;AAapB;;;;;;;;;;;;;GAaG;AACH,wBAAsB,GAAG,CAAC,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAqK9F"}
|
package/dist/jogFns.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ok, err, validationError } from '@faicad/faijs/
|
|
1
|
+
import { ok, err, validationError } from '@faicad/faijs/api';
|
|
2
2
|
import { normalizeSolid } from './internal.js';
|
|
3
3
|
import { developedLength } from './allowanceFns.js';
|
|
4
4
|
import { worldFrames } from './authorFns.js';
|
|
@@ -18,7 +18,7 @@ import { buildLineLeg, buildArcBend, regionEdge, initialSegmentFrame, } from './
|
|
|
18
18
|
* @param spec - the jog specification.
|
|
19
19
|
* @returns the updated part with the jog feature recorded, or an error.
|
|
20
20
|
*/
|
|
21
|
-
export function jog(part, spec) {
|
|
21
|
+
export async function jog(part, spec) {
|
|
22
22
|
if (part.solid === undefined) {
|
|
23
23
|
return err(validationError('NO_SOLID', `part has no solid to attach jog '${jogId(spec)}'`));
|
|
24
24
|
}
|
|
@@ -90,7 +90,7 @@ export function jog(part, spec) {
|
|
|
90
90
|
let devTotal = 0;
|
|
91
91
|
// 1) Flat position leg out to the first bend.
|
|
92
92
|
{
|
|
93
|
-
const built = buildLineLeg(solid, frame, span, thickness, spec.position);
|
|
93
|
+
const built = await buildLineLeg(solid, frame, span, thickness, spec.position);
|
|
94
94
|
if (!built.ok)
|
|
95
95
|
return built;
|
|
96
96
|
solid = built.value.solid;
|
|
@@ -107,7 +107,7 @@ export function jog(part, spec) {
|
|
|
107
107
|
const o = order[i];
|
|
108
108
|
if (o === undefined)
|
|
109
109
|
continue;
|
|
110
|
-
const built = buildArcBend(solid, frame, span, thickness, {
|
|
110
|
+
const built = await buildArcBend(solid, frame, span, thickness, {
|
|
111
111
|
kind: 'arc',
|
|
112
112
|
radius,
|
|
113
113
|
angleDeg,
|
|
@@ -134,7 +134,7 @@ export function jog(part, spec) {
|
|
|
134
134
|
segments.push({ kind: 'arc', dev, angleDeg, direction: o.dir, bendId });
|
|
135
135
|
devTotal += dev;
|
|
136
136
|
if (o.step !== undefined) {
|
|
137
|
-
const stepBuilt = buildLineLeg(solid, frame, span, thickness, o.step);
|
|
137
|
+
const stepBuilt = await buildLineLeg(solid, frame, span, thickness, o.step);
|
|
138
138
|
if (!stepBuilt.ok)
|
|
139
139
|
return stepBuilt;
|
|
140
140
|
solid = stepBuilt.value.solid;
|
|
@@ -145,7 +145,7 @@ export function jog(part, spec) {
|
|
|
145
145
|
}
|
|
146
146
|
// 5) Flat run-out leg, parallel to the original plane, offset by offsetHeight.
|
|
147
147
|
{
|
|
148
|
-
const built = buildLineLeg(solid, frame, span, thickness, runOut);
|
|
148
|
+
const built = await buildLineLeg(solid, frame, span, thickness, runOut);
|
|
149
149
|
if (!built.ok)
|
|
150
150
|
return built;
|
|
151
151
|
solid = built.value.solid;
|
package/dist/jogFns.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jogFns.js","sourceRoot":"","sources":["../src/jogFns.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Result, type Solid, ok, err, validationError } from '@faicad/faijs/brepjs-compat';\nimport type {\n BendFeature,\n BendRule,\n JogFeature,\n JogSpec,\n SheetMetalPart,\n} from './types.js';\nimport { normalizeSolid } from './internal.js';\nimport { developedLength } from './allowanceFns.js';\nimport { worldFrames } from './authorFns.js';\nimport { ROOT_FLAT_ID } from './featureTreeFns.js';\nimport {\n type SegmentFrame,\n buildLineLeg,\n buildArcBend,\n regionEdge,\n initialSegmentFrame,\n} from './contourFlangeFns.js';\n\n/**\n * Author a jog (joggle): two opposite bends (`+θ` then `−θ`) that step a flat by\n * `offsetHeight` perpendicular to its plane, then continue parallel past the step.\n * Built on the contour-flange chainer: a flat position leg, a `+θ` up bend\n * (`jog::<id>::0`), the connecting step run, a `−θ` down bend (`jog::<id>::1`), and\n * a flat run-out leg. The development is EXACT (Σ legs + Σ bend allowances, via the\n * table-aware {@link developedLength}). The connecting step run is\n * `offsetHeight / sin(θ)` so the two bends realize the requested perpendicular step;\n * the result is guarded to a valid single solid. OCCT-WASM-safe construction only.\n *\n * @param part - the sheet metal part to attach a jog to.\n * @param spec - the jog specification.\n * @returns the updated part with the jog feature recorded, or an error.\n */\nexport function jog(part: SheetMetalPart, spec: JogSpec): Result<SheetMetalPart> {\n if (part.solid === undefined) {\n return err(validationError('NO_SOLID', `part has no solid to attach jog '${jogId(spec)}'`));\n }\n const id = jogId(spec);\n if (id.includes('::')) {\n return err(validationError('INVALID_JOG_ID', `jog id must not contain '::', got '${id}'`));\n }\n for (const existing of part.jogs ?? []) {\n if (existing.id === id) {\n return err(validationError('DUPLICATE_JOG', `duplicate jog id '${id}'`));\n }\n }\n\n const thickness = part.thickness;\n if (!Number.isFinite(spec.offsetHeight) || spec.offsetHeight <= 0) {\n return err(validationError('INVALID_JOG_OFFSET', `jog offsetHeight must be positive, got ${spec.offsetHeight}`));\n }\n if (!Number.isFinite(spec.position) || spec.position <= 0) {\n return err(validationError('INVALID_JOG_POSITION', `jog position must be positive, got ${spec.position}`));\n }\n const angleDeg = spec.angle ?? 45;\n if (!Number.isFinite(angleDeg) || angleDeg <= 0 || angleDeg >= 90) {\n return err(validationError('INVALID_JOG_ANGLE', `jog angle must be in (0, 90), got ${angleDeg}`));\n }\n const radius = spec.radius ?? thickness;\n if (!Number.isFinite(radius) || radius <= 0) {\n return err(validationError('INVALID_JOG_RADIUS', `jog radius must be positive, got ${radius}`));\n }\n const runOut = spec.runOut ?? spec.position;\n if (!Number.isFinite(runOut) || runOut <= 0) {\n return err(validationError('INVALID_JOG_RUNOUT', `jog runOut must be positive, got ${runOut}`));\n }\n\n const framesResult = worldFrames(part);\n if (!framesResult.ok) return framesResult;\n const regionId = resolveRegion(spec.region);\n const regionFrame = framesResult.value.get(regionId);\n if (regionFrame === undefined) {\n return err(validationError('UNKNOWN_REGION', `jog '${id}' references unknown region '${spec.region}'`));\n }\n\n const edge = regionEdge(regionFrame, 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', `jog '${id}' offset must be non-negative`));\n }\n if (!Number.isFinite(span) || span <= 0) {\n return err(validationError('INVALID_JOG_WIDTH', `jog '${id}' width must be positive`));\n }\n if (offset + span > edge.length + 1e-6) {\n return err(\n validationError('JOG_OUT_OF_BOUNDS', `jog '${id}' [${offset}, ${offset + span}] exceeds region edge length ${edge.length}`)\n );\n }\n\n const rule: BendRule = spec.rule ?? { innerRadius: radius, kFactor: 0.44 };\n // The connecting step run carries the flat across the offset at angle θ. The two\n // arcs themselves each rise (T+2r)/2·(1−cosθ) perpendicular to the plane (the\n // up-bend rises (T+r)(1−cosθ), the down-bend r(1−cosθ)); the step run adds\n // L·sinθ. Solving for the total perpendicular rise = offsetHeight gives this L, so\n // the run-out bottom face sits exactly offsetHeight above the base bottom face.\n const theta = (angleDeg * Math.PI) / 180;\n const arcRise = (thickness + 2 * radius) * (1 - Math.cos(theta));\n const stepRun = (spec.offsetHeight - arcRise) / Math.sin(theta);\n if (!(stepRun > 0)) {\n return err(\n validationError(\n 'JOG_OFFSET_TOO_SMALL',\n `jog offsetHeight ${spec.offsetHeight} is too small for radius ${radius} at ${angleDeg}° (the bends alone rise ${arcRise.toFixed(3)}); increase offsetHeight or reduce radius/angle`\n )\n );\n }\n\n let frame: SegmentFrame = initialSegmentFrame(edge, regionFrame.n, offset);\n let solid: Solid = part.solid;\n const bends: BendFeature[] = [];\n const segments: JogFeature['segments'] = [];\n const bendIds: string[] = [];\n let devTotal = 0;\n\n // 1) Flat position leg out to the first bend.\n {\n const built = buildLineLeg(solid, frame, span, thickness, spec.position);\n if (!built.ok) return built;\n solid = built.value.solid;\n frame = built.value.frame;\n segments.push({ kind: 'line', dev: spec.position });\n devTotal += spec.position;\n }\n\n // 2) Up bend (+θ), 3) step run, 4) down bend (−θ): the two opposite bends.\n const order: { dir: 'up' | 'down'; step?: number }[] = [\n { dir: 'up', step: stepRun },\n { dir: 'down' },\n ];\n for (let i = 0; i < order.length; i += 1) {\n const o = order[i];\n if (o === undefined) continue;\n const built = buildArcBend(solid, frame, span, thickness, {\n kind: 'arc',\n radius,\n angleDeg,\n direction: o.dir,\n });\n if (!built.ok) return built;\n solid = built.value.solid;\n frame = built.value.frame;\n\n const devResult = developedLength(angleDeg, thickness, { ...rule, innerRadius: radius });\n if (!devResult.ok) return devResult;\n const dev = devResult.value;\n\n const bendId = `jog::${id}::${i}`;\n bendIds.push(bendId);\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,\n direction: o.dir,\n rule: { ...rule, innerRadius: radius },\n });\n segments.push({ kind: 'arc', dev, angleDeg, direction: o.dir, bendId });\n devTotal += dev;\n\n if (o.step !== undefined) {\n const stepBuilt = buildLineLeg(solid, frame, span, thickness, o.step);\n if (!stepBuilt.ok) return stepBuilt;\n solid = stepBuilt.value.solid;\n frame = stepBuilt.value.frame;\n segments.push({ kind: 'line', dev: o.step });\n devTotal += o.step;\n }\n }\n\n // 5) Flat run-out leg, parallel to the original plane, offset by offsetHeight.\n {\n const built = buildLineLeg(solid, frame, span, thickness, runOut);\n if (!built.ok) return built;\n solid = built.value.solid;\n segments.push({ kind: 'line', dev: runOut });\n devTotal += runOut;\n }\n\n const feature: JogFeature = {\n id,\n region: regionId,\n side: spec.side,\n offset,\n span,\n offsetHeight: spec.offsetHeight,\n angleDeg,\n developedLength: devTotal,\n bends: bendIds,\n segments,\n };\n\n return ok({\n ...part,\n solid: normalizeSolid(solid),\n bends: [...part.bends, ...bends],\n jogs: [...(part.jogs ?? []), feature],\n });\n}\n\nfunction jogId(spec: JogSpec): string {\n return spec.id ?? `jog-${spec.region}-${spec.side}`;\n}\n\nfunction resolveRegion(region: string): string {\n return region === 'base' || region === 'face-0' ? ROOT_FLAT_ID : region;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"jogFns.js","sourceRoot":"","sources":["../src/jogFns.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Solid } from './types.js';\nimport {type Result, ok, err, validationError} from '@faicad/faijs/api';\nimport type {\n BendFeature,\n BendRule,\n JogFeature,\n JogSpec,\n SheetMetalPart,\n} from './types.js';\nimport { normalizeSolid } from './internal.js';\nimport { developedLength } from './allowanceFns.js';\nimport { worldFrames } from './authorFns.js';\nimport { ROOT_FLAT_ID } from './featureTreeFns.js';\nimport {\n type SegmentFrame,\n buildLineLeg,\n buildArcBend,\n regionEdge,\n initialSegmentFrame,\n} from './contourFlangeFns.js';\n\n/**\n * Author a jog (joggle): two opposite bends (`+θ` then `−θ`) that step a flat by\n * `offsetHeight` perpendicular to its plane, then continue parallel past the step.\n * Built on the contour-flange chainer: a flat position leg, a `+θ` up bend\n * (`jog::<id>::0`), the connecting step run, a `−θ` down bend (`jog::<id>::1`), and\n * a flat run-out leg. The development is EXACT (Σ legs + Σ bend allowances, via the\n * table-aware {@link developedLength}). The connecting step run is\n * `offsetHeight / sin(θ)` so the two bends realize the requested perpendicular step;\n * the result is guarded to a valid single solid. OCCT-WASM-safe construction only.\n *\n * @param part - the sheet metal part to attach a jog to.\n * @param spec - the jog specification.\n * @returns the updated part with the jog feature recorded, or an error.\n */\nexport async function jog(part: SheetMetalPart, spec: JogSpec): Promise<Result<SheetMetalPart>> {\n if (part.solid === undefined) {\n return err(validationError('NO_SOLID', `part has no solid to attach jog '${jogId(spec)}'`));\n }\n const id = jogId(spec);\n if (id.includes('::')) {\n return err(validationError('INVALID_JOG_ID', `jog id must not contain '::', got '${id}'`));\n }\n for (const existing of part.jogs ?? []) {\n if (existing.id === id) {\n return err(validationError('DUPLICATE_JOG', `duplicate jog id '${id}'`));\n }\n }\n\n const thickness = part.thickness;\n if (!Number.isFinite(spec.offsetHeight) || spec.offsetHeight <= 0) {\n return err(validationError('INVALID_JOG_OFFSET', `jog offsetHeight must be positive, got ${spec.offsetHeight}`));\n }\n if (!Number.isFinite(spec.position) || spec.position <= 0) {\n return err(validationError('INVALID_JOG_POSITION', `jog position must be positive, got ${spec.position}`));\n }\n const angleDeg = spec.angle ?? 45;\n if (!Number.isFinite(angleDeg) || angleDeg <= 0 || angleDeg >= 90) {\n return err(validationError('INVALID_JOG_ANGLE', `jog angle must be in (0, 90), got ${angleDeg}`));\n }\n const radius = spec.radius ?? thickness;\n if (!Number.isFinite(radius) || radius <= 0) {\n return err(validationError('INVALID_JOG_RADIUS', `jog radius must be positive, got ${radius}`));\n }\n const runOut = spec.runOut ?? spec.position;\n if (!Number.isFinite(runOut) || runOut <= 0) {\n return err(validationError('INVALID_JOG_RUNOUT', `jog runOut must be positive, got ${runOut}`));\n }\n\n const framesResult = worldFrames(part);\n if (!framesResult.ok) return framesResult;\n const regionId = resolveRegion(spec.region);\n const regionFrame = framesResult.value.get(regionId);\n if (regionFrame === undefined) {\n return err(validationError('UNKNOWN_REGION', `jog '${id}' references unknown region '${spec.region}'`));\n }\n\n const edge = regionEdge(regionFrame, 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', `jog '${id}' offset must be non-negative`));\n }\n if (!Number.isFinite(span) || span <= 0) {\n return err(validationError('INVALID_JOG_WIDTH', `jog '${id}' width must be positive`));\n }\n if (offset + span > edge.length + 1e-6) {\n return err(\n validationError('JOG_OUT_OF_BOUNDS', `jog '${id}' [${offset}, ${offset + span}] exceeds region edge length ${edge.length}`)\n );\n }\n\n const rule: BendRule = spec.rule ?? { innerRadius: radius, kFactor: 0.44 };\n // The connecting step run carries the flat across the offset at angle θ. The two\n // arcs themselves each rise (T+2r)/2·(1−cosθ) perpendicular to the plane (the\n // up-bend rises (T+r)(1−cosθ), the down-bend r(1−cosθ)); the step run adds\n // L·sinθ. Solving for the total perpendicular rise = offsetHeight gives this L, so\n // the run-out bottom face sits exactly offsetHeight above the base bottom face.\n const theta = (angleDeg * Math.PI) / 180;\n const arcRise = (thickness + 2 * radius) * (1 - Math.cos(theta));\n const stepRun = (spec.offsetHeight - arcRise) / Math.sin(theta);\n if (!(stepRun > 0)) {\n return err(\n validationError(\n 'JOG_OFFSET_TOO_SMALL',\n `jog offsetHeight ${spec.offsetHeight} is too small for radius ${radius} at ${angleDeg}° (the bends alone rise ${arcRise.toFixed(3)}); increase offsetHeight or reduce radius/angle`\n )\n );\n }\n\n let frame: SegmentFrame = initialSegmentFrame(edge, regionFrame.n, offset);\n let solid: Solid = part.solid;\n const bends: BendFeature[] = [];\n const segments: JogFeature['segments'] = [];\n const bendIds: string[] = [];\n let devTotal = 0;\n\n // 1) Flat position leg out to the first bend.\n {\n const built = await buildLineLeg(solid, frame, span, thickness, spec.position);\n if (!built.ok) return built;\n solid = built.value.solid;\n frame = built.value.frame;\n segments.push({ kind: 'line', dev: spec.position });\n devTotal += spec.position;\n }\n\n // 2) Up bend (+θ), 3) step run, 4) down bend (−θ): the two opposite bends.\n const order: { dir: 'up' | 'down'; step?: number }[] = [\n { dir: 'up', step: stepRun },\n { dir: 'down' },\n ];\n for (let i = 0; i < order.length; i += 1) {\n const o = order[i];\n if (o === undefined) continue;\n const built = await buildArcBend(solid, frame, span, thickness, {\n kind: 'arc',\n radius,\n angleDeg,\n direction: o.dir,\n });\n if (!built.ok) return built;\n solid = built.value.solid;\n frame = built.value.frame;\n\n const devResult = developedLength(angleDeg, thickness, { ...rule, innerRadius: radius });\n if (!devResult.ok) return devResult;\n const dev = devResult.value;\n\n const bendId = `jog::${id}::${i}`;\n bendIds.push(bendId);\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,\n direction: o.dir,\n rule: { ...rule, innerRadius: radius },\n });\n segments.push({ kind: 'arc', dev, angleDeg, direction: o.dir, bendId });\n devTotal += dev;\n\n if (o.step !== undefined) {\n const stepBuilt = await buildLineLeg(solid, frame, span, thickness, o.step);\n if (!stepBuilt.ok) return stepBuilt;\n solid = stepBuilt.value.solid;\n frame = stepBuilt.value.frame;\n segments.push({ kind: 'line', dev: o.step });\n devTotal += o.step;\n }\n }\n\n // 5) Flat run-out leg, parallel to the original plane, offset by offsetHeight.\n {\n const built = await buildLineLeg(solid, frame, span, thickness, runOut);\n if (!built.ok) return built;\n solid = built.value.solid;\n segments.push({ kind: 'line', dev: runOut });\n devTotal += runOut;\n }\n\n const feature: JogFeature = {\n id,\n region: regionId,\n side: spec.side,\n offset,\n span,\n offsetHeight: spec.offsetHeight,\n angleDeg,\n developedLength: devTotal,\n bends: bendIds,\n segments,\n };\n\n return ok({\n ...part,\n solid: normalizeSolid(solid),\n bends: [...part.bends, ...bends],\n jogs: [...(part.jogs ?? []), feature],\n });\n}\n\nfunction jogId(spec: JogSpec): string {\n return spec.id ?? `jog-${spec.region}-${spec.side}`;\n}\n\nfunction resolveRegion(region: string): string {\n return region === 'base' || region === 'face-0' ? ROOT_FLAT_ID : region;\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type Result } from '@faicad/faijs/
|
|
1
|
+
import { type Result } from '@faicad/faijs/api';
|
|
2
2
|
import type { LoftedFlangeSpec, SheetMetalPart } from './types.js';
|
|
3
3
|
/**
|
|
4
4
|
* Author a lofted / ruled transition flange between two parallel OPEN profiles.
|
|
@@ -19,5 +19,5 @@ import type { LoftedFlangeSpec, SheetMetalPart } from './types.js';
|
|
|
19
19
|
* @param spec - the lofted flange specification.
|
|
20
20
|
* @returns the updated part with the lofted flange feature recorded, or an error.
|
|
21
21
|
*/
|
|
22
|
-
export declare function authorLoftedFlange(part: SheetMetalPart, spec: LoftedFlangeSpec): Result<SheetMetalPart
|
|
22
|
+
export declare function authorLoftedFlange(part: SheetMetalPart, spec: LoftedFlangeSpec): Promise<Result<SheetMetalPart>>;
|
|
23
23
|
//# sourceMappingURL=loftedFlangeFns.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loftedFlangeFns.d.ts","sourceRoot":"","sources":["../src/loftedFlangeFns.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"loftedFlangeFns.d.ts","sourceRoot":"","sources":["../src/loftedFlangeFns.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,KAAK,MAAM,EAA0H,MAAM,mBAAmB,CAAC;AACvK,OAAO,KAAK,EAAuB,gBAAgB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAexF;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,cAAc,EACpB,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAsEjC"}
|
package/dist/loftedFlangeFns.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ok, err, validationError, line, wireLoop, extrude, face, fuse, isPlanarWire, isSolid, getSolids
|
|
1
|
+
import { ok, err, kernelError, validationError, line, wireLoop, extrude, face, fuse, isPlanarWire, isSolid, getSolids } from '@faicad/faijs/api';
|
|
2
2
|
/**
|
|
3
3
|
* Relative out-of-plane tolerance for the per-quad developability test: a quad is
|
|
4
4
|
* twisted (non-developable) when its far corner sits off the diagonal-triangle plane
|
|
@@ -28,7 +28,7 @@ const DEVELOPABLE_MIN_SCALE = 1e-9;
|
|
|
28
28
|
* @param spec - the lofted flange specification.
|
|
29
29
|
* @returns the updated part with the lofted flange feature recorded, or an error.
|
|
30
30
|
*/
|
|
31
|
-
export function authorLoftedFlange(part, spec) {
|
|
31
|
+
export async function authorLoftedFlange(part, spec) {
|
|
32
32
|
if (spec.id === '' || spec.id.includes('::')) {
|
|
33
33
|
return err(validationError('INVALID_LOFTED_ID', `lofted flange id must be non-empty and must not contain '::', got '${spec.id}'`));
|
|
34
34
|
}
|
|
@@ -53,7 +53,7 @@ export function authorLoftedFlange(part, spec) {
|
|
|
53
53
|
// 3D profile points: profileA in the z=0 plane, profileB at z=height.
|
|
54
54
|
const a3 = spec.profileA.map(([x, y]) => [x, y, 0]);
|
|
55
55
|
const b3 = spec.profileB.map(([x, y]) => [x, y, spec.height]);
|
|
56
|
-
const solidResult = buildLoftedSolid(spec.id, a3, b3, thickness);
|
|
56
|
+
const solidResult = await buildLoftedSolid(spec.id, a3, b3, thickness);
|
|
57
57
|
if (!solidResult.ok)
|
|
58
58
|
return solidResult;
|
|
59
59
|
const dev = developRuled(a3, b3);
|
|
@@ -76,12 +76,16 @@ export function authorLoftedFlange(part, spec) {
|
|
|
76
76
|
loftedFlanges: [...(part.loftedFlanges ?? []), feature],
|
|
77
77
|
});
|
|
78
78
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
79
|
+
let solidOut;
|
|
80
|
+
try {
|
|
81
|
+
solidOut = normalize((await fuse(part.solid, solidResult.value)));
|
|
82
|
+
}
|
|
83
|
+
catch (e) {
|
|
84
|
+
return err(kernelError('FUSE_FAILED', `lofted flange: ${e instanceof Error ? e.message : String(e)}`));
|
|
85
|
+
}
|
|
82
86
|
return ok({
|
|
83
87
|
...part,
|
|
84
|
-
solid:
|
|
88
|
+
solid: solidOut,
|
|
85
89
|
loftedFlanges: [...(part.loftedFlanges ?? []), feature],
|
|
86
90
|
});
|
|
87
91
|
}
|
|
@@ -99,7 +103,7 @@ function normalize(shape) {
|
|
|
99
103
|
* (non-developable) transitions, where a single lofted-then-shelled surface can fail
|
|
100
104
|
* to sew.
|
|
101
105
|
*/
|
|
102
|
-
function buildLoftedSolid(id, a, b, thickness) {
|
|
106
|
+
async function buildLoftedSolid(id, a, b, thickness) {
|
|
103
107
|
let solid;
|
|
104
108
|
for (let i = 0; i + 1 < a.length; i += 1) {
|
|
105
109
|
const a0 = a[i];
|
|
@@ -109,17 +113,19 @@ function buildLoftedSolid(id, a, b, thickness) {
|
|
|
109
113
|
if (a0 === undefined || a1 === undefined || b0 === undefined || b1 === undefined) {
|
|
110
114
|
return err(validationError('LOFTED_QUAD_FAILED', `lofted flange '${id}' failed to index quad ${i}`));
|
|
111
115
|
}
|
|
112
|
-
const plate = buildQuadPlate(id, a0, a1, b1, b0, thickness);
|
|
116
|
+
const plate = await buildQuadPlate(id, a0, a1, b1, b0, thickness);
|
|
113
117
|
if (!plate.ok)
|
|
114
118
|
return plate;
|
|
115
119
|
if (solid === undefined) {
|
|
116
120
|
solid = plate.value;
|
|
117
121
|
}
|
|
118
122
|
else {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
+
try {
|
|
124
|
+
solid = normalize((await fuse(solid, plate.value)));
|
|
125
|
+
}
|
|
126
|
+
catch (e) {
|
|
127
|
+
return err(kernelError('FUSE_FAILED', `lofted quad ${i}: ${e instanceof Error ? e.message : String(e)}`));
|
|
128
|
+
}
|
|
123
129
|
}
|
|
124
130
|
}
|
|
125
131
|
if (solid === undefined) {
|
|
@@ -135,20 +141,22 @@ function buildLoftedSolid(id, a, b, thickness) {
|
|
|
135
141
|
* pair; for the common planar quad this is exact, for a twisted quad it is the
|
|
136
142
|
* faceted plate matching the triangulated development.
|
|
137
143
|
*/
|
|
138
|
-
function buildQuadPlate(id, a0, a1, b1, b0, thickness) {
|
|
139
|
-
const t1 = buildTrianglePlate(id, a0, a1, b1, thickness);
|
|
144
|
+
async function buildQuadPlate(id, a0, a1, b1, b0, thickness) {
|
|
145
|
+
const t1 = await buildTrianglePlate(id, a0, a1, b1, thickness);
|
|
140
146
|
if (!t1.ok)
|
|
141
147
|
return t1;
|
|
142
|
-
const t2 = buildTrianglePlate(id, a0, b1, b0, thickness);
|
|
148
|
+
const t2 = await buildTrianglePlate(id, a0, b1, b0, thickness);
|
|
143
149
|
if (!t2.ok)
|
|
144
150
|
return t2;
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
151
|
+
try {
|
|
152
|
+
return ok(normalize((await fuse(t1.value, t2.value))));
|
|
153
|
+
}
|
|
154
|
+
catch (e) {
|
|
155
|
+
return err(kernelError('FUSE_FAILED', `lofted quad plate: ${e instanceof Error ? e.message : String(e)}`));
|
|
156
|
+
}
|
|
149
157
|
}
|
|
150
158
|
/** A flat triangle (p0,p1,p2) extruded by `thickness` along its own normal. */
|
|
151
|
-
function buildTrianglePlate(id, p0, p1, p2, thickness) {
|
|
159
|
+
async function buildTrianglePlate(id, p0, p1, p2, thickness) {
|
|
152
160
|
const e0 = line(p0, p1);
|
|
153
161
|
const e1 = line(p1, p2);
|
|
154
162
|
const e2 = line(p2, p0);
|
|
@@ -164,10 +172,12 @@ function buildTrianglePlate(id, p0, p1, p2, thickness) {
|
|
|
164
172
|
return faceResult;
|
|
165
173
|
const n = triangleNormal(p0, p1, p2);
|
|
166
174
|
const dir = [n[0] * thickness, n[1] * thickness, n[2] * thickness];
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
175
|
+
try {
|
|
176
|
+
return ok(normalize((await extrude(faceResult.value, dir))));
|
|
177
|
+
}
|
|
178
|
+
catch (e) {
|
|
179
|
+
return err(kernelError('LOFTED_EXTRUDE_FAILED', `lofted triangle '${id}': ${e instanceof Error ? e.message : String(e)}`));
|
|
180
|
+
}
|
|
171
181
|
}
|
|
172
182
|
function triangleNormal(p0, p1, p2) {
|
|
173
183
|
const u = [p1[0] - p0[0], p1[1] - p0[1], p1[2] - p0[2]];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loftedFlangeFns.js","sourceRoot":"","sources":["../src/loftedFlangeFns.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type Result,\n type Vec3,\n type Wire,\n type Solid,\n ok,\n err,\n validationError,\n line,\n wireLoop,\n extrude,\n face,\n fuse,\n isPlanarWire,\n isSolid,\n getSolids,\n} from '@faicad/faijs/brepjs-compat';\nimport type { LoftedFlangeFeature, LoftedFlangeSpec, SheetMetalPart } from './types.js';\n\ntype Pt2 = [number, number];\n\n/**\n * Relative out-of-plane tolerance for the per-quad developability test: a quad is\n * twisted (non-developable) when its far corner sits off the diagonal-triangle plane\n * by more than this fraction of the quad's own size. Relative — not absolute — so a\n * genuinely flat quad is not false-flagged on a large part (numerical noise scales\n * with coordinates), nor a real twist missed on a tiny one.\n */\nconst DEVELOPABLE_REL_TOL = 1e-6;\n/** Floor on the size scale so a degenerate (near-zero-size) quad keeps a sane tolerance. */\nconst DEVELOPABLE_MIN_SCALE = 1e-9;\n\n/**\n * Author a lofted / ruled transition flange between two parallel OPEN profiles.\n * The two profiles are lofted (ruled, straight generators) into a transition surface\n * and thickened to a valid solid; the result is fused onto the part. The developed\n * pattern is produced by TRIANGULATION (the standard transition development): each\n * quad between consecutive vertex pairs is split into two triangles laid flat\n * edge-length-preserving and accumulated into a developed boundary.\n *\n * The triangulated development is EXACT (to tolerance) when the ruled surface is\n * developable — every quad is planar, so the two triangles share their diagonal in\n * 3D and the flat layout preserves all lengths and angles. When a quad is non-planar\n * (twisted ruling) the surface is not developable and the flat layout is an\n * approximation; {@link approximate} is set and the unfold emits a\n * `DEVELOPMENT_APPROXIMATE` warning.\n *\n * @param part - the sheet metal part to attach a lofted flange to.\n * @param spec - the lofted flange specification.\n * @returns the updated part with the lofted flange feature recorded, or an error.\n */\nexport function authorLoftedFlange(\n part: SheetMetalPart,\n spec: LoftedFlangeSpec\n): Result<SheetMetalPart> {\n if (spec.id === '' || spec.id.includes('::')) {\n return err(\n validationError('INVALID_LOFTED_ID', `lofted flange id must be non-empty and must not contain '::', got '${spec.id}'`)\n );\n }\n for (const existing of part.loftedFlanges ?? []) {\n if (existing.id === spec.id) {\n return err(validationError('DUPLICATE_LOFTED', `duplicate lofted flange id '${spec.id}'`));\n }\n }\n if (spec.profileA.length < 2 || spec.profileB.length < 2) {\n return err(\n validationError('INVALID_LOFTED_PROFILE', `lofted flange '${spec.id}' profiles need ≥ 2 points each`)\n );\n }\n if (spec.profileA.length !== spec.profileB.length) {\n return err(\n validationError('PROFILE_VERTEX_MISMATCH', `lofted flange '${spec.id}' profiles must have equal vertex counts (${spec.profileA.length} vs ${spec.profileB.length}) to pair into ruling triangles`)\n );\n }\n if (!Number.isFinite(spec.height) || spec.height <= 0) {\n return err(validationError('INVALID_LOFTED_HEIGHT', `lofted flange '${spec.id}' height must be positive, got ${spec.height}`));\n }\n\n const thickness = spec.thickness ?? part.thickness;\n if (!Number.isFinite(thickness) || thickness <= 0) {\n return err(validationError('INVALID_THICKNESS', `lofted flange '${spec.id}' thickness must be positive`));\n }\n\n // 3D profile points: profileA in the z=0 plane, profileB at z=height.\n const a3: Vec3[] = spec.profileA.map(([x, y]) => [x, y, 0]);\n const b3: Vec3[] = spec.profileB.map(([x, y]) => [x, y, spec.height]);\n\n const solidResult = buildLoftedSolid(spec.id, a3, b3, thickness);\n if (!solidResult.ok) return solidResult;\n\n const dev = developRuled(a3, b3);\n const loopResult = closedLoopWire(dev.loop);\n if (!loopResult.ok) return loopResult;\n\n const feature: LoftedFlangeFeature = {\n id: spec.id,\n developedLoop: dev.loop,\n developedArea: dev.area,\n approximate: dev.approximate,\n };\n\n // The lofted transition is an independent body fused to the part; like a contour\n // flange it carries no straight-bend tree entry (its development is the\n // triangulated loop, not a rectilinear strip).\n if (part.solid === undefined) {\n return ok({\n ...part,\n solid: solidResult.value,\n loftedFlanges: [...(part.loftedFlanges ?? []), feature],\n });\n }\n const fused = fuse(part.solid, solidResult.value);\n if (!fused.ok) return fused;\n\n return ok({\n ...part,\n solid: normalize(fused.value),\n loftedFlanges: [...(part.loftedFlanges ?? []), feature],\n });\n}\n\nfunction normalize(shape: Solid): Solid {\n if (isSolid(shape)) return shape;\n const solids = getSolids(shape);\n return solids.length === 1 ? (solids[0] as Solid) : shape;\n}\n\n/**\n * Build the thickened ruled transition solid as the union of per-quad plates. Each\n * quad of the ruled surface is triangulated and each triangle extruded by\n * `thickness` along its own normal, then all plates are fused. This per-triangle\n * construction is robust on OCCT-WASM for both planar (developable) and twisted\n * (non-developable) transitions, where a single lofted-then-shelled surface can fail\n * to sew.\n */\nfunction buildLoftedSolid(id: string, a: Vec3[], b: Vec3[], thickness: number): Result<Solid> {\n let solid: Solid | undefined;\n for (let i = 0; i + 1 < a.length; i += 1) {\n const a0 = a[i];\n const a1 = a[i + 1];\n const b0 = b[i];\n const b1 = b[i + 1];\n if (a0 === undefined || a1 === undefined || b0 === undefined || b1 === undefined) {\n return err(validationError('LOFTED_QUAD_FAILED', `lofted flange '${id}' failed to index quad ${i}`));\n }\n const plate = buildQuadPlate(id, a0, a1, b1, b0, thickness);\n if (!plate.ok) return plate;\n if (solid === undefined) {\n solid = plate.value;\n } else {\n const fused = fuse(solid, plate.value);\n if (!fused.ok) return fused;\n solid = normalize(fused.value);\n }\n }\n if (solid === undefined) {\n return err(validationError('LOFTED_EMPTY', `lofted flange '${id}' produced no quads`));\n }\n return ok(solid);\n}\n\n/**\n * One quad of the ruled surface (corners a0→a1→b1→b0), thickened into a plate. The\n * quad is split along its a0–b1 diagonal into two triangles lofted to the same\n * triangles offset by `thickness` along the quad normal — robust on a non-planar\n * (twisted) quad where a single planar face would fail. We loft each triangle face\n * pair; for the common planar quad this is exact, for a twisted quad it is the\n * faceted plate matching the triangulated development.\n */\nfunction buildQuadPlate(id: string, a0: Vec3, a1: Vec3, b1: Vec3, b0: Vec3, thickness: number): Result<Solid> {\n const t1 = buildTrianglePlate(id, a0, a1, b1, thickness);\n if (!t1.ok) return t1;\n const t2 = buildTrianglePlate(id, a0, b1, b0, thickness);\n if (!t2.ok) return t2;\n const fused = fuse(t1.value, t2.value);\n if (!fused.ok) return fused;\n return ok(normalize(fused.value));\n}\n\n/** A flat triangle (p0,p1,p2) extruded by `thickness` along its own normal. */\nfunction buildTrianglePlate(id: string, p0: Vec3, p1: Vec3, p2: Vec3, thickness: number): Result<Solid> {\n const e0 = line(p0, p1);\n const e1 = line(p1, p2);\n const e2 = line(p2, p0);\n const loopResult = wireLoop([e0, e1, e2]);\n if (!loopResult.ok) return loopResult;\n const loop = loopResult.value;\n if (!isPlanarWire(loop)) {\n return err(validationError('LOFTED_TRIANGLE_NONPLANAR', `lofted flange '${id}' triangle is not planar`));\n }\n const faceResult = face(loop);\n if (!faceResult.ok) return faceResult;\n const n = triangleNormal(p0, p1, p2);\n const dir: Vec3 = [n[0] * thickness, n[1] * thickness, n[2] * thickness];\n const extruded = extrude(faceResult.value, dir);\n if (!extruded.ok) return extruded;\n return ok(normalize(extruded.value));\n}\n\nfunction triangleNormal(p0: Vec3, p1: Vec3, p2: Vec3): Vec3 {\n const u: Vec3 = [p1[0] - p0[0], p1[1] - p0[1], p1[2] - p0[2]];\n const v: Vec3 = [p2[0] - p0[0], p2[1] - p0[1], p2[2] - p0[2]];\n const c: Vec3 = [u[1] * v[2] - u[2] * v[1], u[2] * v[0] - u[0] * v[2], u[0] * v[1] - u[1] * v[0]];\n const len = Math.hypot(c[0], c[1], c[2]) || 1;\n return [c[0] / len, c[1] / len, c[2] / len];\n}\n\ninterface Development {\n loop: Pt2[];\n area: number;\n approximate: boolean;\n}\n\n/**\n * Triangulated development of a ruled transition between two equal-length vertex\n * lists `a` (z=0) and `b` (z=height). Each quad (a[i],a[i+1],b[i+1],b[i]) is split\n * along the a[i]–b[i+1] diagonal into two triangles; the triangles are laid out\n * flat one strip at a time, hinging each new triangle onto the previously-placed\n * shared edge with its true 3D edge lengths preserved. The developed boundary is the\n * `a` chain laid along the bottom and the `b` chain returning along the top.\n *\n * Developable check: a quad is developable iff its two triangles, sharing the\n * diagonal, are coplanar — equivalently the far corner b[i] lies in the plane of\n * (a[i],a[i+1],b[i+1]). Any quad failing this within tolerance flags the whole\n * development approximate.\n */\nfunction developRuled(a: Vec3[], b: Vec3[]): Development {\n const aFlat: Pt2[] = [];\n const bFlat: Pt2[] = [];\n let area = 0;\n let approximate = false;\n\n // Place the first ruling (a[0]–b[0]) vertically: a[0] at origin, b[0] straight up\n // by its true 3D length, so the developed strip grows along +x.\n const d0 = dist(a[0] as Vec3, b[0] as Vec3);\n let aPrev: Pt2 = [0, 0];\n let bPrev: Pt2 = [0, d0];\n aFlat.push(aPrev);\n bFlat.push(bPrev);\n\n for (let i = 0; i + 1 < a.length; i += 1) {\n const A0 = a[i] as Vec3;\n const A1 = a[i + 1] as Vec3;\n const B0 = b[i] as Vec3;\n const B1 = b[i + 1] as Vec3;\n\n // True 3D edge lengths of this quad. Diagonal A0–B1 splits it into\n // T1=(A0,A1,B1) and T2=(A0,B1,B0).\n const lBottom = dist(A0, A1); // A0→A1\n const lTop = dist(B0, B1); // B0→B1\n const lDiag = dist(A0, B1); // shared diagonal A0→B1\n const lRight = dist(A1, B1); // right ruling A1→B1 (= next quad's left ruling)\n\n // Developable test: is B0 coplanar with (A0, A1, B1)? If not, the quad is\n // twisted and the flat layout cannot preserve all edges — mark approximate.\n // Tolerance is relative to the quad's size so the check is scale-invariant.\n const scale = Math.max(lBottom, lTop, lDiag, lRight, DEVELOPABLE_MIN_SCALE);\n if (planeDistance(A0, A1, B1, B0) > DEVELOPABLE_REL_TOL * scale) approximate = true;\n\n // Place B1 from the known A0(=aPrev, dist=lDiag) and B0(=bPrev, dist=lTop).\n const b1Flat = placeFrom(aPrev, bPrev, lDiag, lTop);\n // Place A1 from A0(=aPrev, dist=lBottom) and the just-placed B1(dist=lRight),\n // preserving the right ruling so it equals the next quad's left ruling exactly.\n const a1Flat = placeFrom(aPrev, b1Flat, lBottom, lRight);\n\n aFlat.push(a1Flat);\n bFlat.push(b1Flat);\n\n area += triArea3(A0, A1, B1) + triArea3(A0, B1, B0);\n aPrev = a1Flat;\n bPrev = b1Flat;\n }\n\n // Developed boundary: a-chain forward, b-chain back.\n const loop: Pt2[] = [...aFlat, ...[...bFlat].reverse()];\n return { loop, area, approximate };\n}\n\n/**\n * Place a new point at distance `r1` from `p1` and `r2` from `p2` in 2D, choosing\n * the solution on the +x side of the directed line p1→p2 (the strip grows toward +x,\n * so successive rulings advance rightward). Falls back to the midpoint if the circles\n * do not intersect (degenerate strip).\n */\nfunction placeFrom(p1: Pt2, p2: Pt2, r1: number, r2: number): Pt2 {\n const dx = p2[0] - p1[0];\n const dy = p2[1] - p1[1];\n const d = Math.hypot(dx, dy);\n if (d < 1e-12) return [p1[0] + r1, p1[1]];\n const a = (r1 * r1 - r2 * r2 + d * d) / (2 * d);\n const h2 = r1 * r1 - a * a;\n const h = h2 > 0 ? Math.sqrt(h2) : 0;\n const mx = p1[0] + (a * dx) / d;\n const my = p1[1] + (a * dy) / d;\n // Perpendicular toward +x: pick the offset whose x is larger.\n const ox = (-dy / d) * h;\n const oy = (dx / d) * h;\n const s1: Pt2 = [mx + ox, my + oy];\n const s2: Pt2 = [mx - ox, my - oy];\n return s1[0] >= s2[0] ? s1 : s2;\n}\n\nfunction dist(p: Vec3, q: Vec3): number {\n return Math.hypot(p[0] - q[0], p[1] - q[1], p[2] - q[2]);\n}\n\nfunction triArea3(p0: Vec3, p1: Vec3, p2: Vec3): number {\n const u: Vec3 = [p1[0] - p0[0], p1[1] - p0[1], p1[2] - p0[2]];\n const v: Vec3 = [p2[0] - p0[0], p2[1] - p0[1], p2[2] - p0[2]];\n const c: Vec3 = [u[1] * v[2] - u[2] * v[1], u[2] * v[0] - u[0] * v[2], u[0] * v[1] - u[1] * v[0]];\n return Math.hypot(c[0], c[1], c[2]) / 2;\n}\n\n/** Perpendicular distance of `q` from the plane through (p0,p1,p2). */\nfunction planeDistance(p0: Vec3, p1: Vec3, p2: Vec3, q: Vec3): number {\n const u: Vec3 = [p1[0] - p0[0], p1[1] - p0[1], p1[2] - p0[2]];\n const v: Vec3 = [p2[0] - p0[0], p2[1] - p0[1], p2[2] - p0[2]];\n const c: Vec3 = [u[1] * v[2] - u[2] * v[1], u[2] * v[0] - u[0] * v[2], u[0] * v[1] - u[1] * v[0]];\n const len = Math.hypot(c[0], c[1], c[2]);\n if (len < 1e-12) return 0;\n const w: Vec3 = [q[0] - p0[0], q[1] - p0[1], q[2] - p0[2]];\n return Math.abs((w[0] * c[0] + w[1] * c[1] + w[2] * c[2]) / len);\n}\n\n/** Trace a closed developed-plane loop (≥ 3 points) into a morph {@link Wire}. */\nfunction closedLoopWire(loop: Pt2[]): Result<Wire> {\n const deduped: Pt2[] = [];\n for (const p of loop) {\n const last = deduped[deduped.length - 1];\n if (last === undefined || Math.hypot(p[0] - last[0], p[1] - last[1]) > 1e-9) deduped.push(p);\n }\n // Drop a trailing point coincident with the first (the loop closes implicitly).\n if (deduped.length > 1) {\n const first = deduped[0] as Pt2;\n const last = deduped[deduped.length - 1] as Pt2;\n if (Math.hypot(first[0] - last[0], first[1] - last[1]) < 1e-9) deduped.pop();\n }\n if (deduped.length < 3) {\n return err(validationError('LOFTED_LOOP_TOO_SMALL', `developed loop has ${deduped.length} points, need ≥ 3`));\n }\n const edges = [];\n for (let i = 0; i < deduped.length; i += 1) {\n const p = deduped[i] as Pt2;\n const next = deduped[(i + 1) % deduped.length] as Pt2;\n edges.push(line([p[0], p[1], 0], [next[0], next[1], 0]));\n }\n return wireLoop(edges);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"loftedFlangeFns.js","sourceRoot":"","sources":["../src/loftedFlangeFns.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Wire, Solid } from './types.js';\nimport {type Result, type Vec3, ok, err, kernelError, validationError, line, wireLoop, extrude, face, fuse, isPlanarWire, isSolid, getSolids} from '@faicad/faijs/api';\nimport type { LoftedFlangeFeature, LoftedFlangeSpec, SheetMetalPart } from './types.js';\n\ntype Pt2 = [number, number];\n\n/**\n * Relative out-of-plane tolerance for the per-quad developability test: a quad is\n * twisted (non-developable) when its far corner sits off the diagonal-triangle plane\n * by more than this fraction of the quad's own size. Relative — not absolute — so a\n * genuinely flat quad is not false-flagged on a large part (numerical noise scales\n * with coordinates), nor a real twist missed on a tiny one.\n */\nconst DEVELOPABLE_REL_TOL = 1e-6;\n/** Floor on the size scale so a degenerate (near-zero-size) quad keeps a sane tolerance. */\nconst DEVELOPABLE_MIN_SCALE = 1e-9;\n\n/**\n * Author a lofted / ruled transition flange between two parallel OPEN profiles.\n * The two profiles are lofted (ruled, straight generators) into a transition surface\n * and thickened to a valid solid; the result is fused onto the part. The developed\n * pattern is produced by TRIANGULATION (the standard transition development): each\n * quad between consecutive vertex pairs is split into two triangles laid flat\n * edge-length-preserving and accumulated into a developed boundary.\n *\n * The triangulated development is EXACT (to tolerance) when the ruled surface is\n * developable — every quad is planar, so the two triangles share their diagonal in\n * 3D and the flat layout preserves all lengths and angles. When a quad is non-planar\n * (twisted ruling) the surface is not developable and the flat layout is an\n * approximation; {@link approximate} is set and the unfold emits a\n * `DEVELOPMENT_APPROXIMATE` warning.\n *\n * @param part - the sheet metal part to attach a lofted flange to.\n * @param spec - the lofted flange specification.\n * @returns the updated part with the lofted flange feature recorded, or an error.\n */\nexport async function authorLoftedFlange(\n part: SheetMetalPart,\n spec: LoftedFlangeSpec\n): Promise<Result<SheetMetalPart>> {\n if (spec.id === '' || spec.id.includes('::')) {\n return err(\n validationError('INVALID_LOFTED_ID', `lofted flange id must be non-empty and must not contain '::', got '${spec.id}'`)\n );\n }\n for (const existing of part.loftedFlanges ?? []) {\n if (existing.id === spec.id) {\n return err(validationError('DUPLICATE_LOFTED', `duplicate lofted flange id '${spec.id}'`));\n }\n }\n if (spec.profileA.length < 2 || spec.profileB.length < 2) {\n return err(\n validationError('INVALID_LOFTED_PROFILE', `lofted flange '${spec.id}' profiles need ≥ 2 points each`)\n );\n }\n if (spec.profileA.length !== spec.profileB.length) {\n return err(\n validationError('PROFILE_VERTEX_MISMATCH', `lofted flange '${spec.id}' profiles must have equal vertex counts (${spec.profileA.length} vs ${spec.profileB.length}) to pair into ruling triangles`)\n );\n }\n if (!Number.isFinite(spec.height) || spec.height <= 0) {\n return err(validationError('INVALID_LOFTED_HEIGHT', `lofted flange '${spec.id}' height must be positive, got ${spec.height}`));\n }\n\n const thickness = spec.thickness ?? part.thickness;\n if (!Number.isFinite(thickness) || thickness <= 0) {\n return err(validationError('INVALID_THICKNESS', `lofted flange '${spec.id}' thickness must be positive`));\n }\n\n // 3D profile points: profileA in the z=0 plane, profileB at z=height.\n const a3: Vec3[] = spec.profileA.map(([x, y]) => [x, y, 0]);\n const b3: Vec3[] = spec.profileB.map(([x, y]) => [x, y, spec.height]);\n\n const solidResult = await buildLoftedSolid(spec.id, a3, b3, thickness);\n if (!solidResult.ok) return solidResult;\n\n const dev = developRuled(a3, b3);\n const loopResult = closedLoopWire(dev.loop);\n if (!loopResult.ok) return loopResult;\n\n const feature: LoftedFlangeFeature = {\n id: spec.id,\n developedLoop: dev.loop,\n developedArea: dev.area,\n approximate: dev.approximate,\n };\n\n // The lofted transition is an independent body fused to the part; like a contour\n // flange it carries no straight-bend tree entry (its development is the\n // triangulated loop, not a rectilinear strip).\n if (part.solid === undefined) {\n return ok({\n ...part,\n solid: solidResult.value,\n loftedFlanges: [...(part.loftedFlanges ?? []), feature],\n });\n }\n let solidOut: Solid;\n try {\n solidOut = normalize((await fuse(part.solid, solidResult.value)) as Solid);\n } catch (e) {\n return err(kernelError('FUSE_FAILED', `lofted flange: ${e instanceof Error ? e.message : String(e)}`));\n }\n\n return ok({\n ...part,\n solid: solidOut,\n loftedFlanges: [...(part.loftedFlanges ?? []), feature],\n });\n}\n\nfunction normalize(shape: Solid): Solid {\n if (isSolid(shape)) return shape;\n const solids = getSolids(shape);\n return solids.length === 1 ? (solids[0] as Solid) : shape;\n}\n\n/**\n * Build the thickened ruled transition solid as the union of per-quad plates. Each\n * quad of the ruled surface is triangulated and each triangle extruded by\n * `thickness` along its own normal, then all plates are fused. This per-triangle\n * construction is robust on OCCT-WASM for both planar (developable) and twisted\n * (non-developable) transitions, where a single lofted-then-shelled surface can fail\n * to sew.\n */\nasync function buildLoftedSolid(id: string, a: Vec3[], b: Vec3[], thickness: number): Promise<Result<Solid>> {\n let solid: Solid | undefined;\n for (let i = 0; i + 1 < a.length; i += 1) {\n const a0 = a[i];\n const a1 = a[i + 1];\n const b0 = b[i];\n const b1 = b[i + 1];\n if (a0 === undefined || a1 === undefined || b0 === undefined || b1 === undefined) {\n return err(validationError('LOFTED_QUAD_FAILED', `lofted flange '${id}' failed to index quad ${i}`));\n }\n const plate = await buildQuadPlate(id, a0, a1, b1, b0, thickness);\n if (!plate.ok) return plate;\n if (solid === undefined) {\n solid = plate.value;\n } else {\n try {\n solid = normalize((await fuse(solid, plate.value)) as Solid);\n } catch (e) {\n return err(kernelError('FUSE_FAILED', `lofted quad ${i}: ${e instanceof Error ? e.message : String(e)}`));\n }\n }\n }\n if (solid === undefined) {\n return err(validationError('LOFTED_EMPTY', `lofted flange '${id}' produced no quads`));\n }\n return ok(solid);\n}\n\n/**\n * One quad of the ruled surface (corners a0→a1→b1→b0), thickened into a plate. The\n * quad is split along its a0–b1 diagonal into two triangles lofted to the same\n * triangles offset by `thickness` along the quad normal — robust on a non-planar\n * (twisted) quad where a single planar face would fail. We loft each triangle face\n * pair; for the common planar quad this is exact, for a twisted quad it is the\n * faceted plate matching the triangulated development.\n */\nasync function buildQuadPlate(id: string, a0: Vec3, a1: Vec3, b1: Vec3, b0: Vec3, thickness: number): Promise<Result<Solid>> {\n const t1 = await buildTrianglePlate(id, a0, a1, b1, thickness);\n if (!t1.ok) return t1;\n const t2 = await buildTrianglePlate(id, a0, b1, b0, thickness);\n if (!t2.ok) return t2;\n try {\n return ok(normalize((await fuse(t1.value, t2.value)) as Solid));\n } catch (e) {\n return err(kernelError('FUSE_FAILED', `lofted quad plate: ${e instanceof Error ? e.message : String(e)}`));\n }\n}\n\n/** A flat triangle (p0,p1,p2) extruded by `thickness` along its own normal. */\nasync function buildTrianglePlate(id: string, p0: Vec3, p1: Vec3, p2: Vec3, thickness: number): Promise<Result<Solid>> {\n const e0 = line(p0, p1);\n const e1 = line(p1, p2);\n const e2 = line(p2, p0);\n const loopResult = wireLoop([e0, e1, e2]);\n if (!loopResult.ok) return loopResult;\n const loop = loopResult.value;\n if (!isPlanarWire(loop)) {\n return err(validationError('LOFTED_TRIANGLE_NONPLANAR', `lofted flange '${id}' triangle is not planar`));\n }\n const faceResult = face(loop);\n if (!faceResult.ok) return faceResult;\n const n = triangleNormal(p0, p1, p2);\n const dir: Vec3 = [n[0] * thickness, n[1] * thickness, n[2] * thickness];\n try {\n return ok(normalize((await extrude(faceResult.value, dir)) as Solid));\n } catch (e) {\n return err(kernelError('LOFTED_EXTRUDE_FAILED', `lofted triangle '${id}': ${e instanceof Error ? e.message : String(e)}`));\n }\n}\n\nfunction triangleNormal(p0: Vec3, p1: Vec3, p2: Vec3): Vec3 {\n const u: Vec3 = [p1[0] - p0[0], p1[1] - p0[1], p1[2] - p0[2]];\n const v: Vec3 = [p2[0] - p0[0], p2[1] - p0[1], p2[2] - p0[2]];\n const c: Vec3 = [u[1] * v[2] - u[2] * v[1], u[2] * v[0] - u[0] * v[2], u[0] * v[1] - u[1] * v[0]];\n const len = Math.hypot(c[0], c[1], c[2]) || 1;\n return [c[0] / len, c[1] / len, c[2] / len];\n}\n\ninterface Development {\n loop: Pt2[];\n area: number;\n approximate: boolean;\n}\n\n/**\n * Triangulated development of a ruled transition between two equal-length vertex\n * lists `a` (z=0) and `b` (z=height). Each quad (a[i],a[i+1],b[i+1],b[i]) is split\n * along the a[i]–b[i+1] diagonal into two triangles; the triangles are laid out\n * flat one strip at a time, hinging each new triangle onto the previously-placed\n * shared edge with its true 3D edge lengths preserved. The developed boundary is the\n * `a` chain laid along the bottom and the `b` chain returning along the top.\n *\n * Developable check: a quad is developable iff its two triangles, sharing the\n * diagonal, are coplanar — equivalently the far corner b[i] lies in the plane of\n * (a[i],a[i+1],b[i+1]). Any quad failing this within tolerance flags the whole\n * development approximate.\n */\nfunction developRuled(a: Vec3[], b: Vec3[]): Development {\n const aFlat: Pt2[] = [];\n const bFlat: Pt2[] = [];\n let area = 0;\n let approximate = false;\n\n // Place the first ruling (a[0]–b[0]) vertically: a[0] at origin, b[0] straight up\n // by its true 3D length, so the developed strip grows along +x.\n const d0 = dist(a[0] as Vec3, b[0] as Vec3);\n let aPrev: Pt2 = [0, 0];\n let bPrev: Pt2 = [0, d0];\n aFlat.push(aPrev);\n bFlat.push(bPrev);\n\n for (let i = 0; i + 1 < a.length; i += 1) {\n const A0 = a[i] as Vec3;\n const A1 = a[i + 1] as Vec3;\n const B0 = b[i] as Vec3;\n const B1 = b[i + 1] as Vec3;\n\n // True 3D edge lengths of this quad. Diagonal A0–B1 splits it into\n // T1=(A0,A1,B1) and T2=(A0,B1,B0).\n const lBottom = dist(A0, A1); // A0→A1\n const lTop = dist(B0, B1); // B0→B1\n const lDiag = dist(A0, B1); // shared diagonal A0→B1\n const lRight = dist(A1, B1); // right ruling A1→B1 (= next quad's left ruling)\n\n // Developable test: is B0 coplanar with (A0, A1, B1)? If not, the quad is\n // twisted and the flat layout cannot preserve all edges — mark approximate.\n // Tolerance is relative to the quad's size so the check is scale-invariant.\n const scale = Math.max(lBottom, lTop, lDiag, lRight, DEVELOPABLE_MIN_SCALE);\n if (planeDistance(A0, A1, B1, B0) > DEVELOPABLE_REL_TOL * scale) approximate = true;\n\n // Place B1 from the known A0(=aPrev, dist=lDiag) and B0(=bPrev, dist=lTop).\n const b1Flat = placeFrom(aPrev, bPrev, lDiag, lTop);\n // Place A1 from A0(=aPrev, dist=lBottom) and the just-placed B1(dist=lRight),\n // preserving the right ruling so it equals the next quad's left ruling exactly.\n const a1Flat = placeFrom(aPrev, b1Flat, lBottom, lRight);\n\n aFlat.push(a1Flat);\n bFlat.push(b1Flat);\n\n area += triArea3(A0, A1, B1) + triArea3(A0, B1, B0);\n aPrev = a1Flat;\n bPrev = b1Flat;\n }\n\n // Developed boundary: a-chain forward, b-chain back.\n const loop: Pt2[] = [...aFlat, ...[...bFlat].reverse()];\n return { loop, area, approximate };\n}\n\n/**\n * Place a new point at distance `r1` from `p1` and `r2` from `p2` in 2D, choosing\n * the solution on the +x side of the directed line p1→p2 (the strip grows toward +x,\n * so successive rulings advance rightward). Falls back to the midpoint if the circles\n * do not intersect (degenerate strip).\n */\nfunction placeFrom(p1: Pt2, p2: Pt2, r1: number, r2: number): Pt2 {\n const dx = p2[0] - p1[0];\n const dy = p2[1] - p1[1];\n const d = Math.hypot(dx, dy);\n if (d < 1e-12) return [p1[0] + r1, p1[1]];\n const a = (r1 * r1 - r2 * r2 + d * d) / (2 * d);\n const h2 = r1 * r1 - a * a;\n const h = h2 > 0 ? Math.sqrt(h2) : 0;\n const mx = p1[0] + (a * dx) / d;\n const my = p1[1] + (a * dy) / d;\n // Perpendicular toward +x: pick the offset whose x is larger.\n const ox = (-dy / d) * h;\n const oy = (dx / d) * h;\n const s1: Pt2 = [mx + ox, my + oy];\n const s2: Pt2 = [mx - ox, my - oy];\n return s1[0] >= s2[0] ? s1 : s2;\n}\n\nfunction dist(p: Vec3, q: Vec3): number {\n return Math.hypot(p[0] - q[0], p[1] - q[1], p[2] - q[2]);\n}\n\nfunction triArea3(p0: Vec3, p1: Vec3, p2: Vec3): number {\n const u: Vec3 = [p1[0] - p0[0], p1[1] - p0[1], p1[2] - p0[2]];\n const v: Vec3 = [p2[0] - p0[0], p2[1] - p0[1], p2[2] - p0[2]];\n const c: Vec3 = [u[1] * v[2] - u[2] * v[1], u[2] * v[0] - u[0] * v[2], u[0] * v[1] - u[1] * v[0]];\n return Math.hypot(c[0], c[1], c[2]) / 2;\n}\n\n/** Perpendicular distance of `q` from the plane through (p0,p1,p2). */\nfunction planeDistance(p0: Vec3, p1: Vec3, p2: Vec3, q: Vec3): number {\n const u: Vec3 = [p1[0] - p0[0], p1[1] - p0[1], p1[2] - p0[2]];\n const v: Vec3 = [p2[0] - p0[0], p2[1] - p0[1], p2[2] - p0[2]];\n const c: Vec3 = [u[1] * v[2] - u[2] * v[1], u[2] * v[0] - u[0] * v[2], u[0] * v[1] - u[1] * v[0]];\n const len = Math.hypot(c[0], c[1], c[2]);\n if (len < 1e-12) return 0;\n const w: Vec3 = [q[0] - p0[0], q[1] - p0[1], q[2] - p0[2]];\n return Math.abs((w[0] * c[0] + w[1] * c[1] + w[2] * c[2]) / len);\n}\n\n/** Trace a closed developed-plane loop (≥ 3 points) into a morph {@link Wire}. */\nfunction closedLoopWire(loop: Pt2[]): Result<Wire> {\n const deduped: Pt2[] = [];\n for (const p of loop) {\n const last = deduped[deduped.length - 1];\n if (last === undefined || Math.hypot(p[0] - last[0], p[1] - last[1]) > 1e-9) deduped.push(p);\n }\n // Drop a trailing point coincident with the first (the loop closes implicitly).\n if (deduped.length > 1) {\n const first = deduped[0] as Pt2;\n const last = deduped[deduped.length - 1] as Pt2;\n if (Math.hypot(first[0] - last[0], first[1] - last[1]) < 1e-9) deduped.pop();\n }\n if (deduped.length < 3) {\n return err(validationError('LOFTED_LOOP_TOO_SMALL', `developed loop has ${deduped.length} points, need ≥ 3`));\n }\n const edges = [];\n for (let i = 0; i < deduped.length; i += 1) {\n const p = deduped[i] as Pt2;\n const next = deduped[(i + 1) % deduped.length] as Pt2;\n edges.push(line([p[0], p[1], 0], [next[0], next[1], 0]));\n }\n return wireLoop(edges);\n}\n"]}
|
package/dist/miterFns.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type Result, type Vec3 } from '@faicad/faijs/
|
|
1
|
+
import { type Result, type Vec3 } from '@faicad/faijs/api';
|
|
2
2
|
import type { SheetMetalPart } from './types.js';
|
|
3
3
|
/** An oriented cutting plane: material on the `+normal` side is removed. */
|
|
4
4
|
export interface MiterPlane {
|
|
@@ -14,7 +14,7 @@ export interface MiterPlane {
|
|
|
14
14
|
* @param plane - the miter plane definition.
|
|
15
15
|
* @returns the updated part with the miter cut applied, or an error.
|
|
16
16
|
*/
|
|
17
|
-
export declare function miterCut(part: SheetMetalPart, plane: MiterPlane): Result<SheetMetalPart
|
|
17
|
+
export declare function miterCut(part: SheetMetalPart, plane: MiterPlane): Promise<Result<SheetMetalPart>>;
|
|
18
18
|
/**
|
|
19
19
|
* Auto corner-miter between two adjacent flanges. The miter plane bisects the two
|
|
20
20
|
* flanges' fold-up directions at their shared corner and is offset by half the gap,
|
|
@@ -27,5 +27,5 @@ export declare function miterCut(part: SheetMetalPart, plane: MiterPlane): Resul
|
|
|
27
27
|
* @param gap - the gap between flanges (default 0).
|
|
28
28
|
* @returns the updated part with the miter corner applied, or an error.
|
|
29
29
|
*/
|
|
30
|
-
export declare function autoMiterCorner(part: SheetMetalPart, flangeIdA: string, flangeIdB: string, gap?: number): Result<SheetMetalPart
|
|
30
|
+
export declare function autoMiterCorner(part: SheetMetalPart, flangeIdA: string, flangeIdB: string, gap?: number): Promise<Result<SheetMetalPart>>;
|
|
31
31
|
//# sourceMappingURL=miterFns.d.ts.map
|
package/dist/miterFns.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"miterFns.d.ts","sourceRoot":"","sources":["../src/miterFns.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"miterFns.d.ts","sourceRoot":"","sources":["../src/miterFns.ts"],"names":[],"mappings":"AAGA,OAAO,EAAC,KAAK,MAAM,EAAE,KAAK,IAAI,EAAoH,MAAM,mBAAmB,CAAC;AAC5K,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAGjD,4EAA4E;AAC5E,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,IAAI,CAAC;IACb,MAAM,EAAE,IAAI,CAAC;CACd;AAED;;;;;;;;GAQG;AACH,wBAAsB,QAAQ,CAAC,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAevG;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,cAAc,EACpB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,GAAG,SAAI,GACN,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAqCjC"}
|