import { SCENARIO_PRESETS } from "./presets"; import type { Mount, MountType, PlateGeometry, ProblemSpec } from "./types"; /** The default problem: the steel sheet on a thread. */ export function defaultSpec(): ProblemSpec { return cloneSpec(SCENARIO_PRESETS[0].spec); } /** Deep-copy a spec (specs are plain data). */ export function cloneSpec(spec: ProblemSpec): ProblemSpec { return JSON.parse(JSON.stringify(spec)) as ProblemSpec; } /** * A reasonable mount of the given type for this plate, used when the mount * type is switched in the controls: holes near the top edge, pads under the * corners, felts at the centre, the vise on the left edge, fingers at the top. */ export function defaultMount(type: MountType, plate: PlateGeometry, previous?: Mount): Mount { const { Lx, Ly } = plate; const ellipse = plate.shape === "ellipse"; // a hole 10 mm in from the top of the plate's outline, on its centreline const top = ellipse ? Ly - 0.01 : Ly - 0.01; switch (type) { case "thread": return { type, x: Lx / 2, y: top, length: 0.3, thread: { name: "nylon monofilament, 0.5 mm", diameter: 0.5e-3, G: 1.0e9 }, }; case "threads": { if (ellipse) { const a = Lx / 2; const b = Ly / 2; const ang = (25 * Math.PI) / 180; return { type, x1: a - (a - 0.012) * Math.sin(ang), y1: b + (b - 0.012) * Math.cos(ang), x2: a + (a - 0.012) * Math.sin(ang), y2: b + (b - 0.012) * Math.cos(ang), length: 0.4, }; } return { type, x1: 0.2 * Lx, y1: top, x2: 0.8 * Lx, y2: top, length: 0.3 }; } case "pads": { const r = Math.min(0.02, 0.15 * Math.min(Lx, Ly)); const inset = ellipse ? 0.3 : 0.1; const pads = ellipse ? [ { x: Lx / 2, y: inset * Ly, rx: r, ry: r }, { x: inset * Lx, y: Ly * 0.7, rx: r, ry: r }, { x: (1 - inset) * Lx, y: Ly * 0.7, rx: r, ry: r }, ] : [ { x: inset * Lx, y: inset * Ly, rx: r, ry: r }, { x: (1 - inset) * Lx, y: inset * Ly, rx: r, ry: r }, { x: inset * Lx, y: (1 - inset) * Ly, rx: r, ry: r }, { x: (1 - inset) * Lx, y: (1 - inset) * Ly, rx: r, ry: r }, ]; return { type, pads, k: 2.5e6, c: 1.2e3 }; } case "cymbal": return { type, r_rod: 0.006, r_felt: Math.min(0.02, 0.1 * Math.min(Lx, Ly)), k: 2e8, c: 6e4, preload: 0.5e-3, }; case "vise": return { type, edge: "x0", depth: Math.min(0.015, 0.1 * Lx), tilt: 90 }; case "pinched": return { type, x: Lx / 2, y: top, radius: 0.008, k: 2000, c: 20, tilt: previous && "tilt" in previous ? previous.tilt : 0, }; } }