1 //! Draw Line
2 
3 use {types, triangulation, DrawState, Graphics};
4 use types::{Color, Radius};
5 use math::{Matrix2d, Scalar};
6 
7 /// The shape of the line
8 #[derive(Copy, Clone)]
9 pub enum Shape {
10     /// Square edges
11     Square,
12     /// Round edges
13     Round,
14     /// Bevel edges
15     Bevel,
16 }
17 
18 /// A colored line with a default border radius
19 #[derive(Copy, Clone)]
20 pub struct Line {
21     /// The line color
22     pub color: Color,
23     /// The line radius
24     pub radius: Radius,
25     /// The line shape
26     pub shape: Shape,
27 }
28 
29 impl Line {
30     /// Creates a new line
new(color: Color, radius: Radius) -> Line31     pub fn new(color: Color, radius: Radius) -> Line {
32         Line {
33             color: color,
34             radius: radius,
35             shape: Shape::Square,
36         }
37     }
38 
39     /// Creates a new line
new_round(color: Color, radius: Radius) -> Line40     pub fn new_round(color: Color, radius: Radius) -> Line {
41         Line {
42             color: color,
43             radius: radius,
44             shape: Shape::Round,
45         }
46     }
47 
48     /// Sets color.
color(mut self, value: Color) -> Self49     pub fn color(mut self, value: Color) -> Self {
50         self.color = value;
51         self
52     }
53 
54     /// Sets radius.
radius(mut self, value: Radius) -> Self55     pub fn radius(mut self, value: Radius) -> Self {
56         self.radius = value;
57         self
58     }
59 
60     /// Sets width.
width(mut self, value: types::Width) -> Self61     pub fn width(mut self, value: types::Width) -> Self {
62         self.radius = 0.5 * value;
63         self
64     }
65 
66     /// Sets shape.
shape(mut self, value: Shape) -> Self67     pub fn shape(mut self, value: Shape) -> Self {
68         self.shape = value;
69         self
70     }
71 
72     /// Draws line using default method between points.
73     #[inline(always)]
draw_from_to<P: Into<types::Vec2d>, G>(&self, from: P, to: P, draw_state: &DrawState, transform: Matrix2d, g: &mut G) where G: Graphics74     pub fn draw_from_to<P: Into<types::Vec2d>, G>(&self,
75                                          from: P,
76                                          to: P,
77                                          draw_state: &DrawState,
78                                          transform: Matrix2d,
79                                          g: &mut G)
80         where G: Graphics
81     {
82         let from: types::Vec2d = from.into();
83         let to: types::Vec2d = to.into();
84         g.line(self, [from[0], from[1], to[0], to[1]], draw_state, transform);
85     }
86 
87     /// Draws line using default method.
88     #[inline(always)]
draw<L: Into<types::Line>, G>(&self, line: L, draw_state: &DrawState, transform: Matrix2d, g: &mut G) where G: Graphics89     pub fn draw<L: Into<types::Line>, G>(&self,
90                                          line: L,
91                                          draw_state: &DrawState,
92                                          transform: Matrix2d,
93                                          g: &mut G)
94         where G: Graphics
95     {
96         g.line(self, line, draw_state, transform);
97     }
98 
99     /// Draws line using triangulation.
draw_tri<L: Into<types::Line>, G>(&self, line: L, draw_state: &DrawState, transform: Matrix2d, g: &mut G) where G: Graphics100     pub fn draw_tri<L: Into<types::Line>, G>(&self,
101                                              line: L,
102                                              draw_state: &DrawState,
103                                              transform: Matrix2d,
104                                              g: &mut G)
105         where G: Graphics
106     {
107         let line = line.into();
108         match self.shape {
109             Shape::Square => {
110                 g.tri_list(draw_state, &self.color, |f| {
111                     triangulation::with_round_border_line_tri_list(2,
112                                                                    transform,
113                                                                    line,
114                                                                    self.radius,
115                                                                    |vertices| f(vertices))
116                 });
117             }
118             Shape::Round => {
119                 g.tri_list(draw_state, &self.color, |f| {
120                     triangulation::with_round_border_line_tri_list(64,
121                                                                    transform,
122                                                                    line,
123                                                                    self.radius,
124                                                                    |vertices| f(vertices))
125                 });
126             }
127             Shape::Bevel => {
128                 g.tri_list(draw_state, &self.color, |f| {
129                     triangulation::with_round_border_line_tri_list(3,
130                                                                    transform,
131                                                                    line,
132                                                                    self.radius,
133                                                                    |vertices| f(vertices))
134                 });
135             }
136         }
137     }
138 
139     /// Draws an arrow
140     ///
141     /// Head size is the sides of the triangle
142     /// between the arrow hooks and the line
draw_arrow<L: Into<types::Line>, G>(&self, line: L, head_size: Scalar, draw_state: &DrawState, transform: Matrix2d, g: &mut G) where G: Graphics143     pub fn draw_arrow<L: Into<types::Line>, G>(&self,
144                                                line: L,
145                                                head_size: Scalar,
146                                                draw_state: &DrawState,
147                                                transform: Matrix2d,
148                                                g: &mut G)
149         where G: Graphics
150     {
151         use Transformed;
152 
153         let line = line.into();
154         self.draw(line, draw_state, transform, g);
155         let diff = [line[2] - line[0], line[3] - line[1]];
156         let arrow_head = transform.trans(line[2], line[3])
157             .orient(diff[0], diff[1]);
158         self.draw([-head_size, head_size, 0.0, 0.0], draw_state, arrow_head, g);
159         self.draw([-head_size, -head_size, 0.0, 0.0],
160                   draw_state,
161                   arrow_head,
162                   g);
163     }
164 }
165 
166 #[cfg(test)]
167 mod test {
168     use super::*;
169 
170     #[test]
test_line()171     fn test_line() {
172         use Colored;
173 
174         let _line = Line::new([0.0; 4], 3.0)
175             .color([1.0; 4])
176             .radius(3.0)
177             .shape(Shape::Round)
178             .hue_deg(1.0);
179     }
180 }
181