haar_lib/geom/
intersect_line_segment.rs

1//! 直線と線分の位置関係
2
3use crate::geom::*;
4use std::cmp::Ordering::*;
5
6/// 直線と線分の位置関係
7#[derive(Clone, Copy, Debug, PartialEq)]
8#[allow(non_camel_case_types)]
9pub enum IntersectLineSegment {
10    /// 線分が直線の左側にある
11    LEFTSIDE,
12    /// 線分が直線の右側にある
13    RIGHTSIDE,
14    /// 線分が直線上にある
15    OVERLAPPED,
16    /// 線分が直線と交差している
17    CROSSED,
18}
19
20impl IntersectLineSegment {
21    /// `LEFTSIDE`かを判定
22    pub fn leftside(self) -> bool {
23        self == Self::LEFTSIDE
24    }
25    /// `RIGHTSIDE`かを判定
26    pub fn rightside(self) -> bool {
27        self == Self::RIGHTSIDE
28    }
29    /// `OVERLAPPED`かを判定
30    pub fn overlapped(self) -> bool {
31        self == Self::OVERLAPPED
32    }
33    /// `CROSSED`かを判定
34    pub fn crossed(self) -> bool {
35        self == Self::CROSSED
36    }
37}
38
39/// 直線と線分の位置関係と交点を求める
40pub fn intersect_line_segment(
41    l: Line,
42    s: Line,
43    eps: Eps,
44) -> (IntersectLineSegment, Option<Vector>) {
45    use self::IntersectLineSegment::*;
46
47    let a = l.diff().cross(s.from - l.from);
48    let b = l.diff().cross(s.to - l.from);
49
50    match (eps.partial_cmp(a, 0.0), eps.partial_cmp(b, 0.0)) {
51        (Some(Equal), Some(Equal)) => (OVERLAPPED, None),
52        (Some(Less), Some(Less)) => (RIGHTSIDE, None),
53        (Some(Greater), Some(Greater)) => (LEFTSIDE, None),
54        _ => (
55            CROSSED,
56            Some(s.from + s.diff() * l.diff().cross(l.from - s.from) / l.cross(s)),
57        ),
58    }
59}