二次元ユークリッド幾何 - 線分と点との接触判定
/// Geometry2D - CCW (直線と点の関係)
use crate::geometry2d::line::*;
use crate::geometry2d::point::*;
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum CCW {
FRONT,
BACK,
RIGHT,
LEFT,
ON,
}
pub fn ccw(l: LineSegment, p: Point) -> CCW {
use CCW::*;
fn equal(x: f64, y: f64) -> bool {
(x - y).abs() < 0.00001
}
let dif = p - l.0;
let dir = l.1 - l.0;
if equal(0.0, dir.0) {
if equal(0.0, dif.0) {
let k = dif.1 / dir.1;
if k > 1.0 {
FRONT
} else if k < 0.0 {
BACK
} else {
ON
}
} else if dir.det(&dif) > 0.0 {
LEFT
} else {
RIGHT
}
} else {
let k = dif.0 / dir.0;
if equal(dir.1 * k, dif.1) {
if k > 1.0 {
FRONT
} else if k < 0.0 {
BACK
} else {
ON
}
} else {
if dir.det(&dif) > 0.0 {
LEFT
} else {
RIGHT
}
}
}
}
#[cfg(test)]
mod test_ccw {
use crate::geometry2d::ccw::*;
use CCW::*;
#[test]
fn it_works() {
let p = Point(1.0, 2.0);
let q = Point(2.0, 0.0);
let l = LineSegment::new(p, q);
assert_eq!(ccw(l, p), ON);
assert_eq!(ccw(l, q), ON);
assert_eq!(ccw(l, Point(1.5, 1.0)), ON);
assert_eq!(ccw(l, Point(3.0, -2.0)), FRONT);
assert_eq!(ccw(l, Point(0.0, 4.0)), BACK);
assert_eq!(ccw(l, Point(0.0, 0.0)), RIGHT);
assert_eq!(ccw(l, Point(10.0, 0.0)), LEFT);
}
}