diff options
| author | Arne Dußin | 2021-01-06 22:44:08 +0100 |
|---|---|---|
| committer | GitHub | 2021-01-06 22:44:08 +0100 |
| commit | 30b23db9e86fdf72a4e7de72213df274ce19123e (patch) | |
| tree | b06b5bf6a21e64ff1bfafff90861532e651352d5 /src/math/line_segment.rs | |
| parent | 0eada0bdcb36a9907c6c928aa707ed6bef03c02f (diff) | |
| parent | 53d376eaeef991850d35318b147f75c8f103319d (diff) | |
| download | graf_karto-30b23db9e86fdf72a4e7de72213df274ce19123e.tar.gz graf_karto-30b23db9e86fdf72a4e7de72213df274ce19123e.zip | |
Merge pull request #25 from LordSentox/better-polygons
Change to polygongraph instead of polygon in roomtool
Diffstat (limited to 'src/math/line_segment.rs')
| -rw-r--r-- | src/math/line_segment.rs | 46 |
1 files changed, 29 insertions, 17 deletions
diff --git a/src/math/line_segment.rs b/src/math/line_segment.rs index 204cf0c..738f56a 100644 --- a/src/math/line_segment.rs +++ b/src/math/line_segment.rs @@ -1,8 +1,9 @@ //! A line segment is like a line, but with a start and an end, with the line only being between //! those two. -use super::{Rect, Surface, TripletOrientation, Vec2}; +use super::{ExactSurface, Rect, TripletOrientation, Vec2}; use alga::general::{ClosedDiv, ClosedMul, ClosedSub}; +use float_cmp::ApproxEq; use nalgebra::{RealField, Scalar}; use num_traits::Zero; use serde::{Deserialize, Serialize}; @@ -37,9 +38,9 @@ impl<T: Scalar + Copy> LineSegment<T> { /// Checks if two segments intersect. This is much more efficient than trying to find the exact /// point of intersection, so it should be used if it is not strictly necessary to know it. - pub fn intersect(ls1: &LineSegment<T>, ls2: &LineSegment<T>) -> bool + pub fn intersect<M: Copy>(ls1: &LineSegment<T>, ls2: &LineSegment<T>, margin: M) -> bool where - T: Scalar + Copy + ClosedSub + ClosedMul + PartialOrd + Zero, + T: Scalar + Copy + ClosedSub + ClosedMul + PartialOrd + Zero + ApproxEq<Margin = M>, { /* This algorithm works by checking the triplet orientation of the first lines points with the * first point of the second line. After that it does the same for the second point of the @@ -56,10 +57,14 @@ impl<T: Scalar + Copy> LineSegment<T> { */ // Cache the necessary orientations. - let ls1_ls2start_orientation = super::triplet_orientation(ls1.start, ls1.end, ls2.start); - let ls1_ls2end_orientation = super::triplet_orientation(ls1.start, ls1.end, ls2.end); - let ls2_ls1start_orientation = super::triplet_orientation(ls2.start, ls2.end, ls1.start); - let ls2_ls1end_orientation = super::triplet_orientation(ls2.start, ls2.end, ls1.end); + let ls1_ls2start_orientation = + super::triplet_orientation(ls1.start, ls1.end, ls2.start, margin); + let ls1_ls2end_orientation = + super::triplet_orientation(ls1.start, ls1.end, ls2.end, margin); + let ls2_ls1start_orientation = + super::triplet_orientation(ls2.start, ls2.end, ls1.start, margin); + let ls2_ls1end_orientation = + super::triplet_orientation(ls2.start, ls2.end, ls1.end, margin); // Check for the first case that wase described (general case). if ls1_ls2start_orientation != ls1_ls2end_orientation @@ -100,9 +105,14 @@ impl<T: Scalar + Copy> LineSegment<T> { /// Try to find the the point where the two line segments intersect. If they do not intersect, /// `None` is returned. If the lines are parallel and intersect (at least part of a line is on /// a part of the other line), inside that region is returned. - pub fn intersection(line_a: &LineSegment<T>, line_b: &LineSegment<T>) -> Option<Vec2<T>> + pub fn intersection<M>( + line_a: &LineSegment<T>, + line_b: &LineSegment<T>, + margin: M, + ) -> Option<Vec2<T>> where - T: ClosedSub + ClosedMul + ClosedDiv + Zero + RealField, + T: ClosedSub + ClosedMul + ClosedDiv + Zero + RealField + ApproxEq<Margin = M>, + M: Copy, { // Calculate the differences of each line value from starting point to end point // coordinate. @@ -115,8 +125,10 @@ impl<T: Scalar + Copy> LineSegment<T> { let d = (dax * dby) - (day * dbx); if d == T::zero() { // The two line segments are parallel, check if one may be on the other. - if super::triplet_orientation(line_a.start, line_a.end, line_b.start) == TripletOrientation::Collinear - && super::triplet_orientation(line_a.start, line_a.end, line_b.end) == TripletOrientation::Collinear + if super::triplet_orientation(line_a.start, line_a.end, line_b.start, margin) + == TripletOrientation::Collinear + && super::triplet_orientation(line_a.start, line_a.end, line_b.end, margin) + == TripletOrientation::Collinear { if line_a.contains_collinear(line_b.start) { Some(line_b.start) @@ -156,16 +168,16 @@ impl<T: Scalar + Copy> LineSegment<T> { /// Find all segments, into which this LineSegment would be splitted, when the points provided /// would cut the segment. The points must be on the line, otherwise this does not make sense. /// Also, no segments of length zero (start point = end point) will be created. - pub fn segments(&self, split_points: &[Vec2<T>]) -> Vec<Vec2<T>> + pub fn segments<M>(&self, split_points: &[Vec2<T>], margin: M) -> Vec<Vec2<T>> where - T: ClosedSub + ClosedMul + PartialOrd + Zero, + T: ClosedSub + ClosedMul + PartialOrd + Zero + ApproxEq<Margin = M>, + M: Copy, { // Make sure all segments are collinear with the segment and actually on it assert_eq!( - split_points - .iter() - .find(|&p| super::triplet_orientation(self.start, self.end, *p) - != TripletOrientation::Collinear), + split_points.iter().find(|&p| super::triplet_orientation( + self.start, self.end, *p, margin + ) != TripletOrientation::Collinear), None ); assert_eq!( |
