aboutsummaryrefslogtreecommitdiff
path: root/src/math/line_segment.rs
diff options
context:
space:
mode:
authorArne Dußin2021-01-06 22:44:08 +0100
committerGitHub2021-01-06 22:44:08 +0100
commit30b23db9e86fdf72a4e7de72213df274ce19123e (patch)
treeb06b5bf6a21e64ff1bfafff90861532e651352d5 /src/math/line_segment.rs
parent0eada0bdcb36a9907c6c928aa707ed6bef03c02f (diff)
parent53d376eaeef991850d35318b147f75c8f103319d (diff)
downloadgraf_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.rs46
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!(