aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArne Dußin2020-11-26 20:52:44 +0100
committerArne Dußin2020-11-26 20:52:44 +0100
commit99e935b63bb023cfd46c8f3d81074d3faf7ce592 (patch)
tree5d9739802114cc30065230ce8d425894ae878a5f
parent19a1221c4bb9df34bb0c14746fc5372d07d1c771 (diff)
parentcf3c8378557457363853d6795e4ddf9e70a4738e (diff)
downloadgraf_karto-99e935b63bb023cfd46c8f3d81074d3faf7ce592.tar.gz
graf_karto-99e935b63bb023cfd46c8f3d81074d3faf7ce592.zip
Merge branch 'polygon-deletion'
-rw-r--r--src/math/mod.rs6
-rw-r--r--src/math/polygon/mod.rs50
-rw-r--r--src/math/rect.rs43
-rw-r--r--src/tool/deletion_tool.rs5
4 files changed, 83 insertions, 21 deletions
diff --git a/src/math/mod.rs b/src/math/mod.rs
index 6f83c98..b84d270 100644
--- a/src/math/mod.rs
+++ b/src/math/mod.rs
@@ -20,6 +20,12 @@ pub trait Surface<T: Scalar + Copy> {
/// Checks if a line segment is entirely contained by this surface.
fn contains_line_segment(&self, line_segment: &LineSegment<T>) -> bool;
+
+ /// Checks if a rectangle is entirely contained inside this surface.
+ fn contains_rect(&self, rect: &Rect<T>) -> bool;
+
+ /// Checks if a polygon is contained wholly by this surface.
+ fn contains_polygon(&self, polygon: &Polygon<T>) -> bool;
}
/// Round a floating point number to the nearest step given by the step argument. For instance, if
diff --git a/src/math/polygon/mod.rs b/src/math/polygon/mod.rs
index ed48751..c9dad91 100644
--- a/src/math/polygon/mod.rs
+++ b/src/math/polygon/mod.rs
@@ -6,7 +6,7 @@ pub mod triangulate;
pub use polygon_graph::*;
pub use triangulate::*;
-use super::{LineSegment, Surface, TripletOrientation, Vec2};
+use super::{LineSegment, Rect, Surface, TripletOrientation, Vec2};
use crate::math;
use nalgebra::{ClosedDiv, ClosedMul, ClosedSub, RealField, Scalar};
use num_traits::Zero;
@@ -361,6 +361,54 @@ impl<
true
}
+
+ fn contains_rect(&self, rect: &Rect<T>) -> bool {
+ /* Turn the rectangle into a vector with its hull line segments. If all hull segments are
+ * contained in the polygon, the rectangle is contained completely.
+ */
+ let hull_edges = [
+ // Top left to bottom left.
+ LineSegment::new(
+ Vec2::new(rect.x, rect.y),
+ Vec2::new(rect.x, rect.y + rect.h),
+ ),
+ // Bottom left to bottom right.
+ LineSegment::new(
+ Vec2::new(rect.x, rect.y + rect.h),
+ Vec2::new(rect.x + rect.w, rect.y + rect.h),
+ ),
+ // Bottom right to top right.
+ LineSegment::new(
+ Vec2::new(rect.x + rect.w, rect.y + rect.h),
+ Vec2::new(rect.x + rect.w, rect.y),
+ ),
+ // Top right to top left.
+ LineSegment::new(
+ Vec2::new(rect.x + rect.w, rect.y),
+ Vec2::new(rect.x, rect.y),
+ ),
+ ];
+
+ hull_edges
+ .iter()
+ .all(|edge| self.contains_line_segment(edge))
+ }
+
+ fn contains_polygon(&self, polygon: &Polygon<T>) -> bool {
+ /* Check for all edges of the polygon that they are contained by the polygon. If they all
+ * are, then the polygon itself must also be contained.
+ */
+ for i in 0..polygon.corners.len() {
+ let next = (i + 1) % polygon.corners.len();
+ if !self
+ .contains_line_segment(&LineSegment::new(polygon.corners[i], polygon.corners[next]))
+ {
+ return false;
+ }
+ }
+
+ true
+ }
}
/* Helper function to calculate the combined angle of a set of points when connecting them one
diff --git a/src/math/rect.rs b/src/math/rect.rs
index 876e728..5f4e5f5 100644
--- a/src/math/rect.rs
+++ b/src/math/rect.rs
@@ -1,9 +1,9 @@
-use super::{LineSegment, Surface, Vec2};
+use super::{LineSegment, Polygon, Surface, Vec2};
//use alga::general::{Additive, Identity};
-use nalgebra::{ClosedAdd, RealField, Scalar};
+use nalgebra::{ClosedAdd, ClosedSub, RealField, Scalar};
use num_traits::identities::Zero;
use serde::{Deserialize, Serialize};
-use std::ops::{Add, AddAssign, Sub};
+use std::ops::{Add, AddAssign};
/// Represents a Rectangle with the value type T.
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize)]
@@ -63,21 +63,6 @@ impl<T: Scalar + Copy> Rect<T> {
|| this.y + this.h < other.y)
}
- /// Returns true if the entire rect is contained inside this rectangle.
- pub fn contains_rect(&self, rect: Rect<T>) -> bool
- where
- T: Add<Output = T> + Sub<Output = T> + PartialOrd + Zero,
- {
- /* True, if the rightmost x-coordinate of the called rectangle is further right or the same
- * as the rightmost coordinate of the given rect.
- */
- let x_exceeds = self.x + self.w - rect.x - rect.w >= T::zero();
- // The same for the y-coordinates
- let y_exceeds = self.y + self.h - rect.y - rect.h >= T::zero();
-
- x_exceeds && y_exceeds && self.x <= rect.x && self.y <= rect.y
- }
-
/// Function to calculate the bounding rectangle that is between two vectors. The order of the
/// vectors is irrelevent for this. As long as they are diagonally opposite of each other, this
/// function will work.
@@ -128,7 +113,7 @@ impl<T: Scalar + Copy> Rect<T> {
}
}
-impl<T: Scalar + Copy + PartialOrd + ClosedAdd> Surface<T> for Rect<T> {
+impl<T: Scalar + Copy + PartialOrd + ClosedAdd + ClosedSub + Zero> Surface<T> for Rect<T> {
fn contains_point(&self, point: &Vec2<T>) -> bool {
point.x >= self.x
&& point.x <= self.x + self.w
@@ -139,6 +124,26 @@ impl<T: Scalar + Copy + PartialOrd + ClosedAdd> Surface<T> for Rect<T> {
fn contains_line_segment(&self, line_segment: &LineSegment<T>) -> bool {
self.contains_point(&line_segment.start) && self.contains_point(&line_segment.end)
}
+
+ fn contains_rect(&self, rect: &Rect<T>) -> bool {
+ /* True, if the rightmost x-coordinate of the called rectangle is further right or the same
+ * as the rightmost coordinate of the given rect.
+ */
+ let x_exceeds = self.x + self.w - rect.x - rect.w >= T::zero();
+ // The same for the y-coordinates
+ let y_exceeds = self.y + self.h - rect.y - rect.h >= T::zero();
+
+ x_exceeds && y_exceeds && self.x <= rect.x && self.y <= rect.y
+ }
+
+ fn contains_polygon(&self, polygon: &Polygon<T>) -> bool {
+ // Check if all vertices of the polygon lie inside the rectangle. If so, the polygon must
+ // be contained in its entirety.
+ polygon
+ .corners()
+ .iter()
+ .all(|&corner| self.contains_point(&corner))
+ }
}
// This is sad, but also sadly necessary :/
diff --git a/src/tool/deletion_tool.rs b/src/tool/deletion_tool.rs
index 5031f5d..17dd949 100644
--- a/src/tool/deletion_tool.rs
+++ b/src/tool/deletion_tool.rs
@@ -25,13 +25,16 @@ impl DeletionTool {
pub fn delete_rect(map_data: &mut MapData, rect: Rect<f32>) {
map_data
.rooms_mut()
- .retain(|&room| !rect.contains_rect(room));
+ .retain(|&room| !rect.contains_rect(&room));
map_data
.walls_mut()
.retain(|&(pos1, pos2)| !rect.contains_point(&pos1) || !rect.contains_point(&pos2));
map_data
.icons_mut()
.retain(|icon| !rect.contains_point(&icon.position));
+ map_data
+ .polygons_mut()
+ .retain(|polygon| !rect.contains_polygon(&polygon));
}
}