+
+ pub fn to_i32(self) -> Point2D<i32> {
+ Point2D {
+ x: self.x as i32,
+ y: self.y as i32,
+ }
+ }
+}
+
+macro_rules! point_op {
+ ($op:tt, $trait:ident($fn:ident), $trait_assign:ident($fn_assign:ident), $rhs:ident = $Rhs:ty => $x:expr, $y:expr) => {
+ impl<T: $trait<Output = T>> $trait<$Rhs> for Point2D<T> {
+ type Output = Self;
+
+ fn $fn(self, $rhs: $Rhs) -> Self {
+ Self {
+ x: self.x $op $x,
+ y: self.y $op $y,
+ }
+ }
+ }
+
+ impl<T: $trait<Output = T> + Copy> $trait_assign<$Rhs> for Point2D<T> {
+ fn $fn_assign(&mut self, $rhs: $Rhs) {
+ *self = Self {
+ x: self.x $op $x,
+ y: self.y $op $y,
+ }
+ }
+ }
+ }
+}
+
+point_op!(+, Add(add), AddAssign(add_assign), rhs = Point2D<T> => rhs.x, rhs.y);
+point_op!(-, Sub(sub), SubAssign(sub_assign), rhs = Point2D<T> => rhs.x, rhs.y);
+point_op!(*, Mul(mul), MulAssign(mul_assign), rhs = Point2D<T> => rhs.x, rhs.y);
+point_op!(/, Div(div), DivAssign(div_assign), rhs = Point2D<T> => rhs.x, rhs.y);
+point_op!(+, Add(add), AddAssign(add_assign), rhs = (T, T) => rhs.0, rhs.1);
+point_op!(-, Sub(sub), SubAssign(sub_assign), rhs = (T, T) => rhs.0, rhs.1);
+point_op!(*, Mul(mul), MulAssign(mul_assign), rhs = (T, T) => rhs.0, rhs.1);
+point_op!(/, Div(div), DivAssign(div_assign), rhs = (T, T) => rhs.0, rhs.1);
+
+////////// multiply point with scalar //////////////////////////////////////////
+impl<T: Mul<Output = T> + Copy> Mul<T> for Point2D<T> {
+ type Output = Self;
+
+ fn mul(self, rhs: T) -> Self {
+ Self {
+ x: self.x * rhs,
+ y: self.y * rhs,
+ }
+ }
+}
+
+impl<T: Mul<Output = T> + Copy> MulAssign<T> for Point2D<T> {
+ fn mul_assign(&mut self, rhs: T) {
+ *self = Self {
+ x: self.x * rhs,
+ y: self.y * rhs,
+ }
+ }
+}
+
+////////// divide point with scalar ////////////////////////////////////////////
+impl<T: Div<Output = T> + Copy> Div<T> for Point2D<T> {
+ type Output = Self;
+
+ fn div(self, rhs: T) -> Self {
+ Self {
+ x: self.x / rhs,
+ y: self.y / rhs,
+ }
+ }
+}
+
+impl<T: Div<Output = T> + Copy> DivAssign<T> for Point2D<T> {
+ fn div_assign(&mut self, rhs: T) {
+ *self = Self {
+ x: self.x / rhs,
+ y: self.y / rhs,
+ }
+ }
+}
+
+impl<T: Neg<Output = T>> Neg for Point2D<T> {
+ type Output = Self;
+
+ fn neg(self) -> Self {
+ Self {
+ x: -self.x,
+ y: -self.y,
+ }
+ }
+}
+
+impl<T> From<(T, T)> for Point2D<T> {
+ fn from(item: (T, T)) -> Self {
+ Point2D {
+ x: item.0,
+ y: item.1,
+ }
+ }
+}
+
+impl<T> From<Point2D<T>> for (T, T) {
+ fn from(item: Point2D<T>) -> Self {
+ (item.x, item.y)
+ }