rustvision/shapes/
line.rs1use crate::{color::Color, image::Image, vec::Vec2d};
4
5use super::Shape;
6
7#[derive(Default, Debug, Clone, Copy, PartialEq)]
9pub struct Line {
10 start: Vec2d,
11 end: Vec2d,
12 color: Color,
13}
14
15impl Line {
16 pub fn new(start: Vec2d, end: Vec2d) -> Self {
18 Self {
19 start,
20 end,
21 ..Default::default()
22 }
23 }
24
25 pub fn with_color(mut self, color: Color) -> Self {
27 self.color = color;
28 self
29 }
30}
31
32impl Shape for Line {
33 fn draw(&self, img: &mut Image) {
34 let p0 = self.start;
36 let p1 = self.end;
37
38 let x0 = p0.x as i64;
39 let y0 = p0.y as i64;
40
41 let x1 = p1.x as i64;
42 let y1 = p1.y as i64;
43
44 let dx = (x1 - x0).abs();
45 let dy = (y1 - y0).abs();
46
47 let sx = (x1 - x0).signum();
48 let sy = (y1 - y0).signum();
49
50 let mut x = x0;
51 let mut y = y0;
52
53 if dx >= dy {
54 let mut e = 2 * dy - dx;
55
56 while x != x1 || y != y1 {
57 img.set(x as usize, y as usize, &self.color);
58
59 x += sx;
60 if e <= 0 {
61 e += 2 * dy;
62 } else {
63 y += sy;
64 e += 2 * dy - 2 * dx;
65 }
66 }
67 } else {
68 let mut e = 2 * dx - dy;
69
70 while x != x1 || y != y1 {
71 img.set(x as usize, y as usize, &self.color);
72
73 y += sy;
74 if e <= 0 {
75 e += 2 * dx;
76 } else {
77 x += sx;
78 e += 2 * dx - 2 * dy;
79 }
80 }
81 }
82 img.set(x as usize, y as usize, &self.color);
83 }
84}
85
86#[cfg(test)]
87mod tests {
88 use super::*;
89 use crate::{rgb, vec2};
90
91 #[test]
92 fn test_line_new() {
93 let start = vec2![10.0, 20.0];
94 let end = vec2![15.0, 10.0];
95 assert_eq!(
96 Line::new(start, end),
97 Line {
98 start,
99 end,
100 color: Color::default()
101 }
102 );
103 }
104
105 #[test]
106 fn test_line_with_color() {
107 let start = vec2![10.0, 20.0];
108 let end = vec2![15.0, 10.0];
109 let color = rgb!(255, 42, 17);
110 assert_eq!(
111 Line::new(start, end).with_color(color),
112 Line { start, end, color }
113 );
114 }
115}