#![allow(dead_code)]
#[allow(dead_code)]
#[derive(Debug, Clone, Copy)]
pub struct Dart {
pub vertex: u32,
pub face: u32,
pub twin: usize,
pub next: usize,
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct DartGraph {
pub darts: Vec<Dart>,
}
#[allow(dead_code)]
pub fn build_dart_graph(indices: &[u32]) -> DartGraph {
let tri_count = indices.len() / 3;
let dart_count = tri_count * 3;
let mut darts = Vec::with_capacity(dart_count);
for t in 0..tri_count {
let base = t * 3;
let f = t as u32;
for k in 0..3 {
darts.push(Dart {
vertex: indices[base + k],
face: f,
twin: usize::MAX,
next: base + (k + 1) % 3,
});
}
}
use std::collections::HashMap;
let pairs: Vec<(u32, u32)> = (0..darts.len())
.map(|i| {
let next_vert = darts[darts[i].next].vertex;
(darts[i].vertex, next_vert)
})
.collect();
let mut edge_map: HashMap<(u32, u32), usize> = HashMap::new();
let mut twins = vec![usize::MAX; darts.len()];
for (i, &(v, nv)) in pairs.iter().enumerate() {
let twin_key = (nv, v);
if let Some(&twin_idx) = edge_map.get(&twin_key) {
twins[i] = twin_idx;
twins[twin_idx] = i;
}
edge_map.insert((v, nv), i);
}
for (i, t) in twins.into_iter().enumerate() {
darts[i].twin = t;
}
DartGraph { darts }
}
#[allow(dead_code)]
pub fn dart_count(graph: &DartGraph) -> usize {
graph.darts.len()
}
#[allow(dead_code)]
pub fn get_dart(graph: &DartGraph, idx: usize) -> Option<&Dart> {
graph.darts.get(idx)
}
#[allow(dead_code)]
pub fn has_twin(graph: &DartGraph, idx: usize) -> bool {
graph.darts.get(idx).is_some_and(|d| d.twin != usize::MAX)
}
#[allow(dead_code)]
pub fn boundary_dart_count(graph: &DartGraph) -> usize {
graph.darts.iter().filter(|d| d.twin == usize::MAX).count()
}
#[allow(dead_code)]
pub fn face_count(graph: &DartGraph) -> usize {
graph.darts.len() / 3
}
#[allow(dead_code)]
pub fn dart_graph_to_json(graph: &DartGraph) -> String {
format!(
"{{\"dart_count\":{},\"face_count\":{},\"boundary_darts\":{}}}",
dart_count(graph),
face_count(graph),
boundary_dart_count(graph)
)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_build_single_triangle() {
let g = build_dart_graph(&[0, 1, 2]);
assert_eq!(dart_count(&g), 3);
}
#[test]
fn test_face_count() {
let g = build_dart_graph(&[0, 1, 2, 1, 3, 2]);
assert_eq!(face_count(&g), 2);
}
#[test]
fn test_boundary_darts_single() {
let g = build_dart_graph(&[0, 1, 2]);
assert_eq!(boundary_dart_count(&g), 3); }
#[test]
fn test_twin_pairing() {
let g = build_dart_graph(&[0, 1, 2, 2, 1, 3]);
let paired = g.darts.iter().filter(|d| d.twin != usize::MAX).count();
assert!(paired >= 2);
}
#[test]
fn test_get_dart() {
let g = build_dart_graph(&[0, 1, 2]);
assert!(get_dart(&g, 0).is_some());
assert!(get_dart(&g, 10).is_none());
}
#[test]
fn test_has_twin() {
let g = build_dart_graph(&[0, 1, 2]);
assert!(!has_twin(&g, 0));
}
#[test]
fn test_empty() {
let g = build_dart_graph(&[]);
assert_eq!(dart_count(&g), 0);
}
#[test]
fn test_dart_vertex() {
let g = build_dart_graph(&[5, 10, 15]);
assert_eq!(g.darts[0].vertex, 5);
assert_eq!(g.darts[1].vertex, 10);
}
#[test]
fn test_next_cycling() {
let g = build_dart_graph(&[0, 1, 2]);
let d0 = &g.darts[0];
let d1 = &g.darts[d0.next];
let d2 = &g.darts[d1.next];
assert_eq!(d2.next, 0);
}
#[test]
fn test_to_json() {
let g = build_dart_graph(&[0, 1, 2]);
let j = dart_graph_to_json(&g);
assert!(j.contains("\"dart_count\":3"));
}
}