mesh_graph/plane_slice/
hash_grid.rs1use glam::{IVec2, Vec2};
2use hashbrown::{HashMap, HashSet};
3use slotmap::{SecondaryMap, SlotMap, new_key_type};
4
5use crate::plane_slice::{Polygon2, PolygonTerminal};
6#[cfg(feature = "rerun")]
7use crate::utils::vec2_array;
8
9new_key_type! { pub struct PolygonId; }
10
11#[derive(Default, Debug, Clone)]
12pub struct HashGrid {
13 map: HashMap<IVec2, Vec<(PolygonTerminal, PolygonId)>>,
14 min_bounds: Vec2,
15 cell_fac: Vec2,
16 polygons: SlotMap<PolygonId, Polygon2>,
17 polygon_cells: SecondaryMap<PolygonId, HashSet<IVec2>>,
18}
19
20impl HashGrid {
21 pub fn new(min_bounds: Vec2, max_bounds: Vec2) -> Self {
22 let width = (max_bounds.x - min_bounds.x).max(0.0001);
23 let height = (max_bounds.y - min_bounds.y).max(0.0001);
24
25 let grid_size_x = width.sqrt().ceil();
26 let grid_size_y = height.sqrt().ceil();
27
28 let cell_fac = Vec2::new(grid_size_x / width, grid_size_y / height);
29
30 HashGrid {
31 map: HashMap::new(),
32 min_bounds,
33 cell_fac,
34 polygons: SlotMap::default(),
35 polygon_cells: SecondaryMap::default(),
36 }
37 }
38
39 pub fn try_take_connecting_polygon(
40 &mut self,
41 point: Vec2,
42 ) -> Option<(PolygonTerminal, PolygonId)> {
43 let key = self.vec2_to_grid(point);
44
45 let mut result = None;
46
47 self.map.entry(key).and_modify(|e| {
48 let mut index = None;
49
50 for (i, (terminal, polygon_id)) in e.iter().enumerate() {
51 let polygon = &self.polygons[*polygon_id];
52 let existing_point = polygon.terminal(*terminal);
53
54 if existing_point.distance_squared(point) < 1e-6 {
55 index = Some(i);
56 break;
57 }
58 }
59
60 if let Some(index) = index {
61 let (terminal, polygon_id) = e.remove(index);
62 result = Some((terminal, polygon_id));
63
64 if !e.iter().any(|(_, id)| *id == polygon_id) {
66 self.polygon_cells[polygon_id].retain(|k| *k != key);
67 }
68 }
69 });
70
71 result
72 }
73
74 pub fn remove_polygon_from_cell(&mut self, polygon_id: PolygonId, cell: IVec2) {
75 self.map.entry(cell).and_modify(|e| {
76 e.retain(|(_, id)| *id != polygon_id);
77 });
78 }
79
80 pub fn insert_polygon_by_terminal(
81 &mut self,
82 terminal: PolygonTerminal,
83 polygon_id: PolygonId,
84 terminal_point: Vec2,
85 ) {
86 let key = self.vec2_to_grid(terminal_point);
87
88 self.map
89 .entry(key)
90 .or_default()
91 .push((terminal, polygon_id));
92
93 self.polygon_cells
94 .entry(polygon_id)
95 .unwrap()
96 .or_default()
97 .insert(key);
98 }
99
100 pub fn insert_line(&mut self, point1: Vec2, point2: Vec2) {
101 #[cfg(feature = "rerun")]
102 {
103 crate::RR
104 .log("insert_line", &rerun::Clear::recursive())
105 .unwrap();
106 crate::RR
107 .log(
108 "insert_line/line",
109 &rerun::LineStrips3D::new([[vec2_array(point1), vec2_array(point2)]]),
110 )
111 .unwrap();
112 }
113
114 if let Some((terminal1, polygon_id1)) = self.try_take_connecting_polygon(point1) {
115 #[cfg(feature = "rerun")]
116 self.polygons[polygon_id1].log_rerun("insert_line/existing_poly1");
117
118 if let Some((terminal2, polygon_id2)) = self.try_take_connecting_polygon(point2) {
119 #[cfg(feature = "rerun")]
120 self.polygons[polygon_id2].log_rerun("insert_line/another_existing_poly2");
121
122 self.merge_polygons(polygon_id1, terminal1, polygon_id2, terminal2);
123 } else {
124 self.extend_polygon(polygon_id1, terminal1, point2);
125 }
126 } else if let Some((terminal2, polygon_id2)) = self.try_take_connecting_polygon(point2) {
127 #[cfg(feature = "rerun")]
128 self.polygons[polygon_id2].log_rerun("insert_line/existing_poly2");
129
130 self.extend_polygon(polygon_id2, terminal2, point1);
131 } else {
132 let new_polygon = Polygon2 {
133 vertices: [point1, point2].into(),
134 };
135 let new_polygon_id = self.polygons.insert(new_polygon);
136
137 self.insert_polygon_by_terminal(PolygonTerminal::Start, new_polygon_id, point1);
138 self.insert_polygon_by_terminal(PolygonTerminal::End, new_polygon_id, point2);
139 }
140 }
141
142 fn merge_polygons(
143 &mut self,
144 polygon_id1: PolygonId,
145 terminal1: PolygonTerminal,
146 polygon_id2: PolygonId,
147 terminal2: PolygonTerminal,
148 ) {
149 if polygon_id1 == polygon_id2 {
150 let polygon = &mut self.polygons[polygon_id1];
151 polygon.close();
152
153 return;
154 }
155
156 for cell in self.polygon_cells[polygon_id2].clone() {
157 self.remove_polygon_from_cell(polygon_id2, cell);
158 }
159 self.polygon_cells.remove(polygon_id2);
160 let polygon2 = self.polygons.remove(polygon_id2).unwrap();
161
162 for cell in self.polygon_cells[polygon_id1].clone() {
163 self.remove_polygon_from_cell(polygon_id1, cell);
164 }
165 let polygon1 = &mut self.polygons[polygon_id1];
166
167 polygon1.merge_polygon(terminal1, polygon2, terminal2);
168
169 let start_point = polygon1.terminal(PolygonTerminal::Start);
170 let end_point = polygon1.terminal(PolygonTerminal::End);
171
172 #[cfg(feature = "rerun")]
173 {
174 crate::RR
175 .log("insert_line", &rerun::Clear::recursive())
176 .unwrap();
177 polygon1.log_rerun("insert_line/merged");
178 }
179
180 self.insert_polygon_by_terminal(PolygonTerminal::Start, polygon_id1, start_point);
181 self.insert_polygon_by_terminal(PolygonTerminal::End, polygon_id1, end_point);
182 }
183
184 fn extend_polygon(
185 &mut self,
186 polygon_id: PolygonId,
187 terminal: PolygonTerminal,
188 new_point: Vec2,
189 ) {
190 let polygon = &mut self.polygons[polygon_id];
191 polygon.extend_by_line(terminal, new_point);
192
193 #[cfg(feature = "rerun")]
194 {
195 crate::RR
196 .log("insert_line", &rerun::Clear::recursive())
197 .unwrap();
198 polygon.log_rerun("insert_line/extended");
199 }
200
201 self.insert_polygon_by_terminal(terminal, polygon_id, new_point);
202 }
203
204 #[inline]
205 fn vec2_to_grid(&self, point: Vec2) -> IVec2 {
206 ((point - self.min_bounds) * self.cell_fac)
207 .floor()
208 .as_ivec2()
209 }
210
211 pub fn into_polygons(self) -> impl Iterator<Item = Polygon2> {
212 self.polygons.into_iter().map(|(_, polygon)| polygon)
213 }
214}