LCOV - code coverage report
Current view: top level - dashql-dataflow/src/ortho_router - geom.rs Coverage Total Hit
Test: DashQL 915828b Lines: 83.1 % 71 59
Test Date: 2026-11-06 19:30:32

            Line data    Source code
       1              : //! Plain geometry: points, rectangles and the four sides.
       2              : 
       3              : /// Coordinates closer than this are the same line (in the caller's
       4              : /// units, typically pixels or points).
       5              : pub(crate) const EPS: f32 = 1e-3;
       6              : 
       7              : /// A point.
       8              : #[derive(Clone, Copy, Debug, Default, PartialEq)]
       9              : pub struct Point {
      10              :     /// The abscissa.
      11              :     pub x: f32,
      12              :     /// The ordinate.
      13              :     pub y: f32,
      14              : }
      15              : 
      16              : impl Point {
      17              :     /// A point at `x`, `y`.
      18        17063 :     pub const fn new(x: f32, y: f32) -> Point {
      19        17063 :         Point { x, y }
      20        17063 :     }
      21              : 
      22              :     /// Whether both coordinates are finite.
      23          687 :     pub fn is_finite(self) -> bool {
      24          687 :         self.x.is_finite() && self.y.is_finite()
      25          687 :     }
      26              : 
      27              :     /// The point moved `d` along a side's outward direction.
      28          438 :     pub(crate) fn toward(self, side: Side, d: f32) -> Point {
      29          438 :         let (dx, dy) = side.direction();
      30          438 :         Point::new(self.x + dx * d, self.y + dy * d)
      31          438 :     }
      32              : 
      33              :     /// Whether two points are the same within [`EPS`].
      34          897 :     pub(crate) fn near(self, other: Point) -> bool {
      35          897 :         (self.x - other.x).abs() <= EPS && (self.y - other.y).abs() <= EPS
      36          897 :     }
      37              : }
      38              : 
      39              : impl From<[f32; 2]> for Point {
      40          248 :     fn from([x, y]: [f32; 2]) -> Point {
      41          248 :         Point::new(x, y)
      42          248 :     }
      43              : }
      44              : 
      45              : impl From<(f32, f32)> for Point {
      46            0 :     fn from((x, y): (f32, f32)) -> Point {
      47            0 :         Point::new(x, y)
      48            0 :     }
      49              : }
      50              : 
      51              : impl From<Point> for [f32; 2] {
      52            0 :     fn from(p: Point) -> [f32; 2] {
      53            0 :         [p.x, p.y]
      54            0 :     }
      55              : }
      56              : 
      57              : /// An axis-aligned rectangle, from its smallest to its largest corner.
      58              : #[derive(Clone, Copy, Debug, Default, PartialEq)]
      59              : pub struct Rect {
      60              :     /// The corner with the smallest coordinates.
      61              :     pub min: Point,
      62              :     /// The corner with the largest coordinates.
      63              :     pub max: Point,
      64              : }
      65              : 
      66              : impl Rect {
      67              :     /// The rectangle between two corners, in any order.
      68           92 :     pub fn from_corners(a: impl Into<Point>, b: impl Into<Point>) -> Rect {
      69           92 :         let (a, b) = (a.into(), b.into());
      70           92 :         Rect {
      71           92 :             min: Point::new(a.x.min(b.x), a.y.min(b.y)),
      72           92 :             max: Point::new(a.x.max(b.x), a.y.max(b.y)),
      73           92 :         }
      74           92 :     }
      75              : 
      76              :     /// The rectangle at `min` of this width and height.
      77           91 :     pub fn from_min_size(min: impl Into<Point>, width: f32, height: f32) -> Rect {
      78           91 :         let min = min.into();
      79           91 :         Rect::from_corners(min, Point::new(min.x + width, min.y + height))
      80           91 :     }
      81              : 
      82              :     /// Its width.
      83            0 :     pub fn width(&self) -> f32 {
      84            0 :         self.max.x - self.min.x
      85            0 :     }
      86              : 
      87              :     /// Its height.
      88            0 :     pub fn height(&self) -> f32 {
      89            0 :         self.max.y - self.min.y
      90            0 :     }
      91              : 
      92              :     /// Whether its corners are finite and in order.
      93          124 :     pub fn is_valid(&self) -> bool {
      94          124 :         self.min.is_finite()
      95          124 :             && self.max.is_finite()
      96          123 :             && self.min.x <= self.max.x
      97          123 :             && self.min.y <= self.max.y
      98          124 :     }
      99              : 
     100              :     /// The rectangle grown by `d` on every side.
     101          155 :     pub fn expand(&self, d: f32) -> Rect {
     102          155 :         Rect {
     103          155 :             min: Point::new(self.min.x - d, self.min.y - d),
     104          155 :             max: Point::new(self.max.x + d, self.max.y + d),
     105          155 :         }
     106          155 :     }
     107              : }
     108              : 
     109              : /// The side of a node a port leaves from: a connector's first segment
     110              : /// goes out that way, and its last segment comes in from that way.
     111              : ///
     112              : /// `Top` is toward smaller `y` and `Bottom` toward larger `y`, as on a
     113              : /// screen where `y` grows downward; with `y` growing upward, swap them.
     114              : #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
     115              : pub enum Side {
     116              :     /// Toward smaller `x`.
     117              :     Left,
     118              :     /// Toward larger `x`.
     119              :     Right,
     120              :     /// Toward smaller `y`.
     121              :     Top,
     122              :     /// Toward larger `y`.
     123              :     Bottom,
     124              : }
     125              : 
     126              : impl Side {
     127              :     /// The unit vector pointing out of the node.
     128          438 :     pub fn direction(self) -> (f32, f32) {
     129          438 :         match self {
     130          217 :             Side::Left => (-1.0, 0.0),
     131          217 :             Side::Right => (1.0, 0.0),
     132            2 :             Side::Top => (0.0, -1.0),
     133            2 :             Side::Bottom => (0.0, 1.0),
     134              :         }
     135          438 :     }
     136              : 
     137              :     /// The opposite side.
     138         5272 :     pub fn opposite(self) -> Side {
     139         5272 :         match self {
     140          163 :             Side::Left => Side::Right,
     141          840 :             Side::Right => Side::Left,
     142         2141 :             Side::Top => Side::Bottom,
     143         2128 :             Side::Bottom => Side::Top,
     144              :         }
     145         5272 :     }
     146              : 
     147              :     /// Whether a segment leaving this side is horizontal.
     148            1 :     pub fn is_horizontal(self) -> bool {
     149            1 :         matches!(self, Side::Left | Side::Right)
     150            1 :     }
     151              : 
     152              :     /// Its index as a search direction (0 to 3).
     153         3538 :     pub(crate) fn index(self) -> usize {
     154         3538 :         self as usize
     155         3538 :     }
     156              : 
     157              :     pub(crate) const ALL: [Side; 4] = [Side::Left, Side::Right, Side::Top, Side::Bottom];
     158              : }
        

Generated by: LCOV version 2.0-1