1import { SCENARIO_PRESETS } from "./presets";
2import type { Mount, MountType, PlateGeometry, ProblemSpec } from "./types";
4/** The default problem: the steel sheet on a thread. */
5export function defaultSpec(): ProblemSpec {
6 return cloneSpec(SCENARIO_PRESETS[0].spec);
7}
9/** Deep-copy a spec (specs are plain data). */
10export function cloneSpec(spec: ProblemSpec): ProblemSpec {
11 return JSON.parse(JSON.stringify(spec)) as ProblemSpec;
12}
14/**
15 * A reasonable mount of the given type for this plate, used when the mount
16 * type is switched in the controls: holes near the top edge, pads under the
17 * corners, felts at the centre, the vise on the left edge, fingers at the top.
18 */
19export function defaultMount(type: MountType, plate: PlateGeometry, previous?: Mount): Mount {
20 const { Lx, Ly } = plate;
21 const ellipse = plate.shape === "ellipse";
22 // a hole 10 mm in from the top of the plate's outline, on its centreline
23 const top = ellipse ? Ly - 0.01 : Ly - 0.01;
24 switch (type) {
25 case "thread":
26 return {
27 type,
28 x: Lx / 2,
29 y: top,
30 length: 0.3,
31 thread: { name: "nylon monofilament, 0.5 mm", diameter: 0.5e-3, G: 1.0e9 },
32 };
33 case "threads": {
34 if (ellipse) {
35 const a = Lx / 2;
36 const b = Ly / 2;
37 const ang = (25 * Math.PI) / 180;
38 return {
39 type,
40 x1: a - (a - 0.012) * Math.sin(ang),
41 y1: b + (b - 0.012) * Math.cos(ang),
42 x2: a + (a - 0.012) * Math.sin(ang),
43 y2: b + (b - 0.012) * Math.cos(ang),
44 length: 0.4,
45 };
46 }
47 return { type, x1: 0.2 * Lx, y1: top, x2: 0.8 * Lx, y2: top, length: 0.3 };
48 }
49 case "pads": {
50 const r = Math.min(0.02, 0.15 * Math.min(Lx, Ly));
51 const inset = ellipse ? 0.3 : 0.1;
52 const pads = ellipse
53 ? [
54 { x: Lx / 2, y: inset * Ly, rx: r, ry: r },
55 { x: inset * Lx, y: Ly * 0.7, rx: r, ry: r },
56 { x: (1 - inset) * Lx, y: Ly * 0.7, rx: r, ry: r },
57 ]
58 : [
59 { x: inset * Lx, y: inset * Ly, rx: r, ry: r },
60 { x: (1 - inset) * Lx, y: inset * Ly, rx: r, ry: r },
61 { x: inset * Lx, y: (1 - inset) * Ly, rx: r, ry: r },
62 { x: (1 - inset) * Lx, y: (1 - inset) * Ly, rx: r, ry: r },
63 ];
64 return { type, pads, k: 2.5e6, c: 1.2e3 };
65 }
66 case "cymbal":
67 return {
68 type,
69 r_rod: 0.006,
70 r_felt: Math.min(0.02, 0.1 * Math.min(Lx, Ly)),
71 k: 2e8,
72 c: 6e4,
73 preload: 0.5e-3,
74 };
75 case "vise":
76 return { type, edge: "x0", depth: Math.min(0.015, 0.1 * Lx), tilt: 90 };
77 case "pinched":
78 return {
79 type,
80 x: Lx / 2,
81 y: top,
82 radius: 0.008,
83 k: 2000,
84 c: 20,
85 tilt: previous && "tilt" in previous ? previous.tilt : 0,
86 };
87 }
88}