visioncortex/
transform.rs

1use crate::{BoundingRect, PointI32};
2
3/// Transformation of coordinate in space
4pub trait Transform {
5    fn transform(&self, vec: &PointI32) -> PointI32;
6    fn transform_rect(&self, rect: &BoundingRect) -> BoundingRect;
7}
8
9/// Equivalent to a Homothetic transform
10#[derive(Default)]
11pub struct RectangularTransform {
12    pub a: BoundingRect,
13    pub b: BoundingRect,
14}
15
16impl RectangularTransform {
17    pub fn new() -> Self {
18        Default::default()
19    }
20
21    pub fn new_rect_rect(a: BoundingRect, b: BoundingRect) -> Self {
22        Self {
23            a,
24            b,
25        }
26    }
27
28    pub fn new_point_point(a: PointI32, b: PointI32) -> Self {
29        Self {
30            a: BoundingRect::new_x_y_w_h(a.x, a.y, 1, 1),
31            b: BoundingRect::new_x_y_w_h(b.x, b.y, 1, 1),
32        }
33    }
34
35    pub fn new_point(b: &PointI32) -> Self {
36        Self {
37            a: BoundingRect::new_x_y_w_h(0, 0, 1, 1),
38            b: BoundingRect::new_x_y_w_h(b.x, b.y, 1, 1),
39        }
40    }
41}
42
43impl Transform for RectangularTransform {
44    fn transform(&self, p: &PointI32) -> PointI32 {
45        if self.a.is_empty() || self.b.is_empty() {
46            return *p;
47        }
48        PointI32 {
49            x: (p.x - self.a.left) * self.b.width() / self.a.width() + self.b.left,
50            y: (p.y - self.a.top) * self.b.height() / self.a.height() + self.b.top,
51        }
52    }
53
54    fn transform_rect(&self, r: &BoundingRect) -> BoundingRect {
55        let a = self.transform(&PointI32 {
56            x: r.left,
57            y: r.top,
58        });
59        let b = self.transform(&PointI32 {
60            x: r.right,
61            y: r.bottom,
62        });
63        BoundingRect {
64            left: a.x,
65            top: a.y,
66            right: b.x,
67            bottom: b.y,
68        }
69    }
70}
71
72#[cfg(test)]
73mod tests {
74    use super::*;
75
76    #[test]
77    fn rectangular_transform() {
78        assert_eq!(
79            RectangularTransform::new_rect_rect(
80                BoundingRect::new_x_y_w_h(1, 1, 2, 2),
81                BoundingRect::new_x_y_w_h(2, 2, 2, 2)
82            )
83            .transform(&PointI32 { x: 2, y: 2 }),
84            PointI32 { x: 3, y: 3 }
85        );
86
87        assert_eq!(
88            RectangularTransform::new_rect_rect(
89                BoundingRect::new_x_y_w_h(1, 1, 2, 2),
90                BoundingRect::new_x_y_w_h(2, 2, 4, 4)
91            )
92            .transform(&PointI32 { x: 2, y: 2 }),
93            PointI32 { x: 4, y: 4 }
94        );
95    }
96}