├── .gitignore ├── Cargo.toml ├── README.md └── src ├── edge.rs ├── face.rs ├── iterators.rs ├── lib.rs ├── mesh.rs ├── ptr.rs ├── util.rs └── vert.rs /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | Cargo.lock 3 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "half_edge_mesh" 3 | version = "1.1.8" 4 | authors = ["Mark Hintz "] 5 | license = "MIT" 6 | description = "A basic implementation of the half-edge mesh data structure. It has a bunch of the functions you probably want in a half-edge mesh, but probably not all of them. I'm intending to add more methods and mutation techniques, as I need them for other projects or as I think of them. Pull requests welcome!" 7 | repository = "https://github.com/mhintz/half-edge-mesh-rs" 8 | readme = "README.md" 9 | keywords = ["half", "edge", "mesh", "graphics", "graph"] 10 | 11 | [dependencies] 12 | cgmath = "^0.16.0" 13 | approx = "^0.1.1" 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Half-Edge Mesh 2 | 3 | This is an implementation of the half-edge mesh data structure in Rust. Suggestions and pull requests welcome! 4 | 5 | The most notable implementation detail is that links to other parts of the mesh (of which there are many) are `Option>>`. This is in order to allow the references to be initialized to null, then set later during mutation methods. Since a half-edge mesh is a graph with many cycles, and some circular references, the entities require null references at some point during initialization (due to the circular references). I believe this implementation is the only way to construct this kind of structure within Rust's borrowing system, short of using raw pointers and unsafe code everywhere. I suppose that in the far future, I could refactor this project to use raw pointers for performance. 6 | 7 | Currently, this data structure is built with mathematical primitives from cgmath. Vectors are `cgmath::Vector3`, and points are `cgmath::Point3`. This makes the API somewhat simpler, since it doesn't need to be type-parameterized for primitive types. It would be possible to refactor out this dependency at some point in the future. 8 | -------------------------------------------------------------------------------- /src/edge.rs: -------------------------------------------------------------------------------- 1 | use std::hash; 2 | 3 | use ptr::{Ptr, EdgePtr, VertPtr, FacePtr, EdgeRc, VertRc, FaceRc}; 4 | use iterators::*; 5 | 6 | #[derive(Debug)] 7 | pub struct Edge { 8 | pub next: EdgePtr, 9 | pub pair: EdgePtr, 10 | pub origin: VertPtr, 11 | pub face: FacePtr, 12 | pub id: u32, 13 | } 14 | 15 | // TODO: change the name of set_*_rc to just set_*, and change the current set_* to set_*_ptr 16 | // because set_*_rc is used way more than set_* at the moment. 17 | impl Edge { 18 | pub fn empty(id: u32) -> Edge { 19 | Edge { 20 | id: id, 21 | next: EdgePtr::empty(), 22 | pair: EdgePtr::empty(), 23 | origin: VertPtr::empty(), 24 | face: FacePtr::empty(), 25 | } 26 | } 27 | 28 | pub fn with_origin(id: u32, origin: VertPtr) -> Edge { 29 | Edge { 30 | id: id, 31 | next: EdgePtr::empty(), 32 | pair: EdgePtr::empty(), 33 | origin: origin, 34 | face: FacePtr::empty(), 35 | } 36 | } 37 | 38 | pub fn take_next(&mut self, next: EdgePtr) { self.next = next; } 39 | 40 | pub fn set_next(&mut self, next: & EdgePtr) { self.next = next.clone(); } 41 | 42 | pub fn set_next_rc(&mut self, next: & EdgeRc) { self.next = Ptr::new(next); } 43 | 44 | pub fn take_pair(&mut self, pair: EdgePtr) { self.pair = pair; } 45 | 46 | pub fn set_pair(&mut self, pair: & EdgePtr) { self.pair = pair.clone(); } 47 | 48 | pub fn set_pair_rc(&mut self, pair: & EdgeRc) { self.pair = Ptr::new(pair); } 49 | 50 | pub fn take_origin(&mut self, origin: VertPtr) { self.origin = origin; } 51 | 52 | pub fn set_origin(&mut self, origin: & VertPtr) { self.origin = origin.clone(); } 53 | 54 | pub fn set_origin_rc(&mut self, origin: & VertRc) { self.origin = Ptr::new(origin); } 55 | 56 | pub fn set_face(&mut self, face: & FacePtr) { self.face = face.clone(); } 57 | 58 | pub fn take_face(&mut self, face: FacePtr) { self.face = face; } 59 | 60 | pub fn set_face_rc(&mut self, face: & FaceRc) { self.face = Ptr::new(face); } 61 | 62 | // The tests in this function are in order of "subjective likeliness of being invalid" 63 | pub fn is_valid(& self) -> bool { self.pair.is_valid() && self.face.is_valid() && self.origin.is_valid() && self.next.is_valid() } 64 | 65 | pub fn get_next(& self) -> Option { self.next.upgrade() } 66 | 67 | pub fn get_pair(& self) -> Option { self.pair.upgrade() } 68 | 69 | pub fn get_origin(& self) -> Option { self.origin.upgrade() } 70 | 71 | pub fn get_face(& self) -> Option { self.face.upgrade() } 72 | 73 | pub fn get_next_next(& self) -> Option { self.get_next().and_then(|n| n.borrow().get_next()) } 74 | 75 | pub fn get_next_pair(& self) -> Option { self.get_next().and_then(|n| n.borrow().get_pair()) } 76 | 77 | pub fn get_target(& self) -> Option { self.get_next().and_then(|n| n.borrow().get_origin()) } 78 | 79 | pub fn get_pair_face(& self) -> Option { self.get_pair().and_then(|p| p.borrow().get_face()) } 80 | 81 | /// Yields edge.origin, then edge.next.origin 82 | /// Gives you first the source of the half-edge, and then its target 83 | pub fn adjacent_verts(& self) -> EdgeAdjacentVertIterator { 84 | EdgeAdjacentVertIterator::new(self) 85 | } 86 | 87 | /// Gives you the edges connected to the source of the half-edge first (in *clockwise* order) 88 | /// and then the edges connected to the target of the half-edge (also *clockwise* order) 89 | pub fn adjacent_edges(& self) -> EdgeAdjacentEdgeIterator { 90 | EdgeAdjacentEdgeIterator::new(self) 91 | } 92 | 93 | /// Yields edge.face, then edge.pair.face 94 | /// Gives you the "left" face to the half edge, and then the "right" face 95 | /// Note that the "right" face is not connected to this edge, but to its pair 96 | pub fn adjacent_faces(& self) -> EdgeAdjacentFaceIterator { 97 | EdgeAdjacentFaceIterator::new(self) 98 | } 99 | } 100 | 101 | impl PartialEq for Edge { 102 | fn eq(& self, other: & Edge) -> bool { self.id == other.id } 103 | } 104 | 105 | impl Eq for Edge {} 106 | 107 | impl hash::Hash for Edge { 108 | fn hash(& self, state: &mut H) where H: hash::Hasher { 109 | state.write_u32(self.id); 110 | state.finish(); 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/face.rs: -------------------------------------------------------------------------------- 1 | use std::hash; 2 | 3 | use cgmath::{Point3, Vector3, EuclideanSpace, InnerSpace}; 4 | use approx::ApproxEq; 5 | 6 | use ptr::{Ptr, EdgePtr, EdgeRc, VertRc}; 7 | use iterators::*; 8 | 9 | // TODO: Better way of figuring out when to run compute_attrs 10 | #[derive(Debug)] 11 | pub struct Face { 12 | pub edge: EdgePtr, 13 | pub normal: Vector3, 14 | pub center: Point3, 15 | pub id: u32, 16 | } 17 | 18 | impl Face { 19 | pub fn empty(id: u32) -> Face { 20 | Face { 21 | id: id, 22 | edge: EdgePtr::empty(), 23 | // Are these sensible defaults? 24 | // Are these values even necessary? 25 | normal: Vector3::unit_z(), 26 | center: Point3::origin(), 27 | } 28 | } 29 | 30 | // Face connected to an existing edge 31 | pub fn with_edge(id: u32, edge: EdgePtr) -> Face { 32 | Face { 33 | id: id, 34 | edge: edge, 35 | normal: Vector3::unit_z(), 36 | center: Point3::origin(), 37 | } 38 | } 39 | 40 | pub fn take_edge(&mut self, edge: EdgePtr) { self.edge = edge; } 41 | 42 | pub fn set_edge(&mut self, edge: & EdgePtr) { self.edge = edge.clone(); } 43 | 44 | pub fn set_edge_rc(&mut self, edge: & EdgeRc) { self.edge = Ptr::new(edge); } 45 | 46 | pub fn is_valid(& self) -> bool { self.edge.is_valid() } 47 | 48 | pub fn get_edge(& self) -> Option { self.edge.upgrade() } 49 | 50 | pub fn num_vertices(& self) -> usize { self.adjacent_verts().count() } 51 | 52 | /// Computes the attributes (normal and center) of this face 53 | /// Note: this only works when the edges and verts are properly connected 54 | /// So wait for the right time during initialization to run this 55 | /// When a face or faces are added to a half edge mesh with one of the 56 | /// provided functions, this function is called, so that the face attributes 57 | /// are correct. 58 | /// TODO: Decide what to do with a degenerate face 59 | pub fn compute_attrs(&mut self) { 60 | let mut center = Point3::origin(); 61 | let mut count: f32 = 0.0; 62 | 63 | let vert_list: Vec = self.adjacent_verts().to_ptr_vec(); 64 | 65 | debug_assert!(vert_list.len() == 3, "should have 3 adjacent vertices"); 66 | 67 | for vert in &vert_list { 68 | let pos = vert.borrow().get_pos(); 69 | center.x += pos.x; 70 | center.y += pos.y; 71 | center.z += pos.z; 72 | count += 1.0; 73 | } 74 | 75 | // Average position of the corner points 76 | self.center = center / count; 77 | 78 | let vert_a = vert_list[0].borrow().get_pos(); 79 | let s1 = vert_list[1].borrow().get_pos() - vert_a; 80 | let s2 = vert_list[2].borrow().get_pos() - vert_a; 81 | self.normal = s1.cross(s2).normalize(); 82 | } 83 | 84 | /// Iterates over the vertices which make up the face in *counterclockwise* order 85 | pub fn adjacent_verts(& self) -> FaceAdjacentVertIterator { 86 | FaceAdjacentVertIterator::new(self.edge.clone()) 87 | } 88 | 89 | /// Iterates over the edges which make up the face in *counterclockwise* order 90 | pub fn adjacent_edges(& self) -> FaceAdjacentEdgeIterator { 91 | FaceAdjacentEdgeIterator::new(self.edge.clone()) 92 | } 93 | 94 | /// Iterates over the faces adjacent to this face in *counterclockwise* order 95 | pub fn adjacent_faces(& self) -> FaceAdjacentFaceIterator { 96 | FaceAdjacentFaceIterator::new(self.edge.clone()) 97 | } 98 | 99 | pub fn distance_to(& self, point: & Point3) -> f32 { 100 | (point - self.center).magnitude() 101 | } 102 | 103 | pub fn directed_distance_to(& self, point: & Point3) -> f32 { 104 | (point - self.center).dot(self.normal) 105 | } 106 | 107 | pub fn can_see(& self, point: & Point3) -> bool { 108 | self.directed_distance_to(point) > f32::default_epsilon() // Small epsilon to handle floating-point errors 109 | } 110 | } 111 | 112 | impl PartialEq for Face { 113 | fn eq(& self, other: & Face) -> bool { self.id == other.id } 114 | } 115 | 116 | impl Eq for Face {} 117 | 118 | impl hash::Hash for Face { 119 | fn hash(& self, state: &mut H) where H: hash::Hasher { 120 | state.write_u32(self.id); 121 | state.finish(); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/iterators.rs: -------------------------------------------------------------------------------- 1 | use std::rc::Rc; 2 | use std::cell::RefCell; 3 | 4 | use edge::Edge; 5 | use ptr::{ 6 | Ptr, 7 | EdgePtr, EdgeRc, 8 | VertPtr, VertRc, 9 | FacePtr, /*FaceRc,*/ 10 | }; 11 | 12 | 13 | /// A trait for converting an interator of Ptr 14 | /// into a vector of `Rc>` 15 | /// TODO: rename this, since it's not exactly a vec of "Ptr", 16 | /// and that's potentially confusing 17 | pub trait ToPtrVec where Self: Iterator> { 18 | fn to_ptr_vec(self) -> Vec>>; 19 | } 20 | 21 | /// Implement the trait for all iterators over Ptr (all the iterators here) 22 | impl ToPtrVec for I where I: Iterator> { 23 | fn to_ptr_vec(self) -> Vec>> { 24 | self.filter_map(|v| v.upgrade()).collect() 25 | } 26 | } 27 | 28 | // EdgeIterators 29 | 30 | enum TwiceIterState { 31 | First, Second, Done 32 | } 33 | 34 | pub struct EdgeAdjacentVertIterator<'a> { 35 | state: TwiceIterState, 36 | start: &'a Edge, 37 | } 38 | 39 | impl<'a> EdgeAdjacentVertIterator<'a> { 40 | pub fn new(target: & Edge) -> EdgeAdjacentVertIterator { 41 | EdgeAdjacentVertIterator { 42 | state: TwiceIterState::First, 43 | start: target, 44 | } 45 | } 46 | } 47 | 48 | impl<'a> Iterator for EdgeAdjacentVertIterator<'a> { 49 | type Item = VertPtr; 50 | 51 | fn next(&mut self) -> Option { 52 | // edge.origin, edge.next.origin 53 | match self.state { 54 | TwiceIterState::First => { 55 | self.state = TwiceIterState::Second; 56 | Some(self.start.origin.clone()) 57 | }, 58 | TwiceIterState::Second => { 59 | self.state = TwiceIterState::Done; 60 | self.start.next.upgrade() 61 | .map(|next_rc| next_rc.borrow().origin.clone()) 62 | }, 63 | TwiceIterState::Done => None, 64 | } 65 | } 66 | } 67 | 68 | pub struct EdgeAdjacentEdgeIterator { 69 | vert_iter_1: Option, 70 | vert_iter_2: Option, 71 | state: DualIterState, 72 | } 73 | 74 | // Implementation here is borrowed from std::iter::Chain 75 | #[derive(Clone)] 76 | enum DualIterState { 77 | // both iterators running 78 | Both, 79 | // only first running 80 | First, 81 | // only second running 82 | Second, 83 | // neither works 84 | // (this doesn't exist on the chain iterator, 85 | // because both must be valid iterators, 86 | // but it can exist here, in case the weak pointers fail to upgrade) 87 | Neither 88 | } 89 | 90 | impl EdgeAdjacentEdgeIterator { 91 | pub fn new(target: & Edge) -> EdgeAdjacentEdgeIterator { 92 | let iter_1_opt: Option = target.origin.upgrade() 93 | .map(|vert_ptr: VertRc| vert_ptr.borrow().adjacent_edges()); 94 | 95 | let iter_2_opt: Option = target.next.upgrade() 96 | .and_then(|edge_next: EdgeRc| edge_next.borrow().origin.upgrade()) 97 | .map(|vert_ptr: VertRc| vert_ptr.borrow().adjacent_edges()); 98 | 99 | // Flexible w.r.t. whether either pointer upgrade fails. 100 | // is this expected behavior? I'm not positive 101 | let state = match (iter_1_opt.as_ref(), iter_2_opt.as_ref()) { 102 | (Some(_), Some(_)) => DualIterState::Both, 103 | (Some(_), None) => DualIterState::First, 104 | (None, Some(_)) => DualIterState::Second, 105 | (None, None) => DualIterState::Neither 106 | }; // <-- because this match is an assignment statement, this semicolon is essential 107 | 108 | EdgeAdjacentEdgeIterator { 109 | state: state, 110 | vert_iter_1: iter_1_opt, 111 | vert_iter_2: iter_2_opt 112 | } 113 | } 114 | } 115 | 116 | impl Iterator for EdgeAdjacentEdgeIterator { 117 | type Item = EdgePtr; 118 | 119 | fn next(&mut self) -> Option { 120 | // edge.origin.adjacent_edges(), edge.next.origin.adjacent_edges() 121 | // unwraps are only OK here because of the nature of the constructor 122 | match self.state { 123 | DualIterState::Both => { 124 | match self.vert_iter_1.as_mut().unwrap().next() { 125 | // val @ *pattern* binds val to the entire object, doesn't destructure the Option 126 | val @ Some(..) => val, 127 | None => { 128 | self.state = DualIterState::Second; 129 | self.vert_iter_2.as_mut().unwrap().next() 130 | } 131 | } 132 | }, 133 | DualIterState::First => self.vert_iter_1.as_mut().unwrap().next(), 134 | DualIterState::Second => self.vert_iter_2.as_mut().unwrap().next(), 135 | DualIterState::Neither => None, 136 | } 137 | } 138 | } 139 | 140 | pub struct EdgeAdjacentFaceIterator<'a> { 141 | start: &'a Edge, 142 | state: TwiceIterState 143 | } 144 | 145 | impl<'a> EdgeAdjacentFaceIterator<'a> { 146 | pub fn new(target: &'a Edge) -> EdgeAdjacentFaceIterator<'a> { 147 | EdgeAdjacentFaceIterator { 148 | start: target, 149 | state: TwiceIterState::First 150 | } 151 | } 152 | } 153 | 154 | impl<'a> Iterator for EdgeAdjacentFaceIterator<'a> { 155 | type Item = FacePtr; 156 | 157 | fn next(&mut self) -> Option { 158 | // edge.face, edge.pair.face 159 | match self.state { 160 | TwiceIterState::First => { 161 | self.state = TwiceIterState::Second; 162 | Some(self.start.face.clone()) 163 | }, 164 | TwiceIterState::Second => { 165 | self.state = TwiceIterState::Done; 166 | self.start.pair.upgrade() 167 | .map(|pair_rc: EdgeRc| pair_rc.borrow().face.clone()) 168 | }, 169 | TwiceIterState::Done => None 170 | } 171 | } 172 | } 173 | 174 | // VertIterators 175 | 176 | pub struct VertAdjacentVertIterator { 177 | start: EdgePtr, 178 | current: Option, 179 | } 180 | 181 | impl VertAdjacentVertIterator { 182 | pub fn new(edge: EdgePtr) -> VertAdjacentVertIterator { 183 | VertAdjacentVertIterator { 184 | start: edge, 185 | current: None, 186 | } 187 | } 188 | } 189 | 190 | impl Iterator for VertAdjacentVertIterator { 191 | type Item = VertPtr; 192 | 193 | fn next(&mut self) -> Option { 194 | // edge.pair.origin 195 | // edge -> edge.pair.next 196 | match self.current.clone() { 197 | Some(cur_weak) => cur_weak.upgrade() 198 | .and_then(|cur_rc: EdgeRc| cur_rc.borrow().pair.upgrade()) 199 | .and_then(|pair_rc: EdgeRc| { 200 | let next_weak: EdgePtr = pair_rc.borrow().next.clone(); 201 | Ptr::merge_upgrade(& next_weak, & self.start) 202 | .and_then(|(next_rc, start_rc)| { 203 | if next_rc == start_rc { 204 | None 205 | } else { 206 | self.current = Some(next_weak); 207 | Some(pair_rc.borrow().origin.clone()) 208 | } 209 | }) 210 | }), 211 | None => self.start.upgrade() 212 | .and_then(|cur_rc: EdgeRc| cur_rc.borrow().pair.upgrade()) 213 | .map(|pair_rc: EdgeRc| { 214 | self.current = Some(self.start.clone()); 215 | pair_rc.borrow().origin.clone() 216 | }), 217 | } 218 | } 219 | } 220 | 221 | pub struct VertAdjacentEdgeIterator { 222 | start: EdgePtr, 223 | current: Option, 224 | } 225 | 226 | impl VertAdjacentEdgeIterator { 227 | pub fn new(edge: EdgePtr) -> VertAdjacentEdgeIterator { 228 | VertAdjacentEdgeIterator { 229 | start: edge, 230 | current: None 231 | } 232 | } 233 | } 234 | 235 | impl Iterator for VertAdjacentEdgeIterator { 236 | type Item = EdgePtr; 237 | 238 | fn next(&mut self) -> Option { 239 | // edge 240 | // edge -> edge.pair.next 241 | match self.current.clone() { 242 | Some(cur_weak) => cur_weak.upgrade() 243 | .and_then(|cur_rc: EdgeRc| cur_rc.borrow().pair.upgrade()) 244 | .map(|pair_rc: EdgeRc| pair_rc.borrow().next.clone()) 245 | .and_then(|next_weak: EdgePtr| { 246 | Ptr::merge_upgrade(& next_weak, & self.start) 247 | .and_then(|(next_rc, start_rc)| { 248 | if next_rc == start_rc { 249 | None 250 | } else { 251 | self.current = Some(next_weak.clone()); 252 | Some(next_weak) 253 | } 254 | }) 255 | }), 256 | None => self.start.upgrade() 257 | .map(|_: EdgeRc| { 258 | self.current = Some(self.start.clone()); 259 | self.start.clone() 260 | }), 261 | } 262 | } 263 | } 264 | 265 | pub struct VertAdjacentFaceIterator { 266 | start: EdgePtr, 267 | current: Option, 268 | } 269 | 270 | impl VertAdjacentFaceIterator { 271 | pub fn new(edge: EdgePtr) -> VertAdjacentFaceIterator { 272 | VertAdjacentFaceIterator { 273 | start: edge, 274 | current: None, 275 | } 276 | } 277 | } 278 | 279 | impl Iterator for VertAdjacentFaceIterator { 280 | type Item = FacePtr; 281 | 282 | fn next(&mut self) -> Option { 283 | // edge.face 284 | // edge -> edge.pair.next 285 | match self.current.clone() { 286 | Some(cur_weak) => cur_weak.upgrade() 287 | .and_then(|cur_rc: EdgeRc| cur_rc.borrow().pair.upgrade()) 288 | .map(|pair_rc: EdgeRc| pair_rc.borrow().next.clone()) 289 | .and_then(|next_weak: EdgePtr| { 290 | Ptr::merge_upgrade(& next_weak, & self.start) 291 | .and_then(|(next_rc, start_rc)| { 292 | if next_rc == start_rc { 293 | None 294 | } else { 295 | self.current = Some(next_weak); 296 | Some(next_rc.borrow().face.clone()) 297 | } 298 | }) 299 | }), 300 | None => self.start.upgrade() 301 | .map(|cur_rc: EdgeRc| { 302 | self.current = Some(self.start.clone()); 303 | cur_rc.borrow().face.clone() 304 | }), 305 | } 306 | } 307 | } 308 | 309 | // FaceIterators 310 | 311 | pub struct FaceAdjacentVertIterator { 312 | start: EdgePtr, 313 | current: Option, 314 | } 315 | 316 | impl FaceAdjacentVertIterator { 317 | pub fn new(edge: EdgePtr) -> FaceAdjacentVertIterator { 318 | FaceAdjacentVertIterator { 319 | start: edge, 320 | current: None, 321 | } 322 | } 323 | } 324 | 325 | impl Iterator for FaceAdjacentVertIterator { 326 | type Item = VertPtr; 327 | 328 | fn next(&mut self) -> Option { 329 | // edge.origin 330 | // edge -> edge.next 331 | match self.current.clone() { 332 | Some(cur_weak) => cur_weak.upgrade() 333 | .map(|cur_rc: EdgeRc| cur_rc.borrow().next.clone()) 334 | .and_then(|next_weak: EdgePtr| { 335 | Ptr::merge_upgrade(& next_weak, & self.start) 336 | .and_then(|(next_rc, start_rc)| { 337 | if next_rc == start_rc { 338 | None 339 | } else { 340 | self.current = Some(next_weak); 341 | Some(next_rc.borrow().origin.clone()) 342 | } 343 | }) 344 | }), 345 | None => self.start.upgrade() 346 | .map(|cur_rc: EdgeRc| { 347 | self.current = Some(self.start.clone()); 348 | cur_rc.borrow().origin.clone() 349 | }), 350 | } 351 | } 352 | } 353 | 354 | pub struct FaceAdjacentEdgeIterator { 355 | start: EdgePtr, 356 | current: Option 357 | } 358 | 359 | impl FaceAdjacentEdgeIterator { 360 | pub fn new(edge: EdgePtr) -> FaceAdjacentEdgeIterator { 361 | FaceAdjacentEdgeIterator { 362 | start: edge, 363 | current: None 364 | } 365 | } 366 | } 367 | 368 | impl Iterator for FaceAdjacentEdgeIterator { 369 | type Item = EdgePtr; 370 | 371 | fn next(&mut self) -> Option { 372 | // edge 373 | // edge -> edge.next 374 | match self.current.clone() { 375 | Some(cur_weak) => cur_weak.upgrade() 376 | .map(|cur_rc: EdgeRc| cur_rc.borrow().next.clone()) 377 | .and_then(|next_weak: EdgePtr| { 378 | Ptr::merge_upgrade(& next_weak, & self.start) 379 | .and_then(|(next_rc, start_rc)| { 380 | if next_rc == start_rc { 381 | None 382 | } else { 383 | self.current = Some(next_weak.clone()); 384 | Some(next_weak) 385 | } 386 | }) 387 | }), 388 | None => { 389 | self.current = Some(self.start.clone()); 390 | Some(self.start.clone()) 391 | }, 392 | } 393 | } 394 | } 395 | 396 | pub struct FaceAdjacentFaceIterator { 397 | start: EdgePtr, 398 | current: Option, 399 | } 400 | 401 | impl FaceAdjacentFaceIterator { 402 | pub fn new(edge: EdgePtr) -> FaceAdjacentFaceIterator { 403 | FaceAdjacentFaceIterator { 404 | start: edge, 405 | current: None 406 | } 407 | } 408 | } 409 | 410 | impl Iterator for FaceAdjacentFaceIterator { 411 | type Item = FacePtr; 412 | 413 | fn next(&mut self) -> Option { 414 | // edge.pair.face 415 | // edge -> edge.next 416 | match self.current.clone() { 417 | Some(cur_weak) => cur_weak.upgrade() 418 | .map(|cur_rc: EdgeRc| cur_rc.borrow().next.clone()) 419 | .and_then(|next_weak: EdgePtr| { 420 | Ptr::merge_upgrade(& next_weak, & self.start) 421 | .and_then(|(next_rc, start_rc)| { 422 | if next_rc == start_rc { 423 | None 424 | } else { 425 | next_rc.borrow().pair.upgrade() 426 | .map(|pair_rc| { 427 | self.current = Some(next_weak); 428 | pair_rc.borrow().face.clone() 429 | }) 430 | } 431 | }) 432 | }), 433 | None => self.start.upgrade() 434 | .and_then(|edge_rc: EdgeRc| edge_rc.borrow().pair.upgrade()) 435 | .map(|pair_rc: EdgeRc| { 436 | self.current = Some(self.start.clone()); 437 | pair_rc.borrow().face.clone() 438 | }), 439 | } 440 | } 441 | } 442 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | // TODO: use clippy linter on this code 2 | 3 | extern crate cgmath; 4 | extern crate approx; 5 | 6 | pub mod ptr; 7 | pub mod edge; 8 | pub mod vert; 9 | pub mod face; 10 | pub mod iterators; 11 | pub mod mesh; 12 | pub mod util; 13 | 14 | pub use self::mesh::HalfEdgeMesh; 15 | pub use self::edge::Edge; 16 | pub use self::vert::Vert; 17 | pub use self::face::Face; 18 | 19 | // Export the pointer types too, in case you need them 20 | pub use self::ptr::*; 21 | 22 | // Export relevant iterators and traits 23 | pub use self::iterators::ToPtrVec; 24 | -------------------------------------------------------------------------------- /src/mesh.rs: -------------------------------------------------------------------------------- 1 | use cgmath::Point3; 2 | 3 | use std::collections::HashMap; 4 | use std::collections::HashSet; 5 | 6 | use edge::Edge; 7 | use vert::Vert; 8 | use face::Face; 9 | use ptr::{Ptr, EdgeRc, VertRc, FaceRc, EdgePtr, VertPtr, FacePtr}; 10 | use iterators::ToPtrVec; 11 | use util::*; 12 | 13 | /// Half-Edge Mesh data structure 14 | /// While it's possible to create non-triangular faces, this code assumes 15 | /// triangular faces in several locations 16 | /// mesh.edges, mesh.vertices, and mesh.faces are `HashMaps` containing reference-counted Pointers 17 | /// to the mesh contents. Usually, these Rc values are the last values to exist. When they 18 | /// are destroyed, the pointed-to contents are destroyed as well. 19 | /// Vertex, edge, and face ids are mesh-specific and unique only within a certain mesh 20 | /// Integer overflow is undefined in Rust, but checked in debug builds. I think this means 21 | /// that it's possible to generate the same id twice, after 2^32-1 ids have been made. 22 | /// Try not to make more than 2^32-1 of any one of them, stuff might get messed up. 23 | /// TODO: Better error reporting, using a custom error type 24 | /// See also: http://blog.burntsushi.net/rust-error-handling/ 25 | /// Probably should do it whenever faces are added or a vertex is modified ? 26 | /// TODO: Better way of updating face-specific data like center and normals 27 | pub struct HalfEdgeMesh { 28 | pub edges: HashMap, 29 | pub vertices: HashMap, 30 | pub faces: HashMap, 31 | cur_edge_id: u32, 32 | cur_vert_id: u32, 33 | cur_face_id: u32, 34 | } 35 | 36 | impl HalfEdgeMesh { 37 | /// Constructs an empty mesh 38 | pub fn empty() -> HalfEdgeMesh { 39 | HalfEdgeMesh { 40 | edges: HashMap::new(), 41 | vertices: HashMap::new(), 42 | faces: HashMap::new(), 43 | cur_edge_id: 0, 44 | cur_vert_id: 0, 45 | cur_face_id: 0, 46 | } 47 | } 48 | 49 | /// Construct a half edge mesh from four points that form a tetrahedron 50 | /// A half-edge mesh requires at least a tetrahedron to be valid. 51 | /// When seen from an arbitrary "front" side of the tetrahedron, the vertices given to this function 52 | /// should be as follows: 53 | /// p1: apex, p2: bottom left front, p3: bottom right front, p4: bottom rear 54 | pub fn from_tetrahedron_pts(p1: Point3, p2: Point3, p3: Point3, p4: Point3) -> HalfEdgeMesh { 55 | // In progress 56 | let mut mesh = HalfEdgeMesh::empty(); 57 | 58 | let v1 = Ptr::new_rc(Vert::empty(mesh.new_vert_id(), p1)); 59 | let v2 = Ptr::new_rc(Vert::empty(mesh.new_vert_id(), p2)); 60 | let v3 = Ptr::new_rc(Vert::empty(mesh.new_vert_id(), p3)); 61 | let v4 = Ptr::new_rc(Vert::empty(mesh.new_vert_id(), p4)); 62 | 63 | let mut tri; 64 | 65 | tri = mesh.make_triangle(& v1, & v2, & v3); 66 | mesh.add_triangle(tri); 67 | tri = mesh.make_triangle(& v2, & v1, & v4); 68 | mesh.add_triangle(tri); 69 | tri = mesh.make_triangle(& v3, & v4, & v1); 70 | mesh.add_triangle(tri); 71 | tri = mesh.make_triangle(& v4, & v3, & v2); 72 | mesh.add_triangle(tri); 73 | 74 | mesh.move_verts(vec![v1, v2, v3, v4]); 75 | 76 | report_connect_err(connect_pairs(&mut mesh)); 77 | 78 | mesh 79 | } 80 | 81 | /// Construct a half edge mesh from six points that form an octahedron 82 | /// p1: top apex, p2: mid left front, p3: mid right front, p4: mid left back, p5: mid right back, p6: bottom apex 83 | pub fn from_octahedron_pts(p1: Point3, p2: Point3, p3: Point3, p4: Point3, p5: Point3, p6: Point3) -> HalfEdgeMesh { 84 | let mut mesh = HalfEdgeMesh::empty(); 85 | 86 | let v1 = Ptr::new_rc(Vert::empty(mesh.new_vert_id(), p1)); 87 | let v2 = Ptr::new_rc(Vert::empty(mesh.new_vert_id(), p2)); 88 | let v3 = Ptr::new_rc(Vert::empty(mesh.new_vert_id(), p3)); 89 | let v4 = Ptr::new_rc(Vert::empty(mesh.new_vert_id(), p4)); 90 | let v5 = Ptr::new_rc(Vert::empty(mesh.new_vert_id(), p5)); 91 | let v6 = Ptr::new_rc(Vert::empty(mesh.new_vert_id(), p6)); 92 | 93 | let mut tri; 94 | 95 | tri = mesh.make_triangle(& v1, & v2, & v3); 96 | mesh.add_triangle(tri); 97 | tri = mesh.make_triangle(& v1, & v4, & v2); 98 | mesh.add_triangle(tri); 99 | tri = mesh.make_triangle(& v1, & v3, & v5); 100 | mesh.add_triangle(tri); 101 | tri = mesh.make_triangle(& v1, & v5, & v4); 102 | mesh.add_triangle(tri); 103 | tri = mesh.make_triangle(& v6, & v3, & v2); 104 | mesh.add_triangle(tri); 105 | tri = mesh.make_triangle(& v6, & v2, & v4); 106 | mesh.add_triangle(tri); 107 | tri = mesh.make_triangle(& v6, & v5, & v3); 108 | mesh.add_triangle(tri); 109 | tri = mesh.make_triangle(& v6, & v4, & v5); 110 | mesh.add_triangle(tri); 111 | 112 | mesh.move_verts(vec![v1, v2, v3, v4, v5, v6]); 113 | 114 | report_connect_err(connect_pairs(&mut mesh)); 115 | 116 | mesh 117 | } 118 | 119 | /// Construct a half edge mesh from a Vec of vertices and a Vec of triplets of indices into 120 | /// the Vec of vertices. 121 | pub fn from_face_vertex_mesh(vertices: &[Point3], indices: &[[usize; 3]]) -> HalfEdgeMesh { 122 | let mut mesh = HalfEdgeMesh::empty(); 123 | let mut id_map: HashMap = HashMap::new(); // Maps indices to ids 124 | 125 | for (idx, pos) in vertices.iter().enumerate() { 126 | let vert = Ptr::new_rc(Vert::empty(mesh.new_vert_id(), *pos)); 127 | id_map.insert(idx, vert.borrow().id); 128 | mesh.push_vert(vert); 129 | } 130 | 131 | for tri in indices.iter() { 132 | let face = Ptr::new_rc(Face::empty(mesh.new_face_id())); 133 | let mut new_edges: Vec = Vec::new(); 134 | 135 | for idx in tri { 136 | if let Some(vert_id) = id_map.get(idx) { 137 | if mesh.vertices.contains_key(vert_id) { 138 | let new_edge_id = mesh.new_edge_id(); 139 | if let Some(vert) = mesh.vertices.get(vert_id) { 140 | let edge = Ptr::new_rc(Edge::with_origin(new_edge_id, Ptr::new(vert))); 141 | edge.borrow_mut().set_face_rc(& face); 142 | vert.borrow_mut().set_edge_rc(& edge); 143 | new_edges.push(edge); 144 | } 145 | } 146 | } 147 | } 148 | 149 | let n_edge_len = new_edges.len(); 150 | for (idx, edge) in new_edges.iter().enumerate() { 151 | edge.borrow_mut().set_next_rc(& new_edges[(idx + 1) % n_edge_len]); 152 | } 153 | 154 | if let Some(ref edge) = new_edges.get(0) { 155 | face.borrow_mut().set_edge_rc(edge); 156 | } 157 | 158 | for edge in new_edges { 159 | mesh.push_edge(edge); 160 | } 161 | 162 | mesh.push_face(face); 163 | } 164 | 165 | report_connect_err(connect_pairs(&mut mesh)); 166 | 167 | mesh 168 | } 169 | 170 | pub fn new_edge_id(&mut self) -> u32 { 171 | self.cur_edge_id += 1; self.cur_edge_id 172 | } 173 | 174 | pub fn new_vert_id(&mut self) -> u32 { 175 | self.cur_vert_id += 1; self.cur_vert_id 176 | } 177 | 178 | pub fn new_face_id(&mut self) -> u32 { 179 | self.cur_face_id += 1; self.cur_face_id 180 | } 181 | 182 | pub fn push_edge(&mut self, edge: EdgeRc) { 183 | let key = edge.borrow().id; 184 | self.edges.insert(key, edge); 185 | } 186 | 187 | pub fn extend_edges(&mut self, edges: & [EdgeRc]) { 188 | for edge in edges { 189 | let key = edge.borrow().id; 190 | self.edges.insert(key, edge.clone()); 191 | } 192 | } 193 | 194 | pub fn move_edges(&mut self, edges: Vec) { 195 | for edge in edges { 196 | let key = edge.borrow().id; 197 | self.edges.insert(key, edge); 198 | } 199 | } 200 | 201 | pub fn push_vert(&mut self, vert: VertRc) { 202 | let key = vert.borrow().id; 203 | self.vertices.insert(key, vert); 204 | } 205 | 206 | pub fn extend_verts(&mut self, verts: & [VertRc]) { 207 | for vert in verts { 208 | let key = vert.borrow().id; 209 | self.vertices.insert(key, vert.clone()); 210 | } 211 | } 212 | 213 | pub fn move_verts(&mut self, verts: Vec) { 214 | for vert in verts { 215 | let key = vert.borrow().id; 216 | self.vertices.insert(key, vert); 217 | } 218 | } 219 | 220 | pub fn push_face(&mut self, face: FaceRc) { 221 | // Ensuring that the attributes are correct before the face gets added here is essential 222 | face.borrow_mut().compute_attrs(); 223 | let key = face.borrow().id; 224 | self.faces.insert(key, face); 225 | } 226 | 227 | pub fn extend_faces(&mut self, faces: & [FaceRc]) { 228 | for face in faces { 229 | face.borrow_mut().compute_attrs(); 230 | let key = face.borrow().id; 231 | self.faces.insert(key, face.clone()); 232 | } 233 | } 234 | 235 | pub fn move_faces(&mut self, faces: Vec) { 236 | for face in faces { 237 | face.borrow_mut().compute_attrs(); 238 | let key = face.borrow().id; 239 | self.faces.insert(key, face); 240 | } 241 | } 242 | 243 | /// Adds a tuple of (face, edge, edge, edge) to the mesh 244 | pub fn add_triangle(&mut self, triangle: (FaceRc, EdgeRc, EdgeRc, EdgeRc)) { 245 | let mut key: u32; 246 | 247 | triangle.0.borrow_mut().compute_attrs(); 248 | key = triangle.0.borrow().id; 249 | self.faces.insert(key, triangle.0); 250 | 251 | key = triangle.1.borrow().id; 252 | self.edges.insert(key, triangle.1); 253 | 254 | key = triangle.2.borrow().id; 255 | self.edges.insert(key, triangle.2); 256 | 257 | key = triangle.3.borrow().id; 258 | self.edges.insert(key, triangle.3); 259 | } 260 | 261 | /// Takes three `Rc>`, 262 | /// creates three edges and one face, and connects them as well as it can 263 | /// Note: since this creates a lone triangle, edge.pair links are 264 | /// still empty after this function 265 | pub fn make_triangle(&mut self, p1: & VertRc, p2: & VertRc, p3: & VertRc) -> (FaceRc, EdgeRc, EdgeRc, EdgeRc) { 266 | // Create triangle edges 267 | let e1 = Ptr::new_rc(Edge::with_origin(self.new_edge_id(), Ptr::new(p1))); 268 | let e2 = Ptr::new_rc(Edge::with_origin(self.new_edge_id(), Ptr::new(p2))); 269 | let e3 = Ptr::new_rc(Edge::with_origin(self.new_edge_id(), Ptr::new(p3))); 270 | 271 | // Be sure to set up vertex connectivity with the new edges 272 | // It doesn't matter which edge a vertex points to, 273 | // so long as it points back to the vertex 274 | p1.borrow_mut().take_edge(Ptr::new(& e1)); 275 | p2.borrow_mut().take_edge(Ptr::new(& e2)); 276 | p3.borrow_mut().take_edge(Ptr::new(& e3)); 277 | 278 | // Set up edge cycle 279 | e1.borrow_mut().take_next(Ptr::new(& e2)); 280 | e2.borrow_mut().take_next(Ptr::new(& e3)); 281 | e3.borrow_mut().take_next(Ptr::new(& e1)); 282 | 283 | // Create triangle face 284 | let f1 = Ptr::new_rc(Face::with_edge(self.new_face_id(), Ptr::new(& e1))); 285 | 286 | // Set up face links 287 | e1.borrow_mut().take_face(Ptr::new(& f1)); 288 | e2.borrow_mut().take_face(Ptr::new(& f1)); 289 | e3.borrow_mut().take_face(Ptr::new(& f1)); 290 | 291 | // Now is the right time to run this, since vertices and edges are connected 292 | f1.borrow_mut().compute_attrs(); 293 | 294 | (f1, e1, e2, e3) 295 | } 296 | 297 | /// Checks if two faces are adjacent by looking for a shared edge 298 | pub fn are_faces_adjacent(& self, face_l: & FaceRc, face_r: & FaceRc) -> bool { 299 | face_l.borrow().adjacent_edges() 300 | .any(|edge| { 301 | edge.upgrade() 302 | .and_then(|e| e.borrow().pair.upgrade()) 303 | .and_then(|e| e.borrow().face.upgrade()) 304 | .map(|f| f == * face_r) == Some(true) 305 | }) 306 | } 307 | 308 | pub fn are_face_ptrs_adjacent(& self, face_l: & FacePtr, face_r: & FacePtr) -> bool { 309 | match Ptr::merge_upgrade(face_l, face_r) { 310 | Some((l_rc, r_rc)) => self.are_faces_adjacent(& l_rc, & r_rc), 311 | None => false, 312 | } 313 | } 314 | 315 | /// Replace a face with three faces, each connected to the new point 316 | /// And one of the face's previous vertices 317 | /// TODO: Make all of these mesh-manipulation functions return a Result<(), &str> to check that manipulation was completed 318 | pub fn triangulate_face(&mut self, point: Point3, target_face: & FaceRc) { 319 | // get face edges 320 | let face_edges = target_face.borrow().adjacent_edges().to_ptr_vec(); 321 | // get face vertexes, assumed to be counter-clockwise 322 | let face_vertices = target_face.borrow().adjacent_verts().to_ptr_vec(); 323 | let vertices_len = face_vertices.len(); 324 | 325 | debug_assert!(face_edges.len() == 3, "should be 3 adjacent edges"); 326 | debug_assert!(vertices_len == 3, "should be 3 adjacent vertices"); // should be 3, or else your faces aren't triangles 327 | 328 | let apex_vert = Ptr::new_rc(Vert::empty(self.new_vert_id(), point)); 329 | 330 | // Add the three new faces - one attached to each of the original face's edges, 331 | // plus two new edges attached to the point 332 | let mut new_lead_edges: Vec = Vec::new(); 333 | let mut new_trail_edges: Vec = Vec::new(); 334 | for (i, base_edge) in face_edges.iter().enumerate() { 335 | // Might not be necessary 336 | base_edge.borrow_mut().take_origin(Ptr::new(& face_vertices[i])); 337 | base_edge.borrow().origin.upgrade().map(|o| o.borrow_mut().take_edge(Ptr::new(base_edge))); 338 | 339 | let new_face = Ptr::new_rc(Face::with_edge(self.new_face_id(), Ptr::new(base_edge))); 340 | let leading_edge = Ptr::new_rc(Edge::with_origin(self.new_edge_id(), Ptr::new(& face_vertices[(i + 1) % vertices_len]))); 341 | let trailing_edge = Ptr::new_rc(Edge::with_origin(self.new_edge_id(), Ptr::new(& apex_vert))); 342 | 343 | base_edge.borrow_mut().take_face(Ptr::new(& new_face)); 344 | leading_edge.borrow_mut().take_face(Ptr::new(& new_face)); 345 | trailing_edge.borrow_mut().take_face(Ptr::new(& new_face)); 346 | 347 | base_edge.borrow_mut().take_next(Ptr::new(& leading_edge)); 348 | leading_edge.borrow_mut().take_next(Ptr::new(& trailing_edge)); 349 | trailing_edge.borrow_mut().take_next(Ptr::new(base_edge)); 350 | 351 | apex_vert.borrow_mut().take_edge(Ptr::new(& trailing_edge)); 352 | 353 | new_lead_edges.push(leading_edge.clone()); 354 | new_trail_edges.push(trailing_edge.clone()); 355 | 356 | self.push_edge(leading_edge); 357 | self.push_edge(trailing_edge); 358 | self.push_face(new_face); 359 | } 360 | 361 | // This step is pretty crucial 362 | self.push_vert(apex_vert); 363 | 364 | let trail_edge_len = new_trail_edges.len(); 365 | 366 | // Should be 3, or else the faces are not triangular, or not enough edges were created 367 | debug_assert!(trail_edge_len == 3, "should be 3 new trailing edges"); 368 | debug_assert!(new_lead_edges.len() == 3, "should be 3 new leading edges"); 369 | 370 | // Connect pairs 371 | for (i, leading_edge) in new_lead_edges.iter().enumerate() { 372 | let trailing_edge = & new_trail_edges[(i + 1) % trail_edge_len]; 373 | leading_edge.borrow_mut().take_pair(Ptr::new(trailing_edge)); 374 | trailing_edge.borrow_mut().take_pair(Ptr::new(leading_edge)); 375 | } 376 | 377 | // Remove the face and the edges from the mesh. 378 | // When the local pointer to this falls out of scope, it should be deallocated 379 | self.faces.remove(& target_face.borrow().id); 380 | } 381 | 382 | pub fn triangulate_face_ptr(&mut self, point: Point3, face: & FacePtr) { 383 | if let Some(face_rc) = face.upgrade() { 384 | self.triangulate_face(point, & face_rc) 385 | } 386 | } 387 | 388 | /// Attach a point to a mesh, replacing many faces (used for the convex hull algorithm) 389 | /// The faces should be a continuously connected group, each adjacent pair of vertices 390 | /// in the border of this group are connected to the point in a new triangular face. 391 | /// The programmer is responsible for ensuring that there are no holes in the passed 392 | /// set of faces. Returns Pointers to the new faces in the result, if successful 393 | pub fn attach_point_for_faces(&mut self, point: Point3, remove_faces: &[FaceRc]) -> Result, &'static str> { 394 | // collect a set of face ids to be removed, for later reference 395 | let outgoing_face_ids: HashSet = remove_faces.iter().map(|f| f.borrow().id).collect(); 396 | let mut horizon_edges: HashMap = HashMap::new(); 397 | let mut remove_edges: Vec = Vec::new(); 398 | let mut remove_verts: Vec = Vec::new(); 399 | let mut horizon_next_map: HashMap = HashMap::new(); 400 | let mut iter_edge: Option = None; 401 | 402 | // for each face in faces 403 | for out_face in remove_faces.iter() { 404 | // iterate over the edges of the face 405 | for face_edge in out_face.borrow().adjacent_edges().to_ptr_vec() { 406 | // check if the opposite face bordered by the edge should also be removed (edge.pair.face) 407 | // any edges which border a face to be removed, should also be removed. 408 | // Any edges which border a face which won't be removed, are part of the "horizon". 409 | let remove_edge = face_edge.borrow().pair.upgrade() 410 | .and_then(|p| p.borrow().face.upgrade()) 411 | .map_or(true, |f| outgoing_face_ids.contains(& f.borrow().id)); 412 | // Remove edges where pointer upgrades don't work 413 | 414 | if remove_edge { 415 | // Removed edges are saved for later in a vec 416 | remove_edges.push(face_edge.borrow().id); 417 | } else { 418 | // The origin vertex of each horizon edge should have it's edge pointer set to the horizon edge 419 | // This is important in case the edge pointer was already set to one of the removed edges 420 | face_edge.borrow().get_origin().map(|o| o.borrow_mut().set_edge_rc(& face_edge)); 421 | // The first horizon edge discovered should be saved as an "iteration" edge 422 | if iter_edge.is_none() { iter_edge = Some(face_edge.clone()); } 423 | // Horizon edges are saved for later in a HashMap (id -> edge) 424 | horizon_edges.insert(face_edge.borrow().id, face_edge.clone()); 425 | } 426 | } 427 | 428 | // likewise, iterate over the vertices of the face 429 | // any vertex which is surrounded by only faces to be removed, should also be removed. 430 | // any vertex which has at least one non-removed face adjacent to it should not be removed. 431 | // Save the removed vertices in a list, to be dealt with later 432 | for face_vert in out_face.borrow().adjacent_verts().to_ptr_vec() { 433 | let remove_vert = face_vert.borrow().adjacent_faces() 434 | .all(|face_ptr| { 435 | face_ptr.upgrade() 436 | .map_or(true, |f| outgoing_face_ids.contains(& f.borrow().id)) 437 | }); 438 | 439 | if remove_vert { 440 | remove_verts.push(face_vert.borrow().id); 441 | } 442 | } 443 | } 444 | 445 | // If no iteration edge was saved, then no horizon edges were found and the faces list is invalid. 446 | if iter_edge.is_none() { return Err("No horizon edges found"); } 447 | 448 | // iterate over the horizon edges 449 | for h_edge in horizon_edges.values() { 450 | // Iterate over the edges at the target end of each horizon edge (edge.next.origin.adjacent_edges()) 451 | if let Some(target_vert) = h_edge.borrow().get_target() { 452 | // find the next horizon edge connected to it. 453 | // If the edge is actually a horizon edge (i.e. it is actually adjacent to a face which won't be removed), 454 | // then this adjacent horizon edge must exist. 455 | for adj_edge in target_vert.borrow().adjacent_edges() { 456 | if let Some(adj_edge_rc) = adj_edge.upgrade() { 457 | let adj_id = adj_edge_rc.borrow().id; 458 | if horizon_edges.contains_key(& adj_id) { 459 | // Save the correspondences between each horizon edge and the next one 460 | horizon_next_map.insert(h_edge.borrow().id, adj_id); 461 | break; 462 | } 463 | } 464 | } 465 | } 466 | } 467 | 468 | // check the horizon edge next correspondences: each next value should itself have a next value. 469 | // In addition, each key value should have some other key's next pointing to it. 470 | // Because of the way the hashmap is constructed, no edge will point to itself (good!) 471 | let horizon_next_keys: HashSet = horizon_next_map.keys().cloned().collect(); 472 | let horizon_next_values: HashSet = horizon_next_map.values().cloned().collect(); 473 | 474 | // Test that the set of keys and values are equal, i.e. keys are a subset of values and vice versa 475 | if horizon_next_keys != horizon_next_values { return Err("Horizon is malformed - it does not form a connected loop"); } 476 | 477 | // Create a vec which iterates over the horizon edges, with adjacent horizon edges adjacent in the vec. 478 | // This will be used twice later 479 | let start_edge = iter_edge.unwrap(); 480 | let start_id = start_edge.borrow().id; 481 | let mut iter_id = start_id; 482 | let mut horizon_vec: Vec = Vec::new(); 483 | // Note: after testing the invariant above that keys and values are equal, 484 | // we know this loop will finish 485 | loop { 486 | horizon_vec.push(self.edges[& iter_id].clone()); 487 | iter_id = horizon_next_map[& iter_id]; 488 | if iter_id == start_id { break; } 489 | } 490 | 491 | // Remove the faces, the edges, and the vertices that were marked for removal 492 | // Do this after all other data structures have been set up, because a valid mesh is required 493 | // for some steps, for example finding a horizon edge's next edge 494 | for out_face in remove_faces { 495 | self.faces.remove(&out_face.borrow().id); 496 | } 497 | 498 | for out_vert_id in &remove_verts { 499 | self.vertices.remove(out_vert_id); 500 | } 501 | 502 | for out_edge_id in &remove_edges { 503 | self.edges.remove(out_edge_id); 504 | } 505 | 506 | // create a new vertex for the point 507 | let apex_vert = Ptr::new_rc(Vert::empty(self.new_vert_id(), point)); 508 | 509 | // Going to iterate twice through the ordered list of horizon edges created earlier 510 | // And set up new mesh entities and their linkage 511 | let horizon_len = horizon_vec.len(); 512 | 513 | let mut return_faces: Vec = Vec::new(); 514 | 515 | // the iterating edge is the 'base edge' 516 | for (idx, base_edge) in horizon_vec.iter().enumerate() { 517 | // the iterating edge's next edge is edges[(i + 1) % edges.len()] 518 | let next_edge = & horizon_vec[(idx + 1) % horizon_len]; 519 | if let Some(next_origin) = next_edge.borrow().origin.upgrade() { 520 | // create a new face, connected to the base edge 521 | let new_face = Ptr::new_rc(Face::with_edge(self.new_face_id(), Ptr::new(base_edge))); 522 | // create two new edges, one leading and one trailing. 523 | // The leading edge connects to the next horizon edge's origin vertex 524 | let new_leading = Ptr::new_rc(Edge::with_origin(self.new_edge_id(), Ptr::new(& next_origin))); 525 | // the trailing edge connects to the new vertex 526 | let new_trailing = Ptr::new_rc(Edge::with_origin(self.new_edge_id(), Ptr::new(& apex_vert))); 527 | // connect the new vertex to the trailing edge (this is repeated many times but is necessary for mesh validity) 528 | apex_vert.borrow_mut().set_edge_rc(& new_trailing); 529 | // connect next ptrs: the horizon edge to the leading edge, the leading to the trailing, and the trailing to the horizon 530 | base_edge.borrow_mut().set_next_rc(& new_leading); 531 | new_leading.borrow_mut().set_next_rc(& new_trailing); 532 | new_trailing.borrow_mut().set_next_rc(base_edge); 533 | // connect all three to the face 534 | base_edge.borrow_mut().set_face_rc(& new_face); 535 | new_leading.borrow_mut().set_face_rc(& new_face); 536 | new_trailing.borrow_mut().set_face_rc(& new_face); 537 | // move the two new edges into the mesh 538 | self.push_edge(new_leading); 539 | self.push_edge(new_trailing); 540 | // move the face into the mesh 541 | return_faces.push(new_face.clone()); 542 | self.push_face(new_face); 543 | } else { 544 | return Err("Could not set up horizon faces correctly"); 545 | } 546 | } 547 | 548 | // move the point vertex into the mesh 549 | self.push_vert(apex_vert); 550 | 551 | // iterate over the horizon edges again. 552 | for (idx, base_edge) in horizon_vec.iter().enumerate() { 553 | // Connect pairs: edge.next to (edge + 1).next.next and vice versa 554 | let next_edge = & horizon_vec[(idx + 1) % horizon_len]; 555 | if let (Some(next_rc), Some(pair_rc)) = (base_edge.borrow().get_next(), next_edge.borrow().get_next_next()) { 556 | next_rc.borrow_mut().set_pair_rc(& pair_rc); 557 | pair_rc.borrow_mut().set_pair_rc(& next_rc); 558 | } else { 559 | return Err("Could not connect pair edges"); 560 | } 561 | } 562 | 563 | Ok(return_faces) 564 | } 565 | 566 | pub fn attach_point_for_face_ptrs(&mut self, point: Point3, faces: &[FacePtr]) -> Result, &'static str> { 567 | let face_ptrs = faces.iter().filter_map(|f| f.upgrade()).collect::>(); 568 | self.attach_point_for_faces(point, &face_ptrs) 569 | } 570 | 571 | /// This function should only work if the vertex has exactly three adjacent edges. 572 | /// Therefore, it has three adjacent faces. 573 | /// The vertices connected to those edges form a new face, and the faces and edges connected 574 | /// to the removed vertex are also removed 575 | pub fn remove_vert(&mut self, vert: &VertRc) -> Result<(), &'static str> { 576 | let vert_b = vert.borrow(); 577 | let mut edges = vert_b.adjacent_edges().to_ptr_vec(); // get e for e in v.edges 578 | // Edges are iterated in clockwise order, but we need counter-clockwise order 579 | // to establish correct .next links 580 | edges.reverse(); 581 | 582 | // Must have 3 edges, so that the surrounding faces can be combined to a triangle 583 | if edges.len() != 3 { return Err("Vertex must have exactly 3 connecting edges"); } 584 | 585 | let new_face = Ptr::new_rc(Face::empty(self.new_face_id())); // n_f 586 | 587 | for (idx, edge) in edges.iter().enumerate() { 588 | let edge_b = edge.borrow(); 589 | edge_b.next.upgrade() 590 | .map(|next: EdgeRc| { 591 | let mut next_bm = next.borrow_mut(); 592 | next_bm.set_face_rc(& new_face); // e.n.f = n_f 593 | next_bm.set_next(& edges[(idx + 1) % edges.len()].borrow().next); // e.n.n = (e + 1).n 594 | new_face.borrow_mut().set_edge_rc(& next); // n_f.e = e.n 595 | next_bm.origin.upgrade() 596 | .map(|o: VertRc| o.borrow_mut().set_edge_rc(& next)); // e.n.o.e = e.n 597 | }); 598 | 599 | edge_b.pair.upgrade() 600 | .map(|p: EdgeRc| self.edges.remove(& p.borrow().id)); // del e.p 601 | self.edges.remove(& edge_b.id); // del e 602 | } 603 | 604 | self.push_face(new_face); // add n_f 605 | 606 | for face in vert_b.adjacent_faces() { 607 | face.upgrade().map(|f: FaceRc| self.faces.remove(& f.borrow().id)); // del f for f in v.faces 608 | } 609 | 610 | self.vertices.remove(& vert_b.id); // del v 611 | 612 | Ok(()) 613 | } 614 | 615 | pub fn remove_vert_ptr(&mut self, point: &VertPtr) -> Result<(), &'static str> { 616 | match point.upgrade() { 617 | Some(point_rc) => self.remove_vert(&point_rc), 618 | None => Err("Provided pointer was invalid"), 619 | } 620 | } 621 | 622 | /// flips an edge between two faces so that the faces are each split by 623 | /// the other diagonal of the parallelogram they form. 624 | pub fn flip_edge(&mut self, _edge: &EdgeRc) { 625 | unimplemented!(); 626 | } 627 | 628 | pub fn flip_edge_ptr(&mut self, edge: &EdgePtr) { 629 | if let Some(edge_rc) = edge.upgrade() { 630 | self.flip_edge(&edge_rc) 631 | } 632 | } 633 | 634 | /// Inserts a vertex at the position, specified by tval, along edge.origin -> edge.next.origin 635 | /// The edge's two neighboring faces are each split into two faces. 636 | /// All four new faces include the new vertex 637 | pub fn split_edge(&mut self, _edge: &EdgeRc, _tval: f32) { 638 | unimplemented!(); 639 | } 640 | 641 | pub fn split_edge_rc(&mut self, edge: &EdgePtr, tval: f32) { 642 | if let Some(edge_rc) = edge.upgrade() { 643 | self.split_edge(& edge_rc, tval) 644 | } 645 | } 646 | } 647 | -------------------------------------------------------------------------------- /src/ptr.rs: -------------------------------------------------------------------------------- 1 | use std::rc::{Rc, Weak}; 2 | use std::cell::RefCell; 3 | 4 | use edge::Edge; 5 | use vert::Vert; 6 | use face::Face; 7 | 8 | pub type EdgePtr = Ptr; 9 | pub type EdgeRc = Rc>; 10 | pub type VertPtr = Ptr; 11 | pub type VertRc = Rc>; 12 | pub type FacePtr = Ptr; 13 | pub type FaceRc = Rc>; 14 | 15 | pub type RcRef = Rc>; 16 | 17 | /// Ptr is essentially a wrapper around `Option>>`, 18 | /// a.k.a. a nullable ref-counted pointer with interior mutability 19 | /// This abstraction is used to get around Rust's 20 | /// validity, borrowing, and ownership rules, especially when constructing or 21 | /// extending the half-edge mesh. 22 | #[derive(Debug)] 23 | pub struct Ptr { 24 | val: Option>> 25 | } 26 | 27 | impl Ptr { 28 | /// Taken by value, so it moves the value out. 29 | /// Use this for constructing brand new objects. 30 | /// Returns an `Rc>`, not a `Ptr`, 31 | /// don't get em mixed up 32 | pub fn new_rc(val: T) -> Rc> { Rc::new(RefCell::new(val)) } 33 | 34 | /// Taken by reference to an existing object. Creates a Ptr 35 | pub fn new(val: & Rc>) -> Ptr { 36 | Ptr { val: Some(Rc::downgrade(val)) } 37 | } 38 | 39 | /// Creates what is effectively a null pointer 40 | pub fn empty() -> Ptr { 41 | Ptr { val: None } 42 | } 43 | 44 | /// Used as a utility function to merge the upgrade of two weak pointers 45 | /// into a single Option wrapping the success of both upgrades 46 | pub fn merge_upgrade(weak_a: & Ptr, weak_b: & Ptr) -> Option<(RcRef, RcRef)> { 47 | match (weak_a.upgrade(), weak_b.upgrade()) { 48 | (Some(strong_a), Some(strong_b)) => Some((strong_a, strong_b)), 49 | _ => None 50 | } 51 | } 52 | 53 | /// Check if the pointer is valid. Requires the pointer to upgrade in order to check 54 | /// that it still points at an existing object 55 | pub fn is_valid(& self) -> bool { self.val.is_some() && self.upgrade().is_some() } 56 | 57 | /// Used as a utility function for upgrading the stored weak pointer. 58 | pub fn upgrade(& self) -> Option>> { 59 | self.val.as_ref().and_then(|v| v.upgrade()) 60 | } 61 | 62 | /// Converts from `Option>>` to `Option<& Weak>>` 63 | /// Like the function of the same name on Option 64 | pub fn as_ref(& self) -> Option<& Weak>> { 65 | self.val.as_ref() 66 | } 67 | } 68 | 69 | impl Clone for Ptr { 70 | fn clone(& self) -> Self { 71 | Ptr { val: self.val.clone() } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/util.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | use ptr::{Ptr, EdgeRc}; 4 | use mesh::HalfEdgeMesh; 5 | 6 | fn merge_tuple_opt(o: (Option, Option)) -> Option<(A, B)> { 7 | match o { 8 | (Some(a), Some(b)) => Some((a, b)), 9 | _ => None 10 | } 11 | } 12 | 13 | fn vert_ab_key(e: & EdgeRc) -> Option<(u32, u32)> { 14 | let id_origin = e.borrow().origin.upgrade().map(|o| o.borrow().id); 15 | let id_next_origin = e.borrow().next.upgrade().and_then(|n| n.borrow().origin.upgrade()).map(|o| o.borrow().id); 16 | merge_tuple_opt((id_origin, id_next_origin)) 17 | } 18 | 19 | fn vert_ba_key(e: & EdgeRc) -> Option<(u32, u32)> { vert_ab_key(e).map(|tuple| (tuple.1, tuple.0)) } 20 | 21 | /// Takes what is assumed to be a fully constructed mesh, with no 22 | /// pair links, and establishes pair links between adjacent edges. 23 | /// If this function runs successfully on a mesh, all links in the mesh 24 | /// should point to their adjacent pair 25 | pub fn connect_pairs(mesh: &mut HalfEdgeMesh) -> Result<(), &'static str> { 26 | // Two-stage algorithm: first collect all edge A -> B relationships, 27 | // Then go through and look for edges that are B -> A 28 | let mut edge_hash: HashMap<(u32, u32), & EdgeRc> = HashMap::new(); 29 | 30 | for ref edge in mesh.edges.values() { 31 | // The types returned by match arms must be the same, 32 | // hence the braces and semicolon used in the first branch 33 | match vert_ab_key(edge) { 34 | Some(key) => { edge_hash.insert(key, edge); }, 35 | // This happens if one of the mesh edges doesn't have a valid .origin or .next.origin pointer 36 | None => { return Err("Could not hash all mesh edges"); } 37 | } 38 | } 39 | 40 | for ref edge in mesh.edges.values() { 41 | // This if statement should skip half the edges, because two 42 | // edge pairs are set each time it's true 43 | if !edge.borrow().pair.is_valid() { 44 | if let Some(key) = vert_ba_key(edge) { 45 | match edge_hash.get(& key) { 46 | Some(pair_edge) => { 47 | // if one edge A -> B matches another edge B -> A, the edges are adjacent 48 | edge.borrow_mut().take_pair(Ptr::new(pair_edge)); 49 | pair_edge.borrow_mut().take_pair(Ptr::new(edge)); 50 | }, 51 | None => { /* Happens when mesh is not closed */ 52 | return Err("Could not find pair edge"); 53 | } 54 | } 55 | } else { 56 | // Theoretically this shouldn't ever happen 57 | // because of the early return in the previous match block 58 | return Err("Could not find reverse hash for mesh edge"); 59 | } 60 | } 61 | } 62 | 63 | Ok(()) 64 | } 65 | 66 | /// Utility function for reporting problems with edge connectivity 67 | pub fn report_connect_err(res: Result<(), &str>) { 68 | if let Err(e) = res { 69 | println!("Error connecting mesh pairs! Mesh is not valid! {}", e); 70 | } 71 | } 72 | 73 | /// Checks if edge pair connections are all valid 74 | pub fn are_edge_pairs_valid(mesh: & HalfEdgeMesh) -> Result<(), &'static str> { 75 | let mut edge_hash: HashMap<(u32, u32), & EdgeRc> = HashMap::new(); 76 | 77 | for ref edge in mesh.edges.values() { 78 | // The types returned by match arms must be the same, 79 | // hence the braces and semicolon used in the first branch 80 | match vert_ab_key(edge) { 81 | Some(key) => { edge_hash.insert(key, edge); }, 82 | // This happens if one of the mesh edges doesn't have a valid .origin or .next.origin pointer 83 | None => { return Err("Could not hash all mesh edges"); } 84 | } 85 | } 86 | 87 | for ref edge in mesh.edges.values() { 88 | match vert_ba_key(edge) { 89 | Some(key) => { 90 | match edge_hash.get(& key) { 91 | Some(ref pair) => { 92 | if (edge.borrow().pair.upgrade().as_ref() != Some(pair)) || 93 | (pair.borrow().pair.upgrade().as_ref() != Some(edge)) { 94 | return Err("Pairs don't match"); 95 | } 96 | }, 97 | None => { return Err("Could not find a pair edge"); } 98 | } 99 | }, 100 | None => { return Err("Could not find reverse hash for mesh edge"); } 101 | } 102 | } 103 | 104 | Ok(()) 105 | } 106 | -------------------------------------------------------------------------------- /src/vert.rs: -------------------------------------------------------------------------------- 1 | use std::hash; 2 | 3 | use cgmath::Point3; 4 | 5 | use ptr::{Ptr, EdgePtr, EdgeRc}; 6 | use iterators::*; 7 | 8 | #[derive(Debug)] 9 | pub struct Vert { 10 | pub edge: EdgePtr, 11 | pub pos: Point3, 12 | pub id: u32, 13 | } 14 | 15 | impl Vert { 16 | /// All structure of the mesh revolves around vertex positions and their connectivity. 17 | /// (Faces are just an abstraction). All vertices must therefore have a concrete position. 18 | pub fn empty(id: u32, pos: Point3) -> Vert { 19 | Vert { 20 | id: id, 21 | edge: EdgePtr::empty(), 22 | pos: pos, 23 | } 24 | } 25 | 26 | /// Vertex connected to an existing edge 27 | pub fn with_edge(id: u32, pos: Point3, edge: EdgePtr) -> Vert { 28 | Vert { 29 | id: id, 30 | edge: edge, 31 | pos: pos, 32 | } 33 | } 34 | 35 | pub fn take_edge(&mut self, edge: EdgePtr) { self.edge = edge; } 36 | 37 | pub fn set_edge(&mut self, edge: & EdgePtr) { self.edge = edge.clone(); } 38 | 39 | pub fn set_edge_rc(&mut self, edge: & EdgeRc) { self.edge = Ptr::new(edge); } 40 | 41 | pub fn move_to(&mut self, pos: Point3) { self.pos = pos; } 42 | 43 | pub fn get_pos(& self) -> Point3 { self.pos } 44 | 45 | pub fn is_valid(& self) -> bool { self.edge.is_valid() } 46 | 47 | pub fn get_edge(& self) -> Option { self.edge.upgrade() } 48 | 49 | /// Important: Iterates over the vertices connected to a vertex in *clockwise* order 50 | pub fn adjacent_verts(& self) -> VertAdjacentVertIterator { 51 | VertAdjacentVertIterator::new(self.edge.clone()) 52 | } 53 | 54 | /// Important: Iterates over the edges connected to a vertex in *clockwise* order 55 | pub fn adjacent_edges(& self) -> VertAdjacentEdgeIterator { 56 | VertAdjacentEdgeIterator::new(self.edge.clone()) 57 | } 58 | 59 | /// Important: Iterates over the faces connected to a vertex in *clockwise* order 60 | pub fn adjacent_faces(& self) -> VertAdjacentFaceIterator { 61 | VertAdjacentFaceIterator::new(self.edge.clone()) 62 | } 63 | } 64 | 65 | impl PartialEq for Vert { 66 | fn eq(& self, other: & Vert) -> bool { self.id == other.id } 67 | } 68 | 69 | impl Eq for Vert {} 70 | 71 | impl hash::Hash for Vert { 72 | fn hash(& self, state: &mut H) where H: hash::Hasher { 73 | state.write_u32(self.id); 74 | state.finish(); 75 | } 76 | } 77 | --------------------------------------------------------------------------------