diff options
| author | Arne Dußin | 2020-11-15 20:38:14 +0100 |
|---|---|---|
| committer | Arne Dußin | 2020-11-15 20:38:14 +0100 |
| commit | 63f292010e51ad8622cccc4d4b6da887e4eaec47 (patch) | |
| tree | c36193c4f60f5b04b6363e5713b63d423fafed77 /src/math/line_segment.rs | |
| parent | 8ae528e9a2b219c5ac2f0b967c0cb91e79921e21 (diff) | |
| download | graf_karto-63f292010e51ad8622cccc4d4b6da887e4eaec47.tar.gz graf_karto-63f292010e51ad8622cccc4d4b6da887e4eaec47.zip | |
Add intersection point algorithm
Diffstat (limited to 'src/math/line_segment.rs')
| -rw-r--r-- | src/math/line_segment.rs | 43 |
1 files changed, 40 insertions, 3 deletions
diff --git a/src/math/line_segment.rs b/src/math/line_segment.rs index 338a681..7dacf54 100644 --- a/src/math/line_segment.rs +++ b/src/math/line_segment.rs @@ -1,6 +1,6 @@ -use super::Vec2; -use alga::general::{ClosedMul, ClosedSub}; -use nalgebra::Scalar; +use super::{Rect, Vec2}; +use alga::general::{ClosedDiv, ClosedMul, ClosedSub}; +use nalgebra::{RealField, Scalar}; use num_traits::Zero; #[derive(Debug)] @@ -89,6 +89,43 @@ impl<T: Scalar + Copy> LineSegment<T> { false } + + pub fn intersection(line_a: &LineSegment<T>, line_b: &LineSegment<T>) -> Option<Vec2<T>> + where + T: ClosedSub + ClosedMul + ClosedDiv + Zero + RealField, + { + // Calculate the differences of each line value from starting point to end point + // coordinate. + let dax = line_a.end.x - line_a.start.x; + let dbx = line_b.end.x - line_b.start.x; + let day = line_a.end.y - line_a.start.y; + let dby = line_b.end.y - line_b.start.y; + + // Calculate determinant to see, if the lines are parallel or not + // TODO: Collinearity check? + let d = (dax * dby) - (day * dbx); + if d == T::zero() { + None + } else { + let ad = (line_a.start.x * line_a.end.y) - (line_a.start.y * line_a.end.x); + let bd = (line_b.start.x * line_b.end.y) - (line_b.start.y * line_b.end.x); + + let out = Vec2::new(((ad * dbx) - (dax * bd)) / d, ((ad * dby) - (day * bd)) / d); + + /* Since the line intersection, not the line segment intersection is calculated, a + * bounding check is necessary, to see if the intersection still lies inside both of + * the segments. We know it's on the lines, so checking with the lines bounding box is + * faster than checking where on the line exactly it would be. + */ + if Rect::bounding_rect(line_a.start, line_a.end).contains(out) + && Rect::bounding_rect(line_b.start, line_b.end).contains(out) + { + Some(out) + } else { + None + } + } + } } #[derive(PartialEq, Eq)] |
