#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct EdgeCreaseExport {
pub edges: Vec<(u32, u32)>,
pub sharpness: Vec<f32>,
}
#[allow(dead_code)]
impl EdgeCreaseExport {
pub fn new() -> Self { Self { edges: Vec::new(), sharpness: Vec::new() } }
pub fn add(&mut self, v0: u32, v1: u32, sharp: f32) {
let e = if v0 < v1 { (v0, v1) } else { (v1, v0) };
self.edges.push(e);
self.sharpness.push(sharp.clamp(0.0, 10.0));
}
pub fn count(&self) -> usize { self.edges.len() }
pub fn get_sharpness(&self, v0: u32, v1: u32) -> Option<f32> {
let e = if v0 < v1 { (v0, v1) } else { (v1, v0) };
self.edges.iter().position(|x| *x == e).map(|i| self.sharpness[i])
}
pub fn to_bytes(&self) -> Vec<u8> {
let mut bytes = Vec::new();
bytes.extend_from_slice(&(self.edges.len() as u32).to_le_bytes());
for (&(v0, v1), &s) in self.edges.iter().zip(self.sharpness.iter()) {
bytes.extend_from_slice(&v0.to_le_bytes());
bytes.extend_from_slice(&v1.to_le_bytes());
bytes.extend_from_slice(&s.to_le_bytes());
}
bytes
}
pub fn byte_size(&self) -> usize { 4 + self.edges.len() * 12 }
pub fn max_sharpness(&self) -> f32 {
self.sharpness.iter().cloned().fold(0.0f32, f32::max)
}
pub fn average_sharpness(&self) -> f32 {
if self.sharpness.is_empty() { return 0.0; }
self.sharpness.iter().sum::<f32>() / self.sharpness.len() as f32
}
}
impl Default for EdgeCreaseExport {
fn default() -> Self { Self::new() }
}
#[allow(dead_code)]
pub fn edge_crease_to_json(ec: &EdgeCreaseExport) -> String {
format!(
"{{\"count\":{},\"max_sharpness\":{},\"avg_sharpness\":{}}}",
ec.count(), ec.max_sharpness(), ec.average_sharpness()
)
}
#[allow(dead_code)]
pub fn validate_edge_crease(ec: &EdgeCreaseExport) -> bool {
ec.edges.len() == ec.sharpness.len()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new() { assert_eq!(EdgeCreaseExport::new().count(), 0); }
#[test]
fn test_add() {
let mut ec = EdgeCreaseExport::new();
ec.add(0, 1, 2.5);
assert_eq!(ec.count(), 1);
}
#[test]
fn test_get_sharpness() {
let mut ec = EdgeCreaseExport::new();
ec.add(0, 1, 3.0);
assert!((ec.get_sharpness(0, 1).expect("should succeed") - 3.0).abs() < 1e-5);
assert!((ec.get_sharpness(1, 0).expect("should succeed") - 3.0).abs() < 1e-5);
}
#[test]
fn test_missing() {
let ec = EdgeCreaseExport::new();
assert!(ec.get_sharpness(0, 1).is_none());
}
#[test]
fn test_to_bytes() {
let mut ec = EdgeCreaseExport::new();
ec.add(0, 1, 1.0);
assert_eq!(ec.to_bytes().len(), ec.byte_size());
}
#[test]
fn test_max_sharpness() {
let mut ec = EdgeCreaseExport::new();
ec.add(0, 1, 2.0);
ec.add(1, 2, 5.0);
assert!((ec.max_sharpness() - 5.0).abs() < 1e-5);
}
#[test]
fn test_clamp() {
let mut ec = EdgeCreaseExport::new();
ec.add(0, 1, 20.0);
assert!((ec.sharpness[0] - 10.0).abs() < 1e-5);
}
#[test]
fn test_validate() {
let mut ec = EdgeCreaseExport::new();
ec.add(0, 1, 1.0);
assert!(validate_edge_crease(&ec));
}
#[test]
fn test_to_json() {
let mut ec = EdgeCreaseExport::new();
ec.add(0, 1, 1.0);
assert!(edge_crease_to_json(&ec).contains("count"));
}
#[test]
fn test_average() {
let mut ec = EdgeCreaseExport::new();
ec.add(0, 1, 2.0);
ec.add(1, 2, 4.0);
assert!((ec.average_sharpness() - 3.0).abs() < 1e-5);
}
#[test]
fn test_default() { assert_eq!(EdgeCreaseExport::default().count(), 0); }
}