1use crate::point::Point;
2use crate::tmspace::TimetricSpace;
3
4fn norm(p: &Point, pwr: f64) -> f64 {
5 p.cs.iter().map(|&c| c.abs().powf(pwr)).sum::<f64>().powf(1.0 / pwr)
6}
7
8fn make_unit_cover_anchors(dim: usize, pwr: f64, rad: f64, n: usize) -> Vec<Point> {
9 let mut index = vec![0usize; dim];
10
11 let step = 2.0 * rad / (n as f64);
12 let mut anchors: Vec<Point> = Vec::with_capacity((n+1).pow(dim as u32));
13
14 loop {
15 let anchor = Point::new(
16 index.iter().map(|&i| -rad + (i as f64) * step).collect::<Vec<f64>>()
17 );
18 if norm(&anchor, pwr) <= 1.5 * rad {
19 anchors.push(anchor);
20 }
21 let mut carry = true;
22 let mut i: usize = 0;
23 while carry && (i < dim) {
24 index[i] += 1;
25 if index[i] > n {
26 index[i] = 0;
27 i += 1;
28 } else {
29 carry = false;
30 }
31 }
32 if i == dim {
33 break
34 }
35 }
36
37 anchors
38}
39
40pub struct RMPAtmo {
42 dim: usize,
43 pwr: f64,
44 atmosph_shift_vec: Point,
45 atmosph_shift_tmp: f64,
46 tau_precision: f64,
47
48 alpha: f64,
49 beta: f64,
50 unit_cover_anchors: Vec<Point>
51}
52
53impl RMPAtmo {
54 pub fn new(dim: usize, pwr: f64, atmosph_shift_vec: &Point, atmosph_shift_tmp: f64, tau_precision: f64) -> Self {
55 let alpha: f64 = 1.0 / (1.0 + atmosph_shift_tmp * norm(atmosph_shift_vec, pwr));
56 let beta: f64 = 1.0 / (1.0 - atmosph_shift_tmp * norm(atmosph_shift_vec, pwr));
57 let n = (2.0 * beta / alpha * (dim as f64).powf(1.0 / pwr)).ceil() as usize;
58 let unit_cover_anchors = make_unit_cover_anchors(dim, pwr, 1.0 / alpha, n);
59 Self{dim, pwr, atmosph_shift_vec: atmosph_shift_vec.clone(), atmosph_shift_tmp, tau_precision, alpha, beta, unit_cover_anchors}
60 }
61
62}
63
64impl TimetricSpace for RMPAtmo {
65 fn dim(&self) -> usize {
66 self.dim
67 }
68
69 fn ftau(&self, t_from: f64, p_from: &Point, p_to: &Point) -> f64 {
70 let mut t: f64 = t_from;
71 loop {
72 let tn = t_from + norm(& p_to.sub(p_from).sub(& self.atmosph_shift_vec.mul(
73 (self.atmosph_shift_tmp * t).sin() - (self.atmosph_shift_tmp * t_from).sin()
74 )), self.pwr);
75 if (t - tn).abs() < self.tau_precision {
76 break tn - t_from;
77 }
78 t = tn;
79 }
80 }
81
82 fn btau(&self, t_to: f64, p_from: &Point, p_to: &Point) -> f64 {
83 let mut t: f64 = t_to;
84 loop {
85 let tn = t_to - norm(& p_to.sub(p_from).sub(& self.atmosph_shift_vec.mul(
86 (self.atmosph_shift_tmp * t_to).sin() - (self.atmosph_shift_tmp * t).sin()
87 )), self.pwr);
88 if (t - tn).abs() < self.tau_precision {
89 break t_to - tn;
90 }
91 t = tn;
92 }
93 }
94
95 fn rho(&self, p1: &Point, p2: &Point) -> f64 {
96 norm(& p1.sub(p2), self.pwr)
97 }
98
99 fn alpha(&self) -> f64 {
100 self.alpha
101 }
102
103 fn beta(&self) -> f64 {
104 self.beta
105 }
106
107 fn make_rc_anchors(&self, anchor: &Point, radius: f64) -> Vec<Point> {
108 self.unit_cover_anchors.iter().map(|a| a.mul(radius).add(&anchor)).collect::<Vec<Point>>()
109 }
110
111}
112
113pub struct RMPWind {
115 dim: usize,
116 pwr: f64,
117 wind: Point,
118 tau_precision: f64,
119
120 alpha: f64,
121 beta: f64,
122 unit_cover_anchors: Vec<Point>
123}
124
125impl RMPWind {
126 pub fn new(dim: usize, pwr: f64, wind: &Point, tau_precision: f64) -> Self {
127 let alpha: f64 = 1.0 / (1.0 + norm(wind, pwr));
128 let beta: f64 = 1.0 / (1.0 - norm(wind, pwr));
129 let n = (2.0 * beta / alpha * (dim as f64).powf(1.0 / pwr)).ceil() as usize;
130 let unit_cover_anchors = make_unit_cover_anchors(dim, pwr, 1.0 / alpha, n);
131 Self{dim, pwr, wind: wind.clone(), tau_precision, alpha, beta, unit_cover_anchors}
132 }
133
134}
135
136impl TimetricSpace for RMPWind {
137 fn dim(&self) -> usize {
138 self.dim
139 }
140
141 fn ftau(&self, _t_from: f64, p_from: &Point, p_to: &Point) -> f64 {
142 let mut t = 0f64;
143 loop {
144 let tn = norm(& p_from.sub(p_to).add(& self.wind.mul(t)), self.pwr);
145 if (t - tn).abs() < self.tau_precision {
146 break tn;
147 }
148 t = tn;
149 }
150 }
151
152 fn btau(&self, _t_to: f64, p_from: &Point, p_to: &Point) -> f64 {
153 self.ftau(0.0, p_from, p_to)
154 }
155
156 fn rho(&self, p1: &Point, p2: &Point) -> f64 {
157 norm(& p1.sub(p2), self.pwr)
158 }
159
160 fn alpha(&self) -> f64 {
161 self.alpha
162 }
163
164 fn beta(&self) -> f64 {
165 self.beta
166 }
167
168 fn make_rc_anchors(&self, anchor: &Point, radius: f64) -> Vec<Point> {
169 self.unit_cover_anchors.iter().map(|a| a.mul(radius).add(&anchor)).collect::<Vec<Point>>()
170 }
171
172}