vrp_core/algorithms/geometry/
point.rs

1#[cfg(test)]
2#[path = "../../../tests/unit/algorithms/geometry/point_test.rs"]
3mod point_test;
4
5use rosomaxa::prelude::Float;
6use std::hash::{Hash, Hasher};
7
8/// Represents a point in 2D space.
9#[derive(Clone, Debug)]
10pub struct Point {
11    /// X value.
12    pub x: Float,
13    /// Y value.
14    pub y: Float,
15}
16
17impl Point {
18    /// Creates a new instance of `Point`.
19    pub fn new(x: Float, y: Float) -> Self {
20        Self { x, y }
21    }
22
23    /// Computes distance from given point to `other`
24    pub fn distance_to_point(&self, other: &Point) -> Float {
25        let delta_x = self.x - other.x;
26        let delta_y = self.y - other.y;
27
28        (delta_x * delta_x + delta_y * delta_y).sqrt()
29    }
30
31    /// Computes distance from line, drawn by points a and b, to the point.
32    pub fn distance_to_line(&self, a: &Point, b: &Point) -> Float {
33        let a_b_distance = a.distance_to_point(b);
34
35        if a_b_distance == 0. {
36            0.
37        } else {
38            (Self::cross_product(a, b, self) / a_b_distance).abs()
39        }
40    }
41
42    /// Computes distance from segment to the point.
43    pub fn distance_to_segment(&self, a: &Point, b: &Point) -> Float {
44        if Self::dot_product(a, b, self) > 0. {
45            return b.distance_to_point(self);
46        }
47
48        if Self::dot_product(b, a, self) > 0. {
49            return a.distance_to_point(self);
50        }
51
52        self.distance_to_line(a, b)
53    }
54
55    /// Computes the dot product AB . BC
56    pub fn dot_product(a: &Point, b: &Point, c: &Point) -> Float {
57        let ab_x = b.x - a.x;
58        let ab_y = b.y - a.y;
59        let bc_x = c.x - b.x;
60        let bc_y = c.y - b.y;
61
62        ab_x * bc_x + ab_y * bc_y
63    }
64
65    /// Computes the cross product AB x AC
66    pub fn cross_product(a: &Point, b: &Point, c: &Point) -> Float {
67        let ab_x = b.x - a.x;
68        let ab_y = b.y - a.y;
69        let ac_x = c.x - a.x;
70        let ac_y = c.y - a.y;
71
72        ab_x * ac_y - ab_y * ac_x
73    }
74}
75
76impl Point {
77    fn transmute(&self) -> (i64, i64) {
78        let x = self.x.to_bits() as i64;
79        let y = self.y.to_bits() as i64;
80
81        (x, y)
82    }
83}
84
85impl Hash for Point {
86    fn hash<H: Hasher>(&self, state: &mut H) {
87        let (x, y) = self.transmute();
88        x.hash(state);
89        y.hash(state);
90    }
91}
92
93impl Eq for Point {}
94
95impl PartialEq for Point {
96    fn eq(&self, other: &Self) -> bool {
97        let (self_x, self_y) = self.transmute();
98        let (other_x, other_y) = other.transmute();
99
100        self_x == other_x && self_y == other_y
101    }
102}