bowling-analysis-system
Version:
A comprehensive system for analyzing bowling techniques using video processing and metrics calculation
156 lines (126 loc) • 4.21 kB
JavaScript
/**
* @module metrics/calculations/angles/AlignmentAngles
* @description Functions for calculating body alignment and posture angles
*/
const { calculateAngleBetweenVectors, getSafeLandmark, createVector } = require('../MetricsUtilities');
/**
* Calculate shoulder alignments for both sides
* @param {Array} landmarks - Array of pose landmarks
* @returns {Object} Left and right shoulder alignments
*/
function calculateShoulderAlignments(landmarks) {
return {
left: calculateLeftShoulderAlignment(landmarks),
right: calculateRightShoulderAlignment(landmarks)
};
}
/**
* Calculate hip alignments for both sides
* @param {Array} landmarks - Array of pose landmarks
* @returns {Object} Left and right hip alignments
*/
function calculateHipAlignments(landmarks) {
return {
left: calculateLeftHipAlignment(landmarks),
right: calculateRightHipAlignment(landmarks)
};
}
/**
* Calculate torso to ground angle
* @param {Array} landmarks - Array of pose landmarks
* @returns {number} Torso to ground angle in degrees
*/
function calculateTorsoToGround(landmarks) {
const midShoulder = getCenterPoint(
getSafeLandmark(landmarks, 11),
getSafeLandmark(landmarks, 12)
);
const midHip = getCenterPoint(
getSafeLandmark(landmarks, 23),
getSafeLandmark(landmarks, 24)
);
if (!midShoulder || !midHip) return null;
const torso = createVector(midHip, midShoulder);
const vertical = { x: 0, y: 1, z: 0 };
return calculateAngleBetweenVectors(torso, vertical);
}
// Individual calculation functions
function calculateLeftShoulderAlignment(landmarks) {
const centerHip = getCenterPoint(
getSafeLandmark(landmarks, 23),
getSafeLandmark(landmarks, 24)
);
const leftShoulder = getSafeLandmark(landmarks, 11);
if (!centerHip || !leftShoulder) return null;
const leftShoulderVector = {
x: leftShoulder.x - centerHip.x,
y: 0,
z: leftShoulder.z - centerHip.z
};
const forward = { x: 0, y: 0, z: 1 };
return calculateAngleBetweenVectors(leftShoulderVector, forward);
}
function calculateRightShoulderAlignment(landmarks) {
const centerHip = getCenterPoint(
getSafeLandmark(landmarks, 23),
getSafeLandmark(landmarks, 24)
);
const rightShoulder = getSafeLandmark(landmarks, 12);
if (!centerHip || !rightShoulder) return null;
const rightShoulderVector = {
x: rightShoulder.x - centerHip.x,
y: 0,
z: rightShoulder.z - centerHip.z
};
const forward = { x: 0, y: 0, z: 1 };
return calculateAngleBetweenVectors(rightShoulderVector, forward);
}
function calculateLeftHipAlignment(landmarks) {
const centerShoulder = getCenterPoint(
getSafeLandmark(landmarks, 11),
getSafeLandmark(landmarks, 12)
);
const leftHip = getSafeLandmark(landmarks, 23);
if (!centerShoulder || !leftHip) return null;
const leftHipVector = {
x: leftHip.x - centerShoulder.x,
y: 0,
z: leftHip.z - centerShoulder.z
};
const forward = { x: 0, y: 0, z: 1 };
return calculateAngleBetweenVectors(leftHipVector, forward);
}
function calculateRightHipAlignment(landmarks) {
const centerShoulder = getCenterPoint(
getSafeLandmark(landmarks, 11),
getSafeLandmark(landmarks, 12)
);
const rightHip = getSafeLandmark(landmarks, 24);
if (!centerShoulder || !rightHip) return null;
const rightHipVector = {
x: rightHip.x - centerShoulder.x,
y: 0,
z: rightHip.z - centerShoulder.z
};
const forward = { x: 0, y: 0, z: 1 };
return calculateAngleBetweenVectors(rightHipVector, forward);
}
/**
* Get center point between two points
* @param {Object} point1 - First point
* @param {Object} point2 - Second point
* @returns {Object} Center point
*/
function getCenterPoint(point1, point2) {
if (!point1 || !point2) return null;
return {
x: (point1.x + point2.x) / 2,
y: (point1.y + point2.y) / 2,
z: (point1.z + point2.z) / 2
};
}
module.exports = {
calculateShoulderAlignments,
calculateHipAlignments,
calculateTorsoToGround
};