1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
use super::{TileBBox, TileBBoxPyramid, TileCoord3};
use std::mem::swap;

pub trait TransformCoord {
	fn flip_y(&mut self);
	fn swap_xy(&mut self);
}

impl TransformCoord for TileCoord3 {
	fn flip_y(&mut self) {
		let max_index = 2u32.pow(self.z as u32) - 1;
		assert!(max_index >= self.y, "error for {self:?}");
		self.y = max_index - self.y;
	}
	fn swap_xy(&mut self) {
		swap(&mut self.x, &mut self.y);
	}
}

impl TransformCoord for TileBBox {
	fn flip_y(&mut self) {
		if !self.is_empty() {
			assert!(self.max >= self.y_max);
			self.y_min = self.max - self.y_min;
			self.y_max = self.max - self.y_max;
			swap(&mut self.y_min, &mut self.y_max);
		}
	}
	fn swap_xy(&mut self) {
		if !self.is_empty() {
			swap(&mut self.x_min, &mut self.y_min);
			swap(&mut self.x_max, &mut self.y_max);
		}
	}
}

impl TransformCoord for TileBBoxPyramid {
	fn swap_xy(&mut self) {
		self.level_bbox.iter_mut().for_each(|b| {
			b.swap_xy();
		});
	}
	fn flip_y(&mut self) {
		self.level_bbox.iter_mut().for_each(|b| {
			b.flip_y();
		});
	}
}

#[cfg(test)]
mod tests {
	use super::{TileBBox, TileCoord3, TransformCoord};

	#[test]
	fn tilecoord3_flip_y() {
		let mut c = TileCoord3::new(1, 2, 3).unwrap();
		c.flip_y();
		assert_eq!(c, TileCoord3::new(1, 5, 3).unwrap());
	}

	#[test]
	fn tilecoord3_swap_xy() {
		let mut coord = TileCoord3::new(3, 4, 5).unwrap();
		coord.swap_xy();
		assert_eq!(coord, TileCoord3::new(4, 3, 5).unwrap());
	}

	#[test]
	fn bbox_flip_y() {
		let test = |a, b, c, d, e| -> TileBBox {
			let mut t = TileBBox::new(a, b, c, d, e).unwrap();
			t.flip_y();
			t
		};

		assert_eq!(test(1, 0, 0, 1, 1), TileBBox::new(1, 0, 0, 1, 1).unwrap());
		assert_eq!(test(2, 0, 0, 1, 1), TileBBox::new(2, 0, 2, 1, 3).unwrap());
		assert_eq!(test(3, 0, 0, 1, 1), TileBBox::new(3, 0, 6, 1, 7).unwrap());
		assert_eq!(test(9, 10, 0, 10, 511), TileBBox::new(9, 10, 0, 10, 511).unwrap());
		assert_eq!(test(9, 0, 10, 511, 10), TileBBox::new(9, 0, 501, 511, 501).unwrap());
	}
}