1use crate::Scalar;
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Clone, Copy, PartialEq)]
6pub enum DensityMapError {
7 WrongDataLength(usize, usize),
10}
11
12#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
14pub struct DensityMap {
15 width: usize,
16 height: usize,
17 scale: usize,
18 data: Vec<Scalar>,
19 steepness: Vec<Scalar>,
20}
21
22impl DensityMap {
23 pub fn new(
45 width: usize,
46 height: usize,
47 scale: usize,
48 data: Vec<u8>,
49 ) -> Result<Self, DensityMapError> {
50 if data.len() == width * height {
51 let data = data
52 .into_iter()
53 .map(|v| v as Scalar / 255.0)
54 .collect::<Vec<_>>();
55 let steepness = (0..data.len())
56 .map(|i| {
57 let col = (i % width) as isize;
58 let row = (i / width) as isize;
59 let mut result = 0.0;
60 for x in (col - 1)..(col + 1) {
61 for y in (row - 1)..(row + 1) {
62 let a = Self::raw_value(x, y, width, height, &data);
63 let b = Self::raw_value(x + 1, y, width, height, &data);
64 let c = Self::raw_value(x + 1, y + 1, width, height, &data);
65 let d = Self::raw_value(x, y + 1, width, height, &data);
66 let ab = (a - b).abs();
67 let cd = (c - d).abs();
68 let ac = (a - c).abs();
69 let bd = (b - d).abs();
70 let ad = (a - d).abs();
71 let bc = (b - c).abs();
72 result += (ab + cd + ac + bd + ad + bc) / 12.0;
73 }
74 }
75 result
76 })
77 .collect::<Vec<_>>();
78 Ok(Self {
79 width,
80 height,
81 scale,
82 data,
83 steepness,
84 })
85 } else {
86 Err(DensityMapError::WrongDataLength(data.len(), width * height))
87 }
88 }
89
90 pub fn scale(&self) -> usize {
92 self.scale
93 }
94
95 pub fn width(&self) -> usize {
97 self.width * self.scale.max(1)
98 }
99
100 pub fn height(&self) -> usize {
102 self.height * self.scale.max(1)
103 }
104
105 pub fn unscaled_width(&self) -> usize {
107 self.width
108 }
109
110 pub fn unscaled_height(&self) -> usize {
112 self.height
113 }
114
115 pub fn values(&self) -> &[Scalar] {
117 &self.data
118 }
119
120 pub fn steepness(&self) -> &[Scalar] {
122 &self.steepness
123 }
124
125 pub fn value_at_point(&self, point: (isize, isize)) -> Scalar {
130 let scale = self.scale.max(1) as isize;
131 let col = point.0 / scale;
132 let row = point.1 / scale;
133 if col >= 0 && col < self.width as _ && row >= 0 && row < self.height as _ {
134 self.data
135 .get(row as usize * self.width + col as usize)
136 .copied()
137 .unwrap_or(0.0)
138 } else {
139 0.0
140 }
141 }
142
143 pub fn steepness_at_point(&self, point: (isize, isize)) -> Scalar {
148 let scale = self.scale.max(1) as isize;
149 let col = point.0 / scale;
150 let row = point.1 / scale;
151 if col >= 0 && col < self.width as _ && row >= 0 && row < self.height as _ {
152 self.steepness
153 .get(row as usize * self.width + col as usize)
154 .copied()
155 .unwrap_or(0.0)
156 } else {
157 0.0
158 }
159 }
160
161 pub fn value_steepness_iter<'a>(
182 &'a self,
183 ) -> impl Iterator<Item = (usize, usize, Scalar, Scalar)> + 'a {
184 self.data
185 .iter()
186 .zip(self.steepness.iter())
187 .enumerate()
188 .map(move |(i, (v, s))| (i % self.width, i / self.width, *v, *s))
189 }
190
191 pub fn change(
200 &mut self,
201 col: usize,
202 row: usize,
203 width: usize,
204 height: usize,
205 data: Vec<u8>,
206 ) -> Result<(), DensityMapError> {
207 if col == 0 && row == 0 && width == self.width && height == self.height {
208 *self = Self::new(width, height, self.scale, data)?;
209 Ok(())
210 } else if data.len() == width * height {
211 for (i, v) in data.into_iter().enumerate() {
212 let x = col + i % width;
213 let y = row + i / width;
214 self.data[y * self.width + x] = v as Scalar / 255.0;
215 }
216 let fx = col.checked_sub(1).unwrap_or(col);
217 let fy = row.checked_sub(1).unwrap_or(row);
218 let tx = (col + width + 1).min(self.width);
219 let ty = (row + height + 1).min(self.height);
220 for row in fy..ty {
221 for col in fx..tx {
222 let mut result = 0.0;
223 {
224 let col = col as isize;
225 let row = row as isize;
226 for x in (col - 1)..(col + 1) {
227 for y in (row - 1)..(row + 1) {
228 let a = Self::raw_value(x, y, self.width, self.height, &self.data);
229 let b =
230 Self::raw_value(x + 1, y, self.width, self.height, &self.data);
231 let c = Self::raw_value(
232 x + 1,
233 y + 1,
234 self.width,
235 self.height,
236 &self.data,
237 );
238 let d =
239 Self::raw_value(x, y + 1, self.width, self.height, &self.data);
240 let ab = (a - b).abs();
241 let cd = (c - d).abs();
242 let ac = (a - c).abs();
243 let bd = (b - d).abs();
244 let ad = (a - d).abs();
245 let bc = (b - c).abs();
246 result += (ab + cd + ac + bd + ad + bc) / 12.0;
247 }
248 }
249 }
250 self.steepness[row * self.width + col] = result;
251 }
252 }
253 Ok(())
254 } else {
255 Err(DensityMapError::WrongDataLength(data.len(), width * height))
256 }
257 }
258
259 fn raw_value(x: isize, y: isize, w: usize, h: usize, data: &[Scalar]) -> Scalar {
260 if x >= 0 && x < w as _ && y >= 0 && y < h as _ {
261 data[y as usize * w + x as usize]
262 } else {
263 0.0
264 }
265 }
266}