use super::{Intersects, has_disjoint_bboxes};
use crate::*;
impl<T> Intersects<Coord<T>> for Rect<T>
where
T: CoordNum,
{
fn intersects(&self, rhs: &Coord<T>) -> bool {
rhs.x >= self.min().x
&& rhs.y >= self.min().y
&& rhs.x <= self.max().x
&& rhs.y <= self.max().y
}
}
symmetric_intersects_impl!(Rect<T>, LineString<T>);
symmetric_intersects_impl!(Rect<T>, MultiLineString<T>);
impl<T> Intersects<Line<T>> for Rect<T>
where
T: GeoNum,
{
fn intersects(&self, rhs: &Line<T>) -> bool {
if !self.intersects(&rhs.bounding_rect()) {
return false;
}
let c0 = self.min();
let c1 = coord! {x: self.max().x, y: self.min().y};
let o0 = T::Ker::orient2d(rhs.start, rhs.end, c0);
let o1 = T::Ker::orient2d(rhs.start, rhs.end, c1);
if o0 != o1 {
return true;
}
let c2 = self.max();
let o2 = T::Ker::orient2d(rhs.start, rhs.end, c2);
if o0 != o2 {
return true;
}
let c3 = coord! {x: self.min().x, y: self.max().y};
let o3 = T::Ker::orient2d(rhs.start, rhs.end, c3);
if o0 != o3 {
return true;
}
debug_assert!(o3 == o0);
o0 == Orientation::Collinear
}
}
symmetric_intersects_impl!(Rect<T>, Point<T>);
symmetric_intersects_impl!(Rect<T>, MultiPoint<T>);
impl<T> Intersects<Polygon<T>> for Rect<T>
where
T: GeoNum,
{
fn intersects(&self, rhs: &Polygon<T>) -> bool {
if has_disjoint_bboxes(self, rhs) {
return false;
}
rhs.coords_iter().take(1).any(|p| self.intersects(&p))
|| self.min().intersects(rhs)
|| rhs.lines_iter().any(|rhs_line| {
self.lines_iter()
.any(|self_line| self_line.intersects(&rhs_line))
})
}
}
symmetric_intersects_impl!(Rect<T>, MultiPolygon<T>);
impl<T> Intersects<Rect<T>> for Rect<T>
where
T: CoordNum,
{
fn intersects(&self, other: &Rect<T>) -> bool {
if self.max().x < other.min().x {
return false;
}
if self.max().y < other.min().y {
return false;
}
if self.min().x > other.max().x {
return false;
}
if self.min().y > other.max().y {
return false;
}
true
}
}
impl<T> Intersects<Triangle<T>> for Rect<T>
where
T: GeoNum,
{
fn intersects(&self, rhs: &Triangle<T>) -> bool {
if has_disjoint_bboxes(self, rhs) {
return false;
}
self.intersects(&rhs.v1())
|| self.min().intersects(rhs)
|| rhs.lines_iter().any(|rhs_line| {
self.lines_iter()
.any(|self_line| self_line.intersects(&rhs_line))
})
}
}
#[cfg(test)]
mod test_line {
use super::*;
use crate::wkt;
#[test]
fn test_overlap_bbox_no_overlap() {
let rect = wkt! {RECT(6 4, 10 0)};
let line = wkt! {LINE(0 0, 10 10)};
assert!(!rect.intersects(&line));
}
#[test]
fn test_degen_line() {
let rect = wkt! {RECT(0 0, 10 10)};
let line = wkt! {LINE(0 0, 0 0)};
assert!(rect.intersects(&line));
}
#[test]
fn test_degen_rect() {
let rect_pt = wkt! {RECT(0 0, 0 10)};
let rect_line1 = wkt! {RECT(0 0, 0 10)};
let rect_line2 = wkt! {RECT(0 0, 10 0)};
let line = wkt! {LINE(0 0, 10 0)};
assert!(rect_pt.intersects(&line));
assert!(rect_line1.intersects(&line));
assert!(rect_line2.intersects(&line));
}
}
#[cfg(test)]
mod test_triangle {
use super::*;
#[test]
fn test_rhs_degenerate_line() {
let s: Rect<f64> = Rect::new((0, 0), (0, 0)).convert();
let l = Line::new(coord! {x: 0.0, y: 0.0}, coord! { x: 0.0, y: 0.0 });
assert!(s.intersects(&l));
}
#[test]
fn test_disjoint() {
let rect: Rect<f64> = Rect::new((0, 0), (10, 10)).convert();
let triangle = Triangle::from([(0., 11.), (1., 11.), (1., 12.)]);
assert!(!rect.intersects(&triangle));
}
#[test]
fn test_partial() {
let rect: Rect<f64> = Rect::new((0, 0), (10, 10)).convert();
let triangle = Triangle::from([(1., 1.), (1., 2.), (2., 1.)]);
assert!(rect.intersects(&triangle));
}
#[test]
fn test_triangle_inside_rect() {
let rect: Rect<f64> = Rect::new((0, 0), (10, 10)).convert();
let triangle = Triangle::from([(1., 1.), (1., 2.), (2., 1.)]);
assert!(rect.intersects(&triangle));
}
#[test]
fn test_rect_inside_triangle() {
let rect: Rect<f64> = Rect::new((1, 1), (2, 2)).convert();
let triangle = Triangle::from([(0., 10.), (10., 0.), (0., 0.)]);
assert!(rect.intersects(&triangle));
}
}
#[cfg(test)]
mod test_polygon {
use super::*;
#[test]
fn test_disjoint() {
let rect: Rect<f64> = Rect::new((0, 0), (10, 10)).convert();
let polygon: Polygon<f64> = Rect::new((11, 11), (12, 12)).to_polygon().convert();
assert!(!rect.intersects(&polygon));
}
#[test]
fn test_partial() {
let rect: Rect<f64> = Rect::new((0, 0), (10, 10)).convert();
let polygon: Polygon<f64> = Rect::new((9, 9), (12, 12)).to_polygon().convert();
assert!(rect.intersects(&polygon));
}
#[test]
fn test_rect_inside_polygon() {
let rect: Rect<f64> = Rect::new((1, 1), (2, 2)).convert();
let polygon: Polygon<f64> = Rect::new((0, 0), (10, 10)).to_polygon().convert();
assert!(rect.intersects(&polygon));
}
#[test]
fn test_polygon_inside_rect() {
let rect: Rect<f64> = Rect::new((0, 0), (10, 10)).convert();
let polygon: Polygon<f64> = Rect::new((1, 1), (2, 2)).to_polygon().convert();
assert!(rect.intersects(&polygon));
}
#[test]
fn test_rect_inside_polygon_hole() {
let bound: Rect<f64> = Rect::new((0, 0), (10, 10)).convert();
let hole = Rect::new((1, 1), (9, 9)).convert();
let rect = Rect::new((4, 4), (6, 6)).convert();
let polygon = Polygon::new(
bound.exterior_coords_iter().collect(),
vec![hole.exterior_coords_iter().collect()],
);
assert!(!rect.intersects(&polygon));
}
#[test]
fn test_rect_equals_polygon_hole() {
let bound: Rect<f64> = Rect::new((0, 0), (10, 10)).convert();
let rect: Rect = Rect::new((4, 4), (6, 6)).convert();
let polygon = Polygon::new(
bound.exterior_coords_iter().collect(),
vec![rect.exterior_coords_iter().collect()],
);
assert!(rect.intersects(&polygon));
}
}