#![allow(dead_code)]
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct FaceRing {
pub vertex: usize,
pub face_indices: Vec<usize>,
}
#[allow(dead_code)]
pub fn face_ring_for_vertex(indices: &[u32], vertex: usize) -> FaceRing {
let tri_count = indices.len() / 3;
let mut faces = Vec::new();
for t in 0..tri_count {
if indices[t * 3] as usize == vertex
|| indices[t * 3 + 1] as usize == vertex
|| indices[t * 3 + 2] as usize == vertex
{
faces.push(t);
}
}
FaceRing {
vertex,
face_indices: faces,
}
}
#[allow(dead_code)]
pub fn all_face_rings(vertex_count: usize, indices: &[u32]) -> Vec<FaceRing> {
let tri_count = indices.len() / 3;
let mut rings: Vec<Vec<usize>> = vec![Vec::new(); vertex_count];
for t in 0..tri_count {
for k in 0..3 {
let vi = indices[t * 3 + k] as usize;
if vi < vertex_count {
rings[vi].push(t);
}
}
}
rings
.into_iter()
.enumerate()
.map(|(vi, face_indices)| FaceRing {
vertex: vi,
face_indices,
})
.collect()
}
#[allow(dead_code)]
pub fn ring_face_count(ring: &FaceRing) -> usize {
ring.face_indices.len()
}
#[allow(dead_code)]
pub fn ring_contains_face(ring: &FaceRing, face: usize) -> bool {
ring.face_indices.contains(&face)
}
#[allow(dead_code)]
pub fn avg_ring_size(rings: &[FaceRing]) -> f32 {
if rings.is_empty() {
return 0.0;
}
let sum: usize = rings.iter().map(|r| r.face_indices.len()).sum();
sum as f32 / rings.len() as f32
}
#[allow(dead_code)]
pub fn max_ring_size(rings: &[FaceRing]) -> usize {
rings
.iter()
.map(|r| r.face_indices.len())
.max()
.unwrap_or(0)
}
#[allow(dead_code)]
pub fn vertices_with_ring_size(rings: &[FaceRing], size: usize) -> Vec<usize> {
rings
.iter()
.filter(|r| r.face_indices.len() == size)
.map(|r| r.vertex)
.collect()
}
#[allow(dead_code)]
pub fn face_ring_to_json(ring: &FaceRing) -> String {
format!(
"{{\"vertex\":{},\"face_count\":{}}}",
ring.vertex,
ring.face_indices.len()
)
}
#[cfg(test)]
mod tests {
use super::*;
fn single_tri() -> Vec<u32> {
vec![0, 1, 2]
}
fn two_tris() -> Vec<u32> {
vec![0, 1, 2, 1, 3, 2]
}
#[test]
fn test_face_ring_single_tri() {
let ring = face_ring_for_vertex(&single_tri(), 0);
assert_eq!(ring_face_count(&ring), 1);
}
#[test]
fn test_face_ring_shared_vertex() {
let ring = face_ring_for_vertex(&two_tris(), 1);
assert_eq!(ring_face_count(&ring), 2);
}
#[test]
fn test_all_face_rings() {
let rings = all_face_rings(4, &two_tris());
assert_eq!(rings.len(), 4);
}
#[test]
fn test_ring_contains_face() {
let ring = face_ring_for_vertex(&single_tri(), 0);
assert!(ring_contains_face(&ring, 0));
assert!(!ring_contains_face(&ring, 1));
}
#[test]
fn test_avg_ring_size() {
let rings = all_face_rings(3, &single_tri());
let avg = avg_ring_size(&rings);
assert!((avg - 1.0).abs() < 1e-6);
}
#[test]
fn test_max_ring_size() {
let rings = all_face_rings(4, &two_tris());
let max = max_ring_size(&rings);
assert_eq!(max, 2);
}
#[test]
fn test_vertices_with_ring_size() {
let rings = all_face_rings(4, &two_tris());
let v = vertices_with_ring_size(&rings, 2);
assert!(v.contains(&1));
assert!(v.contains(&2));
}
#[test]
fn test_empty() {
let rings = all_face_rings(0, &[]);
assert!(rings.is_empty());
}
#[test]
fn test_face_ring_to_json() {
let ring = FaceRing {
vertex: 0,
face_indices: vec![0, 1],
};
let json = face_ring_to_json(&ring);
assert!(json.contains("\"face_count\":2"));
}
#[test]
fn test_vertex_not_in_mesh() {
let ring = face_ring_for_vertex(&single_tri(), 10);
assert_eq!(ring_face_count(&ring), 0);
}
}