Skip to main content

blockworx/widget/
edge.rs

1use crate::grid::px_point;
2use blockworx_geom::Pos2;
3
4/// `RouteEdge` is a pure data type owned by `presentation`; re-exported here
5/// for the widget layer. Its egui mapping lives in [`RouteEdgeExt`].
6pub use crate::presentation::RouteEdge;
7
8/// Pixel-space helpers for [`RouteEdge`]. Kept out of the data model because
9/// they work in world (egui) coordinates.
10pub trait RouteEdgeExt {
11    /// The distance of `pos` projected onto the segment, paired with the
12    /// perpendicular distance from `pos` to the segment. Both in world
13    /// pixels: this pair never leaves widget-layer geometry math, so
14    /// neither side is worth a named unit.
15    fn distance(&self, pos: Pos2) -> (f32, f32);
16    /// The segment's world-space length.
17    fn length(&self) -> f32;
18}
19
20impl RouteEdgeExt for RouteEdge {
21    fn distance(&self, pos: Pos2) -> (f32, f32) {
22        let start: Pos2 = px_point(self.start);
23        let end: Pos2 = px_point(self.end);
24        let line_vec = end - start;
25        let line_len = line_vec.length();
26        if line_len == 0.0 {
27            return (0.0, (pos - start).length());
28        }
29        let t = ((pos - start).dot(line_vec) / line_len.powi(2)).clamp(0.0, 1.0);
30        let projection = start + line_vec * t;
31        let linear_distance = line_len * t;
32        (linear_distance, (pos - projection).length())
33    }
34    fn length(&self) -> f32 {
35        (px_point(self.end) - px_point(self.start)).length()
36    }
37}