Skip to main content

visioncortex/polypartition/util/
general_util.rs

1use crate::PointF64;
2
3pub fn f64_approximately(a: f64, b: f64) -> bool {
4    let epsilon = 1e-7;
5    (a - b).abs() <= epsilon
6}
7
8pub fn point_f64_approximately(p1: PointF64, p2: PointF64) -> bool {
9    f64_approximately(p1.x, p2.x) && f64_approximately(p1.y, p2.y)
10}
11
12pub fn is_convex(p1: &PointF64, p2: &PointF64, p3: &PointF64) -> bool {
13    let tmp = (p3.y - p1.y) * (p2.x - p1.x) - (p3.x - p1.x) * (p2.y - p1.y);
14    tmp.is_sign_positive()
15}
16
17pub fn is_reflex(p1: &PointF64, p2: &PointF64, p3: &PointF64) -> bool {
18    let tmp = (p3.y - p1.y) * (p2.x - p1.x) - (p3.x - p1.x) * (p2.y - p1.y);
19    tmp.is_sign_negative()
20}
21
22pub fn is_inside(p1: &PointF64, p2: &PointF64, p3: &PointF64, p: &PointF64) -> bool {
23    !(is_convex(p1, p, p2) || is_convex(p2, p, p3) || is_convex(p3, p, p1))
24}
25
26pub fn is_in_cone(p1: &PointF64, p2: &PointF64, p3: &PointF64, p: &PointF64) -> bool {
27    if is_convex(p1, p2, p3) {
28        if !is_convex(p1, p2, p) || !is_convex(p2, p3, p) {
29            return false;
30        }
31        true
32    } else {
33        if is_convex(p1, p2, p) || is_convex(p2, p3, p) {
34            return true;
35        }
36        false
37    }
38}
39
40pub fn normalize(p: &PointF64) -> PointF64 {
41    let norm = p.norm();
42    if norm != 0.0 {
43        PointF64::new(p.x / norm, p.y / norm)
44    } else {
45        PointF64::new(0.0, 0.0)
46    }
47}
48
49pub fn distance(p1: &PointF64, p2: &PointF64) -> f64 {
50    (*p1 - *p2).norm()
51}
52
53pub fn intersects(p11: &PointF64, p12: &PointF64, p21: &PointF64, p22: &PointF64) -> bool {
54    let (p11, p12, p21, p22) = (*p11, *p12, *p21, *p22);
55
56    if p11 == p21 || p11 == p22 || p12 == p21 || p12 == p22 {
57        return false;
58    }
59    
60    let v1ort = PointF64::new(p12.y - p11.y, p11.x - p12.x);
61    let v2ort = PointF64::new(p22.y - p21.y, p21.x - p22.x);
62
63    let v = p21 - p11;
64    let dot21 = v.dot(v1ort);
65
66    let v = p22 - p11;
67    let dot22 = v.dot(v1ort);
68
69    let v = p11 - p21;
70    let dot11 = v.dot(v2ort);
71
72    let v = p12 - p21;
73    let dot12 = v.dot(v2ort);
74
75    !((dot11 * dot12).is_sign_positive() || (dot21 * dot22).is_sign_positive())
76}
77
78#[cfg(test)]
79mod tests {
80    use super::*;
81
82    #[test]
83    fn util_general_point() {
84        let p = PointF64::new(1.0, 0.0);
85        assert!(normalize(&p) == p);
86        let p = PointF64::new(1.0, 1.0);
87        assert!(point_f64_approximately(normalize(&p), PointF64::new(1.0 / 2.0_f64.sqrt(), 1.0 / 2.0_f64.sqrt())));
88        let p = PointF64::new(3.0, 3.0);
89        assert!(point_f64_approximately(normalize(&p), PointF64::new(1.0 / 2.0_f64.sqrt(), 1.0 / 2.0_f64.sqrt())));
90    }
91
92    #[test]
93    fn util_general_is_inside() {
94        let p1 = &PointF64::new(-1.0, -1.0);
95        let p2 = &PointF64::new(1.0, -1.0);
96        let p3 = &PointF64::new(0.0, 1.0);
97        let p = &PointF64::new(0.0, 0.5);
98
99        assert!(is_inside(p1, p2, p3, p));
100
101        let p1 = &PointF64::new(-1.0, -1.0);
102        let p2 = &PointF64::new(1.0, -1.0);
103        let p3 = &PointF64::new(0.0, 1.0);
104        let p = &PointF64::new(0.0, 9.0);
105
106        assert!(!is_inside(p1, p2, p3, p));
107    }
108
109    #[test]
110    fn util_general_intersects() {
111        let p11 = &PointF64::new(-1.0, 0.0);
112        let p12 = &PointF64::new(1.0, 0.0);
113        let p21 = &PointF64::new(0.0, -1.0);
114        let p22 = &PointF64::new(0.0, 1.0);
115
116        assert!(intersects(p11, p12, p21, p22));
117
118        let p11 = &PointF64::new(-1.0, 0.0);
119        let p12 = &PointF64::new(1.0, 0.0);
120        let p21 = &PointF64::new(-1.0, -1.0);
121        let p22 = &PointF64::new(1.0, -1.0);
122
123        assert!(!intersects(p11, p12, p21, p22));
124    }
125}