Skip to main content

graphviz_pure_core/
geom.rs

1use crate::math;
2use serde::{Deserialize, Serialize};
3
4/// 2D point in Graphviz points (72 points = 1 inch).
5#[derive(Debug, Clone, Copy, PartialEq, Default, Serialize, Deserialize)]
6pub struct Point {
7    pub x: f64,
8    pub y: f64,
9}
10
11impl Point {
12    #[inline]
13    pub const fn new(x: f64, y: f64) -> Self {
14        Self { x, y }
15    }
16
17    #[inline]
18    pub fn dist(self, other: Self) -> f64 {
19        math::hypot(self.x - other.x, self.y - other.y)
20    }
21
22    /// Safe vector normalization avoiding `NaN` on zero-length vectors (Fixes GV-BUG-006).
23    #[inline]
24    pub fn normalized_or_zero(self) -> Self {
25        let len = math::hypot(self.x, self.y);
26        if len <= 1e-12 {
27            Self::new(0.0, 0.0)
28        } else {
29            Self::new(self.x / len, self.y / len)
30        }
31    }
32}
33
34/// Axis-aligned 2D bounding box `(ll, ur)`.
35#[derive(Debug, Clone, Copy, PartialEq, Default, Serialize, Deserialize)]
36pub struct BoundingBox {
37    pub ll: Point,
38    pub ur: Point,
39}
40
41impl BoundingBox {
42    #[inline]
43    pub const fn new(llx: f64, lly: f64, urx: f64, ury: f64) -> Self {
44        Self {
45            ll: Point::new(llx, lly),
46            ur: Point::new(urx, ury),
47        }
48    }
49
50    #[inline]
51    pub fn width(&self) -> f64 {
52        (self.ur.x - self.ll.x).max(0.0)
53    }
54
55    #[inline]
56    pub fn height(&self) -> f64 {
57        (self.ur.y - self.ll.y).max(0.0)
58    }
59
60    #[inline]
61    pub fn expand_to_include(&mut self, pt: Point) {
62        if pt.x < self.ll.x {
63            self.ll.x = pt.x;
64        }
65        if pt.y < self.ll.y {
66            self.ll.y = pt.y;
67        }
68        if pt.x > self.ur.x {
69            self.ur.x = pt.x;
70        }
71        if pt.y > self.ur.y {
72            self.ur.y = pt.y;
73        }
74    }
75}
76
77/// Cubic Bezier spline chain representing a routed edge.
78#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
79pub struct BezierSegment {
80    /// Control points: `3n + 1` points for `n` cubic Bezier segments.
81    pub points: Vec<Point>,
82    pub start_arrow: Option<Point>,
83    pub end_arrow: Option<Point>,
84}
85
86#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
87pub struct Spline {
88    pub segments: Vec<BezierSegment>,
89}