1use serde::{Deserialize, Serialize};
4use std::ops::Mul;
5
6use crate::dims::Dims;
7use crate::dir::Dir;
8use crate::prelude::Transform;
9use crate::snap::snap_to_grid;
10use crate::transform::{
11 TransformMut, TransformRef, Transformation, Translate, TranslateMut, TranslateRef,
12};
13
14#[derive(
16 Debug, Copy, Clone, Default, Hash, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord,
17)]
18pub struct Point {
19 pub x: i64,
21 pub y: i64,
23}
24
25impl Point {
26 pub const fn new(x: i64, y: i64) -> Self {
28 Self { x, y }
29 }
30
31 pub const fn from_dir_coords(dir: Dir, a: i64, b: i64) -> Self {
36 match dir {
37 Dir::Horiz => Self::new(a, b),
38 Dir::Vert => Self::new(b, a),
39 }
40 }
41
42 #[inline]
52 pub const fn zero() -> Self {
53 Self { x: 0, y: 0 }
54 }
55
56 pub const fn coord(&self, dir: Dir) -> i64 {
58 match dir {
59 Dir::Horiz => self.x,
60 Dir::Vert => self.y,
61 }
62 }
63
64 #[inline]
66 pub fn snap_to_grid(&self, grid: i64) -> Self {
67 self.snap_x_to_grid(grid).snap_y_to_grid(grid)
68 }
69
70 #[inline]
72 pub fn snap_x_to_grid(&self, grid: i64) -> Self {
73 let x = snap_to_grid(self.x, grid);
74 Self { x, y: self.y }
75 }
76
77 #[inline]
79 pub fn snap_y_to_grid(&self, grid: i64) -> Self {
80 let y = snap_to_grid(self.y, grid);
81 Self { x: self.x, y }
82 }
83}
84
85impl TranslateRef for Point {
86 fn translate_ref(&self, p: Point) -> Self {
87 self.translate(p)
88 }
89}
90
91impl TranslateMut for Point {
92 fn translate_mut(&mut self, p: Point) {
93 self.x += p.x;
94 self.y += p.y;
95 }
96}
97
98impl TransformRef for Point {
99 fn transform_ref(&self, trans: Transformation) -> Self {
100 self.transform(trans)
101 }
102}
103
104impl TransformMut for Point {
105 fn transform_mut(&mut self, trans: Transformation) {
106 *self = trans.mat * *self + trans.b;
107 }
108}
109
110impl std::ops::Add<Point> for Point {
111 type Output = Self;
112 fn add(self, rhs: Point) -> Self::Output {
113 Self::new(self.x + rhs.x, self.y + rhs.y)
114 }
115}
116
117impl std::ops::Add<Dims> for Point {
118 type Output = Self;
119 fn add(self, rhs: Dims) -> Self::Output {
120 Self::new(self.x + rhs.width(), self.y + rhs.height())
121 }
122}
123
124impl std::ops::AddAssign<Point> for Point {
125 fn add_assign(&mut self, rhs: Point) {
126 self.x += rhs.x;
127 self.y += rhs.y;
128 }
129}
130
131impl std::ops::AddAssign<Dims> for Point {
132 fn add_assign(&mut self, rhs: Dims) {
133 self.x += rhs.width();
134 self.y += rhs.height();
135 }
136}
137
138impl std::ops::Sub<Point> for Point {
139 type Output = Self;
140 fn sub(self, rhs: Point) -> Self::Output {
141 Self::new(self.x - rhs.x, self.y - rhs.y)
142 }
143}
144
145impl std::ops::SubAssign<Point> for Point {
146 fn sub_assign(&mut self, rhs: Point) {
147 self.x -= rhs.x;
148 self.y -= rhs.y;
149 }
150}
151
152impl std::ops::Neg for Point {
153 type Output = Self;
154 fn neg(self) -> Self::Output {
155 Self {
156 x: -self.x,
157 y: -self.y,
158 }
159 }
160}
161
162impl From<(i64, i64)> for Point {
163 fn from(value: (i64, i64)) -> Self {
164 Self {
165 x: value.0,
166 y: value.1,
167 }
168 }
169}
170
171impl Mul<Point> for Point {
172 type Output = Self;
173
174 fn mul(self, rhs: Point) -> Self::Output {
176 Self::new(self.x * rhs.x, self.y * rhs.y)
177 }
178}
179
180impl Mul<Dims> for Point {
181 type Output = Self;
182
183 fn mul(self, rhs: Dims) -> Self::Output {
186 Self::new(self.x * rhs.w(), self.y * rhs.h())
187 }
188}