#![allow(dead_code)]
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct ExpressionMask {
pub weights: Vec<f32>,
}
#[allow(dead_code)]
pub fn new_expression_mask(count: usize) -> ExpressionMask {
ExpressionMask {
weights: vec![1.0; count],
}
}
#[allow(dead_code)]
pub fn mask_set_region(mask: &mut ExpressionMask, start: usize, end: usize, value: f32) {
let v = value.clamp(0.0, 1.0);
let end = end.min(mask.weights.len());
for w in mask.weights[start..end].iter_mut() {
*w = v;
}
}
#[allow(dead_code)]
pub fn mask_get_region(mask: &ExpressionMask, index: usize) -> f32 {
mask.weights.get(index).copied().unwrap_or(0.0)
}
#[allow(dead_code)]
pub fn mask_apply(mask: &ExpressionMask, deltas: &[f32]) -> Vec<f32> {
deltas
.iter()
.enumerate()
.map(|(i, d)| d * mask.weights.get(i).copied().unwrap_or(0.0))
.collect()
}
#[allow(dead_code)]
pub fn mask_invert(mask: &mut ExpressionMask) {
for w in &mut mask.weights {
*w = 1.0 - *w;
}
}
#[allow(dead_code)]
pub fn mask_union_expr(a: &ExpressionMask, b: &ExpressionMask) -> ExpressionMask {
let len = a.weights.len().max(b.weights.len());
let mut weights = vec![0.0_f32; len];
for (i, w) in weights.iter_mut().enumerate() {
let va = a.weights.get(i).copied().unwrap_or(0.0);
let vb = b.weights.get(i).copied().unwrap_or(0.0);
*w = va.max(vb);
}
ExpressionMask { weights }
}
#[allow(dead_code)]
pub fn mask_vertex_count_em(mask: &ExpressionMask) -> usize {
mask.weights.len()
}
#[allow(dead_code)]
pub fn mask_to_json(mask: &ExpressionMask) -> String {
let vals: Vec<String> = mask.weights.iter().map(|w| format!("{:.4}", w)).collect();
format!("{{\"weights\":[{}]}}", vals.join(","))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn new_mask_all_ones() {
let m = new_expression_mask(10);
assert_eq!(mask_vertex_count_em(&m), 10);
assert!((mask_get_region(&m, 0) - 1.0).abs() < 1e-6);
}
#[test]
fn set_region() {
let mut m = new_expression_mask(10);
mask_set_region(&mut m, 2, 5, 0.0);
assert!(mask_get_region(&m, 3).abs() < 1e-6);
assert!((mask_get_region(&m, 0) - 1.0).abs() < 1e-6);
}
#[test]
fn get_out_of_bounds() {
let m = new_expression_mask(5);
assert!(mask_get_region(&m, 100).abs() < 1e-6);
}
#[test]
fn apply_mask() {
let mut m = new_expression_mask(3);
mask_set_region(&mut m, 1, 2, 0.5);
let deltas = vec![1.0, 1.0, 1.0];
let result = mask_apply(&m, &deltas);
assert!((result[0] - 1.0).abs() < 1e-6);
assert!((result[1] - 0.5).abs() < 1e-6);
}
#[test]
fn invert_mask() {
let mut m = new_expression_mask(3);
mask_set_region(&mut m, 0, 1, 0.3);
mask_invert(&mut m);
assert!((mask_get_region(&m, 0) - 0.7).abs() < 1e-6);
}
#[test]
fn union_masks() {
let mut a = new_expression_mask(3);
mask_set_region(&mut a, 0, 3, 0.3);
let mut b = new_expression_mask(3);
mask_set_region(&mut b, 0, 3, 0.7);
let u = mask_union_expr(&a, &b);
assert!((mask_get_region(&u, 0) - 0.7).abs() < 1e-6);
}
#[test]
fn vertex_count() {
let m = new_expression_mask(42);
assert_eq!(mask_vertex_count_em(&m), 42);
}
#[test]
fn to_json() {
let m = new_expression_mask(2);
let j = mask_to_json(&m);
assert!(j.contains("\"weights\""));
}
#[test]
fn apply_empty_deltas() {
let m = new_expression_mask(3);
let result = mask_apply(&m, &[]);
assert!(result.is_empty());
}
#[test]
fn set_region_clamped() {
let mut m = new_expression_mask(3);
mask_set_region(&mut m, 0, 3, 1.5);
assert!((mask_get_region(&m, 0) - 1.0).abs() < 1e-6);
}
}