@franzenzenhofer/asanakit 0.1.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.
Files changed (174) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +153 -0
  3. package/dist/anatomy/muscles.d.ts +55 -0
  4. package/dist/anatomy/muscles.d.ts.map +1 -0
  5. package/dist/anatomy/muscles.js +79 -0
  6. package/dist/anatomy/muscles.js.map +1 -0
  7. package/dist/anatomy/validate.d.ts +11 -0
  8. package/dist/anatomy/validate.d.ts.map +1 -0
  9. package/dist/anatomy/validate.js +94 -0
  10. package/dist/anatomy/validate.js.map +1 -0
  11. package/dist/cli/commands/export.d.ts +3 -0
  12. package/dist/cli/commands/export.d.ts.map +1 -0
  13. package/dist/cli/commands/export.js +45 -0
  14. package/dist/cli/commands/export.js.map +1 -0
  15. package/dist/cli/commands/info.d.ts +3 -0
  16. package/dist/cli/commands/info.d.ts.map +1 -0
  17. package/dist/cli/commands/info.js +101 -0
  18. package/dist/cli/commands/info.js.map +1 -0
  19. package/dist/cli/commands/render.d.ts +3 -0
  20. package/dist/cli/commands/render.d.ts.map +1 -0
  21. package/dist/cli/commands/render.js +103 -0
  22. package/dist/cli/commands/render.js.map +1 -0
  23. package/dist/cli/index.d.ts +3 -0
  24. package/dist/cli/index.d.ts.map +1 -0
  25. package/dist/cli/index.js +31 -0
  26. package/dist/cli/index.js.map +1 -0
  27. package/dist/cli/resolve.d.ts +12 -0
  28. package/dist/cli/resolve.d.ts.map +1 -0
  29. package/dist/cli/resolve.js +46 -0
  30. package/dist/cli/resolve.js.map +1 -0
  31. package/dist/core/angles.d.ts +12 -0
  32. package/dist/core/angles.d.ts.map +1 -0
  33. package/dist/core/angles.js +27 -0
  34. package/dist/core/angles.js.map +1 -0
  35. package/dist/core/rig.d.ts +8 -0
  36. package/dist/core/rig.d.ts.map +1 -0
  37. package/dist/core/rig.js +97 -0
  38. package/dist/core/rig.js.map +1 -0
  39. package/dist/core/skeleton.d.ts +17 -0
  40. package/dist/core/skeleton.d.ts.map +1 -0
  41. package/dist/core/skeleton.js +144 -0
  42. package/dist/core/skeleton.js.map +1 -0
  43. package/dist/core/types.d.ts +105 -0
  44. package/dist/core/types.d.ts.map +1 -0
  45. package/dist/core/types.js +47 -0
  46. package/dist/core/types.js.map +1 -0
  47. package/dist/core/vec2.d.ts +19 -0
  48. package/dist/core/vec2.d.ts.map +1 -0
  49. package/dist/core/vec2.js +41 -0
  50. package/dist/core/vec2.js.map +1 -0
  51. package/dist/index.d.ts +11 -0
  52. package/dist/index.d.ts.map +1 -0
  53. package/dist/index.js +11 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/library/index.d.ts +27 -0
  56. package/dist/library/index.d.ts.map +1 -0
  57. package/dist/library/index.js +75 -0
  58. package/dist/library/index.js.map +1 -0
  59. package/dist/model/index.d.ts +4 -0
  60. package/dist/model/index.d.ts.map +1 -0
  61. package/dist/model/index.js +4 -0
  62. package/dist/model/index.js.map +1 -0
  63. package/dist/model/parse.d.ts +12 -0
  64. package/dist/model/parse.d.ts.map +1 -0
  65. package/dist/model/parse.js +43 -0
  66. package/dist/model/parse.js.map +1 -0
  67. package/dist/model/pose.d.ts +11 -0
  68. package/dist/model/pose.d.ts.map +1 -0
  69. package/dist/model/pose.js +26 -0
  70. package/dist/model/pose.js.map +1 -0
  71. package/dist/model/schema.d.ts +1122 -0
  72. package/dist/model/schema.d.ts.map +1 -0
  73. package/dist/model/schema.js +178 -0
  74. package/dist/model/schema.js.map +1 -0
  75. package/dist/render/anatomy.d.ts +10 -0
  76. package/dist/render/anatomy.d.ts.map +1 -0
  77. package/dist/render/anatomy.js +77 -0
  78. package/dist/render/anatomy.js.map +1 -0
  79. package/dist/render/annotations.d.ts +9 -0
  80. package/dist/render/annotations.d.ts.map +1 -0
  81. package/dist/render/annotations.js +185 -0
  82. package/dist/render/annotations.js.map +1 -0
  83. package/dist/render/context.d.ts +16 -0
  84. package/dist/render/context.d.ts.map +1 -0
  85. package/dist/render/context.js +2 -0
  86. package/dist/render/context.js.map +1 -0
  87. package/dist/render/figure.d.ts +8 -0
  88. package/dist/render/figure.d.ts.map +1 -0
  89. package/dist/render/figure.js +138 -0
  90. package/dist/render/figure.js.map +1 -0
  91. package/dist/render/index.d.ts +7 -0
  92. package/dist/render/index.d.ts.map +1 -0
  93. package/dist/render/index.js +7 -0
  94. package/dist/render/index.js.map +1 -0
  95. package/dist/render/project.d.ts +18 -0
  96. package/dist/render/project.d.ts.map +1 -0
  97. package/dist/render/project.js +35 -0
  98. package/dist/render/project.js.map +1 -0
  99. package/dist/render/props.d.ts +9 -0
  100. package/dist/render/props.d.ts.map +1 -0
  101. package/dist/render/props.js +178 -0
  102. package/dist/render/props.js.map +1 -0
  103. package/dist/render/raster.d.ts +19 -0
  104. package/dist/render/raster.d.ts.map +1 -0
  105. package/dist/render/raster.js +39 -0
  106. package/dist/render/raster.js.map +1 -0
  107. package/dist/render/scene.d.ts +26 -0
  108. package/dist/render/scene.d.ts.map +1 -0
  109. package/dist/render/scene.js +144 -0
  110. package/dist/render/scene.js.map +1 -0
  111. package/dist/render/sheet.d.ts +20 -0
  112. package/dist/render/sheet.d.ts.map +1 -0
  113. package/dist/render/sheet.js +74 -0
  114. package/dist/render/sheet.js.map +1 -0
  115. package/dist/render/styles.d.ts +77 -0
  116. package/dist/render/styles.d.ts.map +1 -0
  117. package/dist/render/styles.js +122 -0
  118. package/dist/render/styles.js.map +1 -0
  119. package/dist/render/svg.d.ts +19 -0
  120. package/dist/render/svg.d.ts.map +1 -0
  121. package/dist/render/svg.js +40 -0
  122. package/dist/render/svg.js.map +1 -0
  123. package/dist/standards/keypoints.d.ts +31 -0
  124. package/dist/standards/keypoints.d.ts.map +1 -0
  125. package/dist/standards/keypoints.js +118 -0
  126. package/dist/standards/keypoints.js.map +1 -0
  127. package/docs/AUTHORING.md +144 -0
  128. package/package.json +94 -0
  129. package/poses/surf/bottom-turn.pose.yaml +47 -0
  130. package/poses/surf/cutback.pose.yaml +47 -0
  131. package/poses/surf/duck-dive.pose.yaml +47 -0
  132. package/poses/surf/noseride.pose.yaml +48 -0
  133. package/poses/surf/paddling.pose.yaml +48 -0
  134. package/poses/surf/pop-up.pose.yaml +47 -0
  135. package/poses/surf/takeoff.pose.yaml +47 -0
  136. package/poses/surf/tube-stance.pose.yaml +47 -0
  137. package/poses/yoga/ashtanga/adho-mukha-svanasana.pose.yaml +42 -0
  138. package/poses/yoga/ashtanga/ardha-uttanasana.pose.yaml +42 -0
  139. package/poses/yoga/ashtanga/baddha-konasana.pose.yaml +42 -0
  140. package/poses/yoga/ashtanga/balasana.pose.yaml +43 -0
  141. package/poses/yoga/ashtanga/chaturanga-dandasana.pose.yaml +41 -0
  142. package/poses/yoga/ashtanga/dandasana.pose.yaml +42 -0
  143. package/poses/yoga/ashtanga/halasana.pose.yaml +43 -0
  144. package/poses/yoga/ashtanga/janu-sirsasana-a.pose.yaml +42 -0
  145. package/poses/yoga/ashtanga/karnapidasana.pose.yaml +43 -0
  146. package/poses/yoga/ashtanga/marichyasana-a.pose.yaml +42 -0
  147. package/poses/yoga/ashtanga/marichyasana-c.pose.yaml +42 -0
  148. package/poses/yoga/ashtanga/matsyasana.pose.yaml +43 -0
  149. package/poses/yoga/ashtanga/navasana.pose.yaml +42 -0
  150. package/poses/yoga/ashtanga/padahastasana.pose.yaml +42 -0
  151. package/poses/yoga/ashtanga/padangusthasana.pose.yaml +42 -0
  152. package/poses/yoga/ashtanga/padmasana.pose.yaml +43 -0
  153. package/poses/yoga/ashtanga/parsvottanasana.pose.yaml +42 -0
  154. package/poses/yoga/ashtanga/paschimottanasana.pose.yaml +42 -0
  155. package/poses/yoga/ashtanga/prasarita-padottanasana-a.pose.yaml +46 -0
  156. package/poses/yoga/ashtanga/prasarita-padottanasana-c.pose.yaml +46 -0
  157. package/poses/yoga/ashtanga/primary.seq.yaml +74 -0
  158. package/poses/yoga/ashtanga/purvottanasana.pose.yaml +42 -0
  159. package/poses/yoga/ashtanga/salamba-sarvangasana.pose.yaml +43 -0
  160. package/poses/yoga/ashtanga/samasthiti.pose.yaml +29 -0
  161. package/poses/yoga/ashtanga/savasana.pose.yaml +43 -0
  162. package/poses/yoga/ashtanga/setu-bandhasana.pose.yaml +42 -0
  163. package/poses/yoga/ashtanga/sirsasana.pose.yaml +43 -0
  164. package/poses/yoga/ashtanga/supta-padangusthasana.pose.yaml +42 -0
  165. package/poses/yoga/ashtanga/upavistha-konasana.pose.yaml +42 -0
  166. package/poses/yoga/ashtanga/urdhva-dhanurasana.pose.yaml +43 -0
  167. package/poses/yoga/ashtanga/urdhva-hastasana.pose.yaml +42 -0
  168. package/poses/yoga/ashtanga/urdhva-mukha-svanasana.pose.yaml +42 -0
  169. package/poses/yoga/ashtanga/utkatasana.pose.yaml +42 -0
  170. package/poses/yoga/ashtanga/uttanasana.pose.yaml +42 -0
  171. package/poses/yoga/ashtanga/utthita-parsvakonasana.pose.yaml +44 -0
  172. package/poses/yoga/ashtanga/utthita-trikonasana.pose.yaml +44 -0
  173. package/poses/yoga/ashtanga/virabhadrasana-a.pose.yaml +42 -0
  174. package/poses/yoga/ashtanga/virabhadrasana-b.pose.yaml +42 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/render.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAwDzC,eAAO,MAAM,sBAAsB,GAAI,SAAS,OAAO,KAAG,IAsFzD,CAAC"}
@@ -0,0 +1,103 @@
1
+ import { mkdir, writeFile } from 'node:fs/promises';
2
+ import { dirname, extname } from 'node:path';
3
+ import { expandSequence } from '../../library/index.js';
4
+ import { optimizeSvg, renderPng, renderSheet, renderSvg } from '../../render/index.js';
5
+ import { library, parseIntOption, parseStyle, resolvePose } from '../resolve.js';
6
+ const renderOptionsFrom = (o) => ({
7
+ style: parseStyle(o.style),
8
+ width: parseIntOption(o.width, 'width'),
9
+ height: parseIntOption(o.height, 'height'),
10
+ title: o.title === true,
11
+ caption: o.caption === true,
12
+ ...(o.muscles === undefined ? {} : { muscles: o.muscles }),
13
+ ...(o.background === undefined ? {} : { background: o.background }),
14
+ });
15
+ const write = async (path, svg, o) => {
16
+ await mkdir(dirname(path), { recursive: true });
17
+ const body = o.optimize === true ? optimizeSvg(svg) : svg;
18
+ if (extname(path).toLowerCase() === '.png') {
19
+ const width = o.scale === undefined ? undefined : parseIntOption(o.scale, 'scale');
20
+ await writeFile(path, renderPng(body, width === undefined ? {} : { width }));
21
+ }
22
+ else {
23
+ await writeFile(path, body);
24
+ }
25
+ process.stdout.write(`${path}\n`);
26
+ };
27
+ const withCommonOptions = (cmd) => cmd
28
+ .option('-s, --style <style>', 'stick | anatomy | silhouette | blueprint | ink | poster | minimal', 'stick')
29
+ .option('-w, --width <px>', 'canvas width', '600')
30
+ .option('-h, --height <px>', 'canvas height', '800')
31
+ .option('--title', 'draw the pose name above the figure')
32
+ .option('--caption', 'draw the teaching cues below the figure')
33
+ .option('--muscles', 'force the muscle layer on')
34
+ .option('--no-muscles', 'force the muscle layer off')
35
+ .option('--background <color>', 'background colour, or "none" for transparent')
36
+ .option('--optimize', 'run the SVG through svgo')
37
+ .option('--scale <px>', 'PNG output width in pixels (defaults to the canvas width)')
38
+ .option('--lib <dir>', 'load poses from this directory instead of the bundled library');
39
+ export const registerRenderCommands = (program) => {
40
+ withCommonOptions(program
41
+ .command('render <pose>')
42
+ .description('Render one pose (a .pose.yaml file, or a library id) to SVG or PNG')
43
+ .requiredOption('-o, --out <file>', 'output path; the extension picks the format (.svg or .png)')).action(async (ref, options) => {
44
+ const pose = await resolvePose(ref, options.lib);
45
+ await write(options.out, renderSvg(pose, renderOptionsFrom(options)), options);
46
+ });
47
+ withCommonOptions(program
48
+ .command('sheet [poses...]')
49
+ .description('Render many poses into one contact sheet')
50
+ .requiredOption('-o, --out <file>', 'output path (.svg or .png)')
51
+ .option('-c, --columns <n>', 'columns in the grid', '6')
52
+ .option('--sequence <id>', 'lay out a whole sequence in practice order')
53
+ .option('--all', 'every pose in the library')
54
+ .option('--sheet-title <text>', 'title printed across the top')
55
+ .option('--numbered', 'number each cell')).action(async (refs, options) => {
56
+ const lib = await library(options.lib);
57
+ let poses;
58
+ if (options.sequence !== undefined) {
59
+ const sequence = lib.sequences.get(options.sequence);
60
+ if (sequence === undefined) {
61
+ throw new Error(`Unknown sequence "${options.sequence}". Known: ${[...lib.sequences.keys()].join(', ')}`);
62
+ }
63
+ poses = expandSequence(sequence, lib).map((step) => ({ ...step.pose, name: step.label }));
64
+ }
65
+ else if (options.all === true) {
66
+ poses = [...lib.poses.values()];
67
+ }
68
+ else {
69
+ poses = await Promise.all(refs.map((ref) => resolvePose(ref, options.lib)));
70
+ }
71
+ if (poses.length === 0)
72
+ throw new Error('Nothing to render: pass pose ids, --all, or --sequence <id>');
73
+ const sheetOptions = {
74
+ ...renderOptionsFrom(options),
75
+ columns: parseIntOption(options.columns, 'columns'),
76
+ cellWidth: parseIntOption(options.width, 'width'),
77
+ cellHeight: parseIntOption(options.height, 'height'),
78
+ title: true,
79
+ ...(options.sheetTitle === undefined ? {} : { sheetTitle: options.sheetTitle }),
80
+ ...(options.numbered === undefined ? {} : { numbered: options.numbered }),
81
+ };
82
+ await write(options.out, renderSheet(poses, sheetOptions), options);
83
+ });
84
+ withCommonOptions(program
85
+ .command('sequence <id>')
86
+ .description('Render every pose of a sequence into a directory, numbered in practice order')
87
+ .requiredOption('-o, --out <dir>', 'output directory')
88
+ .option('--format <ext>', 'svg or png', 'svg')).action(async (id, options) => {
89
+ const lib = await library(options.lib);
90
+ const sequence = lib.sequences.get(id);
91
+ if (sequence === undefined) {
92
+ throw new Error(`Unknown sequence "${id}". Known: ${[...lib.sequences.keys()].join(', ')}`);
93
+ }
94
+ const steps = expandSequence(sequence, lib);
95
+ const pad = String(steps.length).length;
96
+ for (const [i, step] of steps.entries()) {
97
+ const n = String(i + 1).padStart(pad, '0');
98
+ const path = `${options.out}/${n}-${step.pose.id}${step.side === 'right' ? '-right' : ''}.${options.format}`;
99
+ await write(path, renderSvg({ ...step.pose, name: step.label }, renderOptionsFrom(options)), options);
100
+ }
101
+ });
102
+ };
103
+ //# sourceMappingURL=render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../../../src/cli/commands/render.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import { PoseParseError } from '../model/index.js';
4
+ import { registerExportCommands } from './commands/export.js';
5
+ import { registerInfoCommands } from './commands/info.js';
6
+ import { registerRenderCommands } from './commands/render.js';
7
+ const program = new Command();
8
+ program
9
+ .name('asanakit')
10
+ .description('Programmatic stick-figure and anatomical infographics for yoga and surf postures.')
11
+ .version('0.1.0')
12
+ .showHelpAfterError();
13
+ registerRenderCommands(program);
14
+ registerInfoCommands(program);
15
+ registerExportCommands(program);
16
+ const fail = (error) => {
17
+ if (error instanceof PoseParseError) {
18
+ process.stderr.write(`${error.message}\n`);
19
+ }
20
+ else {
21
+ process.stderr.write(`asanakit: ${error instanceof Error ? error.message : String(error)}\n`);
22
+ }
23
+ process.exit(1);
24
+ };
25
+ try {
26
+ await program.parseAsync(process.argv);
27
+ }
28
+ catch (error) {
29
+ fail(error);
30
+ }
31
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAE9D,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,UAAU,CAAC;KAChB,WAAW,CAAC,mFAAmF,CAAC;KAChG,OAAO,CAAC,OAAO,CAAC;KAChB,kBAAkB,EAAE,CAAC;AAExB,sBAAsB,CAAC,OAAO,CAAC,CAAC;AAChC,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAC9B,sBAAsB,CAAC,OAAO,CAAC,CAAC;AAEhC,MAAM,IAAI,GAAG,CAAC,KAAc,EAAS,EAAE;IACrC,IAAI,KAAK,YAAY,cAAc,EAAE,CAAC;QACpC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;IAC7C,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAChG,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC;AAEF,IAAI,CAAC;IACH,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AACzC,CAAC;AAAC,OAAO,KAAK,EAAE,CAAC;IACf,IAAI,CAAC,KAAK,CAAC,CAAC;AACd,CAAC"}
@@ -0,0 +1,12 @@
1
+ import { type Library } from '../library/index.js';
2
+ import { type PoseSpec } from '../model/index.js';
3
+ import { type StyleId } from '../render/index.js';
4
+ export declare const library: (root?: string) => Promise<Library>;
5
+ /**
6
+ * A pose reference is either a path to a .pose.yaml file or an id in the bundled
7
+ * library. Files win, so a local override never silently resolves to a built-in.
8
+ */
9
+ export declare const resolvePose: (ref: string, libRoot?: string) => Promise<PoseSpec>;
10
+ export declare const parseStyle: (value: string) => StyleId;
11
+ export declare const parseIntOption: (value: string, name: string) => number;
12
+ //# sourceMappingURL=resolve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/cli/resolve.ts"],"names":[],"mappings":"AACA,OAAO,EAAe,KAAK,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAgB,KAAK,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,EAAwB,KAAK,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAIxE,eAAO,MAAM,OAAO,GAAU,OAAO,MAAM,KAAG,OAAO,CAAC,OAAO,CAI5D,CAAC;AAUF;;;GAGG;AACH,eAAO,MAAM,WAAW,GAAU,KAAK,MAAM,EAAE,UAAU,MAAM,KAAG,OAAO,CAAC,QAAQ,CAUjF,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,OAAO,MAAM,KAAG,OAG1C,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,OAAO,MAAM,EAAE,MAAM,MAAM,KAAG,MAI5D,CAAC"}
@@ -0,0 +1,46 @@
1
+ import { stat } from 'node:fs/promises';
2
+ import { loadLibrary } from '../library/index.js';
3
+ import { loadPoseFile } from '../model/index.js';
4
+ import { isStyleId, STYLE_IDS } from '../render/index.js';
5
+ let cached = null;
6
+ export const library = async (root) => {
7
+ if (root !== undefined)
8
+ return loadLibrary(root);
9
+ cached ??= await loadLibrary();
10
+ return cached;
11
+ };
12
+ const isFile = async (path) => {
13
+ try {
14
+ return (await stat(path)).isFile();
15
+ }
16
+ catch {
17
+ return false;
18
+ }
19
+ };
20
+ /**
21
+ * A pose reference is either a path to a .pose.yaml file or an id in the bundled
22
+ * library. Files win, so a local override never silently resolves to a built-in.
23
+ */
24
+ export const resolvePose = async (ref, libRoot) => {
25
+ if (await isFile(ref))
26
+ return loadPoseFile(ref);
27
+ const lib = await library(libRoot);
28
+ const pose = lib.poses.get(ref);
29
+ if (pose === undefined) {
30
+ const known = [...lib.poses.keys()].slice(0, 8).join(', ');
31
+ throw new Error(`No pose file or library id "${ref}". Try: ${known}... (run "asanakit list")`);
32
+ }
33
+ return pose;
34
+ };
35
+ export const parseStyle = (value) => {
36
+ if (!isStyleId(value))
37
+ throw new Error(`Unknown style "${value}". Available: ${STYLE_IDS.join(', ')}`);
38
+ return value;
39
+ };
40
+ export const parseIntOption = (value, name) => {
41
+ const n = Number(value);
42
+ if (!Number.isFinite(n) || n <= 0)
43
+ throw new Error(`--${name} must be a positive number, got "${value}"`);
44
+ return n;
45
+ };
46
+ //# sourceMappingURL=resolve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../src/cli/resolve.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,OAAO,EAAE,WAAW,EAAgB,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,YAAY,EAAiB,MAAM,mBAAmB,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAgB,MAAM,oBAAoB,CAAC;AAExE,IAAI,MAAM,GAAmB,IAAI,CAAC;AAElC,MAAM,CAAC,MAAM,OAAO,GAAG,KAAK,EAAE,IAAa,EAAoB,EAAE;IAC/D,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,WAAW,CAAC,IAAI,CAAC,CAAC;IACjD,MAAM,KAAK,MAAM,WAAW,EAAE,CAAC;IAC/B,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF,MAAM,MAAM,GAAG,KAAK,EAAE,IAAY,EAAoB,EAAE;IACtD,IAAI,CAAC;QACH,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAAE,GAAW,EAAE,OAAgB,EAAqB,EAAE;IACpF,IAAI,MAAM,MAAM,CAAC,GAAG,CAAC;QAAE,OAAO,YAAY,CAAC,GAAG,CAAC,CAAC;IAEhD,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IACnC,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAChC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,MAAM,KAAK,GAAG,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3D,MAAM,IAAI,KAAK,CAAC,+BAA+B,GAAG,WAAW,KAAK,2BAA2B,CAAC,CAAC;IACjG,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,KAAa,EAAW,EAAE;IACnD,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,KAAK,iBAAiB,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACvG,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,KAAa,EAAE,IAAY,EAAU,EAAE;IACpE,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IACxB,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,KAAK,IAAI,oCAAoC,KAAK,GAAG,CAAC,CAAC;IAC1G,OAAO,CAAC,CAAC;AACX,CAAC,CAAC"}
@@ -0,0 +1,12 @@
1
+ type Point = readonly [number, number];
2
+ export declare const degToRad: (deg: number) => number;
3
+ export declare const radToDeg: (rad: number) => number;
4
+ /** Wrap an angle into the half-open range (-180, 180]. */
5
+ export declare const normalizeDeg: (deg: number) => number;
6
+ /**
7
+ * Interior angle at `b` formed by the segments b->a and b->c, in [0, 180].
8
+ * This is how anatomy reports joint angles: 180 = fully extended limb.
9
+ */
10
+ export declare const interiorAngle: (a: Point, b: Point, c: Point) => number;
11
+ export {};
12
+ //# sourceMappingURL=angles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"angles.d.ts","sourceRoot":"","sources":["../../src/core/angles.ts"],"names":[],"mappings":"AAAA,KAAK,KAAK,GAAG,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAMvC,eAAO,MAAM,QAAQ,GAAI,KAAK,MAAM,KAAG,MAA2B,CAAC;AAEnE,eAAO,MAAM,QAAQ,GAAI,KAAK,MAAM,KAAG,MAA2B,CAAC;AAEnE,0DAA0D;AAC1D,eAAO,MAAM,YAAY,GAAI,KAAK,MAAM,KAAG,MAG1C,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,aAAa,GAAI,GAAG,KAAK,EAAE,GAAG,KAAK,EAAE,GAAG,KAAK,KAAG,MAU5D,CAAC"}
@@ -0,0 +1,27 @@
1
+ const DEG_PER_RAD = 180 / Math.PI;
2
+ const HALF_TURN = 180;
3
+ const FULL_TURN = 360;
4
+ export const degToRad = (deg) => deg / DEG_PER_RAD;
5
+ export const radToDeg = (rad) => rad * DEG_PER_RAD;
6
+ /** Wrap an angle into the half-open range (-180, 180]. */
7
+ export const normalizeDeg = (deg) => {
8
+ const wrapped = ((deg % FULL_TURN) + FULL_TURN) % FULL_TURN;
9
+ return wrapped > HALF_TURN ? wrapped - FULL_TURN : wrapped;
10
+ };
11
+ /**
12
+ * Interior angle at `b` formed by the segments b->a and b->c, in [0, 180].
13
+ * This is how anatomy reports joint angles: 180 = fully extended limb.
14
+ */
15
+ export const interiorAngle = (a, b, c) => {
16
+ const ux = a[0] - b[0];
17
+ const uy = a[1] - b[1];
18
+ const vx = c[0] - b[0];
19
+ const vy = c[1] - b[1];
20
+ const lu = Math.hypot(ux, uy);
21
+ const lv = Math.hypot(vx, vy);
22
+ if (lu === 0 || lv === 0)
23
+ return 0;
24
+ const cos = Math.min(1, Math.max(-1, (ux * vx + uy * vy) / (lu * lv)));
25
+ return radToDeg(Math.acos(cos));
26
+ };
27
+ //# sourceMappingURL=angles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"angles.js","sourceRoot":"","sources":["../../src/core/angles.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,GAAG,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC;AAClC,MAAM,SAAS,GAAG,GAAG,CAAC;AACtB,MAAM,SAAS,GAAG,GAAG,CAAC;AAEtB,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,GAAW,EAAU,EAAE,CAAC,GAAG,GAAG,WAAW,CAAC;AAEnE,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,GAAW,EAAU,EAAE,CAAC,GAAG,GAAG,WAAW,CAAC;AAEnE,0DAA0D;AAC1D,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,GAAW,EAAU,EAAE;IAClD,MAAM,OAAO,GAAG,CAAC,CAAC,GAAG,GAAG,SAAS,CAAC,GAAG,SAAS,CAAC,GAAG,SAAS,CAAC;IAC5D,OAAO,OAAO,GAAG,SAAS,CAAC,CAAC,CAAC,OAAO,GAAG,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC;AAC7D,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAQ,EAAE,CAAQ,EAAE,CAAQ,EAAU,EAAE;IACpE,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACvB,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACvB,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACvB,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACvB,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;IAC9B,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;IAC9B,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IACnC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;IACvE,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAClC,CAAC,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { Rig, ViewConfig, ViewId } from './types.js';
2
+ export declare const DEFAULT_RIG: Rig;
3
+ /**
4
+ * Views are 2D projections of a 3D body, so they only need two foreshortening
5
+ * factors plus a rule for which way the feet point.
6
+ */
7
+ export declare const VIEWS: Record<ViewId, ViewConfig>;
8
+ //# sourceMappingURL=rig.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rig.d.ts","sourceRoot":"","sources":["../../src/core/rig.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAW,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAwFnE,eAAO,MAAM,WAAW,EAAE,GAIzB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAK5C,CAAC"}
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Bone lengths are fractions of stature (1.0 = sole to crown) and follow the
3
+ * classic 7.5-heads canon used in anatomical drawing, with hip height at ~0.53
4
+ * of stature. The rig is authored for the figure's LEFT side and the center
5
+ * chain; the right side is generated by mirroring, so a symmetric pose needs
6
+ * the same joint angles on both sides.
7
+ *
8
+ * `restAngle` is the bone's angle relative to its parent bone in the neutral
9
+ * standing pose. A pose therefore expresses joint rotations the way anatomy
10
+ * does: as a deviation from anatomical neutral.
11
+ */
12
+ const CENTER_BONES = [
13
+ { id: 'pelvis', parent: null, attach: 'end', length: 0.1, restAngle: 0, side: 'center', group: 'torso' },
14
+ { id: 'spine', parent: 'pelvis', attach: 'end', length: 0.17, restAngle: 0, side: 'center', group: 'torso' },
15
+ { id: 'neck', parent: 'spine', attach: 'end', length: 0.06, restAngle: 0, side: 'center', group: 'torso' },
16
+ { id: 'head', parent: 'neck', attach: 'end', length: 0.13, restAngle: 0, side: 'center', group: 'head' },
17
+ ];
18
+ const LEFT_BONES = [
19
+ {
20
+ id: 'clavicleL',
21
+ parent: 'spine',
22
+ attach: 'end',
23
+ length: 0.1,
24
+ restAngle: -90,
25
+ side: 'left',
26
+ group: 'torso',
27
+ lateral: true,
28
+ },
29
+ {
30
+ id: 'upperArmL',
31
+ parent: 'clavicleL',
32
+ attach: 'end',
33
+ angleParent: 'spine',
34
+ length: 0.165,
35
+ restAngle: 180,
36
+ side: 'left',
37
+ group: 'arm',
38
+ },
39
+ { id: 'forearmL', parent: 'upperArmL', attach: 'end', length: 0.145, restAngle: 0, side: 'left', group: 'arm' },
40
+ { id: 'handL', parent: 'forearmL', attach: 'end', length: 0.055, restAngle: 0, side: 'left', group: 'arm' },
41
+ {
42
+ id: 'hipL',
43
+ parent: 'pelvis',
44
+ attach: 'start',
45
+ length: 0.085,
46
+ restAngle: -90,
47
+ side: 'left',
48
+ group: 'torso',
49
+ lateral: true,
50
+ },
51
+ {
52
+ id: 'thighL',
53
+ parent: 'hipL',
54
+ attach: 'end',
55
+ angleParent: 'pelvis',
56
+ length: 0.245,
57
+ restAngle: 180,
58
+ side: 'left',
59
+ group: 'leg',
60
+ },
61
+ { id: 'shinL', parent: 'thighL', attach: 'end', length: 0.245, restAngle: 0, side: 'left', group: 'leg', flexSign: -1 },
62
+ {
63
+ id: 'footL',
64
+ parent: 'shinL',
65
+ attach: 'end',
66
+ length: 0.09,
67
+ restAngle: 70,
68
+ side: 'left',
69
+ group: 'leg',
70
+ foot: true,
71
+ },
72
+ ];
73
+ const RIGHT_SUFFIX = /L$/;
74
+ const mirrorId = (id) => (RIGHT_SUFFIX.test(id) ? id.replace(RIGHT_SUFFIX, 'R') : id);
75
+ const mirrorBone = (bone) => ({
76
+ ...bone,
77
+ id: mirrorId(bone.id),
78
+ parent: bone.parent === null ? null : mirrorId(bone.parent),
79
+ ...(bone.angleParent === undefined ? {} : { angleParent: mirrorId(bone.angleParent) }),
80
+ side: 'right',
81
+ });
82
+ export const DEFAULT_RIG = {
83
+ name: 'humanoid-2d',
84
+ // Parents precede children, so a single forward pass solves the chain.
85
+ bones: [...CENTER_BONES, ...LEFT_BONES, ...LEFT_BONES.map(mirrorBone)],
86
+ };
87
+ /**
88
+ * Views are 2D projections of a 3D body, so they only need two foreshortening
89
+ * factors plus a rule for which way the feet point.
90
+ */
91
+ export const VIEWS = {
92
+ front: { lateralScale: 1, footScale: 0.45, mirrorLimbs: true },
93
+ back: { lateralScale: 1, footScale: 0.45, mirrorLimbs: true },
94
+ side: { lateralScale: 0.18, footScale: 1, mirrorLimbs: false },
95
+ 'three-quarter': { lateralScale: 0.7, footScale: 0.8, mirrorLimbs: false },
96
+ };
97
+ //# sourceMappingURL=rig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rig.js","sourceRoot":"","sources":["../../src/core/rig.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { BoneDef, KinematicPose, Rig, Skeleton, ViewId } from './types.js';
2
+ /**
3
+ * Which way a positive angle turns a right-side bone.
4
+ *
5
+ * Lateral bones (clavicle, hip) always mirror - that is what puts the right
6
+ * shoulder on the other side of the spine. Limbs only mirror when the figure
7
+ * faces us; in profile both arms swing the same way, because we are looking at
8
+ * both of them from the same side.
9
+ */
10
+ export declare const sideSign: (bone: BoneDef, view: ViewId) => number;
11
+ /**
12
+ * Forward kinematics: turn a pose (joint angles) into world-space bone segments,
13
+ * named landmarks and bounds. Pure and deterministic - the same pose always
14
+ * yields byte-identical geometry.
15
+ */
16
+ export declare const solveSkeleton: (pose: KinematicPose, rig: Rig) => Skeleton;
17
+ //# sourceMappingURL=skeleton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skeleton.d.ts","sourceRoot":"","sources":["../../src/core/skeleton.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,OAAO,EAIP,aAAa,EAEb,GAAG,EACH,QAAQ,EACR,MAAM,EACP,MAAM,YAAY,CAAC;AASpB;;;;;;;GAOG;AACH,eAAO,MAAM,QAAQ,GAAI,MAAM,OAAO,EAAE,MAAM,MAAM,KAAG,MAItD,CAAC;AA8GF;;;;GAIG;AACH,eAAO,MAAM,aAAa,GAAI,MAAM,aAAa,EAAE,KAAK,GAAG,KAAG,QAwB7D,CAAC"}
@@ -0,0 +1,144 @@
1
+ import { VIEWS } from './rig.js';
2
+ import { add, fromPolar, midpoint } from './vec2.js';
3
+ const boneLength = (bone, pose) => {
4
+ const view = VIEWS[pose.view];
5
+ const foreshorten = (bone.lateral ? view.lateralScale : 1) * (bone.foot ? view.footScale : 1);
6
+ return bone.length * foreshorten * pose.root.scale;
7
+ };
8
+ /**
9
+ * Which way a positive angle turns a right-side bone.
10
+ *
11
+ * Lateral bones (clavicle, hip) always mirror - that is what puts the right
12
+ * shoulder on the other side of the spine. Limbs only mirror when the figure
13
+ * faces us; in profile both arms swing the same way, because we are looking at
14
+ * both of them from the same side.
15
+ */
16
+ export const sideSign = (bone, view) => {
17
+ if (bone.side !== 'right')
18
+ return 1;
19
+ if (bone.lateral === true)
20
+ return -1;
21
+ return VIEWS[view].mirrorLimbs ? -1 : 1;
22
+ };
23
+ /**
24
+ * Where the left/right offset points on screen.
25
+ *
26
+ * Facing the viewer it lies in the picture plane, so it swings with the torso: a
27
+ * tilted chest tilts the shoulder line. Seen from the side it points into the
28
+ * screen, so it must project as a small sideways nudge and nothing else - if it
29
+ * rotated with the torso, a figure in a horizontal plank would end up with one
30
+ * shoulder above the other and one hand hovering off the floor.
31
+ */
32
+ const isDepthAxis = (bone, view) => bone.lateral === true && VIEWS[view].lateralScale < 1;
33
+ const relativeAngle = (bone, pose, parentAngle, joint) => {
34
+ if (isDepthAxis(bone, pose.view))
35
+ return bone.side === 'right' ? 180 : 0;
36
+ return parentAngle + sideSign(bone, pose.view) * (bone.restAngle + joint);
37
+ };
38
+ const assertKnownJoints = (pose, rig) => {
39
+ const known = new Set(rig.bones.map((b) => b.id));
40
+ const names = [...Object.keys(pose.joints), ...Object.keys(pose.world ?? {})];
41
+ for (const joint of names) {
42
+ if (!known.has(joint)) {
43
+ throw new Error(`Unknown bone "${joint}". Known bones: ${[...known].sort().join(', ')}`);
44
+ }
45
+ }
46
+ };
47
+ /** Where a bone begins: the start or the end of the bone it hangs off. */
48
+ const originOf = (bone, parent, pose) => {
49
+ if (parent === null)
50
+ return pose.root.position;
51
+ return bone.attach === 'start' ? parent.start : parent.end;
52
+ };
53
+ /** Which direction this bone's rest angle is measured against. */
54
+ const aimOf = (bone, parent, solved, pose) => {
55
+ const aimedAt = bone.angleParent === undefined ? parent : solved[bone.angleParent];
56
+ return aimedAt === null || aimedAt === undefined ? pose.root.rotation : aimedAt.worldAngle;
57
+ };
58
+ const solveBone = (bone, solved, pose) => {
59
+ const parent = bone.parent === null ? null : solved[bone.parent];
60
+ if (bone.parent !== null && parent === undefined) {
61
+ throw new Error(`Bone "${bone.id}" is listed before its parent "${bone.parent}"`);
62
+ }
63
+ const joint = (pose.joints[bone.id] ?? 0) * (bone.flexSign ?? 1);
64
+ const worldAngle = pose.world?.[bone.id] ?? relativeAngle(bone, pose, aimOf(bone, parent ?? null, solved, pose), joint);
65
+ const start = originOf(bone, parent ?? null, pose);
66
+ const length = boneLength(bone, pose);
67
+ return {
68
+ id: bone.id,
69
+ start,
70
+ end: add(start, fromPolar(worldAngle, length)),
71
+ worldAngle,
72
+ length,
73
+ side: bone.side,
74
+ group: bone.group,
75
+ };
76
+ };
77
+ const solveBones = (pose, rig) => {
78
+ const solved = {};
79
+ for (const bone of rig.bones)
80
+ solved[bone.id] = solveBone(bone, solved, pose);
81
+ return solved;
82
+ };
83
+ const landmarksOf = (b) => ({
84
+ hipCenter: b.pelvis.start,
85
+ waist: b.pelvis.end,
86
+ chest: b.spine.end,
87
+ neckBase: b.neck.start,
88
+ headCenter: midpoint(b.head.start, b.head.end),
89
+ headTop: b.head.end,
90
+ shoulderL: b.clavicleL.end,
91
+ elbowL: b.upperArmL.end,
92
+ wristL: b.forearmL.end,
93
+ handTipL: b.handL.end,
94
+ shoulderR: b.clavicleR.end,
95
+ elbowR: b.upperArmR.end,
96
+ wristR: b.forearmR.end,
97
+ handTipR: b.handR.end,
98
+ hipJointL: b.hipL.end,
99
+ kneeL: b.thighL.end,
100
+ ankleL: b.shinL.end,
101
+ toeL: b.footL.end,
102
+ hipJointR: b.hipR.end,
103
+ kneeR: b.thighR.end,
104
+ ankleR: b.shinR.end,
105
+ toeR: b.footR.end,
106
+ });
107
+ const boundsOf = (points) => ({
108
+ minX: Math.min(...points.map((p) => p[0])),
109
+ maxX: Math.max(...points.map((p) => p[0])),
110
+ minY: Math.min(...points.map((p) => p[1])),
111
+ maxY: Math.max(...points.map((p) => p[1])),
112
+ });
113
+ const transformPoint = (p, dy, flip) => [flip ? -p[0] : p[0], p[1] + dy];
114
+ const transformBone = (bone, dy, flip) => ({
115
+ ...bone,
116
+ start: transformPoint(bone.start, dy, flip),
117
+ end: transformPoint(bone.end, dy, flip),
118
+ worldAngle: flip ? 180 - bone.worldAngle : bone.worldAngle,
119
+ });
120
+ /**
121
+ * Forward kinematics: turn a pose (joint angles) into world-space bone segments,
122
+ * named landmarks and bounds. Pure and deterministic - the same pose always
123
+ * yields byte-identical geometry.
124
+ */
125
+ export const solveSkeleton = (pose, rig) => {
126
+ assertKnownJoints(pose, rig);
127
+ const raw = solveBones(pose, rig);
128
+ const rawPoints = Object.values(raw).flatMap((b) => [b.start, b.end]);
129
+ const dy = pose.grounded ? -boundsOf(rawPoints).minY : 0;
130
+ const flip = pose.flip ?? false;
131
+ const bones = Object.fromEntries(Object.entries(raw).map(([id, bone]) => [id, transformBone(bone, dy, flip)]));
132
+ const landmarks = landmarksOf(bones);
133
+ const bounds = boundsOf(Object.values(bones).flatMap((b) => [b.start, b.end]));
134
+ return {
135
+ rig,
136
+ view: pose.view,
137
+ scale: pose.root.scale,
138
+ bones,
139
+ landmarks,
140
+ bounds,
141
+ height: bounds.maxY - bounds.minY,
142
+ };
143
+ };
144
+ //# sourceMappingURL=skeleton.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skeleton.js","sourceRoot":"","sources":["../../src/core/skeleton.ts"],"names":[],"mappings":"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"}