1pub use super::grid::*;
4use std::f64;
5
6const INF: f64 = f64::MAX;
7
8fn dt1d_float(f: &Vec<f64>) -> Vec<f64> {
10 let mut d = vec![0f64; f.len()];
11 let mut v = vec![0i32; f.len()];
12 let mut z = vec![0f64; f.len() + 1];
13 let mut k = 0i32;
14 v[0] = 0;
15 z[0] = -INF;
16 z[1] = INF;
17
18 for q in 1..f.len() {
19 let mut s = ((f[q]+(q*q) as f64)-(f[v[k as usize] as usize]+(v[k as usize]*v[k as usize]) as f64))/(2*q as i32-2*v[k as usize]) as f64;
20 while s <= z[k as usize] {
21 k -= 1;
22 s = ((f[q]+(q*q) as f64)-(f[v[k as usize] as usize]+(v[k as usize]*v[k as usize]) as f64))/(2*q as i32-2*v[k as usize]) as f64;
23 }
24 k += 1;
25 v[k as usize] = q as i32;
26 z[k as usize] = s;
27 z[k as usize + 1] = INF;
28 }
29
30 k = 0;
31 for q in 0..f.len() {
32 while z[k as usize + 1] <= q as f64 {
33 k += 1;
34 }
35 d[q] = ((q as i32-v[k as usize])*(q as i32-v[k as usize])) as f64 + f[v[k as usize] as usize];
36 }
37
38 d
39}
40
41fn dt2d_float(im: &FloatGrid) -> FloatGrid {
43 let mut im = im.clone();
44 let width = im.width();
45 let height = im.height();
46 let mut f = vec![0f64; if width > height { width } else { height }];
47
48 for x in 0..width {
50 for y in 0..height {
51 f[y] = *im.get(x, y).unwrap();
52 }
53 let d = dt1d_float(&f);
54 for y in 0..height {
55 im.set(x, y, d[y]);
56 }
57 }
58
59 for y in 0..height {
61 for x in 0..width {
62 f[x] = *im.get(x, y).unwrap();
63 }
64 let d = dt1d_float(&f);
65 for x in 0..width {
66 im.set(x, y, d[x]);
67 }
68 }
69
70 im
71}
72
73pub fn dt1d(im: &Vec<bool>) -> Vec<f64> {
75 let mut out = Vec::with_capacity(im.len());
76 for x in 0..im.len() {
77 out[x] = if im[x] { 0. } else { INF };
78 }
79
80 dt1d_float(&out)
81}
82
83pub fn dt2d(im: &BoolGrid) -> FloatGrid {
85 let width = im.width();
86 let height = im.height();
87
88 let mut out = FloatGrid::new(width, height);
89 for (x, y, &val) in im.iter() {
90 out.set(x, y, if val { 0. } else { INF });
91 }
92
93 dt2d_float(&out)
94}