#![allow(dead_code)]
#[derive(Debug, Clone)]
pub struct FacialAsymmetryMorphConfig {
pub left_scale: f32,
pub right_scale: f32,
pub vertical_offset: f32,
pub horizontal_shift: f32,
}
impl Default for FacialAsymmetryMorphConfig {
fn default() -> Self {
Self {
left_scale: 1.0,
right_scale: 1.0,
vertical_offset: 0.0,
horizontal_shift: 0.0,
}
}
}
#[derive(Debug, Clone)]
pub struct FacialAsymmetryMorph {
pub config: FacialAsymmetryMorphConfig,
pub intensity: f32,
pub enabled: bool,
}
impl FacialAsymmetryMorph {
pub fn new() -> Self {
Self {
config: FacialAsymmetryMorphConfig::default(),
intensity: 0.0,
enabled: true,
}
}
}
impl Default for FacialAsymmetryMorph {
fn default() -> Self {
Self::new()
}
}
pub fn new_facial_asymmetry_morph() -> FacialAsymmetryMorph {
FacialAsymmetryMorph::new()
}
pub fn facial_asym_set_left_scale(morph: &mut FacialAsymmetryMorph, v: f32) {
morph.config.left_scale = v.clamp(0.5, 1.5);
}
pub fn facial_asym_set_right_scale(morph: &mut FacialAsymmetryMorph, v: f32) {
morph.config.right_scale = v.clamp(0.5, 1.5);
}
pub fn facial_asym_set_vertical_offset(morph: &mut FacialAsymmetryMorph, v: f32) {
morph.config.vertical_offset = v.clamp(-1.0, 1.0);
}
pub fn facial_asym_set_horizontal_shift(morph: &mut FacialAsymmetryMorph, v: f32) {
morph.config.horizontal_shift = v.clamp(-1.0, 1.0);
}
pub fn facial_asym_score(morph: &FacialAsymmetryMorph) -> f32 {
let scale_diff = (morph.config.left_scale - morph.config.right_scale).abs();
(scale_diff + morph.config.vertical_offset.abs() * 0.5) * morph.intensity
}
pub fn facial_asymmetry_to_json(morph: &FacialAsymmetryMorph) -> String {
format!(
r#"{{"intensity":{},"left_scale":{},"right_scale":{},"vertical_offset":{},"horizontal_shift":{}}}"#,
morph.intensity,
morph.config.left_scale,
morph.config.right_scale,
morph.config.vertical_offset,
morph.config.horizontal_shift,
)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new() {
let m = new_facial_asymmetry_morph();
assert!((m.config.left_scale - 1.0).abs() < 1e-6 );
}
#[test]
fn test_left_scale_clamp() {
let mut m = new_facial_asymmetry_morph();
facial_asym_set_left_scale(&mut m, 3.0);
assert!((m.config.left_scale - 1.5).abs() < 1e-6 );
}
#[test]
fn test_right_scale() {
let mut m = new_facial_asymmetry_morph();
facial_asym_set_right_scale(&mut m, 0.9);
assert!((m.config.right_scale - 0.9).abs() < 1e-6 );
}
#[test]
fn test_vertical_offset() {
let mut m = new_facial_asymmetry_morph();
facial_asym_set_vertical_offset(&mut m, 0.3);
assert!((m.config.vertical_offset - 0.3).abs() < 1e-6 );
}
#[test]
fn test_horizontal_shift() {
let mut m = new_facial_asymmetry_morph();
facial_asym_set_horizontal_shift(&mut m, -0.2);
assert!((m.config.horizontal_shift - (-0.2)).abs() < 1e-6 );
}
#[test]
fn test_score_symmetric() {
let m = new_facial_asymmetry_morph();
assert!((facial_asym_score(&m) - 0.0).abs() < 1e-6 );
}
#[test]
fn test_score_asymmetric() {
let mut m = new_facial_asymmetry_morph();
facial_asym_set_left_scale(&mut m, 1.2);
facial_asym_set_right_scale(&mut m, 0.8);
m.intensity = 1.0;
assert!(facial_asym_score(&m) > 0.0 );
}
#[test]
fn test_json_key() {
let m = new_facial_asymmetry_morph();
let j = facial_asymmetry_to_json(&m);
assert!(j.contains("left_scale") );
}
#[test]
fn test_default_enabled() {
let m = FacialAsymmetryMorph::default();
assert!(m.enabled );
}
}