#![allow(dead_code)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum CreaseRegion {
Forehead,
GlabellaLines,
NasolabialFold,
Marionette,
CrowsFeet,
NeckLines,
}
#[derive(Debug, Clone)]
pub struct CreaseEntry {
pub region: CreaseRegion,
pub depth: f32,
pub sharpness: f32,
}
#[derive(Debug, Clone)]
pub struct CreaseDepthMorph {
pub creases: Vec<CreaseEntry>,
pub global_scale: f32,
pub morph_count: usize,
pub enabled: bool,
}
impl CreaseDepthMorph {
pub fn new(morph_count: usize) -> Self {
CreaseDepthMorph {
creases: Vec::new(),
global_scale: 1.0,
morph_count,
enabled: true,
}
}
}
pub fn new_crease_depth_morph(morph_count: usize) -> CreaseDepthMorph {
CreaseDepthMorph::new(morph_count)
}
pub fn cdm_add_crease(morph: &mut CreaseDepthMorph, entry: CreaseEntry) {
morph.creases.push(entry);
}
pub fn cdm_set_global_scale(morph: &mut CreaseDepthMorph, scale: f32) {
morph.global_scale = scale.clamp(0.0, 2.0);
}
pub fn cdm_clear(morph: &mut CreaseDepthMorph) {
morph.creases.clear();
}
pub fn cdm_evaluate(morph: &CreaseDepthMorph) -> Vec<f32> {
if !morph.enabled || morph.morph_count == 0 {
return vec![];
}
let avg = if morph.creases.is_empty() {
0.0
} else {
morph.creases.iter().map(|c| c.depth).sum::<f32>() / morph.creases.len() as f32
};
let w = (avg * morph.global_scale).clamp(0.0, 1.0);
vec![w; morph.morph_count]
}
pub fn cdm_set_enabled(morph: &mut CreaseDepthMorph, enabled: bool) {
morph.enabled = enabled;
}
pub fn cdm_crease_count(morph: &CreaseDepthMorph) -> usize {
morph.creases.len()
}
pub fn cdm_to_json(morph: &CreaseDepthMorph) -> String {
format!(
r#"{{"crease_count":{},"global_scale":{},"morph_count":{},"enabled":{}}}"#,
morph.creases.len(),
morph.global_scale,
morph.morph_count,
morph.enabled
)
}
#[cfg(test)]
mod tests {
use super::*;
fn make_crease(region: CreaseRegion, depth: f32) -> CreaseEntry {
CreaseEntry {
region,
depth,
sharpness: 0.5,
}
}
#[test]
fn test_initial_empty() {
let m = new_crease_depth_morph(4);
assert_eq!(cdm_crease_count(&m), 0 );
}
#[test]
fn test_add_crease() {
let mut m = new_crease_depth_morph(4);
cdm_add_crease(&mut m, make_crease(CreaseRegion::Forehead, 0.5));
assert_eq!(cdm_crease_count(&m), 1 );
}
#[test]
fn test_clear() {
let mut m = new_crease_depth_morph(4);
cdm_add_crease(&mut m, make_crease(CreaseRegion::CrowsFeet, 0.8));
cdm_clear(&mut m);
assert_eq!(cdm_crease_count(&m), 0 );
}
#[test]
fn test_global_scale_clamped() {
let mut m = new_crease_depth_morph(4);
cdm_set_global_scale(&mut m, 5.0);
assert!((m.global_scale - 2.0).abs() < 1e-6 );
}
#[test]
fn test_evaluate_length() {
let m = new_crease_depth_morph(5);
assert_eq!(
cdm_evaluate(&m).len(),
5
);
}
#[test]
fn test_evaluate_empty_creases() {
let m = new_crease_depth_morph(4);
let out = cdm_evaluate(&m);
assert!((out[0]).abs() < 1e-6 );
}
#[test]
fn test_evaluate_disabled() {
let mut m = new_crease_depth_morph(4);
cdm_set_enabled(&mut m, false);
assert!(cdm_evaluate(&m).is_empty() );
}
#[test]
fn test_to_json_has_crease_count() {
let m = new_crease_depth_morph(4);
let j = cdm_to_json(&m);
assert!(j.contains("\"crease_count\"") );
}
#[test]
fn test_enabled_default() {
let m = new_crease_depth_morph(4);
assert!(m.enabled );
}
#[test]
fn test_evaluate_avg_depth() {
let mut m = new_crease_depth_morph(2);
cdm_add_crease(&mut m, make_crease(CreaseRegion::Marionette, 0.4));
cdm_add_crease(&mut m, make_crease(CreaseRegion::NeckLines, 0.6));
let out = cdm_evaluate(&m);
assert!((out[0] - 0.5).abs() < 1e-5 );
}
}