cv_core/
point.rs

1use derive_more::{AsMut, AsRef, Deref, DerefMut, From, Into};
2use nalgebra::{Point3, Unit, Vector3, Vector4};
3
4/// This trait is implemented for homogeneous projective 3d coordinate.
5pub trait Projective: From<Vector4<f64>> + Clone + Copy {
6    /// Retrieve the homogeneous vector.
7    ///
8    /// No constraints are put on this vector. All components can move freely and it is not normalized.
9    /// However, this vector may be normalized if desired and it will still be equivalent to the original.
10    /// You may wish to normalize it if you want to avoid floating point precision issues, for instance.
11    fn homogeneous(self) -> Vector4<f64>;
12
13    /// Retrieve the euclidean 3d point by normalizing the homogeneous coordinate.
14    ///
15    /// This may fail, as a homogeneous coordinate can exist at near-infinity (like a star in the sky),
16    /// whereas a 3d euclidean point cannot (it would overflow).
17    fn point(self) -> Option<Point3<f64>> {
18        Point3::from_homogeneous(self.homogeneous())
19    }
20
21    /// Convert the euclidean 3d point into homogeneous coordinates.
22    fn from_point(point: Point3<f64>) -> Self {
23        point.to_homogeneous().into()
24    }
25
26    /// Retrieve the normalized bearing of the coordinate.
27    fn bearing(self) -> Unit<Vector3<f64>> {
28        Unit::new_normalize(self.bearing_unnormalized())
29    }
30
31    /// Retrieve the unnormalized bearing of the coordinate.
32    ///
33    /// Use this when you know that you do not need the bearing to be normalized,
34    /// and it may increase performance. Otherwise use [`Projective::bearing`].
35    fn bearing_unnormalized(self) -> Vector3<f64> {
36        self.homogeneous().xyz()
37    }
38}
39
40/// A 3d point which is relative to the camera's optical center and orientation where
41/// the positive X axis is right, positive Y axis is down, and positive Z axis is forwards
42/// from the optical center of the camera. The unit of distance of a `CameraPoint` is
43/// unspecified and relative to the current reconstruction.
44#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, AsMut, AsRef, Deref, DerefMut, From, Into)]
45pub struct CameraPoint(pub Vector4<f64>);
46
47impl Projective for CameraPoint {
48    fn homogeneous(self) -> Vector4<f64> {
49        self.into()
50    }
51}
52
53/// A point in "world" coordinates.
54/// This means that the real-world units of the pose are unknown, but the
55/// unit of distance and orientation are the same as the current reconstruction.
56///
57/// The reason that the unit of measurement is typically unknown is because if
58/// the whole world is scaled by any factor `n` (excluding the camera itself), then
59/// the normalized image coordinates will be exactly same on every frame. Due to this,
60/// the scaling of the world is chosen arbitrarily.
61///
62/// To extract the real scale of the world, a known distance between two `WorldPoint`s
63/// must be used to scale the whole world (and all translations between cameras). At
64/// that point, the world will be appropriately scaled. It is recommended not to make
65/// the `WorldPoint` in the reconstruction scale to the "correct" scale. This is for
66/// two reasons:
67///
68/// Firstly, because it is possible for scale drift to occur due to the above situation,
69/// the further in the view graph you go from the reference measurement, the more the scale
70/// will drift from the reference. It would give a false impression that the scale is known
71/// globally when it is only known locally if the whole reconstruction was scaled.
72///
73/// Secondly, as the reconstruction progresses, the reference points might get rescaled
74/// as optimization of the reconstruction brings everything into global consistency.
75/// This means that, while the reference points would be initially scaled correctly,
76/// any graph optimization might cause them to drift in scale as well.
77///
78/// Please scale your points on-demand. When you need to know a real distance in the
79/// reconstruction, please use the closest known refenence in the view graph to scale
80/// it appropriately. In the future we will add APIs to utilize references
81/// as optimization constraints when a known reference reconstruction is present.
82///
83/// If you must join two reconstructions, please solve for the similarity (rotation, translation and scale)
84/// between the two reconstructions using an optimizer. APIs will eventually be added to perform this operation
85/// as well.
86#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, AsMut, AsRef, Deref, DerefMut, From, Into)]
87pub struct WorldPoint(pub Vector4<f64>);
88
89impl Projective for WorldPoint {
90    fn homogeneous(self) -> Vector4<f64> {
91        self.into()
92    }
93}