gluesql_core/data/
point.rs

1use {
2    super::ValueError,
3    crate::result::{Error, Result},
4    regex::Regex,
5    serde::{Deserialize, Serialize},
6    std::fmt,
7};
8
9#[derive(Copy, Debug, Clone, Serialize, Deserialize)]
10pub struct Point {
11    pub x: f64,
12    pub y: f64,
13}
14
15impl Point {
16    pub fn new(x: f64, y: f64) -> Self {
17        Self { x, y }
18    }
19
20    pub fn from_wkt(v: &str) -> Result<Self> {
21        let re = Regex::new(r"POINT\s*\(\s*(-?\d*\.?\d+)\s+(-?\d*\.?\d+)\s*\)").unwrap();
22
23        if let Some(captures) = re.captures(v) {
24            let x = captures[1]
25                .parse::<f64>()
26                .map_err(|_| Error::Value(ValueError::FailedToParsePoint(v.to_owned())))?;
27            let y = captures[2]
28                .parse::<f64>()
29                .map_err(|_| Error::Value(ValueError::FailedToParsePoint(v.to_owned())))?;
30            Ok(Self { x, y })
31        } else {
32            Err(Error::Value(ValueError::FailedToParsePoint(v.to_owned())))
33        }
34    }
35
36    pub fn calc_distance(&self, other: &Point) -> f64 {
37        let dx = self.x - other.x;
38        let dy = self.y - other.y;
39        f64::sqrt(dx * dx + dy * dy)
40    }
41}
42
43impl PartialEq for Point {
44    fn eq(&self, other: &Self) -> bool {
45        self.x == other.x && self.y == other.y
46    }
47}
48
49impl Eq for Point {}
50
51impl fmt::Display for Point {
52    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53        write!(f, "POINT({} {})", self.x, self.y)
54    }
55}