Files
Codeman/packages/gesture-control/src/gesture/landmarks.ts
T
arkonandClaude Opus 4.8 09a142d14b feat: vendor gesture-control source into packages/gesture-control
Bring the Ark0N/codeman-gesture-control repo in-tree as the codeman-gesture-control
workspace package so the hand-tracking overlay can be developed in the Codeman repo.
New npm run build:gesture bundles src/codeman/entry.ts into the served
gesture-codeman.js; scripts/build.mjs reruns it on every production build.
Source formatted to Codeman's prettier style.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 20:48:20 +02:00

79 lines
1.6 KiB
TypeScript

// MediaPipe hand landmark indices and the bone connections between them.
// See: https://developers.google.com/mediapipe/solutions/vision/hand_landmarker
//
// 21 landmarks per hand, each normalized to [0,1] in image space.
export const LANDMARK = {
WRIST: 0,
THUMB_CMC: 1,
THUMB_MCP: 2,
THUMB_IP: 3,
THUMB_TIP: 4,
INDEX_MCP: 5,
INDEX_PIP: 6,
INDEX_DIP: 7,
INDEX_TIP: 8,
MIDDLE_MCP: 9,
MIDDLE_PIP: 10,
MIDDLE_DIP: 11,
MIDDLE_TIP: 12,
RING_MCP: 13,
RING_PIP: 14,
RING_DIP: 15,
RING_TIP: 16,
PINKY_MCP: 17,
PINKY_PIP: 18,
PINKY_DIP: 19,
PINKY_TIP: 20,
} as const;
/** Pairs of landmark indices that form the hand skeleton, for overlay drawing. */
export const HAND_CONNECTIONS: ReadonlyArray<readonly [number, number]> = [
// Thumb
[0, 1],
[1, 2],
[2, 3],
[3, 4],
// Index
[0, 5],
[5, 6],
[6, 7],
[7, 8],
// Middle
[5, 9],
[9, 10],
[10, 11],
[11, 12],
// Ring
[9, 13],
[13, 14],
[14, 15],
[15, 16],
// Pinky
[13, 17],
[17, 18],
[18, 19],
[19, 20],
// Palm base
[0, 17],
];
export interface NormalizedLandmark {
x: number;
y: number;
z: number;
visibility?: number;
}
/** Euclidean distance between two normalized landmarks (x/y plane). */
export function dist2d(a: NormalizedLandmark, b: NormalizedLandmark): number {
const dx = a.x - b.x;
const dy = a.y - b.y;
return Math.hypot(dx, dy);
}
/** Midpoint of two normalized landmarks (x/y plane). */
export function midpoint(a: NormalizedLandmark, b: NormalizedLandmark): { x: number; y: number } {
return { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 };
}