chunk_diff/util/
rect.rs

1use super::{chunk::Chunk, point::Point};
2use num_integer::Integer;
3use serde::{Deserialize, Serialize};
4
5#[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq, Hash)]
6pub struct Rect {
7    width: usize,
8    height: usize,
9}
10
11impl Rect {
12    pub fn new(width: usize, height: usize) -> Self {
13        Self { width, height }
14    }
15
16    pub fn width(&self) -> usize {
17        self.width
18    }
19
20    pub fn height(&self) -> usize {
21        self.height
22    }
23
24    pub fn area(&self) -> usize {
25        self.width * self.height
26    }
27
28    pub fn divide(&self, rect: &Rect) -> Vec<Chunk> {
29        let (x_count, x_remainder) = self.width.div_rem(&rect.width);
30        let (y_count, y_remainder) = self.height.div_rem(&rect.height);
31        let count = match (x_remainder, y_remainder) {
32            (0, 0) => x_count * y_count,
33            (0, _) => x_count * y_count + x_count,
34            (_, 0) => x_count * y_count + y_count,
35            (_, _) => x_count * y_count + x_count + y_count + 1,
36        };
37        let mut buffer = Vec::with_capacity(count);
38
39        for y in 0..y_count {
40            for x in 0..x_count {
41                buffer.push(Chunk::new(
42                    Point::new(x * rect.width, y * rect.height),
43                    Self::new(rect.width, rect.height),
44                ));
45            }
46        }
47        if x_remainder != 0 {
48            for y in 0..y_count {
49                buffer.push(Chunk::new(
50                    Point::new(x_count * rect.width, y * rect.height),
51                    Self::new(x_remainder, rect.height),
52                ));
53            }
54        }
55        if y_remainder != 0 {
56            for x in 0..x_count {
57                buffer.push(Chunk::new(
58                    Point::new(x * rect.width, y_count * rect.height),
59                    Self::new(rect.width, y_remainder),
60                ));
61            }
62        }
63        if x_remainder != 0 && y_remainder != 0 {
64            buffer.push(Chunk::new(
65                Point::new(x_count * rect.width, y_count * rect.height),
66                Self::new(x_remainder, y_remainder),
67            ));
68        }
69
70        buffer
71    }
72}