1#[derive(Default, Debug, Clone, Copy, PartialEq)]
2pub struct ViewBox {
3 pub min_x: Option<f32>,
4 pub min_y: Option<f32>,
5 pub max_x: Option<f32>,
6 pub max_y: Option<f32>,
7}
8
9impl ViewBox {
10 pub fn new(min_x: f32, min_y: f32, max_x: f32, max_y: f32) -> Self {
11 Self {
12 min_x: Some(min_x),
13 min_y: Some(min_y),
14 max_x: Some(max_x),
15 max_y: Some(max_y),
16 }
17 }
18
19 pub fn add(&self, other: &Self) -> Self {
20 Self {
21 min_x: Self::min_option(self.min_x, other.min_x),
22 min_y: Self::min_option(self.min_y, other.min_y),
23 max_x: Self::max_option(self.max_x, other.max_x),
24 max_y: Self::max_option(self.max_y, other.max_y),
25 }
26 }
27
28 pub fn min_x(&self) -> f32 {
29 self.min_x.unwrap_or_default()
30 }
31
32 pub fn min_y(&self) -> f32 {
33 self.min_y.unwrap_or_default()
34 }
35
36 pub fn max_x(&self) -> f32 {
37 self.max_x.unwrap_or_default()
38 }
39
40 pub fn max_y(&self) -> f32 {
41 self.max_y.unwrap_or_default()
42 }
43
44 pub fn width(&self) -> f32 {
45 (self.min_x() - self.max_x()).abs()
46 }
47
48 pub fn height(&self) -> f32 {
49 (self.min_y() - self.max_y()).abs()
50 }
51
52 fn min_option(a: Option<f32>, b: Option<f32>) -> Option<f32> {
53 match (a, b) {
54 (Some(a), Some(b)) => Some(a.min(b)),
55 (Some(a), None) => Some(a),
56 (None, Some(b)) => Some(b),
57 (None, None) => None,
58 }
59 }
60
61 fn max_option(a: Option<f32>, b: Option<f32>) -> Option<f32> {
62 match (a, b) {
63 (Some(a), Some(b)) => Some(a.max(b)),
64 (Some(a), None) => Some(a),
65 (None, Some(b)) => Some(b),
66 (None, None) => None,
67 }
68 }
69
70 pub fn with_margin(mut self, margin: f32) -> Self {
71 self.min_x = self.min_x.map(|x| x - margin);
72 self.min_y = self.min_y.map(|y| y - margin);
73 self.max_x = self.max_x.map(|x| x + margin);
74 self.max_y = self.max_y.map(|y| y + margin);
75 self
76 }
77}