1use core::sync::atomic::{AtomicUsize, Ordering};
2
3use crate::{
4 DelaunayTriangulation, HasPosition, Point2, SpadeNum, Triangulation, TriangulationExt,
5};
6
7use super::FixedVertexHandle;
8
9#[cfg(feature = "serde")]
10use serde::{Deserialize, Serialize};
11
12use alloc::vec::Vec;
13
14pub trait HintGenerator<S: SpadeNum>: Default {
31 fn get_hint(&self, position: Point2<S>) -> FixedVertexHandle;
35
36 fn notify_vertex_lookup(&self, vertex: FixedVertexHandle);
38 fn notify_vertex_inserted(&mut self, vertex: FixedVertexHandle, vertex_position: Point2<S>);
40 fn notify_vertex_removed(
42 &mut self,
43 swapped_in_point: Option<Point2<S>>,
44 vertex: FixedVertexHandle,
45 vertex_position: Point2<S>,
46 );
47
48 fn initialize_from_triangulation<TR, V>(triangulation: &TR) -> Self
50 where
51 TR: Triangulation<Vertex = V>,
52 V: HasPosition<Scalar = S>;
53}
54
55#[derive(Default, Debug)]
74#[cfg_attr(
75 feature = "serde",
76 derive(Serialize, Deserialize),
77 serde(crate = "serde")
78)]
79pub struct LastUsedVertexHintGenerator {
80 #[cfg_attr(feature = "serde", serde(skip))]
82 index: AtomicUsize,
83}
84
85impl Clone for LastUsedVertexHintGenerator {
86 fn clone(&self) -> Self {
87 Self {
88 index: AtomicUsize::new(self.index.load(Ordering::Relaxed)),
89 }
90 }
91}
92
93impl<S: SpadeNum> HintGenerator<S> for LastUsedVertexHintGenerator {
94 fn get_hint(&self, _: Point2<S>) -> FixedVertexHandle {
95 FixedVertexHandle::new(self.index.load(Ordering::Relaxed))
96 }
97
98 fn notify_vertex_lookup(&self, vertex: FixedVertexHandle) {
99 self.index.store(vertex.index(), Ordering::Relaxed);
100 }
101
102 fn notify_vertex_inserted(&mut self, vertex: FixedVertexHandle, _: Point2<S>) {
103 <Self as HintGenerator<S>>::notify_vertex_lookup(self, vertex);
104 }
105
106 fn notify_vertex_removed(
107 &mut self,
108 _swapped_in_point: Option<Point2<S>>,
109 vertex: FixedVertexHandle,
110 _vertex_position: Point2<S>,
111 ) {
112 let hint = FixedVertexHandle::new(vertex.index().saturating_sub(1));
115 <Self as HintGenerator<S>>::notify_vertex_lookup(self, hint);
116 }
117
118 fn initialize_from_triangulation<TR, V>(_: &TR) -> Self
119 where
120 TR: Triangulation,
121 V: HasPosition<Scalar = S>,
122 {
123 Self::default()
124 }
125}
126
127pub type HierarchyHintGenerator<S> = HierarchyHintGeneratorWithBranchFactor<S, 16>;
148
149#[derive(Debug, Clone)]
150#[cfg_attr(
151 feature = "serde",
152 derive(Serialize, Deserialize),
153 serde(crate = "serde")
154)]
155#[doc(hidden)]
156pub struct HierarchyHintGeneratorWithBranchFactor<S: SpadeNum, const BRANCH_FACTOR: u32> {
157 hierarchy: Vec<DelaunayTriangulation<Point2<S>>>,
158 num_elements_of_base_triangulation: usize,
159}
160
161impl<S: SpadeNum, const BRANCH_FACTOR: u32> Default
162 for HierarchyHintGeneratorWithBranchFactor<S, BRANCH_FACTOR>
163{
164 fn default() -> Self {
165 Self {
166 hierarchy: Vec::new(),
167 num_elements_of_base_triangulation: 0,
168 }
169 }
170}
171
172impl<S: SpadeNum, const BRANCH_FACTOR: u32> HintGenerator<S>
173 for HierarchyHintGeneratorWithBranchFactor<S, BRANCH_FACTOR>
174{
175 fn get_hint(&self, position: Point2<S>) -> FixedVertexHandle {
176 let mut nearest = FixedVertexHandle::new(0);
177 for layer in self.hierarchy.iter().rev().skip(1) {
178 nearest = layer.walk_to_nearest_neighbor(nearest, position).fix();
179 let hint_generator: &LastUsedVertexHintGenerator = layer.hint_generator();
180 <LastUsedVertexHintGenerator as HintGenerator<S>>::notify_vertex_lookup(
181 hint_generator,
182 nearest,
183 );
184 nearest = FixedVertexHandle::new(nearest.index() * BRANCH_FACTOR as usize);
185 }
186 nearest
187 }
188
189 fn notify_vertex_lookup(&self, _: FixedVertexHandle) {}
190
191 fn notify_vertex_inserted(&mut self, vertex: FixedVertexHandle, vertex_position: Point2<S>) {
192 self.num_elements_of_base_triangulation += 1;
193
194 let mut index = vertex.index() as u32;
196
197 let mut remainder = 0;
198 for triangulation in &mut self.hierarchy {
199 remainder = index % BRANCH_FACTOR;
200 index /= BRANCH_FACTOR;
201
202 if remainder == 0 {
203 triangulation.insert(vertex_position).unwrap();
204 } else {
205 break;
206 }
207 }
208
209 if remainder == 0 {
210 let mut new_layer = DelaunayTriangulation::new();
211 let position_of_vertex_0 = self
212 .hierarchy
213 .first()
214 .map(|layer| layer.vertex(FixedVertexHandle::new(0)).position())
215 .unwrap_or(vertex_position);
216 new_layer.insert(position_of_vertex_0).unwrap();
217 self.hierarchy.push(new_layer);
218 }
219 }
220
221 fn notify_vertex_removed(
222 &mut self,
223 mut swapped_in_point: Option<Point2<S>>,
224 vertex: FixedVertexHandle,
225 _vertex_position: Point2<S>,
226 ) {
227 if self.num_elements_of_base_triangulation == 1 {
228 *self = Default::default();
230 return;
231 }
232
233 let index = vertex.index() as u32;
234
235 let mut current_divisor = BRANCH_FACTOR;
236 self.num_elements_of_base_triangulation -= 1;
237 let mut last_layer_size = self.num_elements_of_base_triangulation;
238
239 for triangulation in &mut self.hierarchy {
240 let remainder = index % current_divisor;
241 let index_to_remove = index / current_divisor;
242 current_divisor *= BRANCH_FACTOR;
243
244 if remainder == 0 {
245 if let Some(swapped_point) = swapped_in_point.as_ref() {
247 if (triangulation.num_vertices() - 1) * (BRANCH_FACTOR as usize)
248 != last_layer_size
249 {
250 triangulation.insert(*swapped_point).unwrap();
253 }
254 }
255 triangulation.remove(FixedVertexHandle::new(index_to_remove as usize));
256 }
257
258 let prev_num_vertices = last_layer_size as u32;
259 let max_num_vertices = prev_num_vertices.div_ceil(BRANCH_FACTOR);
260 if triangulation.num_vertices() as u32 > max_num_vertices {
261 let vertex_to_pop = FixedVertexHandle::new(triangulation.num_vertices() - 1);
263 swapped_in_point = None;
264 triangulation.remove(vertex_to_pop);
265 }
266
267 last_layer_size = triangulation.num_vertices();
268 }
269
270 if let [.., ref before_last, _] = self.hierarchy.as_slice() {
271 if before_last.num_vertices() == 1 {
272 self.hierarchy.pop();
274 }
275 }
276 }
277
278 fn initialize_from_triangulation<TR, V>(triangulation: &TR) -> Self
279 where
280 TR: Triangulation<Vertex = V>,
281 V: HasPosition<Scalar = S>,
282 {
283 let mut result = Self::default();
284
285 if triangulation.num_vertices() == 0 {
286 return result;
287 }
288
289 let mut current_step = BRANCH_FACTOR as usize;
290 loop {
291 let vertices = triangulation
292 .vertices()
293 .map(|v| v.position())
294 .step_by(current_step)
295 .collect::<Vec<_>>();
296
297 result.hierarchy.push(
298 DelaunayTriangulation::bulk_load_stable(vertices)
299 .expect("Failed to load hierarchy layer."),
300 );
301
302 if current_step >= triangulation.num_vertices() {
303 break;
304 }
305
306 current_step *= BRANCH_FACTOR as usize;
307 }
308
309 result.num_elements_of_base_triangulation = triangulation.num_vertices();
310 result
311 }
312}
313
314#[cfg(test)]
315mod test {
316 use rand::{seq::IndexedRandom as _, RngCore, SeedableRng};
317
318 use crate::{
319 handles::FixedVertexHandle, test_utilities, DelaunayTriangulation, InsertionError, Point2,
320 Triangulation, TriangulationExt,
321 };
322
323 use alloc::vec::Vec;
324
325 const BRANCH_FACTOR: u32 = 3;
326
327 type HierarchyTriangulation = DelaunayTriangulation<
328 Point2<f64>,
329 (),
330 (),
331 (),
332 super::HierarchyHintGeneratorWithBranchFactor<f64, BRANCH_FACTOR>,
333 >;
334
335 #[test]
336 fn hierarchy_hint_generator_test() -> Result<(), InsertionError> {
337 let vertices = test_utilities::random_points_with_seed(1025, test_utilities::SEED);
338 let triangulation = HierarchyTriangulation::bulk_load(vertices.clone())?;
339
340 hierarchy_sanity_check(&triangulation);
341
342 let mut triangulation = HierarchyTriangulation::new();
344 for vertex in vertices {
345 triangulation.insert(vertex)?;
346 }
347 hierarchy_sanity_check(&triangulation);
348 Ok(())
349 }
350
351 fn hierarchy_sanity_check(triangulation: &HierarchyTriangulation) {
352 let expected_len = if triangulation.num_vertices() <= 1 {
353 triangulation.num_vertices()
354 } else {
355 (triangulation.num_vertices() as f64)
356 .log(BRANCH_FACTOR as f64)
357 .ceil() as usize
358 };
359
360 assert_eq!(triangulation.hint_generator.hierarchy.len(), expected_len);
361
362 for vertex in triangulation.vertices() {
363 let position = vertex.position();
364 let base_index = vertex.fix().index() as u32;
365 let mut power = BRANCH_FACTOR;
366
367 for layer in &triangulation.hint_generator().hierarchy {
368 if base_index % power == 0 {
369 let corresponding_vertex =
370 FixedVertexHandle::new((base_index / power) as usize);
371 assert_eq!(layer.vertex(corresponding_vertex).position(), position);
372 power *= BRANCH_FACTOR;
373 } else {
374 assert!(layer.locate_vertex(position).is_none());
375 }
376 }
377 }
378 }
379
380 #[test]
381 fn test_hierarchy_hint_generator_bulk_load_small() -> Result<(), InsertionError> {
382 let mut rng = rand::rngs::StdRng::from_seed(*test_utilities::SEED);
383 let mut seed_fn = || {
384 let mut seed = [0u8; 32];
385 rng.fill_bytes(seed.as_mut());
386 seed
387 };
388
389 for size in 0..5 {
390 let vertices = test_utilities::random_points_with_seed(size, &seed_fn());
391 let triangulation = HierarchyTriangulation::bulk_load(vertices)?;
392 hierarchy_sanity_check(&triangulation);
393 triangulation.sanity_check();
394 }
395
396 for size in 1..20 {
397 let vertices = test_utilities::random_points_with_seed(1 + size * 26, &seed_fn());
398 let triangulation = HierarchyTriangulation::bulk_load_stable(vertices)?;
399 hierarchy_sanity_check(&triangulation);
400 }
401 Ok(())
402 }
403
404 #[test]
405 fn hierarchy_hint_generator_removal_test() -> Result<(), InsertionError> {
406 let vertices = test_utilities::random_points_with_seed(300, test_utilities::SEED);
407 let mut triangulation = HierarchyTriangulation::bulk_load(vertices)?;
408
409 let mut rng = rand::rngs::StdRng::from_seed(*test_utilities::SEED2);
410 while let Some(to_remove) = triangulation
411 .fixed_vertices()
412 .collect::<Vec<_>>()
413 .choose(&mut rng)
414 {
415 triangulation.remove(*to_remove);
416 hierarchy_sanity_check(&triangulation);
417 }
418 Ok(())
419 }
420}