half_edge_map.zig (2107B)
1 const std = @import("std"); 2 3 const HalfEdgeMap = @This(); 4 5 const HalfEdge = struct { 6 head: u32, 7 tail: u32, 8 }; 9 10 map: std.AutoArrayHashMapUnmanaged(HalfEdge, u32), 11 12 pub fn init(indices: []u32, allocator: std.mem.Allocator) !HalfEdgeMap { 13 const num_indices: u32 = @intCast(indices.len); 14 const num_triangles = num_indices / 3; 15 16 var map = std.AutoArrayHashMapUnmanaged(HalfEdge, u32){}; 17 try map.ensureTotalCapacity(allocator, num_indices); 18 19 for (0..num_triangles) |triangle_idx| { 20 const i = @as(u32, @intCast(triangle_idx)) * 3; 21 const a = indices[i]; 22 const b = indices[i + 1]; 23 const c = indices[i + 2]; 24 map.putAssumeCapacityNoClobber(.{ .head = a, .tail = b }, c); 25 map.putAssumeCapacityNoClobber(.{ .head = b, .tail = c }, a); 26 map.putAssumeCapacityNoClobber(.{ .head = c, .tail = a }, b); 27 } 28 return .{ 29 .map = map, 30 }; 31 } 32 33 pub fn insert(self: *HalfEdgeMap, tri: [3]u32) void { 34 const a = tri[0]; 35 const b = tri[1]; 36 const c = tri[2]; 37 self.map.putAssumeCapacityNoClobber(.{ .head = a, .tail = b }, c); 38 self.map.putAssumeCapacityNoClobber(.{ .head = b, .tail = c }, a); 39 self.map.putAssumeCapacityNoClobber(.{ .head = c, .tail = a }, b); 40 } 41 42 pub fn remove(self: *HalfEdgeMap, tri: [3]u32) bool { 43 const success0 = self.map.swapRemove(.{ .head = tri[0], .tail = tri[1] }); 44 const success1 = self.map.swapRemove(.{ .head = tri[1], .tail = tri[2] }); 45 const success2 = self.map.swapRemove(.{ .head = tri[2], .tail = tri[0] }); 46 return success0 and success1 and success2; 47 } 48 49 pub fn adjacentTo(self: *HalfEdgeMap, tri: [3]u32, side: u32) ?[3]u32 { 50 const a = tri[(side + 1) % 3]; 51 const b = tri[side]; 52 const c = self.map.get(.{ .head = a, .tail = b }) orelse { 53 return null; 54 }; 55 return [3]u32{ a, b, c }; 56 } 57 58 pub fn count(self: *const HalfEdgeMap) usize { 59 return self.map.count(); 60 } 61 62 pub fn pop(self: *HalfEdgeMap) [3]u32 { 63 const kv = self.map.pop(); 64 const tri = [3]u32{ kv.key.head, kv.key.tail, kv.value }; 65 _ = self.remove(tri); 66 return tri; 67 }