1use crate::{Color, Point, Vector, Xform};
2use serde::{Deserialize, Serialize};
3use std::fmt;
4use std::ops::{Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Sub, SubAssign};
5use uuid::Uuid;
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
8#[serde(tag = "type", rename = "Line")]
9pub struct Line {
10 pub guid: String,
11 pub name: String,
12 #[serde(rename = "x0")]
13 _x0: f32,
14 #[serde(rename = "y0")]
15 _y0: f32,
16 #[serde(rename = "z0")]
17 _z0: f32,
18 #[serde(rename = "x1")]
19 _x1: f32,
20 #[serde(rename = "y1")]
21 _y1: f32,
22 #[serde(rename = "z1")]
23 _z1: f32,
24 pub width: f32,
25 pub linecolor: Color,
26 #[serde(default = "Xform::identity")]
27 pub xform: Xform,
28}
29
30impl Default for Line {
31 fn default() -> Self {
32 Self {
33 _x0: 0.0,
34 _y0: 0.0,
35 _z0: 0.0,
36 _x1: 0.0,
37 _y1: 0.0,
38 _z1: 1.0,
39 guid: Uuid::new_v4().to_string(),
40 name: "my_line".to_string(),
41 linecolor: Color::white(),
42 width: 1.0,
43 xform: Xform::identity(),
44 }
45 }
46}
47
48impl Line {
49 pub fn new(x0: f32, y0: f32, z0: f32, x1: f32, y1: f32, z1: f32) -> Self {
50 Self {
51 _x0: x0,
52 _y0: y0,
53 _z0: z0,
54 _x1: x1,
55 _y1: y1,
56 _z1: z1,
57 ..Default::default()
58 }
59 }
60
61 pub fn from_points(p1: &Point, p2: &Point) -> Self {
62 Self::new(p1.x(), p1.y(), p1.z(), p2.x(), p2.y(), p2.z())
63 }
64
65 pub fn with_name(name: &str, x0: f32, y0: f32, z0: f32, x1: f32, y1: f32, z1: f32) -> Self {
66 Self {
67 name: name.to_string(),
68 _x0: x0,
69 _y0: y0,
70 _z0: z0,
71 _x1: x1,
72 _y1: y1,
73 _z1: z1,
74 ..Default::default()
75 }
76 }
77
78 pub fn x0(&self) -> f32 {
79 self._x0
80 }
81 pub fn y0(&self) -> f32 {
82 self._y0
83 }
84 pub fn z0(&self) -> f32 {
85 self._z0
86 }
87 pub fn x1(&self) -> f32 {
88 self._x1
89 }
90 pub fn y1(&self) -> f32 {
91 self._y1
92 }
93 pub fn z1(&self) -> f32 {
94 self._z1
95 }
96
97 pub fn set_x0(&mut self, v: f32) {
98 self._x0 = v;
99 }
100 pub fn set_y0(&mut self, v: f32) {
101 self._y0 = v;
102 }
103 pub fn set_z0(&mut self, v: f32) {
104 self._z0 = v;
105 }
106 pub fn set_x1(&mut self, v: f32) {
107 self._x1 = v;
108 }
109 pub fn set_y1(&mut self, v: f32) {
110 self._y1 = v;
111 }
112 pub fn set_z1(&mut self, v: f32) {
113 self._z1 = v;
114 }
115
116 pub fn length(&self) -> f32 {
117 let dx = self._x1 - self._x0;
118 let dy = self._y1 - self._y0;
119 let dz = self._z1 - self._z0;
120 (dx * dx + dy * dy + dz * dz).sqrt()
121 }
122
123 pub fn squared_length(&self) -> f32 {
124 let dx = self._x1 - self._x0;
125 let dy = self._y1 - self._y0;
126 let dz = self._z1 - self._z0;
127 dx * dx + dy * dy + dz * dz
128 }
129
130 pub fn to_vector(&self) -> Vector {
131 Vector::new(
132 self._x1 - self._x0,
133 self._y1 - self._y0,
134 self._z1 - self._z0,
135 )
136 }
137
138 pub fn point_at(&self, t: f32) -> Point {
139 let s = 1.0 - t;
140 Point::new(
141 s * self._x0 + t * self._x1,
142 s * self._y0 + t * self._y1,
143 s * self._z0 + t * self._z1,
144 )
145 }
146
147 pub fn start(&self) -> Point {
148 Point::new(self._x0, self._y0, self._z0)
149 }
150
151 pub fn end(&self) -> Point {
152 Point::new(self._x1, self._y1, self._z1)
153 }
154}
155
156impl Index<usize> for Line {
157 type Output = f32;
158
159 fn index(&self, index: usize) -> &Self::Output {
160 match index {
161 0 => &self._x0,
162 1 => &self._y0,
163 2 => &self._z0,
164 3 => &self._x1,
165 4 => &self._y1,
166 5 => &self._z1,
167 _ => panic!("Index out of bounds"),
168 }
169 }
170}
171
172impl IndexMut<usize> for Line {
173 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
174 match index {
175 0 => &mut self._x0,
176 1 => &mut self._y0,
177 2 => &mut self._z0,
178 3 => &mut self._x1,
179 4 => &mut self._y1,
180 5 => &mut self._z1,
181 _ => panic!("Index out of bounds"),
182 }
183 }
184}
185
186impl AddAssign<&Vector> for Line {
187 fn add_assign(&mut self, other: &Vector) {
188 self._x0 += other.x();
189 self._y0 += other.y();
190 self._z0 += other.z();
191 self._x1 += other.x();
192 self._y1 += other.y();
193 self._z1 += other.z();
194 }
195}
196
197impl SubAssign<&Vector> for Line {
198 fn sub_assign(&mut self, other: &Vector) {
199 self._x0 -= other.x();
200 self._y0 -= other.y();
201 self._z0 -= other.z();
202 self._x1 -= other.x();
203 self._y1 -= other.y();
204 self._z1 -= other.z();
205 }
206}
207
208impl MulAssign<f32> for Line {
209 fn mul_assign(&mut self, factor: f32) {
210 self._x0 *= factor;
211 self._y0 *= factor;
212 self._z0 *= factor;
213 self._x1 *= factor;
214 self._y1 *= factor;
215 self._z1 *= factor;
216 }
217}
218
219impl DivAssign<f32> for Line {
220 fn div_assign(&mut self, factor: f32) {
221 self._x0 /= factor;
222 self._y0 /= factor;
223 self._z0 /= factor;
224 self._x1 /= factor;
225 self._y1 /= factor;
226 self._z1 /= factor;
227 }
228}
229
230impl Add<&Vector> for Line {
231 type Output = Line;
232
233 fn add(self, other: &Vector) -> Line {
234 let mut result = self;
235 result += other;
236 result
237 }
238}
239
240impl Sub<&Vector> for Line {
241 type Output = Line;
242
243 fn sub(self, other: &Vector) -> Line {
244 let mut result = self;
245 result -= other;
246 result
247 }
248}
249
250impl Mul<f32> for Line {
251 type Output = Line;
252
253 fn mul(self, factor: f32) -> Line {
254 let mut result = self;
255 result *= factor;
256 result
257 }
258}
259
260impl Div<f32> for Line {
261 type Output = Line;
262
263 fn div(self, factor: f32) -> Line {
264 let mut result = self;
265 result /= factor;
266 result
267 }
268}
269
270impl fmt::Display for Line {
271 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
272 write!(
273 f,
274 "Line({}, {}, {}, {}, {}, {})",
275 self._x0, self._y0, self._z0, self._x1, self._y1, self._z1
276 )
277 }
278}
279
280impl Line {
281 pub fn jsondump(&self) -> Result<String, Box<dyn std::error::Error>> {
282 Ok(serde_json::to_string_pretty(self)?)
283 }
284
285 pub fn jsonload(json_data: &str) -> Result<Self, Box<dyn std::error::Error>> {
286 Ok(serde_json::from_str(json_data)?)
287 }
288}
289
290#[path = "line_test.rs"]
291#[cfg(test)]
292mod line_test;