1use crate::{
4 math::{Matrix2d, Scalar},
5 triangulation, types,
6 types::{Color, Radius, Resolution},
7 DrawState, Graphics,
8};
9
10#[derive(Copy, Clone)]
12pub enum Shape {
13 Square,
15 Round,
17 RoundWithResolution(Resolution),
19 Bevel,
21}
22
23impl Shape {
24 fn resolution(&self) -> u32 {
26 use Shape::*;
27
28 match self {
29 Square => 2,
30 Bevel => 3,
31 Round => 64,
32 RoundWithResolution(n) => *n,
33 }
34 }
35}
36
37#[derive(Copy, Clone)]
39pub struct Line {
40 pub color: Color,
42 pub radius: Radius,
44 pub shape: Shape,
46}
47
48impl Line {
49 pub fn new(color: Color, radius: Radius) -> Line {
51 Line {
52 color,
53 radius,
54 shape: Shape::Square,
55 }
56 }
57
58 pub fn new_round(color: Color, radius: Radius) -> Line {
60 Line {
61 color,
62 radius,
63 shape: Shape::Round,
64 }
65 }
66
67 pub fn color(mut self, value: Color) -> Self {
69 self.color = value;
70 self
71 }
72
73 pub fn radius(mut self, value: Radius) -> Self {
75 self.radius = value;
76 self
77 }
78
79 pub fn width(mut self, value: types::Width) -> Self {
81 self.radius = 0.5 * value;
82 self
83 }
84
85 pub fn shape(mut self, value: Shape) -> Self {
87 self.shape = value;
88 self
89 }
90
91 #[inline(always)]
93 pub fn draw_from_to<P: Into<types::Vec2d>, G>(
94 &self,
95 from: P,
96 to: P,
97 draw_state: &DrawState,
98 transform: Matrix2d,
99 g: &mut G,
100 ) where
101 G: Graphics,
102 {
103 let from: types::Vec2d = from.into();
104 let to: types::Vec2d = to.into();
105 g.line(
106 self,
107 [from[0], from[1], to[0], to[1]],
108 draw_state,
109 transform,
110 );
111 }
112
113 #[inline(always)]
115 pub fn draw<L: Into<types::Line>, G>(
116 &self,
117 line: L,
118 draw_state: &DrawState,
119 transform: Matrix2d,
120 g: &mut G,
121 ) where
122 G: Graphics,
123 {
124 g.line(self, line, draw_state, transform);
125 }
126
127 pub fn draw_tri<L: Into<types::Line>, G>(
129 &self,
130 line: L,
131 draw_state: &DrawState,
132 transform: Matrix2d,
133 g: &mut G,
134 ) where
135 G: Graphics,
136 {
137 let line = line.into();
138 g.tri_list(draw_state, &self.color, |f| {
139 triangulation::with_round_border_line_tri_list(
140 self.shape.resolution(),
141 transform,
142 line,
143 self.radius,
144 |vertices| f(vertices),
145 )
146 });
147 }
148
149 pub fn draw_arrow<L: Into<types::Line>, G>(
154 &self,
155 line: L,
156 head_size: Scalar,
157 draw_state: &DrawState,
158 transform: Matrix2d,
159 g: &mut G,
160 ) where
161 G: Graphics,
162 {
163 use crate::Transformed;
164
165 let line = line.into();
166 self.draw(line, draw_state, transform, g);
167 let diff = [line[2] - line[0], line[3] - line[1]];
168 let arrow_head = transform.trans(line[2], line[3]).orient(diff[0], diff[1]);
169 self.draw([-head_size, head_size, 0.0, 0.0], draw_state, arrow_head, g);
170 self.draw(
171 [-head_size, -head_size, 0.0, 0.0],
172 draw_state,
173 arrow_head,
174 g,
175 );
176 }
177}
178
179#[cfg(test)]
180mod test {
181 use super::*;
182
183 #[test]
184 fn test_line() {
185 use crate::Colored;
186
187 let _line = Line::new([0.0; 4], 3.0)
188 .color([1.0; 4])
189 .radius(3.0)
190 .shape(Shape::Round)
191 .hue_deg(1.0);
192 }
193}