use geo_types::Coord;
use crate::TileError;
use crate::vertex::Vertex;
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
}
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;
}
if inside(a, min, max) || inside(b, min, max) {
return true;
}
let (dx, dy) = (
i128::from(b.x) - i128::from(a.x),
i128::from(b.y) - i128::from(a.y),
);
let side = |x: i32, y: i32| {
dx * (i128::from(y) - i128::from(a.y)) - dy * (i128::from(x) - i128::from(a.x))
};
let s = [
side(min.x, min.y),
side(max.x, min.y),
side(min.x, max.y),
side(max.x, max.y),
];
!(s.iter().all(|&v| v > 0) || s.iter().all(|&v| v < 0))
}
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)?,
}))
}