#![allow(dead_code)]
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct FaceRegion {
name: String,
vertex_indices: Vec<u32>,
bounds_min: [f32; 3],
bounds_max: [f32; 3],
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct RegionMask {
bits: Vec<bool>,
}
#[allow(dead_code)]
pub fn new_face_region(name: &str, vertex_indices: &[u32], bounds_min: [f32; 3], bounds_max: [f32; 3]) -> FaceRegion {
FaceRegion {
name: name.to_string(),
vertex_indices: vertex_indices.to_vec(),
bounds_min,
bounds_max,
}
}
#[allow(dead_code)]
pub fn region_vertex_count(region: &FaceRegion) -> usize {
region.vertex_indices.len()
}
#[allow(dead_code)]
pub fn region_contains_vertex(region: &FaceRegion, idx: u32) -> bool {
region.vertex_indices.contains(&idx)
}
#[allow(dead_code)]
pub fn region_bounds(region: &FaceRegion) -> ([f32; 3], [f32; 3]) {
(region.bounds_min, region.bounds_max)
}
#[allow(dead_code)]
pub fn merge_face_regions(a: &FaceRegion, b: &FaceRegion) -> FaceRegion {
let mut indices = a.vertex_indices.clone();
for &idx in &b.vertex_indices {
if !indices.contains(&idx) {
indices.push(idx);
}
}
let min = [
a.bounds_min[0].min(b.bounds_min[0]),
a.bounds_min[1].min(b.bounds_min[1]),
a.bounds_min[2].min(b.bounds_min[2]),
];
let max = [
a.bounds_max[0].max(b.bounds_max[0]),
a.bounds_max[1].max(b.bounds_max[1]),
a.bounds_max[2].max(b.bounds_max[2]),
];
FaceRegion {
name: format!("{}+{}", a.name, b.name),
vertex_indices: indices,
bounds_min: min,
bounds_max: max,
}
}
#[allow(dead_code)]
pub fn region_to_mask(region: &FaceRegion, total_vertices: usize) -> RegionMask {
let mut bits = vec![false; total_vertices];
for &idx in ®ion.vertex_indices {
if (idx as usize) < total_vertices {
bits[idx as usize] = true;
}
}
RegionMask { bits }
}
#[allow(dead_code)]
pub fn region_mask_union(a: &RegionMask, b: &RegionMask) -> RegionMask {
let len = a.bits.len().max(b.bits.len());
let mut bits = vec![false; len];
for i in 0..len {
let va = a.bits.get(i).copied().unwrap_or(false);
let vb = b.bits.get(i).copied().unwrap_or(false);
bits[i] = va || vb;
}
RegionMask { bits }
}
#[allow(dead_code)]
pub fn region_mask_intersect(a: &RegionMask, b: &RegionMask) -> RegionMask {
let len = a.bits.len().min(b.bits.len());
let mut bits = vec![false; len];
for i in 0..len {
bits[i] = a.bits[i] && b.bits[i];
}
RegionMask { bits }
}
#[cfg(test)]
mod tests {
use super::*;
fn sample_region() -> FaceRegion {
new_face_region("nose", &[0, 1, 2, 5], [0.0, 0.0, 0.0], [1.0, 1.0, 1.0])
}
#[test]
fn test_new_face_region() {
let r = sample_region();
assert_eq!(r.name, "nose");
assert_eq!(r.vertex_indices.len(), 4);
}
#[test]
fn test_region_vertex_count() {
let r = sample_region();
assert_eq!(region_vertex_count(&r), 4);
}
#[test]
fn test_region_contains_vertex() {
let r = sample_region();
assert!(region_contains_vertex(&r, 2));
assert!(!region_contains_vertex(&r, 3));
}
#[test]
fn test_region_bounds() {
let r = sample_region();
let (mn, mx) = region_bounds(&r);
assert_eq!(mn, [0.0, 0.0, 0.0]);
assert_eq!(mx, [1.0, 1.0, 1.0]);
}
#[test]
fn test_merge_face_regions() {
let a = new_face_region("a", &[0, 1], [0.0, 0.0, 0.0], [1.0, 1.0, 1.0]);
let b = new_face_region("b", &[1, 2], [-1.0, 0.0, 0.0], [2.0, 1.0, 1.0]);
let m = merge_face_regions(&a, &b);
assert_eq!(region_vertex_count(&m), 3);
assert_eq!(m.bounds_min[0], -1.0);
assert_eq!(m.bounds_max[0], 2.0);
}
#[test]
fn test_region_to_mask() {
let r = new_face_region("r", &[1, 3], [0.0; 3], [1.0; 3]);
let mask = region_to_mask(&r, 5);
assert!(!mask.bits[0]);
assert!(mask.bits[1]);
assert!(!mask.bits[2]);
assert!(mask.bits[3]);
}
#[test]
fn test_region_mask_union() {
let a = RegionMask { bits: vec![true, false, true] };
let b = RegionMask { bits: vec![false, true, false] };
let u = region_mask_union(&a, &b);
assert!(u.bits[0] && u.bits[1] && u.bits[2]);
}
#[test]
fn test_region_mask_intersect() {
let a = RegionMask { bits: vec![true, false, true] };
let b = RegionMask { bits: vec![true, true, false] };
let i = region_mask_intersect(&a, &b);
assert!(i.bits[0]);
assert!(!i.bits[1]);
assert!(!i.bits[2]);
}
#[test]
fn test_mask_union_different_lengths() {
let a = RegionMask { bits: vec![true] };
let b = RegionMask { bits: vec![false, true, true] };
let u = region_mask_union(&a, &b);
assert_eq!(u.bits.len(), 3);
assert!(u.bits[0]);
}
#[test]
fn test_empty_region() {
let r = new_face_region("empty", &[], [0.0; 3], [0.0; 3]);
assert_eq!(region_vertex_count(&r), 0);
}
}