Skip to main content

oxihuman_morph/
high_arch_morph.rs

1// Copyright (C) 2026 COOLJAPAN OU (Team KitaSan)
2// SPDX-License-Identifier: Apache-2.0
3#![allow(dead_code)]
4
5//! High arch (pes cavus) foot morph.
6
7/// High arch configuration.
8#[derive(Debug, Clone)]
9pub struct HighArchMorphConfig {
10    pub arch_rise: f32,
11    pub supination: f32,
12    pub claw_toe: f32,
13}
14
15impl Default for HighArchMorphConfig {
16    fn default() -> Self {
17        Self {
18            arch_rise: 0.0,
19            supination: 0.0,
20            claw_toe: 0.0,
21        }
22    }
23}
24
25/// High arch morph state.
26#[derive(Debug, Clone)]
27pub struct HighArchMorph {
28    pub config: HighArchMorphConfig,
29    pub intensity: f32,
30    pub enabled: bool,
31}
32
33impl HighArchMorph {
34    pub fn new() -> Self {
35        Self {
36            config: HighArchMorphConfig::default(),
37            intensity: 0.0,
38            enabled: true,
39        }
40    }
41}
42
43impl Default for HighArchMorph {
44    fn default() -> Self {
45        Self::new()
46    }
47}
48
49/// Create a new HighArchMorph.
50pub fn new_high_arch_morph() -> HighArchMorph {
51    HighArchMorph::new()
52}
53
54/// Set arch rise factor (0.0–1.0).
55pub fn high_arch_set_rise(morph: &mut HighArchMorph, v: f32) {
56    morph.config.arch_rise = v.clamp(0.0, 1.0);
57}
58
59/// Set supination factor (0.0–1.0).
60pub fn high_arch_set_supination(morph: &mut HighArchMorph, v: f32) {
61    morph.config.supination = v.clamp(0.0, 1.0);
62}
63
64/// Set claw toe deformation factor.
65pub fn high_arch_set_claw_toe(morph: &mut HighArchMorph, v: f32) {
66    morph.config.claw_toe = v.clamp(0.0, 1.0);
67}
68
69/// Compute effective arch height (1.0 = normal, >1.0 = raised).
70pub fn high_arch_height(morph: &HighArchMorph) -> f32 {
71    1.0 + morph.intensity * morph.config.arch_rise
72}
73
74/// Serialize to JSON.
75pub fn high_arch_to_json(morph: &HighArchMorph) -> String {
76    format!(
77        r#"{{"intensity":{},"arch_rise":{},"supination":{},"claw_toe":{}}}"#,
78        morph.intensity, morph.config.arch_rise, morph.config.supination, morph.config.claw_toe,
79    )
80}
81
82#[cfg(test)]
83mod tests {
84    use super::*;
85
86    #[test]
87    fn test_new() {
88        let m = new_high_arch_morph();
89        assert!((m.config.arch_rise - 0.0).abs() < 1e-6 /* default */);
90    }
91
92    #[test]
93    fn test_rise_clamp() {
94        let mut m = new_high_arch_morph();
95        high_arch_set_rise(&mut m, 3.0);
96        assert!((m.config.arch_rise - 1.0).abs() < 1e-6 /* clamped */);
97    }
98
99    #[test]
100    fn test_supination() {
101        let mut m = new_high_arch_morph();
102        high_arch_set_supination(&mut m, 0.5);
103        assert!((m.config.supination - 0.5).abs() < 1e-6 /* stored */);
104    }
105
106    #[test]
107    fn test_claw_toe() {
108        let mut m = new_high_arch_morph();
109        high_arch_set_claw_toe(&mut m, 0.2);
110        assert!((m.config.claw_toe - 0.2).abs() < 1e-6 /* stored */);
111    }
112
113    #[test]
114    fn test_height_normal() {
115        let m = new_high_arch_morph();
116        assert!((high_arch_height(&m) - 1.0).abs() < 1e-6 /* baseline */);
117    }
118
119    #[test]
120    fn test_height_raised() {
121        let mut m = new_high_arch_morph();
122        high_arch_set_rise(&mut m, 1.0);
123        m.intensity = 1.0;
124        assert!(high_arch_height(&m) > 1.0 /* raised */);
125    }
126
127    #[test]
128    fn test_json_keys() {
129        let m = new_high_arch_morph();
130        let j = high_arch_to_json(&m);
131        assert!(j.contains("arch_rise") /* key */);
132    }
133
134    #[test]
135    fn test_default_enabled() {
136        let m = HighArchMorph::default();
137        assert!(m.enabled /* enabled */);
138    }
139
140    #[test]
141    fn test_clone() {
142        let m = new_high_arch_morph();
143        let c = m.clone();
144        assert!((c.config.claw_toe - m.config.claw_toe).abs() < 1e-6 /* equal */);
145    }
146}