Skip to main content

blockworx_router/
point.rs

1use blockworx_doc::geometry::GridPoint;
2use blockworx_geom::{
3    Pos2,
4    grid::{grid_i32, px},
5};
6
7use crate::coord::{CoordX, CoordY};
8
9/// A lattice point: a column and a row on the routing grid.
10#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
11pub struct Point {
12    pub x: CoordX,
13    pub y: CoordY,
14}
15
16impl std::fmt::Display for Point {
17    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
18        write!(f, "({},{})", self.x, self.y)
19    }
20}
21
22impl Point {
23    /// The grid origin, used as the inert fallback where a point must exist.
24    pub const ZERO: Point = Point {
25        x: CoordX::ZERO,
26        y: CoordY::ZERO,
27    };
28
29    pub fn manhattan_distance(self, other: Point) -> i32 {
30        (self.x - other.x).abs() + (self.y - other.y).abs()
31    }
32}
33
34pub fn point(x: impl Into<CoordX>, y: impl Into<CoordY>) -> Point {
35    Point {
36        x: x.into(),
37        y: y.into(),
38    }
39}
40
41impl std::ops::Add<CoordX> for Point {
42    type Output = Self;
43    fn add(self, rhs: CoordX) -> Self {
44        Point {
45            x: self.x + rhs,
46            y: self.y,
47        }
48    }
49}
50
51impl std::ops::Add<CoordY> for Point {
52    type Output = Self;
53    fn add(self, rhs: CoordY) -> Self {
54        Point {
55            x: self.x,
56            y: self.y + rhs,
57        }
58    }
59}
60
61impl std::ops::Add<Point> for Point {
62    type Output = Self;
63    fn add(self, rhs: Point) -> Self {
64        Point {
65            x: self.x + rhs.x,
66            y: self.y + rhs.y,
67        }
68    }
69}
70
71/// A world position onto the lattice point nearest it. The lattice and the
72/// document's grid are the same grid, so this is
73/// [`blockworx_geom::grid::grid_i32`] per axis — the same rounding
74/// `grid_point` commits with, so a wire previewed and a wire stored agree.
75impl From<Pos2> for Point {
76    fn from(pos: Pos2) -> Self {
77        Point {
78            x: CoordX::from(grid_i32(pos.x)),
79            y: CoordY::from(grid_i32(pos.y)),
80        }
81    }
82}
83
84/// The inverse: round-tripping a [`Pos2`] moves it to its nearest lattice
85/// point.
86impl From<Point> for Pos2 {
87    fn from(point: Point) -> Self {
88        Pos2::new(px(point.x.raw()), px(point.y.raw()))
89    }
90}
91
92impl From<GridPoint> for Point {
93    fn from(g: GridPoint) -> Self {
94        Point {
95            x: CoordX::from(g.x),
96            y: CoordY::from(g.y),
97        }
98    }
99}
100
101impl From<Point> for GridPoint {
102    fn from(p: Point) -> Self {
103        GridPoint {
104            x: p.x.raw(),
105            y: p.y.raw(),
106        }
107    }
108}