react-native-nitro-pose-exercises 1.1.11 → 1.1.13
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.
|
@@ -616,53 +616,62 @@ if (!isPostureValid(config.postureFamily, config.visibilityThreshold)) {
|
|
|
616
616
|
// Posture Gates
|
|
617
617
|
// ═══════════════════════════════════════════════════════════
|
|
618
618
|
|
|
619
|
-
|
|
620
|
-
|
|
619
|
+
private fun isPostureValid(family: PostureFamily, threshold: Double): Boolean {
|
|
620
|
+
if (_landmarks.size < 33) return false
|
|
621
621
|
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
622
|
+
val ls = _landmarks[11]; val rs = _landmarks[12]
|
|
623
|
+
val lh = _landmarks[23]; val rh = _landmarks[24]
|
|
624
|
+
val lk = _landmarks[25]; val rk = _landmarks[26]
|
|
625
|
+
val la = _landmarks[27]; val ra = _landmarks[28]
|
|
626
626
|
|
|
627
|
-
|
|
627
|
+
// Only require torso visible — knees and ankles are optional
|
|
628
|
+
val torsoVisible = ls.visibility > threshold && rs.visibility > threshold &&
|
|
628
629
|
lh.visibility > threshold && rh.visibility > threshold
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
return when (family) {
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
630
|
+
if (!torsoVisible) return false
|
|
631
|
+
|
|
632
|
+
val shoulderY = (ls.y + rs.y) / 2
|
|
633
|
+
val hipY = (lh.y + rh.y) / 2
|
|
634
|
+
val shoulderX = (ls.x + rs.x) / 2
|
|
635
|
+
val hipX = (lh.x + rh.x) / 2
|
|
636
|
+
|
|
637
|
+
val kneesVisible = lk.visibility > threshold && rk.visibility > threshold
|
|
638
|
+
val anklesVisible = la.visibility > threshold && ra.visibility > threshold
|
|
639
|
+
val kneeY = if (kneesVisible) (lk.y + rk.y) / 2 else hipY
|
|
640
|
+
val ankleY = if (anklesVisible) (la.y + ra.y) / 2 else kneeY
|
|
641
|
+
|
|
642
|
+
return when (family) {
|
|
643
|
+
PostureFamily.HORIZONTALPRONE, PostureFamily.SUPINE -> {
|
|
644
|
+
val ys = if (anklesVisible)
|
|
645
|
+
listOf(shoulderY, hipY, ankleY)
|
|
646
|
+
else
|
|
647
|
+
listOf(shoulderY, hipY)
|
|
648
|
+
(ys.max() - ys.min()) < 0.25
|
|
649
|
+
}
|
|
650
|
+
PostureFamily.STANDINGUPRIGHT -> {
|
|
651
|
+
if (kneesVisible) {
|
|
652
|
+
shoulderY < hipY - 0.08 &&
|
|
653
|
+
hipY < kneeY + 0.05 &&
|
|
654
|
+
(if (anklesVisible) kneeY < ankleY else true)
|
|
655
|
+
} else {
|
|
656
|
+
shoulderY < hipY - 0.08
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
PostureFamily.SEATED -> {
|
|
660
|
+
if (kneesVisible) {
|
|
661
|
+
shoulderY < hipY - 0.05 && kotlin.math.abs(hipY - kneeY) < 0.20
|
|
662
|
+
} else {
|
|
663
|
+
shoulderY < hipY - 0.05
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
PostureFamily.SIDEPLANK -> {
|
|
667
|
+
val ySpread = kotlin.math.abs(shoulderY - hipY)
|
|
668
|
+
val shoulderHipDx = kotlin.math.abs(shoulderX - hipX)
|
|
669
|
+
ySpread < 0.20 && shoulderHipDx < 0.15
|
|
670
|
+
}
|
|
671
|
+
PostureFamily.INVERTED -> {
|
|
672
|
+
if (!anklesVisible) false
|
|
673
|
+
else hipY < shoulderY && hipY < ankleY
|
|
674
|
+
}
|
|
675
|
+
PostureFamily.NONE -> true
|
|
667
676
|
}
|
|
668
677
|
}
|
|
@@ -345,7 +345,7 @@ private func processExerciseLogic() {
|
|
|
345
345
|
// MARK: - Posture Gates
|
|
346
346
|
// ═══════════════════════════════════════════════════════════
|
|
347
347
|
|
|
348
|
-
private func isPostureValid(family: PostureFamily, threshold: Double) -> Bool
|
|
348
|
+
private func isPostureValid(family: PostureFamily, threshold: Double) -> Bool {
|
|
349
349
|
guard _landmarks.count >= 33 else { return false }
|
|
350
350
|
|
|
351
351
|
let ls = _landmarks[11], rs = _landmarks[12]
|
|
@@ -353,38 +353,55 @@ private func isPostureValid(family: PostureFamily, threshold: Double) -> Bool {
|
|
|
353
353
|
let lk = _landmarks[25], rk = _landmarks[26]
|
|
354
354
|
let la = _landmarks[27], ra = _landmarks[28]
|
|
355
355
|
|
|
356
|
-
|
|
357
|
-
|
|
356
|
+
// Only require torso visible — knees and ankles are optional
|
|
357
|
+
let torsoVisible = ls.visibility > threshold && rs.visibility > threshold
|
|
358
|
+
&& lh.visibility > threshold && rh.visibility > threshold
|
|
359
|
+
guard torsoVisible else { return false }
|
|
358
360
|
|
|
359
361
|
let shoulderY = (ls.y + rs.y) / 2
|
|
360
362
|
let hipY = (lh.y + rh.y) / 2
|
|
361
363
|
let shoulderX = (ls.x + rs.x) / 2
|
|
362
364
|
let hipX = (lh.x + rh.x) / 2
|
|
363
365
|
|
|
364
|
-
let kneesVisible = lk.visibility >
|
|
365
|
-
let anklesVisible = la.visibility >
|
|
366
|
+
let kneesVisible = lk.visibility > threshold && rk.visibility > threshold
|
|
367
|
+
let anklesVisible = la.visibility > threshold && ra.visibility > threshold
|
|
366
368
|
let kneeY = kneesVisible ? (lk.y + rk.y) / 2 : hipY
|
|
367
369
|
let ankleY = anklesVisible ? (la.y + ra.y) / 2 : kneeY
|
|
368
370
|
|
|
369
371
|
switch family {
|
|
370
372
|
case .horizontalprone, .supine:
|
|
371
|
-
|
|
373
|
+
// Horizontal body — torso, plus ankles if visible
|
|
374
|
+
let ys: [Double] = anklesVisible
|
|
375
|
+
? [shoulderY, hipY, ankleY]
|
|
376
|
+
: [shoulderY, hipY]
|
|
372
377
|
return ((ys.max() ?? 0) - (ys.min() ?? 0)) < 0.25
|
|
373
378
|
|
|
374
379
|
case .standingupright:
|
|
375
|
-
|
|
376
|
-
|
|
380
|
+
// Torso vertical (shoulders above hips). If knees visible, check chain.
|
|
381
|
+
if kneesVisible {
|
|
382
|
+
return shoulderY < hipY - 0.08
|
|
383
|
+
&& hipY < kneeY + 0.05
|
|
384
|
+
&& (anklesVisible ? kneeY < ankleY : true)
|
|
385
|
+
} else {
|
|
386
|
+
return shoulderY < hipY - 0.08
|
|
387
|
+
}
|
|
377
388
|
|
|
378
389
|
case .seated:
|
|
379
|
-
|
|
380
|
-
|
|
390
|
+
// Forward-leaning torso. If knees visible, also check hip-knee distance.
|
|
391
|
+
if kneesVisible {
|
|
392
|
+
return shoulderY < hipY - 0.05 && Swift.abs(hipY - kneeY) < 0.20
|
|
393
|
+
} else {
|
|
394
|
+
return shoulderY < hipY - 0.05
|
|
395
|
+
}
|
|
381
396
|
|
|
382
397
|
case .sideplank:
|
|
398
|
+
// Body horizontal, shoulders and hips stacked in x
|
|
383
399
|
let ySpread = Swift.abs(shoulderY - hipY)
|
|
384
400
|
let shoulderHipDx = Swift.abs(shoulderX - hipX)
|
|
385
401
|
return ySpread < 0.20 && shoulderHipDx < 0.15
|
|
386
402
|
|
|
387
403
|
case .inverted:
|
|
404
|
+
// Genuinely needs ankles — hips highest of all three
|
|
388
405
|
guard anklesVisible else { return false }
|
|
389
406
|
return hipY < shoulderY && hipY < ankleY
|
|
390
407
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-nitro-pose-exercises",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.13",
|
|
4
4
|
"description": "Real-time on-device exercise tracking for React Native. Rep counting, form validation, and skeleton overlay powered by Apple Vision (iOS) and Google ML Kit (Android) with VisionCamera v5 via Nitro Modules.",
|
|
5
5
|
"main": "./lib/module/index.js",
|
|
6
6
|
"types": "./lib/typescript/src/index.d.ts",
|
|
@@ -73,6 +73,7 @@
|
|
|
73
73
|
"@react-native/eslint-config": "0.85.3",
|
|
74
74
|
"@react-native/jest-preset": "0.85.3",
|
|
75
75
|
"@release-it/conventional-changelog": "^10.0.6",
|
|
76
|
+
"@shopify/react-native-skia": "^2.6.4",
|
|
76
77
|
"@types/react": "^19.2.0",
|
|
77
78
|
"commitlint": "^20.5.0",
|
|
78
79
|
"del-cli": "^7.0.0",
|