|
|
|
@ -1,7 +1,5 @@
@@ -1,7 +1,5 @@
|
|
|
|
|
pub type Scalar = f64; |
|
|
|
|
|
|
|
|
|
pub const EPSILON: Scalar = std::f64::EPSILON * 100.; |
|
|
|
|
|
|
|
|
|
pub type Vec2 = nalgebra::Vector2<Scalar>; |
|
|
|
|
pub type Point2 = nalgebra::Point2<Scalar>; |
|
|
|
|
|
|
|
|
@ -37,7 +35,7 @@ impl Region<Scalar> for Region1 {
@@ -37,7 +35,7 @@ impl Region<Scalar> for Region1 {
|
|
|
|
|
use Region1::*; |
|
|
|
|
match self { |
|
|
|
|
Empty => false, |
|
|
|
|
Singleton(n1) => *n1 == *n, |
|
|
|
|
Singleton(n1) => relative_eq!(n1, n), |
|
|
|
|
Range(l, u) => *l <= *n && *n <= *u, |
|
|
|
|
Union(r1, r2) => r1.contains(n) || r2.contains(n), |
|
|
|
|
Full => true, |
|
|
|
@ -69,8 +67,7 @@ impl Line2 {
@@ -69,8 +67,7 @@ impl Line2 {
|
|
|
|
|
|
|
|
|
|
pub fn intersect(&self, other: &Line2) -> Option<Point2> { |
|
|
|
|
// if two lines are parallel
|
|
|
|
|
// TODO: epsilon?
|
|
|
|
|
if (self.dir * other.dir).sin_angle() == 0. { |
|
|
|
|
if relative_eq!((self.dir / other.dir).sin_angle(), 0.) { |
|
|
|
|
return None; |
|
|
|
|
} |
|
|
|
|
// TODO: respect extent
|
|
|
|
@ -82,8 +79,7 @@ impl Line2 {
@@ -82,8 +79,7 @@ impl Line2 {
|
|
|
|
|
b_v.cos_angle(), |
|
|
|
|
b_v.sin_angle(), |
|
|
|
|
); |
|
|
|
|
let t_b = |
|
|
|
|
(a_0.x * a_s - a_0.y * a_c + a_0.x * a_s + b_0.y * a_c) / (a_s * b_c - a_c * b_s); |
|
|
|
|
let t_b = (a_0.x * a_s - a_0.y * a_c + a_0.x * a_s + b_0.y * a_c) / (a_s * b_c - a_c * b_s); |
|
|
|
|
Some(b.evaluate(t_b)) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -94,6 +90,7 @@ pub enum Region2 {
@@ -94,6 +90,7 @@ pub enum Region2 {
|
|
|
|
|
// single point at 0
|
|
|
|
|
Singleton(Point2), |
|
|
|
|
Line(Line2), |
|
|
|
|
#[allow(dead_code)] |
|
|
|
|
Union(Box<Region2>, Box<Region2>), |
|
|
|
|
Full, |
|
|
|
|
} |
|
|
|
@ -108,16 +105,7 @@ impl Region<Point2> for Region2 {
@@ -108,16 +105,7 @@ impl Region<Point2> for Region2 {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn contains(&self, p: &Point2) -> bool { |
|
|
|
|
use Region2::*; |
|
|
|
|
self.nearest(p).map_or(false, |n| n == *p) // TODO: epsilon?
|
|
|
|
|
|
|
|
|
|
// match self {
|
|
|
|
|
// Empty => false,
|
|
|
|
|
// Singleton(n1) => *n1 == n,
|
|
|
|
|
// Line(_, _, _) => unimplemented!(),
|
|
|
|
|
// Union(r1, r2) => r1.contains(n) || r2.contains(n),
|
|
|
|
|
// Full => true,
|
|
|
|
|
// }
|
|
|
|
|
self.nearest(p).map_or(false, |n| relative_eq!(n, p)) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn nearest(&self, p: &Point2) -> Option<Point2> { |
|
|
|
@ -155,7 +143,7 @@ impl Region2 {
@@ -155,7 +143,7 @@ impl Region2 {
|
|
|
|
|
use Region2::*; |
|
|
|
|
match (self, other) { |
|
|
|
|
(Empty, _) | (_, Empty) => Empty, |
|
|
|
|
(Full, r @ _) | (r @ _, Full) => r.clone(), |
|
|
|
|
(Full, r) | (r, Full) => r.clone(), |
|
|
|
|
(Singleton(n1), Singleton(n2)) => { |
|
|
|
|
if n1 == n2 { |
|
|
|
|
Singleton(*n1) |
|
|
|
@ -163,7 +151,7 @@ impl Region2 {
@@ -163,7 +151,7 @@ impl Region2 {
|
|
|
|
|
Empty |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
(Singleton(n), o @ _) | (o @ _, Singleton(n)) => { |
|
|
|
|
(Singleton(n), o) | (o, Singleton(n)) => { |
|
|
|
|
if o.contains(n) { |
|
|
|
|
Singleton(*n) |
|
|
|
|
} else { |
|
|
|
@ -177,4 +165,4 @@ impl Region2 {
@@ -177,4 +165,4 @@ impl Region2 {
|
|
|
|
|
_ => unimplemented!(), |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|