1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
use crate::{Bearing, CameraPoint, CameraPose, RelativeCameraPose, WorldPoint};
use nalgebra::{IsometryMatrix3, Vector3};
pub trait TriangulatorObservances {
fn triangulate_observances<B: Bearing>(
&self,
pairs: impl IntoIterator<Item = (CameraPose, B)>,
) -> Option<WorldPoint>;
}
pub trait TriangulatorRelative {
fn triangulate_relative<A: Bearing, B: Bearing>(
&self,
relative_pose: RelativeCameraPose,
a: A,
b: B,
) -> Option<CameraPoint>;
}
impl<T> TriangulatorRelative for T
where
T: TriangulatorObservances,
{
fn triangulate_relative<A: Bearing, B: Bearing>(
&self,
RelativeCameraPose(pose): RelativeCameraPose,
a: A,
b: B,
) -> Option<CameraPoint> {
use core::iter::once;
self.triangulate_observances(
once((CameraPose::identity(), a.bearing()))
.chain(once((CameraPose(pose), b.bearing()))),
)
.map(|p| CameraPoint(p.0))
}
}
pub trait TriangulatorProject {
fn triangulate_project<B: Bearing>(
&self,
from: CameraPoint,
onto: B,
translation: Vector3<f64>,
) -> Option<f64>;
}
impl<T> TriangulatorProject for T
where
T: TriangulatorRelative,
{
fn triangulate_project<B: Bearing>(
&self,
from: CameraPoint,
onto: B,
translation: Vector3<f64>,
) -> Option<f64> {
let eye = from.0;
let target = eye + translation;
let up = from.coords.cross(&translation);
let fake_pose = RelativeCameraPose(IsometryMatrix3::look_at_lh(&eye, &target, &up));
self.triangulate_relative(fake_pose, onto, Vector3::z_axis())
.map(|point| {
let delta = point.0 - eye;
let dir = translation.normalize();
delta.dot(&dir)
})
}
}