parry2d/utils/
point_in_triangle.rs1use crate::math::{Point, Real};
4
5#[derive(Eq, PartialEq, Debug, Copy, Clone)]
6pub enum Orientation {
8 Ccw,
10 Cw,
12 None,
14}
15
16pub fn corner_direction(p1: &Point<Real>, p2: &Point<Real>, p3: &Point<Real>) -> Orientation {
32 let v1 = p1 - p2;
33 let v2 = p3 - p2;
34 let cross: Real = v1.perp(&v2);
35
36 match cross
37 .partial_cmp(&0.0)
38 .expect("Found NaN while computing corner direction.")
39 {
40 core::cmp::Ordering::Less => Orientation::Ccw,
41 core::cmp::Ordering::Equal => Orientation::None,
42 core::cmp::Ordering::Greater => Orientation::Cw,
43 }
44}
45
46pub fn is_point_in_triangle(
49 p: &Point<Real>,
50 v1: &Point<Real>,
51 v2: &Point<Real>,
52 v3: &Point<Real>,
53) -> Option<bool> {
54 let d1 = corner_direction(p, v1, v2);
55 let d2 = corner_direction(p, v2, v3);
56 let d3 = corner_direction(p, v3, v1);
57
58 let has_cw = d1 == Orientation::Cw || d2 == Orientation::Cw || d3 == Orientation::Cw;
59 let has_ccw = d1 == Orientation::Ccw || d2 == Orientation::Ccw || d3 == Orientation::Ccw;
60
61 if d1 == Orientation::None && d2 == Orientation::None && d3 == Orientation::None {
62 None
63 } else {
64 Some(!(has_cw && has_ccw))
65 }
66}