ndslive_math/
bounding_box.rs1use crate::tileid::PackedTileId;
7use crate::wgs84::Wgs84;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
14pub struct NdsBoundingBox {
15 pub min_x: i32,
17 pub min_y: i32,
19 pub max_x: i32,
21 pub max_y: i32,
23}
24
25impl NdsBoundingBox {
26 pub fn new(min_x: i32, min_y: i32, max_x: i32, max_y: i32) -> Self {
28 NdsBoundingBox {
29 min_x,
30 min_y,
31 max_x,
32 max_y,
33 }
34 }
35
36 pub fn intersects(&self, other: &NdsBoundingBox) -> bool {
41 !(self.max_x < other.min_x
42 || self.min_x > other.max_x
43 || self.max_y < other.min_y
44 || self.min_y > other.max_y)
45 }
46
47 pub fn contains(&self, other: &NdsBoundingBox) -> bool {
49 self.min_x <= other.min_x
50 && self.max_x >= other.max_x
51 && self.min_y <= other.min_y
52 && self.max_y >= other.max_y
53 }
54
55 pub fn from_tile(tile: &PackedTileId) -> Self {
67 let (sw_x, sw_y) = tile.south_west_corner();
68 let (ne_x, ne_y) = tile.north_east_corner();
69 NdsBoundingBox {
70 min_x: sw_x as i32,
71 min_y: sw_y as i32,
72 max_x: ne_x as i32,
73 max_y: ne_y as i32,
74 }
75 }
76
77 pub fn from_wgs84_corners(sw: &Wgs84, ne: &Wgs84) -> Self {
81 let (min_x, min_y) = sw.to_nds_coordinates();
82 let (max_x, max_y) = ne.to_nds_coordinates();
83 NdsBoundingBox {
84 min_x,
85 min_y,
86 max_x,
87 max_y,
88 }
89 }
90}
91
92#[cfg(test)]
93mod tests {
94 use super::*;
95
96 #[test]
97 fn identical_boxes_intersect_and_contain() {
98 let a = NdsBoundingBox::new(0, 0, 100, 100);
99 let b = NdsBoundingBox::new(0, 0, 100, 100);
100 assert!(a.intersects(&b));
101 assert!(a.contains(&b));
102 }
103
104 #[test]
105 fn disjoint_boxes() {
106 let a = NdsBoundingBox::new(0, 0, 100, 100);
107 let b = NdsBoundingBox::new(200, 200, 300, 300);
108 assert!(!a.intersects(&b));
109 assert!(!a.contains(&b));
110 }
111
112 #[test]
113 fn partial_overlap_no_containment() {
114 let a = NdsBoundingBox::new(0, 0, 100, 100);
115 let b = NdsBoundingBox::new(50, 50, 150, 150);
116 assert!(a.intersects(&b));
117 assert!(!a.contains(&b));
118 }
119
120 #[test]
121 fn inner_box_contained() {
122 let a = NdsBoundingBox::new(0, 0, 100, 100);
123 let b = NdsBoundingBox::new(10, 10, 20, 20);
124 assert!(a.intersects(&b));
125 assert!(a.contains(&b));
126 }
127
128 #[test]
129 fn from_tile_matches_corners() {
130 let t = PackedTileId::from_i64(131072).unwrap();
131 let bb = NdsBoundingBox::from_tile(&t);
132 assert_eq!(bb.min_x, 0);
133 assert_eq!(bb.min_y, 0);
134 }
135}