flo_curves/bezier/path/graph_path/
edge.rs

1use super::{GraphPath, GraphEdgeRef, GraphEdge, GraphPathEdge, GraphPathEdgeKind};
2use crate::bezier::curve::*;
3use crate::bezier::bounds::*;
4use crate::geo::*;
5
6use std::fmt;
7use std::cell::*;
8
9impl<Point: Coordinate, Label> GraphPathEdge<Point, Label> {
10    ///
11    /// Creates a new graph path edge
12    /// 
13    #[inline]
14    pub (crate) fn new(kind: GraphPathEdgeKind, (cp1, cp2): (Point, Point), end_idx: usize, label: Label, following_edge_idx: usize) -> GraphPathEdge<Point, Label> {
15        GraphPathEdge {
16            label, kind, cp1, cp2, end_idx, following_edge_idx, bbox: RefCell::new(None)
17        }
18    }
19
20    ///
21    /// Invalidates the cache for this edge
22    ///
23    #[inline]
24    pub (crate) fn invalidate_cache(&self) {
25        (*self.bbox.borrow_mut()) = None;
26    }
27}
28
29impl<'a, Point: 'a, Label: 'a+Copy> GraphEdge<'a, Point, Label> {
30    ///
31    /// Creates a new graph edge (with an edge kind of 'exterior')
32    /// 
33    #[inline]
34    pub (crate) fn new(graph: &'a GraphPath<Point, Label>, edge: GraphEdgeRef) -> GraphEdge<'a, Point, Label> {
35        test_assert!(edge.start_idx < graph.points.len());
36        test_assert!(edge.edge_idx < graph.points[edge.start_idx].forward_edges.len());
37
38        GraphEdge {
39            graph:  graph,
40            edge:   edge
41        }
42    }
43
44    ///
45    /// Returns true if this edge is going backwards around the path
46    ///
47    #[inline]
48    pub fn is_reversed(&self) -> bool {
49        self.edge.reverse
50    }
51
52    ///
53    /// Retrieves a reference to the edge in the graph
54    ///
55    #[inline]
56    fn edge(&self) -> &GraphPathEdge<Point, Label> {
57        &self.graph.points[self.edge.start_idx].forward_edges[self.edge.edge_idx]
58    }
59
60    ///
61    /// Returns if this is an interior or an exterior edge in the path
62    /// 
63    pub fn kind(&self) -> GraphPathEdgeKind {
64        self.edge().kind
65    }
66
67    ///
68    /// Returns the index of the start point of this edge
69    /// 
70    #[inline]
71    pub fn start_point_index(&self) -> usize {
72        if self.edge.reverse {
73            self.edge().end_idx
74        } else {
75            self.edge.start_idx
76        }
77    }
78
79    ///
80    /// Returns the index of the end point of this edge
81    /// 
82    #[inline]
83    pub fn end_point_index(&self) -> usize {
84        if self.edge.reverse {
85            self.edge.start_idx
86        } else {
87            self.edge().end_idx
88        }
89    }
90
91    ///
92    /// The label attached to this edge
93    ///
94    #[inline]
95    pub fn label(&self) -> Label {
96        self.edge().label
97    }
98}
99
100impl<'a, Point: 'a+Coordinate, Label: 'a> Geo for GraphEdge<'a, Point, Label> {
101    type Point = Point;
102}
103
104impl<'a, Point: 'a+Coordinate, Label: 'a+Copy> BezierCurve for GraphEdge<'a, Point, Label> {
105    ///
106    /// The start point of this curve
107    /// 
108    #[inline]
109    fn start_point(&self) -> Self::Point {
110        self.graph.points[self.start_point_index()].position
111    }
112
113    ///
114    /// The end point of this curve
115    /// 
116    #[inline]
117    fn end_point(&self) -> Self::Point {
118        self.graph.points[self.end_point_index()].position
119    }
120
121    ///
122    /// The control points in this curve
123    /// 
124    #[inline]
125    fn control_points(&self) -> (Self::Point, Self::Point) {
126        let edge = self.edge();
127
128        if self.edge.reverse {
129            (edge.cp2, edge.cp1)
130        } else {
131            (edge.cp1, edge.cp2)
132        }
133    }
134    
135    ///
136    /// Faster but less accurate bounding box for a curve
137    /// 
138    /// This will produce a bounding box that contains the curve but which may be larger than necessary
139    /// 
140    #[inline]
141    fn fast_bounding_box<Bounds: BoundingBox<Point=Self::Point>>(&self) -> Bounds {
142        let edge                = self.edge();
143
144        let mut bbox            = edge.bbox.borrow_mut();
145
146        if let Some((ref min, ref max)) = *bbox {
147            Bounds::from_min_max(*min, *max)
148        } else {
149            let start           = self.graph.points[self.edge.start_idx].position;
150            let end             = self.graph.points[edge.end_idx].position;
151            let control_points  = (edge.cp1, edge.cp2);
152
153            let min             = Self::Point::from_smallest_components(start, end);
154            let min             = Self::Point::from_smallest_components(min, control_points.0);
155            let min             = Self::Point::from_smallest_components(min, control_points.1);
156
157            let max             = Self::Point::from_biggest_components(start, end);
158            let max             = Self::Point::from_biggest_components(max, control_points.0);
159            let max             = Self::Point::from_biggest_components(max, control_points.1);
160
161            let bounds          = Bounds::from_min_max(min, max);
162
163            *bbox = Some((bounds.min(), bounds.max()));
164            bounds
165        }
166    }
167
168    ///
169    /// Computes the bounds of this bezier curve
170    /// 
171    #[inline]
172    fn bounding_box<Bounds: BoundingBox<Point=Self::Point>>(&self) -> Bounds {
173        let edge        = self.edge();
174
175        let start       = self.graph.points[self.edge.start_idx].position;
176        let end         = self.graph.points[edge.end_idx].position;
177        let (cp1, cp2)  = (edge.cp1, edge.cp2);
178
179        let bounds: Bounds = bounding_box4(start, cp1, cp2, end);
180
181        bounds
182    }
183}
184
185impl<'a, Point: 'a+Coordinate, Label: 'a+Copy> HasBoundingBox for GraphEdge<'a, Point, Label> {
186    #[inline]
187    fn get_bounding_box<Bounds: BoundingBox<Point=Self::Point>>(&self) -> Bounds {
188        self.fast_bounding_box()
189    }
190}
191
192impl<'a, Point: fmt::Debug, Label: 'a+Copy> fmt::Debug for GraphEdge<'a, Point, Label> {
193    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
194        write!(f, "{:?}: {:?} -> {:?} ({:?} -> {:?} ({:?}, {:?}))", self.kind(), self.edge.start_idx, self.edge().end_idx, self.graph.points[self.edge.start_idx].position, self.graph.points[self.edge().end_idx].position, self.edge().cp1, self.edge().cp2)
195    }
196}