Skip to main content

oxihuman_morph/
condyle_morph.rs

1// Copyright (C) 2026 COOLJAPAN OU (Team KitaSan)
2// SPDX-License-Identifier: Apache-2.0
3#![allow(dead_code)]
4
5#[derive(Debug, Clone)]
6pub struct CondyleMorph {
7    pub offset_x: f32,
8    pub offset_y: f32,
9    pub size: f32,
10}
11
12pub fn new_condyle_morph() -> CondyleMorph {
13    CondyleMorph {
14        offset_x: 0.0,
15        offset_y: 0.0,
16        size: 0.0,
17    }
18}
19
20pub fn cy_set_offset_x(m: &mut CondyleMorph, v: f32) {
21    m.offset_x = v.clamp(-1.0, 1.0);
22}
23
24pub fn cy_set_offset_y(m: &mut CondyleMorph, v: f32) {
25    m.offset_y = v.clamp(-1.0, 1.0);
26}
27
28pub fn cy_set_size(m: &mut CondyleMorph, v: f32) {
29    m.size = v.clamp(0.0, 1.0);
30}
31
32pub fn cy_overall_weight(m: &CondyleMorph) -> f32 {
33    (m.offset_x.abs() + m.offset_y.abs() + m.size) / 3.0
34}
35
36pub fn cy_blend(a: &CondyleMorph, b: &CondyleMorph, t: f32) -> CondyleMorph {
37    let t = t.clamp(0.0, 1.0);
38    CondyleMorph {
39        offset_x: a.offset_x + (b.offset_x - a.offset_x) * t,
40        offset_y: a.offset_y + (b.offset_y - a.offset_y) * t,
41        size: a.size + (b.size - a.size) * t,
42    }
43}
44
45pub fn cy_is_displaced(m: &CondyleMorph) -> bool {
46    m.offset_x.abs() > 0.3 || m.offset_y.abs() > 0.3
47}
48
49#[cfg(test)]
50mod tests {
51    use super::*;
52
53    #[test]
54    fn test_new_defaults() {
55        /* zero init */
56        let m = new_condyle_morph();
57        assert_eq!(m.offset_x, 0.0);
58        assert_eq!(m.offset_y, 0.0);
59        assert_eq!(m.size, 0.0);
60    }
61
62    #[test]
63    fn test_set_offset_x() {
64        /* valid offset */
65        let mut m = new_condyle_morph();
66        cy_set_offset_x(&mut m, 0.5);
67        assert!((m.offset_x - 0.5).abs() < 1e-6);
68    }
69
70    #[test]
71    fn test_set_offset_x_clamp_high() {
72        /* clamp high */
73        let mut m = new_condyle_morph();
74        cy_set_offset_x(&mut m, 5.0);
75        assert_eq!(m.offset_x, 1.0);
76    }
77
78    #[test]
79    fn test_set_offset_y_clamp_low() {
80        /* clamp low */
81        let mut m = new_condyle_morph();
82        cy_set_offset_y(&mut m, -5.0);
83        assert_eq!(m.offset_y, -1.0);
84    }
85
86    #[test]
87    fn test_set_size() {
88        /* valid size */
89        let mut m = new_condyle_morph();
90        cy_set_size(&mut m, 0.6);
91        assert!((m.size - 0.6).abs() < 1e-6);
92    }
93
94    #[test]
95    fn test_overall_weight() {
96        /* average of abs offsets and size */
97        let m = CondyleMorph {
98            offset_x: 0.3,
99            offset_y: 0.6,
100            size: 0.9,
101        };
102        assert!((cy_overall_weight(&m) - 0.6).abs() < 1e-5);
103    }
104
105    #[test]
106    fn test_is_displaced_false() {
107        /* default not displaced */
108        let m = new_condyle_morph();
109        assert!(!cy_is_displaced(&m));
110    }
111
112    #[test]
113    fn test_is_displaced_true() {
114        /* offset above threshold */
115        let m = CondyleMorph {
116            offset_x: 0.5,
117            offset_y: 0.0,
118            size: 0.0,
119        };
120        assert!(cy_is_displaced(&m));
121    }
122
123    #[test]
124    fn test_blend() {
125        /* midpoint blend */
126        let a = CondyleMorph {
127            offset_x: -1.0,
128            offset_y: -1.0,
129            size: 0.0,
130        };
131        let b = CondyleMorph {
132            offset_x: 1.0,
133            offset_y: 1.0,
134            size: 1.0,
135        };
136        let c = cy_blend(&a, &b, 0.5);
137        assert!((c.offset_x - 0.0).abs() < 1e-6);
138    }
139
140    #[test]
141    fn test_clone() {
142        /* clone is independent */
143        let m = CondyleMorph {
144            offset_x: 0.2,
145            offset_y: 0.5,
146            size: 0.8,
147        };
148        let m2 = m.clone();
149        assert_eq!(m.size, m2.size);
150    }
151}