summaryrefslogtreecommitdiff
path: root/src/lib.rs
blob: c28487f867eb13240c37cd27ac11a645a4dc6c12 (plain) (blame)
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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
mod dimensions;
mod internal;
mod point;
mod rect;

pub use internal::Internal;
pub use dimensions::{Dimensions, HasDimensions};
pub use point::{Point, HasPosition};
pub use rect::{Rect, HasRect};

pub enum Orientation {
    Horizontal,
    Vertical,
}

// -----------------------------------------------------------------------------
// Orphaned code

impl Point<i32> {
    pub fn rotate_around(&self, origin: Self, radians: f64) -> Self {
        let sin = radians.sin();
        let cos = radians.cos();
        let x_diff = (self.x - origin.x) as f64;
        let y_diff = (self.y - origin.y) as f64;
        let x2 = (x_diff * cos) - (y_diff * sin);
        let y2 = (x_diff * sin) + (y_diff * cos);
        Point::new(x2.round() as i32 + origin.x, y2.round() as i32 + origin.y)
    }

    pub fn intersect<R: Into<Rect<i32, u32>>>(&self, rect: R) -> Option<Point<i32>> {
        let rect = rect.into();
        let left = self.x - rect.origin.x;
        let top = self.y - rect.origin.y;
        if left >= 0 && top >= 0 && rect.width() as i32 > left && rect.height() as i32 > top {
            Some(Point::new(left, top))
        } else {
            None
        }
    }
}

#[cfg(test)]
mod tests {
    use crate::Point;

    #[rustfmt::skip]
    macro_rules! p {($x:expr, $y:expr) => {Point::new($x, $y)};}

    fn rad(d: f64) -> f64 {
        d.to_radians()
    }

    #[test]
    fn quarter_turns_zero_origin() {
        let o = p!(0, 0);
        assert_eq!(p!(10, 10), p!(10, 10));
        assert_eq!(p!(10, 0).rotate_around(o, rad(0.0)), p!(10, 0));
        assert_eq!(p!(10, 0).rotate_around(o, rad(1.0)), p!(10, 0));
        assert_eq!(p!(10, 0).rotate_around(o, rad(90.0)), p!(0, 10));
        assert_eq!(p!(10, 0).rotate_around(o, rad(180.0)), p!(-10, 0));
        assert_eq!(p!(10, 0).rotate_around(o, rad(270.0)), p!(0, -10));
        assert_eq!(p!(10, 0).rotate_around(o, rad(360.0)), p!(10, 0));
        assert_eq!(p!(10, 0).rotate_around(o, rad(450.0)), p!(0, 10));
        assert_eq!(p!(10, 0).rotate_around(o, rad(-0.0)), p!(10, 0));
        assert_eq!(p!(10, 0).rotate_around(o, rad(-1.0)), p!(10, 0));
        assert_eq!(p!(10, 0).rotate_around(o, rad(-90.0)), p!(0, -10));
        assert_eq!(p!(10, 0).rotate_around(o, rad(-450.0)), p!(0, -10));
    }

    #[test]
    fn partial_turns_zero_origin() {
        let o = p!(0, 0);
        assert_eq!(p!(10, 0).rotate_around(o, rad(30.0)), p!(9, 5));
        assert_eq!(p!(10, 0).rotate_around(o, rad(45.0)), p!(7, 7));
        assert_eq!(p!(10, 0).rotate_around(o, rad(60.0)), p!(5, 9));
        assert_eq!(p!(10, 0).rotate_around(o, rad(120.0)), p!(-5, 9));
    }

    #[test]
    fn positive_origin() {
        let o = p!(10, 10);
        assert_eq!(p!(15, 10).rotate_around(o, rad(0.0)), p!(15, 10));
        assert_eq!(p!(15, 10).rotate_around(o, rad(45.0)), p!(14, 14));
        assert_eq!(p!(15, 10).rotate_around(o, rad(90.0)), p!(10, 15));
        assert_eq!(p!(0, 0).rotate_around(o, rad(0.0)), p!(0, 0));
        assert_eq!(p!(0, 0).rotate_around(o, rad(45.0)), p!(10, -4));
        assert_eq!(p!(0, 0).rotate_around(o, rad(90.0)), p!(20, 0));
    }


    use crate::Rect;
    macro_rules! r {
        ($x:expr,$y:expr;$w:expr,$h:expr) => {
            Rect::<i32,u32>::new($x,$y,$w,$h)
        };
    }

    #[test]
    fn intersection() {
        // Intersecting two null rects
        assert_eq!(r!(0,0;0,0), r!(0,0;0,0).intersect(r!(0,0;0,0)));
        // Intersecting two identical rects
        assert_eq!(r!(0,0;4,4), r!(0,0;4,4).intersect(r!(0,0;4,4)));
        // Intersecting two signed identical rects
        assert_eq!(r!(-4,-4;4,4), r!(-4,-4;4,4).intersect(r!(-4,-4;4,4)));
        // Intersecting two horizontally-displaced rects
        assert_eq!(r!(2,0;2,4), r!(0,0;4,4).intersect(r!(2,0;4,4)));
        assert_eq!(r!(2,0;2,4), r!(2,0;4,4).intersect(r!(0,0;4,4)));
        // Intersecting two vertically-displaced rects
        assert_eq!(r!(0,2;4,2), r!(0,0;4,4).intersect(r!(0,2;4,4)));
        assert_eq!(r!(0,2;4,2), r!(0,2;4,4).intersect(r!(0,0;4,4)));
        // Intersecting two adjacent rects
        assert_eq!(r!(0,0;0,0), r!(0,0;4,4).intersect(r!(0,4;4,4)));
        assert_eq!(r!(0,0;0,0), r!(0,0;4,4).intersect(r!(4,0;4,4)));
        assert_eq!(r!(0,0;0,0), r!(0,0;4,4).intersect(r!(4,4;4,4)));
        // Intersecting two almost-adjacent rects
        assert_eq!(r!(0,0;0,0), r!(0,0;4,4).intersect(r!(0,5;4,4)));
        assert_eq!(r!(0,0;0,0), r!(0,0;4,4).intersect(r!(5,0;4,4)));
        assert_eq!(r!(0,0;0,0), r!(0,0;4,4).intersect(r!(5,5;4,4)));
        // Intersecting two distant rects
        assert_eq!(r!(0,0;0,0), r!(0,0;4,4).intersect(r!(  0,100;4,4)));
        assert_eq!(r!(0,0;0,0), r!(0,0;4,4).intersect(r!(100,  0;4,4)));
        assert_eq!(r!(0,0;0,0), r!(0,0;4,4).intersect(r!(100,100;4,4)));
    }
}