1use nalgebra::{Point2, Vector2};
11use ndarray::{s, Array2, ArrayView2, ArrayViewMut2};
12use serde::Serialize;
13
14use crate::{
15 cell_map::Bounds, extensions::Point2Ext, map_metadata::CellMapMetadata, CellMap, Error, Layer,
16};
17
18pub trait Slicer<'a, L, T>
35where
36 L: Layer,
37{
38 type Output;
40
41 type OutputMut;
43
44 fn slice(&self, data: &'a Array2<T>) -> Option<Self::Output>;
47
48 fn slice_mut(&self, data: &'a mut Array2<T>) -> Option<Self::OutputMut>;
51
52 fn advance(&mut self);
54
55 fn index(&self) -> Option<Point2<usize>>;
58
59 fn reset(&mut self, layer: Option<L>);
63}
64
65pub(crate) type RectBounds = Vector2<(usize, usize)>;
67
68#[derive(Debug, Clone, Copy)]
71pub struct Cells {
72 bounds: RectBounds,
73 index: Point2<usize>,
74}
75
76#[derive(Debug, Clone, Copy)]
80pub struct Windows {
81 bounds: RectBounds,
82 index: Point2<usize>,
83 semi_width: Vector2<usize>,
84}
85
86#[derive(Debug, Clone)]
92#[allow(missing_copy_implementations)]
93pub struct Line {
94 bounds: Bounds,
95 map_meta: CellMapMetadata,
96
97 start_parent: Point2<f64>,
98 end_parent: Point2<f64>,
99
100 dir: Vector2<f64>,
101 dir_sign: Vector2<f64>,
102
103 start_map: Point2<f64>,
104 end_map: Point2<f64>,
105 current_map: Option<Point2<f64>>,
106
107 end_index: Point2<usize>,
108
109 #[cfg(feature = "debug_iters")]
110 step_report_file: std::sync::Arc<std::fs::File>,
111}
112
113#[derive(Debug, Clone, Copy, Serialize)]
114struct LineStepData {
115 start_parent: Point2<f64>,
116 end_parent: Point2<f64>,
117
118 dir: Vector2<f64>,
119 dir_sign: Vector2<f64>,
120
121 start_map: Point2<f64>,
122 end_map: Point2<f64>,
123 current_map: Option<Point2<f64>>,
124
125 end_index: Point2<usize>,
126
127 delta: Vector2<f64>,
128}
129
130impl Cells {
135 pub(crate) fn from_map<L: Layer, T>(map: &CellMap<L, T>) -> Self {
136 let cells = map.num_cells();
137 Self {
138 bounds: Vector2::new((0, cells.x), (0, cells.y)),
139 index: Point2::new(0, 0),
140 }
141 }
142}
143
144impl<'a, L, T> Slicer<'a, L, T> for Cells
145where
146 L: Layer,
147 T: 'a,
148{
149 type Output = &'a T;
150 type OutputMut = &'a mut T;
151
152 fn slice(&self, data: &'a Array2<T>) -> Option<Self::Output> {
153 data.get(self.index.as_array2_index())
154 }
155
156 fn slice_mut(&self, data: &'a mut Array2<T>) -> Option<Self::OutputMut> {
157 data.get_mut(self.index.as_array2_index())
158 }
159
160 fn advance(&mut self) {
161 self.index.x += 1;
162
163 if !self.index.in_bounds(&self.bounds) {
164 self.index.y += 1;
165 self.index.x = self.bounds.x.0;
166 }
167 }
168
169 fn index(&self) -> Option<Point2<usize>> {
170 if self.index.in_bounds(&self.bounds) {
171 Some(self.index)
172 } else {
173 None
174 }
175 }
176
177 fn reset(&mut self, _layer: Option<L>) {
178 self.index = Point2::new(self.bounds.x.0, self.bounds.y.0);
179 }
180}
181
182impl Windows {
183 pub(crate) fn from_map<L: Layer, T>(
184 map: &CellMap<L, T>,
185 semi_width: Vector2<usize>,
186 ) -> Result<Self, Error> {
187 let cells = map.num_cells();
188
189 if semi_width.x * 2 + 1 > cells.x || semi_width.y * 2 + 1 > cells.y {
190 Err(Error::WindowLargerThanMap(
191 semi_width * 2 + Vector2::new(1, 1),
192 cells,
193 ))
194 } else {
195 let bounds = Vector2::new(
196 (semi_width.x, cells.x - semi_width.x),
197 (semi_width.y, cells.y - semi_width.y),
198 );
199
200 Ok(Self {
201 bounds,
202 index: Point2::new(bounds.x.0, bounds.y.0),
203 semi_width,
204 })
205 }
206 }
207}
208
209impl<'a, L, T> Slicer<'a, L, T> for Windows
210where
211 L: Layer,
212 T: 'a,
213{
214 type Output = ArrayView2<'a, T>;
215 type OutputMut = ArrayViewMut2<'a, T>;
216
217 fn slice(&self, data: &'a Array2<T>) -> Option<Self::Output> {
218 if self.index.in_bounds(&self.bounds) {
219 let x0 = self.index.x - self.semi_width.x;
220 let x1 = self.index.x + self.semi_width.x + 1;
221 let y0 = self.index.y - self.semi_width.y;
222 let y1 = self.index.y + self.semi_width.y + 1;
223 Some(data.slice(s![y0..y1, x0..x1]))
224 } else {
225 None
226 }
227 }
228
229 fn slice_mut(&self, data: &'a mut Array2<T>) -> Option<Self::OutputMut> {
230 if self.index.in_bounds(&self.bounds) {
231 let x0 = self.index.x - self.semi_width.x;
232 let x1 = self.index.x + self.semi_width.x + 1;
233 let y0 = self.index.y - self.semi_width.y;
234 let y1 = self.index.y + self.semi_width.y + 1;
235 Some(data.slice_mut(s![y0..y1, x0..x1]))
236 } else {
237 None
238 }
239 }
240
241 fn advance(&mut self) {
242 self.index.x += 1;
243
244 if !self.index.in_bounds(&self.bounds) {
245 self.index.y += 1;
246 self.index.x = self.bounds.x.0;
247 }
248 }
249
250 fn index(&self) -> Option<Point2<usize>> {
251 if self.index.in_bounds(&self.bounds) {
252 Some(self.index)
253 } else {
254 None
255 }
256 }
257
258 fn reset(&mut self, _layer: Option<L>) {
259 self.index = Point2::new(self.bounds.x.0, self.bounds.y.0);
260 }
261}
262
263impl Line {
264 pub(crate) fn from_map<L: Layer, T>(
265 map_meta: CellMapMetadata,
266 start_parent: Point2<f64>,
267 end_parent: Point2<f64>,
268 ) -> Result<Self, Error> {
269 let start_map = map_meta.to_parent.inverse_transform_point(&start_parent);
273 let end_map = map_meta.to_parent.inverse_transform_point(&end_parent);
274
275 let map_x_bounds = (
277 map_meta.cell_bounds.x.0 as f64,
278 map_meta.cell_bounds.x.1 as f64,
279 );
280 let map_y_bounds = (
281 map_meta.cell_bounds.y.0 as f64,
282 map_meta.cell_bounds.y.1 as f64,
283 );
284
285 if start_map.x < map_x_bounds.0
287 || start_map.x > map_x_bounds.1
288 || start_map.y < map_y_bounds.0
289 || start_map.y > map_y_bounds.1
290 {
291 return Err(Error::PositionOutsideMap(
292 "Line::Start".into(),
293 start_parent,
294 ));
295 }
296
297 if end_map.x < map_x_bounds.0
298 || end_map.x > map_x_bounds.1
299 || end_map.y < map_y_bounds.0
300 || end_map.y > map_y_bounds.1
301 {
302 return Err(Error::PositionOutsideMap("Line::End".into(), start_parent));
303 }
304
305 let dir = end_map - start_map;
307
308 let dir_sign = dir.map(|v| if v < 0.0 { 0.0 } else { 1.0 });
310
311 let end_cell = map_meta
313 .index(end_parent)
314 .ok_or_else(|| Error::PositionOutsideMap("Line::End".into(), end_parent))?;
315
316 Ok(Self {
317 bounds: map_meta.cell_bounds,
318 map_meta,
319 start_parent,
320 end_parent,
321 dir,
322 dir_sign,
323 start_map,
324 end_map,
325 current_map: Some(start_map),
326 end_index: end_cell,
327 #[cfg(feature = "debug_iters")]
328 step_report_file: std::sync::Arc::new(
329 std::fs::OpenOptions::new()
330 .create(true)
331 .truncate(true)
332 .write(true)
333 .open("line_step_report.json")
334 .unwrap(),
335 ),
336 })
337 }
338
339 fn get_current_index(&self) -> Option<Point2<usize>> {
341 let current_map_isize = self.current_map?.map(|e| e as isize);
344 self.map_meta.cell_bounds.get_index(current_map_isize)
345 }
346}
347
348impl<'a, L, T> Slicer<'a, L, T> for Line
349where
350 L: Layer,
351 T: 'a,
352{
353 type Output = &'a T;
354
355 type OutputMut = &'a mut T;
356
357 fn slice(&self, data: &'a Array2<T>) -> Option<Self::Output> {
358 let index = self.get_current_index()?;
360
361 data.get(index.as_array2_index())
362 }
363
364 fn slice_mut(&self, data: &'a mut Array2<T>) -> Option<Self::OutputMut> {
365 let index = self.get_current_index()?;
367
368 data.get_mut(index.as_array2_index())
369 }
370
371 fn advance(&mut self) {
372 let curr_index = match self.get_current_index() {
374 Some(i) => i,
375 None => return,
376 };
377
378 let param = (self.current_map.unwrap() - self.start_map).norm()
381 / (self.end_map - self.start_map).norm();
382
383 let delta_param: Vector2<f64> = ((curr_index.cast() + self.dir_sign)
387 - self.current_map.unwrap())
388 .component_div(&self.dir)
389 + Vector2::from_element(self.map_meta.cell_boundary_precision);
390
391 let delta = delta_param.x.min(delta_param.y);
393
394 if delta + param > 1.0 {
397 self.current_map = None;
398 }
399 else {
401 self.current_map = Some(self.current_map.unwrap() + (self.dir * delta));
402 }
403
404 #[cfg(feature = "debug_iters")]
406 {
407 use std::io::Write;
408
409 let rpt = LineStepData {
410 start_parent: self.start_parent,
411 end_parent: self.end_parent,
412 dir: self.dir,
413 dir_sign: self.dir_sign,
414 start_map: self.start_map,
415 end_map: self.end_map,
416 current_map: self.current_map,
417 end_index: self.end_index,
418 delta: delta_param,
419 };
420
421 let val = serde_json::to_string_pretty(&rpt).unwrap();
422
423 writeln!(
424 std::sync::Arc::<std::fs::File>::get_mut(&mut self.step_report_file).unwrap(),
425 "{},",
426 val
427 )
428 .unwrap();
429 }
430 }
431
432 fn index(&self) -> Option<Point2<usize>> {
433 self.get_current_index()
434 }
435
436 fn reset(&mut self, _layer: Option<L>) {
437 self.current_map = Some(self.start_map)
438 }
439}