word_cloud/placement/
from_center_placer.rs1use crate::geometry::Rectangle;
2use rand::Rng;
3
4use super::PlacementStrategy;
5
6type IVector = (i32, i32);
7
8pub struct FromCenterPlacer {
9 viewport: Rectangle,
10 cur_dir: Directions,
11 precision: i32,
12}
13
14impl FromCenterPlacer {
15 pub fn new(viewport: Rectangle, precision: u32) -> FromCenterPlacer {
16 FromCenterPlacer {
17 viewport,
18 cur_dir: Directions::random(),
19 precision: precision as i32,
20 }
21 }
22}
23
24impl PlacementStrategy for FromCenterPlacer {
25 fn find_next_place(
26 &mut self,
27 start_pos: Option<crate::geometry::Vector>,
28 r: &Rectangle,
29 ) -> Option<crate::geometry::Vector> {
30 let start_pos = match start_pos {
31 Some(pos) => pos,
32 None => {
33 self.cur_dir = Directions::random();
34 return Some((self.viewport.center().0, self.viewport.center().1));
35 }
36 };
37
38 let dir = &self.cur_dir;
39 let delta = dir.to_vector();
40
41 let next_pos: (i32, i32);
42 let new_x = start_pos.0 as i32 + delta.0 * self.precision;
43 let new_y = start_pos.1 as i32 + delta.1 * self.precision;
44 if (new_x >= 0) && (r.size().0 as i32 + new_x < self.viewport.x2() as i32) {
45 next_pos = (start_pos.0 as i32 + delta.0, start_pos.1 as i32);
46 } else if (new_y >= 0) && (r.size().1 as i32 + new_y < self.viewport.y2() as i32) {
47 next_pos = (self.viewport.center().0 as i32, new_y)
48 } else {
49 return None;
50 }
51
52 Some((next_pos.0 as u32, next_pos.1 as u32))
53 }
54}
55
56#[derive(Eq, PartialEq, Hash, Clone)]
57enum Directions {
58 TopRight,
59 TopLeft,
60 BottomLeft,
61 BottomRight,
62}
63
64impl Directions {
65 fn random() -> Directions {
66 let mut generator = rand::thread_rng();
67 let rand = generator.gen_range(0..=3);
68
69 match rand {
70 0 => Self::TopRight,
71 1 => Self::TopLeft,
72 2 => Self::BottomLeft,
73 3 => Self::BottomRight,
74 _ => panic!("This should not happen"),
75 }
76 }
77
78 fn to_vector(&self) -> IVector {
79 match self {
80 Self::TopRight => (-1, -1),
81 Self::TopLeft => (1, -1),
82 Self::BottomLeft => (1, 1),
83 Self::BottomRight => (-1, 1),
84 }
85 }
86}