1use crate::tolerance::{Tolerance, SCALE, TO_DEGREES, TO_RADIANS};
2use serde::{ser::Serialize as SerTrait, Deserialize, Serialize};
3use std::fmt;
4use std::ops::{
5 Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign,
6};
7use uuid::Uuid;
8
9#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
11#[serde(tag = "type", rename = "Vector")]
12pub struct Vector {
13 pub guid: String,
14 pub name: String,
15 #[serde(rename = "x")]
16 _x: f32,
17 #[serde(rename = "y")]
18 _y: f32,
19 #[serde(rename = "z")]
20 _z: f32,
21 #[serde(skip)]
22 _length: f32,
23 #[serde(skip)]
24 _has_length: bool,
25}
26
27impl Vector {
28 pub fn new(x: f32, y: f32, z: f32) -> Self {
30 Self {
31 _x: x,
32 _y: y,
33 _z: z,
34 guid: Uuid::new_v4().to_string(),
35 name: "my_vector".to_string(),
36 _length: 0.0,
37 _has_length: false,
38 }
39 }
40
41 pub fn zero() -> Self {
43 Self::new(0.0, 0.0, 0.0)
44 }
45
46 pub fn x_axis() -> Self {
53 Self::new(1.0, 0.0, 0.0)
54 }
55
56 pub fn y_axis() -> Self {
63 Self::new(0.0, 1.0, 0.0)
64 }
65
66 pub fn x(&self) -> f32 {
68 self._x
69 }
70 pub fn y(&self) -> f32 {
71 self._y
72 }
73 pub fn z(&self) -> f32 {
74 self._z
75 }
76
77 pub fn set_x(&mut self, v: f32) {
79 self._x = v;
80 self.invalidate_length_cache();
81 }
82 pub fn set_y(&mut self, v: f32) {
83 self._y = v;
84 self.invalidate_length_cache();
85 }
86 pub fn set_z(&mut self, v: f32) {
87 self._z = v;
88 self.invalidate_length_cache();
89 }
90
91 pub fn z_axis() -> Self {
98 Self::new(0.0, 0.0, 1.0)
99 }
100
101 pub fn from_start_and_end(start: &Vector, end: &Vector) -> Self {
115 Self::new(end._x - start._x, end._y - start._y, end._z - start._z)
116 }
117
118 fn invalidate_length_cache(&mut self) {
124 self._has_length = false;
125 }
126
127 pub fn compute_length(&self) -> f32 {
134 (self._x * self._x + self._y * self._y + self._z * self._z).sqrt()
135 }
136
137 pub fn magnitude(&mut self) -> f32 {
144 if !self._has_length {
145 self._length = self.compute_length();
146 self._has_length = true;
147 }
148 self._length
149 }
150
151 pub fn length_squared(&self) -> f32 {
153 self._x * self._x + self._y * self._y + self._z * self._z
154 }
155
156 pub fn normalize_self(&mut self) {
158 let len = self.magnitude();
159 if len > Tolerance::ZERO_TOLERANCE as f32 {
160 self._x /= len;
161 self._y /= len;
162 self._z /= len;
163 self.invalidate_length_cache();
164 }
165 }
166
167 pub fn normalize(&self) -> Self {
169 let mut result = self.clone();
170 result.normalize_self();
171 result
172 }
173
174 pub fn reverse(&mut self) {
176 self._x = -self._x;
177 self._y = -self._y;
178 self._z = -self._z;
179 }
181
182 pub fn scale(&mut self, factor: f32) {
184 self._x *= factor;
185 self._y *= factor;
186 self._z *= factor;
187 self.invalidate_length_cache();
188 }
189
190 pub fn scale_up(&mut self) {
192 self.scale(SCALE as f32);
193 }
194
195 pub fn scale_down(&mut self) {
197 self.scale(1.0 / SCALE as f32);
198 }
199
200 pub fn dot(&self, other: &Vector) -> f32 {
212 self._x * other._x + self._y * other._y + self._z * other._z
213 }
214
215 pub fn cross(&self, other: &Vector) -> Vector {
227 Vector::new(
228 self._y * other._z - self._z * other._y,
229 self._z * other._x - self._x * other._z,
230 self._x * other._y - self._y * other._x,
231 )
232 }
233
234 pub fn angle(&self, other: &Vector, sign_by_cross_product: bool) -> f32 {
236 let dotp = self.dot(other);
237 let len_product = self.compute_length() * other.compute_length();
238
239 if len_product < Tolerance::ZERO_TOLERANCE as f32 {
240 return 0.0;
241 }
242
243 let cos_angle = (dotp / len_product).clamp(-1.0, 1.0);
244 let mut angle = cos_angle.acos() * TO_DEGREES as f32;
245
246 if sign_by_cross_product {
247 let cp = self.cross(other);
248 if cp.z() < 0.0 {
249 angle = -angle;
250 }
251 }
252
253 angle
254 }
255
256 pub fn projection(&self, onto: &Vector) -> (Vector, f32, Vector, f32) {
264 self.projection_with(onto, Tolerance::ZERO_TOLERANCE as f32)
265 }
266
267 pub fn projection_with(&self, onto: &Vector, tolerance: f32) -> (Vector, f32, Vector, f32) {
269 let onto_len_sq = onto.length_squared();
270
271 if onto_len_sq < tolerance {
272 return (Vector::zero(), 0.0, Vector::zero(), 0.0);
273 }
274
275 let onto_len = onto_len_sq.sqrt();
277 let onto_unit = Vector::new(onto._x / onto_len, onto._y / onto_len, onto._z / onto_len);
278
279 let projected_len = self.dot(&onto_unit);
281 let projection_vec = Vector::new(
282 onto_unit._x * projected_len,
283 onto_unit._y * projected_len,
284 onto_unit._z * projected_len,
285 );
286
287 let perp_vec = Vector::new(
289 self._x - projection_vec._x,
290 self._y - projection_vec._y,
291 self._z - projection_vec._z,
292 );
293 let perp_len = perp_vec.compute_length();
294
295 (projection_vec, projected_len, perp_vec, perp_len)
296 }
297
298 pub fn is_parallel_to(&self, other: &Vector) -> i32 {
301 let len_product = self.compute_length() * other.compute_length();
302
303 if len_product <= 0.0 {
304 return 0;
305 }
306
307 let cos_angle = self.dot(other) / len_product;
308 let angle_in_radians = Tolerance::ANGLE_TOLERANCE_DEGREES as f32 * TO_RADIANS as f32;
309 let cos_tolerance = angle_in_radians.cos();
310
311 if cos_angle >= cos_tolerance {
312 1 } else if cos_angle <= -cos_tolerance {
314 -1 } else {
316 0 }
318 }
319
320 pub fn get_leveled_vector(&self, vertical_height: f32) -> Vector {
322 let mut copy = self.clone();
323 copy.normalize_self();
324
325 if vertical_height != 0.0 {
326 let reference = Vector::z_axis();
327 let angle = copy.angle(&reference, true); let inclined_offset_by_vertical_distance = vertical_height / angle.cos();
330 copy.scale(inclined_offset_by_vertical_distance);
331 }
332
333 copy
334 }
335
336 pub fn perpendicular_to(&mut self, v: &Vector) -> bool {
339 let i: usize;
341 let j: usize;
342 let k: usize;
343 let a: f32;
344 let b: f32;
345
346 if v.y().abs() > v.x().abs() {
347 if v.z().abs() > v.y().abs() {
348 i = 2;
350 j = 1;
351 k = 0;
352 a = v.z();
353 b = -v.y();
354 } else if v.z().abs() >= v.x().abs() {
355 i = 1;
357 j = 2;
358 k = 0;
359 a = v.y();
360 b = -v.z();
361 } else {
362 i = 1;
364 j = 0;
365 k = 2;
366 a = v.y();
367 b = -v.x();
368 }
369 } else if v.z().abs() > v.x().abs() {
370 i = 2;
372 j = 0;
373 k = 1;
374 a = v.z();
375 b = -v.x();
376 } else if v.z().abs() > v.y().abs() {
377 i = 0;
379 j = 2;
380 k = 1;
381 a = v.x();
382 b = -v.z();
383 } else {
384 i = 0;
386 j = 1;
387 k = 2;
388 a = v.x();
389 b = -v.y();
390 }
391
392 let mut coords = [0.0, 0.0, 0.0];
393 coords[i] = b;
394 coords[j] = a;
395 coords[k] = 0.0;
396
397 self._x = coords[0];
398 self._y = coords[1];
399 self._z = coords[2];
400 self.invalidate_length_cache();
401
402 a != 0.0
403 }
404
405 pub fn cosine_law(
411 triangle_edge_length_a: f32,
412 triangle_edge_length_b: f32,
413 angle_in_degrees_between_edges: f32,
414 degrees: bool,
415 ) -> f32 {
416 let angle = if degrees {
417 angle_in_degrees_between_edges * TO_RADIANS as f32
418 } else {
419 angle_in_degrees_between_edges
420 };
421
422 (triangle_edge_length_a.powi(2) + triangle_edge_length_b.powi(2)
423 - 2.0 * triangle_edge_length_a * triangle_edge_length_b * angle.cos())
424 .sqrt()
425 }
426
427 pub fn sine_law_angle(
429 triangle_edge_length_a: f32,
430 angle_in_degrees_in_front_of_a: f32,
431 triangle_edge_length_b: f32,
432 degrees: bool,
433 ) -> f32 {
434 let angle_a = if degrees {
435 angle_in_degrees_in_front_of_a * TO_RADIANS as f32
436 } else {
437 angle_in_degrees_in_front_of_a
438 };
439
440 let sin_b = (triangle_edge_length_b * angle_a.sin()) / triangle_edge_length_a;
441 let angle_b = sin_b.asin();
442
443 if degrees {
444 angle_b * TO_DEGREES as f32
445 } else {
446 angle_b
447 }
448 }
449
450 pub fn sine_law_length(
452 triangle_edge_length_a: f32,
453 angle_in_degrees_in_front_of_a: f32,
454 angle_in_degrees_in_front_of_b: f32,
455 degrees: bool,
456 ) -> f32 {
457 let angle_a = if degrees {
458 angle_in_degrees_in_front_of_a * TO_RADIANS as f32
459 } else {
460 angle_in_degrees_in_front_of_a
461 };
462
463 let angle_b = if degrees {
464 angle_in_degrees_in_front_of_b * TO_RADIANS as f32
465 } else {
466 angle_in_degrees_in_front_of_b
467 };
468
469 (triangle_edge_length_a * angle_b.sin()) / angle_a.sin()
470 }
471
472 pub fn angle_between_vector_xy_components(vector: &Vector) -> f32 {
474 vector._y.atan2(vector._x) * TO_DEGREES as f32
475 }
476
477 #[allow(dead_code)]
479 pub fn angle_between_vector_xy_components_degrees(vector: &Vector) -> f32 {
480 Self::angle_between_vector_xy_components(vector)
481 }
482
483 pub fn sum_of_vectors(vectors: &[Vector]) -> Vector {
485 let mut result = Vector::zero();
486 for vector in vectors {
487 result._x += vector._x;
488 result._y += vector._y;
489 result._z += vector._z;
490 }
491 result
492 }
493
494 pub fn coordinate_direction_3angles(&self, degrees: bool) -> [f32; 3] {
496 let length = self.compute_length();
497 if length < Tolerance::ZERO_TOLERANCE as f32 {
498 return [0.0, 0.0, 0.0];
499 }
500
501 let cos_alpha = self._x / length;
502 let cos_beta = self._y / length;
503 let cos_gamma = self._z / length;
504
505 let alpha = cos_alpha.acos();
506 let beta = cos_beta.acos();
507 let gamma = cos_gamma.acos();
508
509 if degrees {
510 [
511 alpha * TO_DEGREES as f32,
512 beta * TO_DEGREES as f32,
513 gamma * TO_DEGREES as f32,
514 ]
515 } else {
516 [alpha, beta, gamma]
517 }
518 }
519
520 pub fn coordinate_direction_2angles(&self, degrees: bool) -> [f32; 2] {
522 let length_xy = (self._x * self._x + self._y * self._y).sqrt();
523 let length = self.compute_length();
524
525 if length < Tolerance::ZERO_TOLERANCE as f32 {
526 return [0.0, 0.0];
527 }
528
529 let phi = self._y.atan2(self._x);
530 let theta = length_xy.atan2(self._z);
531
532 if degrees {
533 [phi * TO_DEGREES as f32, theta * TO_DEGREES as f32]
534 } else {
535 [phi, theta]
536 }
537 }
538
539 pub fn jsondump(&self) -> Result<String, Box<dyn std::error::Error>> {
545 let mut buf = Vec::new();
546 let formatter = serde_json::ser::PrettyFormatter::with_indent(b" ");
547 let mut ser = serde_json::Serializer::with_formatter(&mut buf, formatter);
548 SerTrait::serialize(self, &mut ser)?;
549 Ok(String::from_utf8(buf)?)
550 }
551
552 pub fn jsonload(json_data: &str) -> Result<Self, Box<dyn std::error::Error>> {
554 Ok(serde_json::from_str(json_data)?)
555 }
556
557 pub fn to_json(&self, filepath: &str) -> Result<(), Box<dyn std::error::Error>> {
559 let json = self.jsondump()?;
560 std::fs::write(filepath, json)?;
561 Ok(())
562 }
563
564 pub fn from_json(filepath: &str) -> Result<Self, Box<dyn std::error::Error>> {
566 let json = std::fs::read_to_string(filepath)?;
567 Self::jsonload(&json)
568 }
569}
570
571impl Default for Vector {
572 fn default() -> Self {
573 Self::new(0.0, 0.0, 0.0)
574 }
575}
576
577impl Index<usize> for Vector {
579 type Output = f32;
580
581 fn index(&self, index: usize) -> &Self::Output {
582 match index {
583 0 => &self._x,
584 1 => &self._y,
585 2 => &self._z,
586 _ => panic!("Index out of bounds for Vector"),
587 }
588 }
589}
590
591impl IndexMut<usize> for Vector {
592 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
593 self.invalidate_length_cache();
594 match index {
595 0 => &mut self._x,
596 1 => &mut self._y,
597 2 => &mut self._z,
598 _ => panic!("Index out of bounds for Vector"),
599 }
600 }
601}
602
603impl Add for Vector {
605 type Output = Vector;
606
607 fn add(self, other: Vector) -> Vector {
608 Vector::new(
609 self.x() + other.x(),
610 self.y() + other.y(),
611 self.z() + other.z(),
612 )
613 }
614}
615
616impl Add for &Vector {
617 type Output = Vector;
618
619 fn add(self, other: &Vector) -> Vector {
620 Vector::new(
621 self.x() + other.x(),
622 self.y() + other.y(),
623 self.z() + other.z(),
624 )
625 }
626}
627
628impl Sub for Vector {
629 type Output = Vector;
630
631 fn sub(self, other: Vector) -> Vector {
632 Vector::new(
633 self.x() - other.x(),
634 self.y() - other.y(),
635 self.z() - other.z(),
636 )
637 }
638}
639
640impl Sub for &Vector {
641 type Output = Vector;
642
643 fn sub(self, other: &Vector) -> Vector {
644 Vector::new(
645 self.x() - other.x(),
646 self.y() - other.y(),
647 self.z() - other.z(),
648 )
649 }
650}
651
652impl Mul<f32> for Vector {
653 type Output = Vector;
654
655 fn mul(self, scalar: f32) -> Vector {
656 Vector::new(self.x() * scalar, self.y() * scalar, self.z() * scalar)
657 }
658}
659
660impl Mul<f32> for &Vector {
661 type Output = Vector;
662
663 fn mul(self, scalar: f32) -> Vector {
664 Vector::new(self.x() * scalar, self.y() * scalar, self.z() * scalar)
665 }
666}
667
668impl Div<f32> for Vector {
669 type Output = Vector;
670
671 fn div(self, scalar: f32) -> Vector {
672 Vector::new(self.x() / scalar, self.y() / scalar, self.z() / scalar)
673 }
674}
675
676impl Div<f32> for &Vector {
677 type Output = Vector;
678
679 fn div(self, scalar: f32) -> Vector {
680 Vector::new(self.x() / scalar, self.y() / scalar, self.z() / scalar)
681 }
682}
683
684impl Neg for Vector {
685 type Output = Vector;
686
687 fn neg(self) -> Vector {
688 Vector::new(-self.x(), -self.y(), -self.z())
689 }
690}
691
692impl Neg for &Vector {
693 type Output = Vector;
694
695 fn neg(self) -> Vector {
696 Vector::new(-self.x(), -self.y(), -self.z())
697 }
698}
699
700impl AddAssign for Vector {
702 fn add_assign(&mut self, other: Vector) {
703 self.set_x(self.x() + other.x());
704 self.set_y(self.y() + other.y());
705 self.set_z(self.z() + other.z());
706 }
707}
708
709impl AddAssign<&Vector> for Vector {
710 fn add_assign(&mut self, other: &Vector) {
711 self.set_x(self.x() + other.x());
712 self.set_y(self.y() + other.y());
713 self.set_z(self.z() + other.z());
714 }
715}
716
717impl SubAssign for Vector {
718 fn sub_assign(&mut self, other: Vector) {
719 self.set_x(self.x() - other.x());
720 self.set_y(self.y() - other.y());
721 self.set_z(self.z() - other.z());
722 }
723}
724
725impl SubAssign<&Vector> for Vector {
726 fn sub_assign(&mut self, other: &Vector) {
727 self.set_x(self.x() - other.x());
728 self.set_y(self.y() - other.y());
729 self.set_z(self.z() - other.z());
730 }
731}
732
733impl MulAssign<f32> for Vector {
734 fn mul_assign(&mut self, scalar: f32) {
735 self.set_x(self.x() * scalar);
736 self.set_y(self.y() * scalar);
737 self.set_z(self.z() * scalar);
738 }
739}
740
741impl DivAssign<f32> for Vector {
742 fn div_assign(&mut self, scalar: f32) {
743 self.set_x(self.x() / scalar);
744 self.set_y(self.y() / scalar);
745 self.set_z(self.z() / scalar);
746 }
747}
748
749impl fmt::Display for Vector {
750 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
751 write!(
752 f,
753 "Vector({}, {}, {}, {}, {})",
754 self.x(),
755 self.y(),
756 self.z(),
757 self.guid,
758 self.name
759 )
760 }
761}
762
763#[cfg(test)]
764#[path = "vector_test.rs"]
765mod tests;