angle-between-landmarks
Version:
This library calculates the angle between three landmarks
1 lines • 5.95 kB
Source Map (JSON)
{"version":3,"file":"index.cjs","sources":["../src/index.ts"],"sourcesContent":["/**\n * Calculate angles between landmarks\n * @author Yousuf Kalim\n */\n\n/**\n * With this function we will calculate the degrees of an angle\n * @param {Number} x1 first joint's x-axis\n * @param {Number} y1 first joint's y-axis\n * @param {Number} x2 second joint's x-axis\n * @param {Number} y2 second joint's y-axis\n * @param {Number} x3 third joint's x-axis\n * @param {Number} y3 third joint's y-axis\n * @param {Boolean} small boolean value to check if we have to return lower or upper angles\n * @param {Boolean} round boolean value to check if we have to return round\n * @return {Number} degree 0 to 360\n */\nconst calculateDegrees = (\n x1: number,\n y1: number,\n x2: number,\n y2: number,\n x3: number,\n y3: number,\n small: boolean,\n round: boolean,\n): number => {\n // Making the radians from joint angles\n const A = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));\n const B = Math.sqrt(Math.pow(x2 - x3, 2) + Math.pow(y2 - y3, 2));\n const C = Math.sqrt(Math.pow(x3 - x1, 2) + Math.pow(y3 - y1, 2));\n const jointAngleRadians = Math.acos((B * B + A * A - C * C) / (2 * B * A));\n\n // Making the degree from radians angle\n let jointAngleDegrees = Math.round((jointAngleRadians * 180.0) / Math.PI);\n\n // This will prevent negative values (it will convert -90 to 270)\n jointAngleDegrees = (jointAngleDegrees + 360) % 360;\n\n if (small) {\n // we have to return lower angle\n jointAngleDegrees = Math.min(jointAngleDegrees, 360 - jointAngleDegrees);\n } else {\n // Otherwise we will send upper angle\n jointAngleDegrees = Math.max(jointAngleDegrees, 360 - jointAngleDegrees);\n }\n\n if (round) {\n // Making round from 0\n jointAngleDegrees = Math.round(jointAngleDegrees);\n }\n\n // Finally return the calculated angle\n return jointAngleDegrees;\n};\n\ninterface Landmarks {\n x: number | string;\n y: number | string;\n}\n\ninterface ValidateArgs {\n landmarks1: {\n x: number;\n y: number;\n };\n landmarks2: {\n x: number;\n y: number;\n };\n landmarks3: {\n x: number;\n y: number;\n };\n}\n\n// This function will validate the arguments\nconst validateArgs = (\n landmarks1: Landmarks,\n landmarks2: Landmarks,\n landmarks3: Landmarks,\n opt: { small: boolean; round: boolean },\n): ValidateArgs => {\n if (!landmarks1 || !landmarks2 || !landmarks3) {\n throw new Error('Please provide landmarks');\n }\n if (!opt) {\n throw new Error('Please provide options');\n }\n if (\n [landmarks1, landmarks2, landmarks3].some(\n (landmark) =>\n isNaN(parseFloat(landmark.x as string)) || isNaN(parseFloat(landmark.y as string)),\n )\n ) {\n throw new Error('Please provide landmarks with correct x and y values');\n }\n if (typeof opt.small !== 'boolean' || typeof opt.round !== 'boolean') {\n throw new Error('Please provide options with correct small and round values');\n }\n\n return {\n landmarks1: {\n x: parseFloat(landmarks1.x as string),\n y: parseFloat(landmarks1.y as string),\n },\n landmarks2: {\n x: parseFloat(landmarks2.x as string),\n y: parseFloat(landmarks2.y as string),\n },\n landmarks3: {\n x: parseFloat(landmarks3.x as string),\n y: parseFloat(landmarks3.y as string),\n },\n };\n};\n\n/**\n * With this function we will calculate the degrees of an angle\n * @return {Number} degree 0 to 360\n * @param landmarks1\n * @param landmarks2\n * @param landmarks3\n * @param opt\n */\nconst findAngle = (\n landmarks1: Landmarks,\n landmarks2: Landmarks,\n landmarks3: Landmarks,\n opt = { small: false, round: true },\n): number => {\n const validatedArgs = validateArgs(landmarks1, landmarks2, landmarks3, opt);\n const { x: x1, y: y1 } = validatedArgs.landmarks1;\n const { x: x2, y: y2 } = validatedArgs.landmarks2;\n const { x: x3, y: y3 } = validatedArgs.landmarks3;\n const { small, round } = opt;\n const angle = calculateDegrees(x1, y1, x2, y2, x3, y3, small, round);\n return angle;\n};\n\nexport default findAngle;\n"],"names":["landmarks1","landmarks2","landmarks3","opt","small","round","x1","y1","x2","y2","x3","y3","A","B","C","jointAngleRadians","jointAngleDegrees","validatedArgs","Error","some","landmark","isNaN","parseFloat","x","y","validateArgs","_validatedArgs$landma","_validatedArgs$landma2","Math","sqrt","pow","acos","PI","min","max"],"mappings":"eA6HkB,SAChBA,EACAC,EACAC,EACAC,QAAAA,IAAAA,IAAAA,EAAM,CAAEC,OAAO,EAAOC,OAAO,IAE7B,IAjHAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAP,EACAC,EAGMO,EACAC,EACAC,EACAC,EAGeC,EAiGFC,EAtDA,SACnBjB,EACAC,EACAC,EACAC,GAEA,IAAKH,IAAeC,IAAeC,EACjC,MAAM,IAASgB,MAAC,4BAElB,IAAKf,EACH,MAAM,UAAU,0BAElB,GACE,CAACH,EAAYC,EAAYC,GAAYiB,KACnC,SAACC,GAAQ,OACFC,MAACC,WAAWF,EAASG,KAAiBF,MAAMC,WAAWF,EAASI,GAAa,GAGtF,MAAM,IAASN,MAAC,wDAElB,GAAyB,kBAAdf,EAAIC,OAA4C,kBAAXD,EAACE,MAC/C,UAAea,MAAC,8DAGlB,MAAO,CACLlB,WAAY,CACVuB,EAAGD,WAAWtB,EAAWuB,GACzBC,EAAGF,WAAWtB,EAAWwB,IAE3BvB,WAAY,CACVsB,EAAGD,WAAWrB,EAAWsB,GACzBC,EAAGF,WAAWrB,EAAWuB,IAE3BtB,WAAY,CACVqB,EAAGD,WAAWpB,EAAWqB,GACzBC,EAAGF,WAAWpB,EAAWsB,IAG/B,CAgBwBC,CAAazB,EAAYC,EAAYC,EAAYC,GACvEuB,EAAyBT,EAAcjB,WACvC2B,EAAyBV,EAAchB,WACdgB,EAAAA,EAAcf,WAGvC,OAvHAI,EAkHaoB,EAALH,EAjHRhB,EAiHoBmB,EAALF,EAhHfhB,EAiHamB,EAALJ,EAhHRd,EAgHoBkB,EAALH,EA/Gfd,EAgHQa,EAAAA,EA/GRZ,EA+Gea,EAAAA,EA9GfpB,EA+GyBD,EAAjBC,MA9GRC,EA8GyBF,EAAVE,MA3GTO,EAAIgB,KAAKC,KAAKD,KAAKE,IAAItB,EAAKF,EAAI,GAAKsB,KAAKE,IAAIrB,EAAKF,EAAI,IACvDM,EAAIe,KAAKC,KAAKD,KAAKE,IAAItB,EAAKE,EAAI,GAAKkB,KAAKE,IAAIrB,EAAKE,EAAI,IACvDG,EAAIc,KAAKC,KAAKD,KAAKE,IAAIpB,EAAKJ,EAAI,GAAKsB,KAAKE,IAAInB,EAAKJ,EAAI,IACvDQ,EAAoBa,KAAKG,MAAMlB,EAAIA,EAAID,EAAIA,EAAIE,EAAIA,IAAM,EAAID,EAAID,IAMvEI,IAHqBA,EAAGY,KAAKvB,MAA2B,IAApBU,EAA6Ba,KAAKI,KAG7B,KAAO,IAI9ChB,EAFEZ,EAEkBwB,KAAKK,IAAIjB,EAAmB,IAAMA,GAGlCY,KAAKM,IAAIlB,EAAmB,IAAMA,GAGpDX,IAEFW,EAAoBY,KAAKvB,MAAMW,IAI1BA,CAqFT"}