use core::cmp::Ordering;
use geo_types::Coord;
use crate::TileError;
use crate::geom::orient;
use crate::vertex::Vertex;
#[inline]
fn inside(c: Coord<i32>, min: Coord<i32>, max: Coord<i32>) -> bool {
c.x >= min.x && c.x <= max.x && c.y >= min.y && c.y <= max.y
}
#[inline]
pub(crate) fn segment_intersects(
a: Coord<i32>,
b: Coord<i32>,
min: Coord<i32>,
max: Coord<i32>,
) -> bool {
if a.x.min(b.x) > max.x || a.x.max(b.x) < min.x || a.y.min(b.y) > max.y || a.y.max(b.y) < min.y
{
return false;
}
inside(a, min, max) || inside(b, min, max) || line_meets_box(a, b, min, max)
}
pub(crate) fn line_meets_box(
a: Coord<i32>,
b: Coord<i32>,
min: Coord<i32>,
max: Coord<i32>,
) -> bool {
let s = [
orient(a, b, min),
orient(a, b, Coord { x: max.x, y: min.y }),
orient(a, b, Coord { x: min.x, y: max.y }),
orient(a, b, max),
];
!(s.iter().all(|&v| v == Ordering::Greater) || s.iter().all(|&v| v == Ordering::Less))
}
pub(crate) fn to_local<V: Vertex>(v: V, origin: Coord<i32>) -> Result<V, TileError> {
let p = v.position();
Ok(v.with_position(Coord {
x: p.x.checked_sub(origin.x).ok_or(TileError::Overflow)?,
y: p.y.checked_sub(origin.y).ok_or(TileError::Overflow)?,
}))
}