use core::ops::{Deref, DerefMut};
pub const MAX_COORD: i64 = 1 << 40;
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Point {
pub x: i64,
pub y: i64,
}
impl Point {
#[inline]
pub const fn new(x: i64, y: i64) -> Self {
Point { x, y }
}
#[inline]
pub const fn in_range(self) -> bool {
self.x >= -MAX_COORD && self.x <= MAX_COORD && self.y >= -MAX_COORD && self.y <= MAX_COORD
}
}
impl From<(i64, i64)> for Point {
#[inline]
fn from((x, y): (i64, i64)) -> Self {
Point { x, y }
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct PointF {
pub x: f64,
pub y: f64,
}
impl PointF {
#[inline]
pub const fn new(x: f64, y: f64) -> Self {
PointF { x, y }
}
}
impl From<Point> for PointF {
#[inline]
fn from(p: Point) -> Self {
PointF {
x: p.x as f64,
y: p.y as f64,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Rect {
pub min: Point,
pub max: Point,
}
impl Rect {
pub fn new(a: Point, b: Point) -> Self {
Rect {
min: Point::new(a.x.min(b.x), a.y.min(b.y)),
max: Point::new(a.x.max(b.x), a.y.max(b.y)),
}
}
pub fn of_points<'a, I: IntoIterator<Item = &'a Point>>(pts: I) -> Option<Rect> {
let mut it = pts.into_iter();
let first = *it.next()?;
let mut r = Rect {
min: first,
max: first,
};
for p in it {
r.add_point(*p);
}
Some(r)
}
#[inline]
pub fn add_point(&mut self, p: Point) {
self.min.x = self.min.x.min(p.x);
self.min.y = self.min.y.min(p.y);
self.max.x = self.max.x.max(p.x);
self.max.y = self.max.y.max(p.y);
}
#[inline]
pub fn union(&self, o: &Rect) -> Rect {
Rect {
min: Point::new(self.min.x.min(o.min.x), self.min.y.min(o.min.y)),
max: Point::new(self.max.x.max(o.max.x), self.max.y.max(o.max.y)),
}
}
#[inline]
pub fn intersects(&self, o: &Rect) -> bool {
self.min.x <= o.max.x
&& o.min.x <= self.max.x
&& self.min.y <= o.max.y
&& o.min.y <= self.max.y
}
#[inline]
pub fn contains_point(&self, p: Point) -> bool {
p.x >= self.min.x && p.x <= self.max.x && p.y >= self.min.y && p.y <= self.max.y
}
#[inline]
pub fn contains_rect(&self, o: &Rect) -> bool {
self.contains_point(o.min) && self.contains_point(o.max)
}
#[inline]
pub fn expand(&self, d: i64) -> Rect {
Rect {
min: Point::new(self.min.x.saturating_sub(d), self.min.y.saturating_sub(d)),
max: Point::new(self.max.x.saturating_add(d), self.max.y.saturating_add(d)),
}
}
#[inline]
pub fn width(&self) -> i64 {
self.max.x - self.min.x
}
#[inline]
pub fn height(&self) -> i64 {
self.max.y - self.min.y
}
}
macro_rules! point_vec_newtype {
($(#[$m:meta])* $name:ident) => {
$(#[$m])*
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(transparent))]
pub struct $name(pub Vec<Point>);
impl $name {
#[inline]
pub const fn new() -> Self {
$name(Vec::new())
}
#[inline]
pub fn bbox(&self) -> Option<Rect> {
Rect::of_points(self.0.iter())
}
#[inline]
pub fn into_inner(self) -> Vec<Point> {
self.0
}
}
impl Deref for $name {
type Target = Vec<Point>;
#[inline]
fn deref(&self) -> &Vec<Point> {
&self.0
}
}
impl DerefMut for $name {
#[inline]
fn deref_mut(&mut self) -> &mut Vec<Point> {
&mut self.0
}
}
impl From<Vec<Point>> for $name {
#[inline]
fn from(v: Vec<Point>) -> Self {
$name(v)
}
}
impl From<&[Point]> for $name {
#[inline]
fn from(v: &[Point]) -> Self {
$name(v.to_vec())
}
}
impl From<&[(i64, i64)]> for $name {
fn from(v: &[(i64, i64)]) -> Self {
$name(v.iter().map(|&p| Point::from(p)).collect())
}
}
impl<const N: usize> From<[(i64, i64); N]> for $name {
fn from(v: [(i64, i64); N]) -> Self {
$name(v.iter().map(|&p| Point::from(p)).collect())
}
}
impl FromIterator<Point> for $name {
fn from_iter<I: IntoIterator<Item = Point>>(it: I) -> Self {
$name(it.into_iter().collect())
}
}
impl AsRef<[Point]> for $name {
#[inline]
fn as_ref(&self) -> &[Point] {
&self.0
}
}
};
}
point_vec_newtype!(
Path
);
point_vec_newtype!(
Ring
);
impl Ring {
pub fn signed_area2(&self) -> i128 {
crate::query::ring_area2(&self.0)
}
pub fn is_ccw(&self) -> bool {
self.signed_area2() > 0
}
pub fn reverse_orientation(&mut self) {
if self.0.len() > 1 {
self.0[1..].reverse();
}
}
pub fn edges(&self) -> impl Iterator<Item = (Point, Point)> + '_ {
let n = self.0.len();
(0..n).map(move |i| (self.0[i], self.0[(i + 1) % n]))
}
}
impl From<Ring> for Path {
fn from(r: Ring) -> Path {
let mut v = r.0;
if let Some(&f) = v.first() {
v.push(f);
}
Path(v)
}
}
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Polygon {
pub outer: Ring,
pub holes: Vec<Ring>,
}
impl Polygon {
pub fn new(outer: impl Into<Ring>, holes: Vec<Ring>) -> Self {
Polygon {
outer: outer.into(),
holes,
}
}
pub fn rings(&self) -> impl Iterator<Item = &Ring> {
core::iter::once(&self.outer).chain(self.holes.iter())
}
pub fn bbox(&self) -> Option<Rect> {
self.outer.bbox()
}
pub fn signed_area2(&self) -> i128 {
self.rings().map(|r| r.signed_area2()).sum()
}
pub fn vertex_count(&self) -> usize {
self.rings().map(|r| r.len()).sum()
}
}
impl From<Ring> for Polygon {
fn from(r: Ring) -> Self {
Polygon {
outer: r,
holes: Vec::new(),
}
}
}
pub type PolygonSet = Vec<Polygon>;
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct TaggedRing {
pub points: Vec<Point>,
pub tags: Vec<u64>,
}
impl TaggedRing {
pub fn uniform(ring: impl Into<Ring>, tag: u64) -> Self {
let r = ring.into();
let n = r.len();
TaggedRing {
points: r.0,
tags: vec![tag; n],
}
}
pub fn into_ring(self) -> Ring {
Ring(self.points)
}
}
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct TaggedPath {
pub points: Vec<Point>,
pub tags: Vec<u64>,
}
impl TaggedPath {
pub fn uniform(path: impl Into<Path>, tag: u64) -> Self {
let p = path.into();
let n = p.len().saturating_sub(1);
TaggedPath {
points: p.0,
tags: vec![tag; n],
}
}
pub fn into_path(self) -> Path {
Path(self.points)
}
}
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct TaggedPolygon {
pub outer: TaggedRing,
pub holes: Vec<TaggedRing>,
}
impl TaggedPolygon {
pub fn into_polygon(self) -> Polygon {
Polygon {
outer: self.outer.into_ring(),
holes: self.holes.into_iter().map(TaggedRing::into_ring).collect(),
}
}
}
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct PolyNode {
pub ring: Ring,
pub tags: Vec<u64>,
pub is_hole: bool,
pub parent: Option<usize>,
pub children: Vec<usize>,
}
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct PolyTree {
pub nodes: Vec<PolyNode>,
pub roots: Vec<usize>,
}
impl PolyTree {
pub fn is_empty(&self) -> bool {
self.nodes.is_empty()
}
pub fn polygons(&self) -> impl Iterator<Item = Polygon> + '_ {
self.outer_indices().map(move |i| self.polygon_at(i))
}
pub fn tagged_polygons(&self) -> impl Iterator<Item = TaggedPolygon> + '_ {
self.outer_indices().map(move |i| {
let n = &self.nodes[i];
TaggedPolygon {
outer: TaggedRing {
points: n.ring.0.clone(),
tags: n.tags.clone(),
},
holes: n
.children
.iter()
.map(|&h| TaggedRing {
points: self.nodes[h].ring.0.clone(),
tags: self.nodes[h].tags.clone(),
})
.collect(),
}
})
}
pub fn polygon_at(&self, i: usize) -> Polygon {
let n = &self.nodes[i];
Polygon {
outer: n.ring.clone(),
holes: n
.children
.iter()
.map(|&h| self.nodes[h].ring.clone())
.collect(),
}
}
pub fn outer_indices(&self) -> impl Iterator<Item = usize> + '_ {
let mut stack: Vec<usize> = self.roots.iter().rev().copied().collect();
core::iter::from_fn(move || {
while let Some(i) = stack.pop() {
let n = &self.nodes[i];
for &h in n.children.iter().rev() {
for &isl in self.nodes[h].children.iter().rev() {
stack.push(isl);
}
}
if !n.is_hole {
return Some(i);
}
}
None
})
}
pub fn to_polygon_set(&self) -> PolygonSet {
let mut v: PolygonSet = self.polygons().collect();
v.sort_by(|a, b| a.outer.0.cmp(&b.outer.0));
v
}
pub fn to_tagged_polygons(&self) -> Vec<TaggedPolygon> {
let mut v: Vec<TaggedPolygon> = self.tagged_polygons().collect();
v.sort_by(|a, b| a.outer.points.cmp(&b.outer.points));
v
}
pub fn signed_area2(&self) -> i128 {
self.nodes.iter().map(|n| n.ring.signed_area2()).sum()
}
}