visioncortex/polypartition/util/
general_util.rs1use 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}