oxihuman_mesh/
mesh_edge_loop_select.rs1#![allow(dead_code)]
2
3use std::collections::HashMap;
6
7#[allow(dead_code)]
8#[derive(Debug, Clone)]
9pub struct EdgeLoopSelect {
10 pub edges: Vec<(u32, u32)>,
11 pub closed: bool,
12}
13
14fn canonical(a: u32, b: u32) -> (u32, u32) {
15 if a < b {
16 (a, b)
17 } else {
18 (b, a)
19 }
20}
21
22#[allow(dead_code)]
23pub fn select_edge_loop(indices: &[u32], start_a: u32, start_b: u32) -> EdgeLoopSelect {
24 let mut adj: HashMap<u32, Vec<u32>> = HashMap::new();
25 for tri in indices.chunks(3) {
26 if tri.len() == 3 {
27 for &(a, b) in &[(tri[0], tri[1]), (tri[1], tri[2]), (tri[2], tri[0])] {
28 adj.entry(a).or_default().push(b);
29 adj.entry(b).or_default().push(a);
30 }
31 }
32 }
33 let mut edges = vec![canonical(start_a, start_b)];
34 let mut current = start_b;
35 let mut prev = start_a;
36 for _ in 0..indices.len() {
37 if let Some(neighbors) = adj.get(¤t) {
38 let next = neighbors.iter().find(|&&n| n != prev && n != current);
39 if let Some(&n) = next {
40 let e = canonical(current, n);
41 if edges.contains(&e) {
42 break;
43 }
44 edges.push(e);
45 prev = current;
46 current = n;
47 } else {
48 break;
49 }
50 } else {
51 break;
52 }
53 }
54 let closed = edges.len() > 2 && current == start_a;
55 EdgeLoopSelect { edges, closed }
56}
57
58#[allow(dead_code)]
59pub fn loop_edge_count(sel: &EdgeLoopSelect) -> usize {
60 sel.edges.len()
61}
62
63#[allow(dead_code)]
64pub fn loop_is_closed_els(sel: &EdgeLoopSelect) -> bool {
65 sel.closed
66}
67
68#[allow(dead_code)]
69pub fn loop_vertices_els(sel: &EdgeLoopSelect) -> Vec<u32> {
70 let mut verts = Vec::new();
71 for &(a, b) in &sel.edges {
72 if !verts.contains(&a) {
73 verts.push(a);
74 }
75 if !verts.contains(&b) {
76 verts.push(b);
77 }
78 }
79 verts
80}
81
82#[allow(dead_code)]
83pub fn grow_loop_selection(sel: &mut EdgeLoopSelect, indices: &[u32]) {
84 let verts = loop_vertices_els(sel);
85 for tri in indices.chunks(3) {
86 if tri.len() == 3 {
87 for &(a, b) in &[(tri[0], tri[1]), (tri[1], tri[2]), (tri[2], tri[0])] {
88 if verts.contains(&a) || verts.contains(&b) {
89 let e = canonical(a, b);
90 if !sel.edges.contains(&e) {
91 sel.edges.push(e);
92 }
93 }
94 }
95 }
96 }
97}
98
99#[allow(dead_code)]
100pub fn shrink_loop_selection(sel: &mut EdgeLoopSelect) {
101 if sel.edges.len() > 1 {
102 sel.edges.pop();
103 }
104}
105
106#[allow(dead_code)]
107pub fn loop_to_json(sel: &EdgeLoopSelect) -> String {
108 let es: Vec<String> = sel
109 .edges
110 .iter()
111 .map(|(a, b)| format!("[{},{}]", a, b))
112 .collect();
113 format!(
114 "{{\"edge_count\":{},\"closed\":{},\"edges\":[{}]}}",
115 sel.edges.len(),
116 sel.closed,
117 es.join(",")
118 )
119}
120
121#[allow(dead_code)]
122pub fn clear_loop_selection(sel: &mut EdgeLoopSelect) {
123 sel.edges.clear();
124 sel.closed = false;
125}
126
127#[cfg(test)]
128mod tests {
129 use super::*;
130
131 #[test]
132 fn test_select() {
133 let s = select_edge_loop(&[0, 1, 2], 0, 1);
134 assert!(!s.edges.is_empty());
135 }
136 #[test]
137 fn test_edge_count() {
138 let s = select_edge_loop(&[0, 1, 2], 0, 1);
139 assert!(loop_edge_count(&s) >= 1);
140 }
141 #[test]
142 fn test_vertices() {
143 let s = select_edge_loop(&[0, 1, 2], 0, 1);
144 let v = loop_vertices_els(&s);
145 assert!(v.contains(&0));
146 }
147 #[test]
148 fn test_grow() {
149 let mut s = EdgeLoopSelect {
150 edges: vec![(0, 1)],
151 closed: false,
152 };
153 grow_loop_selection(&mut s, &[0, 1, 2]);
154 assert!(s.edges.len() > 1);
155 }
156 #[test]
157 fn test_shrink() {
158 let mut s = EdgeLoopSelect {
159 edges: vec![(0, 1), (1, 2)],
160 closed: false,
161 };
162 shrink_loop_selection(&mut s);
163 assert_eq!(s.edges.len(), 1);
164 }
165 #[test]
166 fn test_to_json() {
167 let s = EdgeLoopSelect {
168 edges: vec![(0, 1)],
169 closed: false,
170 };
171 assert!(loop_to_json(&s).contains("\"edge_count\":1"));
172 }
173 #[test]
174 fn test_clear() {
175 let mut s = EdgeLoopSelect {
176 edges: vec![(0, 1)],
177 closed: true,
178 };
179 clear_loop_selection(&mut s);
180 assert!(s.edges.is_empty());
181 assert!(!s.closed);
182 }
183 #[test]
184 fn test_closed_flag() {
185 let s = EdgeLoopSelect {
186 edges: vec![],
187 closed: true,
188 };
189 assert!(loop_is_closed_els(&s));
190 }
191 #[test]
192 fn test_empty_select() {
193 let s = select_edge_loop(&[], 0, 1);
194 assert_eq!(loop_edge_count(&s), 1);
195 }
196 #[test]
197 fn test_shrink_min() {
198 let mut s = EdgeLoopSelect {
199 edges: vec![(0, 1)],
200 closed: false,
201 };
202 shrink_loop_selection(&mut s);
203 assert_eq!(s.edges.len(), 1);
204 }
205}