You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

211 lines
5.2 KiB

  1. #![allow(dead_code)]
  2. use std::collections::HashSet;
  3. use glc::vector::Vector2f;
  4. use specs::world::Index;
  5. use crate::components::{Position, Shape};
  6. pub struct Raster {
  7. size: f32,
  8. quads: OffsetVec<OffsetVec<Quad>>,
  9. }
  10. #[derive(Default)]
  11. struct OffsetVec<T>
  12. where
  13. T: Default,
  14. {
  15. origin: usize,
  16. data: Vec<T>,
  17. }
  18. #[derive(Default)]
  19. pub struct Quad {
  20. entities: HashSet<Index>,
  21. }
  22. impl Raster {
  23. pub fn new(size: f32) -> Self {
  24. Self {
  25. size,
  26. quads: OffsetVec::new(),
  27. }
  28. }
  29. pub fn size(&self) -> f32 {
  30. self.size
  31. }
  32. pub fn insert(&mut self, id: Index, position: &Position) -> bool {
  33. self.update_quads(position, |q| {
  34. q.entities.insert(id);
  35. })
  36. }
  37. pub fn remove(&mut self, id: &Index, position: &Position) -> bool {
  38. self.update_quads(position, |q| {
  39. q.entities.remove(id);
  40. })
  41. }
  42. pub fn quads(&self) -> impl Iterator<Item = (isize, isize, &Quad)> {
  43. self.quads.data.iter().enumerate().flat_map(move |(x, vy)| {
  44. vy.data.iter().enumerate().map(move |(y, q)| {
  45. (
  46. x as isize - self.quads.origin as isize,
  47. y as isize - vy.origin as isize,
  48. q,
  49. )
  50. })
  51. })
  52. }
  53. fn update_quads<F>(&mut self, position: &Position, mut f: F) -> bool
  54. where
  55. F: FnMut(&mut Quad),
  56. {
  57. let p = position.pos;
  58. match position.shape {
  59. Shape::Dot => {
  60. let x = (p.x / self.size).round() as isize;
  61. let y = (p.y / self.size).round() as isize;
  62. f(self.quads.get_mut(x).get_mut(y));
  63. true
  64. }
  65. Shape::Circle(r) => {
  66. let s = self.size;
  67. let min_x = ((p.x - r) / s).round() as isize - 1;
  68. let max_x = ((p.x + r) / s).round() as isize + 1;
  69. let min_y = ((p.y - r) / s).round() as isize - 1;
  70. let max_y = ((p.y + r) / s).round() as isize + 1;
  71. let sr = r * r;
  72. let s = self.size / 2.0;
  73. let mut ret = false;
  74. for x in min_x..=max_x {
  75. for y in min_y..=max_y {
  76. let fx = x as f32 * self.size;
  77. let fy = y as f32 * self.size;
  78. let quad = self.quads.get_mut(x).get_mut(y);
  79. if (Vector2f::new(fx - s, fy - s) - p).length_sqr() < sr
  80. || (Vector2f::new(fx + s, fy - s) - p).length_sqr() < sr
  81. || (Vector2f::new(fx - s, fy + s) - p).length_sqr() < sr
  82. || (Vector2f::new(fx + s, fy + s) - p).length_sqr() < sr
  83. {
  84. f(quad);
  85. ret = true;
  86. }
  87. }
  88. }
  89. ret
  90. }
  91. }
  92. }
  93. fn get_quad(&self, x: isize, y: isize) -> Option<&Quad> {
  94. let row = self.quads.get(x)?;
  95. let quad = row.get(y)?;
  96. Some(quad)
  97. }
  98. fn get_quad_mut(&mut self, x: isize, y: isize) -> &mut Quad {
  99. self.quads.get_mut(x).get_mut(y)
  100. }
  101. }
  102. impl<T> OffsetVec<T>
  103. where
  104. T: Default,
  105. {
  106. pub fn new() -> Self {
  107. Self {
  108. origin: 0,
  109. data: Vec::new(),
  110. }
  111. }
  112. pub fn get(&self, i: isize) -> Option<&T> {
  113. let low = (0usize - self.origin) as isize;
  114. let high = (self.data.len() - self.origin) as isize - 1;
  115. if i < low || i > high {
  116. None
  117. } else {
  118. Some(&self.data[(i - low) as usize])
  119. }
  120. }
  121. pub fn get_mut(&mut self, i: isize) -> &mut T {
  122. let low = 0isize - self.origin as isize;
  123. let high = (self.data.len() - self.origin) as isize - 1;
  124. if i > high {
  125. let add = (i - low + 1) as usize;
  126. self.data.resize_with(add, Default::default);
  127. } else if i < low {
  128. let add = (low - i) as usize;
  129. let mut prefix = Vec::new();
  130. prefix.resize_with(add, Default::default);
  131. prefix.append(&mut self.data);
  132. self.data = prefix;
  133. self.origin += add;
  134. }
  135. &mut self.data[(i + self.origin as isize) as usize]
  136. }
  137. }
  138. impl Quad {
  139. pub fn is_empty(&self) -> bool {
  140. self.entities.is_empty()
  141. }
  142. }
  143. #[cfg(test)]
  144. mod tests {
  145. use super::*;
  146. #[test]
  147. fn vec_get_mut() {
  148. let mut vec = OffsetVec::<usize>::new();
  149. assert_eq!(vec.origin, 0);
  150. assert_eq!(vec.data, Vec::<usize>::new());
  151. *vec.get_mut(0) = 100;
  152. assert_eq!(vec.origin, 0);
  153. assert_eq!(vec.data, vec![100]);
  154. *vec.get_mut(1) = 101;
  155. assert_eq!(vec.origin, 0);
  156. assert_eq!(vec.data, vec![100, 101]);
  157. *vec.get_mut(-2) = 98;
  158. assert_eq!(vec.origin, 2);
  159. assert_eq!(vec.data, vec![98, 0, 100, 101]);
  160. *vec.get_mut(4) = 104;
  161. assert_eq!(vec.origin, 2);
  162. assert_eq!(vec.data, vec![98, 0, 100, 101, 0, 0, 104]);
  163. *vec.get_mut(-4) = 96;
  164. assert_eq!(vec.origin, 4);
  165. assert_eq!(vec.data, vec![96, 0, 98, 0, 100, 101, 0, 0, 104]);
  166. }
  167. }