1use crate::{
2 camera::cahv::*, camera::model::*, error, matrix::Matrix, max, min, util::vec_to_str,
3 vector::Vector,
4};
5
6use serde::{Deserialize, Serialize};
7
8#[derive(Serialize, Deserialize, Debug, Clone)]
9pub struct Cahvor {
10 #[serde(with = "crate::vector::vector_format")]
12 pub c: Vector,
13
14 #[serde(with = "crate::vector::vector_format")]
16 pub a: Vector,
17
18 #[serde(with = "crate::vector::vector_format")]
20 pub h: Vector,
21
22 #[serde(with = "crate::vector::vector_format")]
24 pub v: Vector,
25
26 #[serde(with = "crate::vector::vector_format")]
28 pub o: Vector,
29
30 #[serde(with = "crate::vector::vector_format")]
32 pub r: Vector,
33}
34
35impl Cahvor {
36 pub fn default() -> Self {
37 Cahvor {
38 c: Vector::default(),
39 a: Vector::default(),
40 h: Vector::default(),
41 v: Vector::default(),
42 o: Vector::default(),
43 r: Vector::default(),
44 }
45 }
46
47 pub fn hc(&self) -> f64 {
48 self.a.dot_product(&self.h)
49 }
50
51 pub fn vc(&self) -> f64 {
52 self.a.dot_product(&self.v)
53 }
54
55 pub fn hs(&self) -> f64 {
56 let cp = self.a.cross_product(&self.h);
57 cp.len()
58 }
59
60 pub fn vs(&self) -> f64 {
63 let cp = self.a.cross_product(&self.v);
64 cp.len()
65 }
66
67 pub fn zeta(&self, p: &Vector) -> f64 {
68 p.subtract(&self.c).dot_product(&self.o)
69 }
70
71 pub fn _lambda(&self, p: &Vector, z: f64) -> Vector {
72 let o = self.o.scale(z);
73 p.subtract(&self.c).subtract(&o)
74 }
75
76 pub fn lambda(&self, p: &Vector) -> Vector {
77 let z = self.zeta(p);
78 self._lambda(&p, z)
79 }
80
81 pub fn tau(&self, p: &Vector) -> f64 {
82 let z = self.zeta(p);
83 let l = self._lambda(p, z);
84
85 l.dot_product(&l) / z.powi(2)
86 }
87
88 pub fn mu(&self, p: &Vector) -> f64 {
89 let t = self.tau(p);
90 self.r.x + self.r.y * t + self.r.z * t.powi(2)
91 }
92
93 pub fn corrected_point(&self, p: &Vector) -> Vector {
94 let mut l = self.lambda(p);
95 let m = self.mu(p);
96 l = l.scale(m);
97 p.add(&l)
98 }
99
100 pub fn rotation_matrix(&self, _w: f64, _o: f64, _k: f64) -> Matrix {
101 let w = _w.to_radians();
102 let o = _o.to_radians();
103 let k = _k.to_radians();
104
105 Matrix::new_with_values(
106 o.cos() * k.cos(),
107 w.sin() * o.sin() * k.sin() + w.cos() * k.sin(),
108 -(w.cos() * o.sin() * k.cos() + w.sin() * k.sin()),
109 0.0,
110 -(o.cos() * k.sin()),
111 -(w.sin() * o.sin() * k.sin() + w.cos() * k.cos()),
112 w.cos() * o.sin() * k.sin() + w.sin() * k.cos(),
113 0.0,
114 o.sin(),
115 -(w.sin() * o.cos()),
116 w.cos() * o.cos(),
117 0.0,
118 0.0,
119 0.0,
120 0.0,
121 1.0,
122 )
123 }
124
125 pub fn project_object_to_image_point(&self, p: &Vector) -> ImageCoordinate {
126 ImageCoordinate {
127 sample: self.i(p),
128 line: self.j(p),
129 }
130 }
131
132 pub fn i(&self, p: &Vector) -> f64 {
134 let pmc = p.subtract(&self.c);
135 let a = pmc.dot_product(&self.h);
136 let b = pmc.dot_product(&self.a);
137 a / b
138 }
139
140 pub fn j(&self, p: &Vector) -> f64 {
142 let pmc = p.subtract(&self.c);
143 let a = pmc.dot_product(&self.v);
144 let b = pmc.dot_product(&self.a);
145 a / b
146 }
147}
148
149impl CameraModelTrait for Cahvor {
150 fn model_type(&self) -> ModelType {
151 ModelType::CAHVOR
152 }
153
154 fn c(&self) -> Vector {
155 self.c
156 }
157
158 fn a(&self) -> Vector {
159 self.a
160 }
161
162 fn h(&self) -> Vector {
163 self.h
164 }
165
166 fn v(&self) -> Vector {
167 self.v
168 }
169
170 fn o(&self) -> Vector {
171 self.o
172 }
173
174 fn r(&self) -> Vector {
175 self.r
176 }
177
178 fn e(&self) -> Vector {
179 Vector::default()
180 }
181
182 fn box_clone(&self) -> Box<dyn CameraModelTrait + 'static> {
183 Box::new((*self).clone())
184 }
185
186 fn f(&self) -> f64 {
187 self.hs()
188 }
189
190 fn ls_to_look_vector(&self, coordinate: &ImageCoordinate) -> error::Result<LookVector> {
192 let line = coordinate.line;
193 let sample = coordinate.sample;
194
195 let origin = self.c;
196
197 let f = self.v.subtract(&self.a.scale(line));
198 let g = self.h.subtract(&self.a.scale(sample));
199 let mut rr = f.cross_product(&g).normalized();
200
201 let t = self.v.cross_product(&self.h);
202 if t.dot_product(&self.a) < 0.0 {
203 rr = rr.inversed();
204 }
205
206 let omega = rr.dot_product(&self.o);
207 let omega_2 = omega * omega;
208 let wo = self.o.scale(omega);
209 let lambda = rr.subtract(&wo);
210 let tau = lambda.dot_product(&lambda) / omega_2;
211 let k1 = 1.0 + self.r.x;
212 let k3 = self.r.y * tau;
213 let k5 = self.r.z * tau * tau;
214 let mu = self.r.x + k3 + k5;
215 let mut u = 1.0 - mu;
216
217 for i in 0..(MAXITER + 1) {
218 if i >= MAXITER {
219 return Err("cahvor 2d to 3d: Too many iterations");
220 }
221
222 let u_2 = u * u;
223 let poly = ((k5 * u_2 + k3) * u_2 + k1) * u - 1.0;
224 let deriv = (5.0 * k5 * u_2 + 3.0 * k3) * u_2 + k1;
225 if deriv <= EPSILON {
226 return Err("Cahvor 2d to 3d: Distortion is too negative");
227 } else {
228 let du = poly / deriv;
229 u -= du;
230 if du.abs() < CONV {
231 break;
232 }
233 }
234 }
235
236 Ok(LookVector {
237 origin,
238 look_direction: rr.subtract(&lambda.scale(1.0 - u)).normalized(),
239 })
240 }
241
242 fn xyz_to_ls(&self, xyz: &Vector, infinity: bool) -> ImageCoordinate {
244 if infinity {
245 let omega = xyz.dot_product(&self.o);
246 let omega_2 = omega * omega;
247 let wo = self.o.scale(omega);
248 let lambda = xyz.subtract(&wo);
249 let tau = lambda.dot_product(&lambda) / omega_2;
250 let mu = self.r.x + (self.r.y * tau) + (self.r.z * tau * tau);
251 let pp_c = xyz.add(&lambda.scale(mu));
252
253 let alpha = pp_c.dot_product(&self.a);
254 let beta = pp_c.dot_product(&self.h);
255 let gamma = pp_c.dot_product(&self.v);
256
257 ImageCoordinate {
258 sample: beta / alpha,
259 line: gamma / alpha,
260 }
261 } else {
262 let p_c = xyz.subtract(&self.c);
263 let omega = p_c.dot_product(&self.o);
264 let omega_2 = omega * omega;
265 let wo = self.o.scale(omega);
266 let lambda = p_c.subtract(&wo);
267 let tau = lambda.dot_product(&lambda) / omega_2;
268 let mu = self.r.x + (self.r.y * tau) + (self.r.z * tau * tau);
269 let pp = xyz.add(&lambda.scale(mu));
270
271 let pp_c = pp.subtract(&self.c);
272 let alpha = pp_c.dot_product(&self.a);
273 let beta = pp_c.dot_product(&self.h);
274 let gamma = pp_c.dot_product(&self.v);
275
276 ImageCoordinate {
277 sample: beta / alpha,
278 line: gamma / alpha,
279 }
280 }
281 }
282
283 fn pixel_angle_horiz(&self) -> f64 {
284 let a = self.v.dot_product(&self.a);
285 let s = self.a.scale(a);
286 let f = self.v.subtract(&s).len();
287 (1.0 / f).atan()
288 }
289
290 fn pixel_angle_vert(&self) -> f64 {
291 let a = self.h.dot_product(&self.a);
292 let s = self.a.scale(a);
293 let f = self.h.subtract(&s).len();
294 (1.0 / f).atan()
295 }
296
297 fn serialize(&self) -> String {
298 format!(
299 "{};{};{};{};{};{}",
300 vec_to_str(&self.c.to_vec()),
301 vec_to_str(&self.a.to_vec()),
302 vec_to_str(&self.h.to_vec()),
303 vec_to_str(&self.v.to_vec()),
304 vec_to_str(&self.o.to_vec()),
305 vec_to_str(&self.r.to_vec())
306 )
307 }
308}
309
310pub fn linearize(
312 camera_model: &Cahvor,
313 cahvor_width: usize,
314 cahvor_height: usize,
315 cahv_width: usize,
316 cahv_height: usize,
317) -> Cahv {
318 let minfov = true;
319
320 let mut output_camera = Cahv::default();
321 output_camera.c = camera_model.c;
322
323 let hpts = vec![
324 Vector::default(),
325 Vector::new(0.0, (cahvor_height as f64 - 1.0) / 2.0, 0.0),
326 Vector::new(0.0, cahvor_height as f64 - 1.0, 0.0),
327 Vector::new(cahvor_width as f64 - 1.0, 0.0, 0.0),
328 Vector::new(
329 cahvor_width as f64 - 1.0,
330 (cahvor_height as f64 - 1.0) / 2.0,
331 0.0,
332 ),
333 Vector::new(cahvor_width as f64, cahvor_height as f64, 0.0)
334 .subtract(&Vector::new(1.0, 1.0, 0.0)),
335 ];
336
337 let vpts = vec![
338 Vector::default(),
339 Vector::new((cahvor_width as f64 - 1.0) / 2.0, 0.0, 0.0),
340 Vector::new(cahvor_width as f64 - 1.0, 0.0, 0.0),
341 Vector::new(0.0, cahvor_height as f64 - 1.0, 0.0),
342 Vector::new(
343 (cahvor_width as f64 - 1.0) / 2.0,
344 cahvor_height as f64 - 1.0,
345 0.0,
346 ),
347 Vector::new(cahvor_width as f64, cahvor_height as f64, 0.0)
348 .subtract(&Vector::new(1.0, 1.0, 0.0)),
349 ];
350
351 for local in vpts.iter() {
352 if let Ok(lv) = camera_model.ls_to_look_vector(&ImageCoordinate {
353 line: local.y,
354 sample: local.x,
355 }) {
356 output_camera.a = output_camera.a.add(&lv.look_direction);
357 }
358 }
359
360 for local in hpts.iter() {
361 if let Ok(lv) = camera_model.ls_to_look_vector(&ImageCoordinate {
362 line: local.y,
363 sample: local.x,
364 }) {
365 output_camera.a = output_camera.a.add(&lv.look_direction);
366 }
367 }
368
369 output_camera.a = output_camera.a.normalized();
370
371 let mut dn = camera_model.a.cross_product(&camera_model.h).normalized();
372 let mut rt = dn.cross_product(&output_camera.a);
373 dn = output_camera.a.cross_product(&rt).normalized();
374 rt = rt.normalized();
375
376 let mut hmin = 1.0;
377 let mut hmax = -1.0;
378 for loop_ in hpts.iter() {
379 if let Ok(lv) = camera_model.ls_to_look_vector(&ImageCoordinate {
380 line: loop_.y,
381 sample: loop_.x,
382 }) {
383 let u3 = lv.look_direction;
384 let sn = output_camera
385 .a
386 .cross_product(&u3.subtract(&dn.scale(dn.dot_product(&u3))).normalized())
387 .len();
388 hmin = min!(hmin, sn);
389 hmax = max!(hmax, sn);
390 }
391 }
392
393 let mut vmin = 1.0;
394 let mut vmax = -1.0;
395 for loop_ in vpts.iter() {
396 if let Ok(lv) = camera_model.ls_to_look_vector(&ImageCoordinate {
397 line: loop_.y,
398 sample: loop_.x,
399 }) {
400 let u3 = lv.look_direction;
401 let sn = output_camera
402 .a
403 .cross_product(&u3.subtract(&rt.scale(rt.dot_product(&u3))).normalized())
404 .len();
405 vmin = min!(vmin, sn);
406 vmax = max!(vmax, sn);
407 }
408 }
409
410 println!("{}, {} -- {}, {}", hmin, hmax, vmin, vmax);
411 let image_center = Vector::new(cahv_width as f64, cahv_height as f64, 0.0)
412 .subtract(&Vector::new(1.0, 1.0, 0.0))
413 .scale(0.5);
414 println!("image_center -> {:?}", image_center);
415 let image_center_2 = image_center.multiply(&image_center);
416 println!("image_center_2 -> {:?}", image_center_2);
417
418 let scale_factors = if minfov {
419 image_center_2
420 .divide(&Vector::new(hmin * hmin, vmin * vmin, 0.0))
421 .subtract(&image_center_2)
422 .sqrt()
423 } else {
424 image_center_2
425 .divide(&Vector::new(hmax * hmax, vmax * vmax, 0.0))
426 .subtract(&image_center_2)
427 .sqrt()
428 };
429
430 println!("scale_factors -> {:?}", scale_factors);
431 output_camera.h = rt
432 .scale(scale_factors.x)
433 .add(&output_camera.a.scale(image_center.x));
434 output_camera.v = dn
435 .scale(scale_factors.y)
436 .add(&output_camera.a.scale(image_center.y));
437
438 output_camera
439}