diff options
| author | Arne Dußin | 2020-11-23 23:38:52 +0100 |
|---|---|---|
| committer | Arne Dußin | 2020-11-23 23:38:52 +0100 |
| commit | e62275d90d3ebf379e8ab268cb77d8eaf6d1cf07 (patch) | |
| tree | 5f8aee175d048e40b8b496157816177e0597e0f9 /src/math/polygon.rs | |
| parent | bff1955c38480f2dffd0a10c16ef46dc11320752 (diff) | |
| parent | 3b0c99351da92410bbfaba233e40376b767cb64e (diff) | |
| download | graf_karto-e62275d90d3ebf379e8ab268cb77d8eaf6d1cf07.tar.gz graf_karto-e62275d90d3ebf379e8ab268cb77d8eaf6d1cf07.zip | |
Merge branch 'triangulation' into polygon-rooms
Diffstat (limited to 'src/math/polygon.rs')
| -rw-r--r-- | src/math/polygon.rs | 170 |
1 files changed, 0 insertions, 170 deletions
diff --git a/src/math/polygon.rs b/src/math/polygon.rs deleted file mode 100644 index 5cf8104..0000000 --- a/src/math/polygon.rs +++ /dev/null @@ -1,170 +0,0 @@ -use super::{PolygonGraph, Vec2}; -use nalgebra::{ClosedDiv, ClosedMul, ClosedSub, RealField, Scalar}; -use num_traits::Zero; -use serde::{Deserialize, Serialize}; -use std::ops::Neg; - -#[derive(Debug, Deserialize, Serialize, PartialEq)] -// TODO: Support polygons with holes -pub struct Polygon<T: Scalar + Copy> { - pub corners: Vec<Vec2<T>>, -} - -impl<T: Scalar + Copy> Polygon<T> { - pub fn new(corners: Vec<Vec2<T>>) -> Self { - Self { corners } - } - - /// Check whether a point is inside a polygon or not. If a point lies on an edge, it also - /// counts as inside the polygon. - pub fn contains_point(&self, p: Vec2<T>) -> bool - where - T: Zero + ClosedSub + ClosedMul + ClosedDiv + Neg<Output = T> + PartialOrd, - { - let n = self.corners.len(); - - let a = self.corners[n - 1]; - let mut b = self.corners[n - 2]; - let mut ax; - let mut ay = a.y - p.y; - let mut bx = b.x - p.x; - let mut by = b.y - p.y; - - let mut lup = by > ay; - for i in 0..n { - // ax = bx; - ay = by; - b = self.corners[i]; - bx = b.x - p.x; - by = b.y - p.y; - - if ay == by { - continue; - } - lup = by > ay; - } - - let mut depth = 0; - for i in 0..n { - ax = bx; - ay = by; - let b = &self.corners[i]; - bx = b.x - p.x; - by = b.y - p.y; - - if ay < T::zero() && by < T::zero() { - // both "up" or both "down" - continue; - } - if ay > T::zero() && by > T::zero() { - // both "up" or both "down" - continue; - } - if ax < T::zero() && bx < T::zero() { - // both points on the left - continue; - } - - if ay == by && (if ax < bx { ax } else { bx }) <= T::zero() { - return true; - } - if ay == by { - continue; - } - - let lx = ax + (((bx - ax) * -ay) / (by - ay)); - if lx == T::zero() { - // point on edge - return true; - } - if lx > T::zero() { - depth += 1; - } - if ay == T::zero() && lup && by > ay { - // hit vertex, both up - depth -= 1; - } - if ay == T::zero() && !lup && by < ay { - // hit vertex, both down - depth -= 1; - } - - lup = by > ay; - } - - (depth & 1) == 1 - } - - /// Join this polygon with another, ensuring the area of the two stays the same, but the - /// overlap is not doubled, but instead joined into one. - /// Returns the Polygons themselves, if there is no overlap - pub fn unite(self, other: Polygon<T>) -> Vec<Polygon<T>> - where - T: RealField, - { - let mut graph = PolygonGraph::from_polygon(&self); - graph.add_all(&other); - - // TODO: Make bounding box support multiple polygons - vec![graph.bounding_polygon()] - } -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn polygon_contains() { - let polygon = Polygon::new(vec![ - Vec2::new(0., 0.), - Vec2::new(-1., 1.), - Vec2::new(0., 2.), - Vec2::new(1., 3.), - Vec2::new(3., 1.5), - Vec2::new(2., 0.), - Vec2::new(1., 1.), - ]); - - assert!(!polygon.contains_point(Vec2::new(1., -2.))); - assert!(!polygon.contains_point(Vec2::new(-1., 0.5))); - assert!(polygon.contains_point(Vec2::new(0., 0.5))); - assert!(polygon.contains_point(Vec2::new(0.5, 1.))); - assert!(polygon.contains_point(Vec2::new(0.5, 1.5))); - assert!(!polygon.contains_point(Vec2::new(-2., 1.9))); - assert!(!polygon.contains_point(Vec2::new(0., 3.))); - assert!(polygon.contains_point(Vec2::new(1., 3.))); - } - - #[test] - fn polygon_union() { - let first = Polygon::new(vec![ - Vec2::new(-2., 1.), - Vec2::new(-0.5, 2.5), - Vec2::new(2., 2.), - Vec2::new(0.5, 1.5), - Vec2::new(1., 0.), - Vec2::new(-0.5, 1.), - ]); - - let second = Polygon::new(vec![ - Vec2::new(0., 0.), - Vec2::new(-2., 2.), - Vec2::new(3., 2.), - Vec2::new(1.5, 0.), - ]); - - let union = first.unite(second); - assert_eq!(union.len(), 1); - let union = &union[0]; - - println!("Union of the two polygons: {:?}", union); - - assert_eq!(union.corners.len(), 11); - assert!(union - .corners - .iter() - .find(|&p| p.x == 0. && p.y == 0.) - .is_some()); - } -} |
