makepad_vector/geometry/
line_segment.rs

1use crate::geometry::{F64Ext, Point, Transform, Transformation};
2use std::cmp::Ordering;
3
4/// A quadratic bezier curve segment in 2-dimensional Euclidian space.
5#[derive(Clone, Copy, Debug, PartialEq)]
6#[repr(C)]
7pub struct LineSegment {
8    pub p0: Point,
9    pub p1: Point,
10}
11
12impl LineSegment {
13    /// Creates a new line segment with the given endpoints.
14    pub fn new(p0: Point, p1: Point) -> LineSegment {
15        LineSegment { p0, p1 }
16    }
17
18    /// Compares `self` to the point `p`.
19    ///
20    /// Returns `Ordering::Less` if `self` lies below `p`, `Ordering::Greater` if `self` lies
21    /// above `p`, and `Ordering::Equal` if `self` is incident to `p`.
22    pub fn compare_to_point(self, p: Point) -> Option<Ordering> {
23        // Compute the signed area of the triangle with vertices `p`, `p0`, and `p1`.
24        (p - self.p0).cross(self.p1 - p).partial_cmp(&0.0)
25    }
26
27    /// Returns the intersection point of the supporting line of `self` with the vertical line
28    /// through `x`, or None if these lines are coincident.
29    pub fn intersect_with_vertical_line(self, x: f64) -> Option<Point> {
30        let dx = self.p1.x - self.p0.x;
31        if dx == 0.0 {
32            return None;
33        }
34        let dx1 = x - self.p0.x;
35        let dx2 = self.p1.x - x;
36        Some(Point {
37            x,
38            y: if dx1 <= dx2 {
39                self.p0.y.ext_lerp(self.p1.y, dx1 / dx)
40            } else {
41                self.p1.y.ext_lerp(self.p0.y, dx2 / dx)
42            },
43        })
44    }
45}
46
47impl Transform for LineSegment {
48    fn transform<T>(self, t: &T) -> LineSegment
49    where
50        T: Transformation,
51    {
52        LineSegment::new(self.p0.transform(t), self.p1.transform(t))
53    }
54
55    fn transform_mut<T>(&mut self, t: &T)
56    where
57        T: Transformation,
58    {
59        *self = self.transform(t);
60    }
61}