physdes/point.rs
1// #![no_std]
2
3use super::Vector2;
4use crate::generic::{Contain, Displacement, MinDist, Overlap};
5use crate::interval::{Hull, Intersect};
6// use core::cmp::Ordering;
7// #[cfg(any(test, feature = "std"))]
8#[cfg(test)]
9use core::hash;
10use core::ops::{Add, Neg, Sub};
11use num_traits::Num;
12
13/// The code defines a generic Point struct with x and y coordinates.
14///
15/// Properties:
16///
17/// * `xcoord`: The `xcoord` property represents the x-coordinate of a point in a two-dimensional space.
18/// It is a generic type `T`, which means it can be any type that implements the necessary traits for
19/// the `Point` struct.
20/// * `ycoord`: The `ycoord` property represents the y-coordinate of a point in a two-dimensional space.
21/// It is a generic type `T`, which means it can be any type that implements the necessary traits for
22/// the `Point` struct.
23#[derive(PartialEq, Eq, Copy, PartialOrd, Ord, Clone, Hash, Debug, Default)]
24pub struct Point<T1, T2> {
25 /// x portion of the Point object
26 pub xcoord: T1,
27 /// y portion of the Point object
28 pub ycoord: T2,
29}
30
31impl<T1, T2> Point<T1, T2> {
32 /// The `new` function creates a new `Point` with the given x and y coordinates.
33 ///
34 /// Arguments:
35 ///
36 /// * `xcoord`: The `xcoord` parameter represents the x-coordinate of the point. It is of type `T`,
37 /// which means it can be any type that implements the necessary traits for mathematical operations.
38 /// * `ycoord`: The `ycoord` parameter represents the y-coordinate of the point. It is used to
39 /// specify the vertical position of the point in a two-dimensional coordinate system.
40 ///
41 /// Returns:
42 ///
43 /// The `new` function returns a new instance of the `Point` struct with the specified `xcoord` and
44 /// `ycoord` values.
45 ///
46 /// # Examples
47 ///
48 /// ```
49 /// use physdes::point::Point;
50 /// assert_eq!(Point::new(3, 4).xcoord, 3);
51 /// assert_eq!(Point::new(3, 4).ycoord, 4);
52 /// ```
53 #[inline]
54 pub const fn new(xcoord: T1, ycoord: T2) -> Self {
55 Point { xcoord, ycoord }
56 }
57}
58
59/// Implements the `Display` trait for the `Point` struct, which allows it to be
60/// printed in the format `(x, y)` where `x` and `y` are the coordinates of the point.
61///
62/// This implementation assumes that the `xcoord` and `ycoord` fields of the `Point`
63/// struct implement the `std::fmt::Display` trait, which is enforced by the generic
64/// type constraints `T1: std::fmt::Display` and `T2: std::fmt::Display`.
65impl<T1: std::fmt::Display, T2: std::fmt::Display> std::fmt::Display for Point<T1, T2> {
66 #[inline]
67 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
68 write!(f, "({}, {})", self.xcoord, self.ycoord)
69 }
70}
71
72/// Flips the coordinates of the `Point` struct, swapping the `xcoord` and `ycoord` fields.
73///
74/// This is a convenience method that can be used to quickly create a new `Point` with the
75/// `xcoord` and `ycoord` fields swapped. It is implemented for `Point` structs where both
76/// the `xcoord` and `ycoord` fields implement the `Clone` trait.
77///
78/// # Examples
79///
80/// use my_crate::Point;
81///
82/// let p = Point { xcoord: 1, ycoord: 2 };
83/// let flipped = p.flip();
84/// assert_eq!(flipped, Point { xcoord: 2, ycoord: 1 });
85///
86impl<T1: Clone, T2: Clone> Point<T1, T2> {
87 #[inline]
88 pub fn flip(&self) -> Point<T2, T1> {
89 Point {
90 xcoord: self.ycoord.clone(),
91 ycoord: self.xcoord.clone(),
92 }
93 }
94}
95
96// impl<T1: Ord + Copy, T2: Ord + Copy> PartialOrd for Point<T1, T2> {
97// fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
98// Some((self.xcoord, self.ycoord).cmp(&(other.xcoord, other.ycoord)))
99// // Some(self.xcoord.partial_cmp(&other.xcoord).then(self.ycoord.partial_cmp(&other.ycoord)))
100// }
101// }
102
103// impl<T, U> Overlap<U> for Point<T1, T2>
104// where
105// U: Overlap<T1, T2>,
106// {
107// fn overlaps(&self, other: &U) -> bool {
108// other.overlaps(&self.xcoord) && other.overlaps(&self.ycoord)
109// }
110// }
111
112// impl<T, U> Contain<U> for Point<T1, T2>
113// where
114// T: Contain<U>,
115// {
116// fn contains(&self, other: &U) -> bool {
117// self.xcoord.contains(other) && self.ycoord.contains(other)
118// }
119// }
120
121/// Checks if two `Point` instances overlap.
122///
123/// This implementation checks if the `xcoord` and `ycoord` components of the two `Point` instances
124/// overlap, using the `Overlap` trait implementation for their respective component types.
125///
126/// # Example
127///
128/// use your_crate::Point;
129///
130/// let p1 = Point::new(1, 2);
131/// let p2 = Point::new(2, 3);
132/// assert!(p1.overlaps(&p2));
133///
134impl<T1, T2, U1, U2> Overlap<Point<U1, U2>> for Point<T1, T2>
135where
136 T1: Overlap<U1>,
137 T2: Overlap<U2>,
138{
139 /// The `overlaps` function checks if two points overlap in both x and y coordinates.
140 ///
141 /// Arguments:
142 ///
143 /// * `other`: The `other` parameter in the `overlaps` method is a reference to another `Point`
144 /// struct with generic types `U1` and `U2`.
145 ///
146 /// Returns:
147 ///
148 /// The `overlaps` method is returning a boolean value, which indicates whether the x-coordinate of
149 /// the current `Point` instance overlaps with the x-coordinate of the `other` `Point` instance, and
150 /// whether the y-coordinate of the current `Point` instance overlaps with the y-coordinate of the
151 /// `other` `Point` instance. The method returns `true` if both conditions are met, and
152 #[inline]
153 fn overlaps(&self, other: &Point<U1, U2>) -> bool {
154 self.xcoord.overlaps(&other.xcoord) && self.ycoord.overlaps(&other.ycoord)
155 }
156}
157
158/// Checks if a `Point<T1, T2>` contains a `Point<U1, U2>`.
159///
160/// This implementation checks if the `xcoord` and `ycoord` fields of the `Point<T1, T2>`
161/// contain the corresponding fields of the `Point<U1, U2>`. The `T1` and `T2` types
162/// must implement the `Contain` trait for `U1` and `U2` respectively.
163impl<T1, T2, U1, U2> Contain<Point<U1, U2>> for Point<T1, T2>
164where
165 T1: Contain<U1>,
166 T2: Contain<U2>,
167{
168 /// The `contains` function checks if a Point contains another Point by comparing their x and y
169 /// coordinates.
170 ///
171 /// Arguments:
172 ///
173 /// * `other`: The `other` parameter is a reference to a `Point` struct with generic types `U1` and
174 /// `U2`. It represents another point that you want to check for containment within the current
175 /// `Point` instance.
176 ///
177 /// Returns:
178 ///
179 /// The `contains` method is returning a boolean value, which indicates whether the `xcoord` and
180 /// `ycoord` of the current `Point` instance contain the `xcoord` and `ycoord` of the `other`
181 /// `Point` instance respectively.
182 #[inline]
183 fn contains(&self, other: &Point<U1, U2>) -> bool {
184 self.xcoord.contains(&other.xcoord) && self.ycoord.contains(&other.ycoord)
185 }
186}
187
188/// The above Rust code is implementing a trait `MinDist` for the `Point` struct. The `MinDist` trait
189/// defines a method `min_dist_with` that calculates the minimum distance between two points based on
190/// the minimum distance between their individual coordinates (`xcoord` and `ycoord`). The
191/// implementation specifies that the minimum distance between two points is calculated by adding the
192/// minimum distances between their respective x and y coordinates.
193impl<T1, T2, U1, U2> MinDist<Point<U1, U2>> for Point<T1, T2>
194where
195 T1: MinDist<U1>,
196 T2: MinDist<U2>,
197{
198 /// The function calculates the minimum distance between two points in a two-dimensional space.
199 ///
200 /// Arguments:
201 ///
202 /// * `other`: The `other` parameter is a reference to a `Point` struct with generic types `U1` and
203 /// `U2`.
204 ///
205 /// Returns:
206 ///
207 /// The `min_dist_with` method is returning the sum of the minimum distances between the
208 /// x-coordinate of `self` and the x-coordinate of `other`, and the y-coordinate of `self` and the
209 /// y-coordinate of `other`.
210 #[inline]
211 fn min_dist_with(&self, other: &Point<U1, U2>) -> u32 {
212 self.xcoord.min_dist_with(&other.xcoord) + self.ycoord.min_dist_with(&other.ycoord)
213 }
214}
215
216/// The above Rust code is implementing a `Displacement` trait for the `Point` struct. The
217/// `Displacement` trait is generic over two types `T1` and `T2`, and it requires that `T1` and `T2`
218/// implement the `Displacement` trait with an associated type `Output`.
219impl<T1, T2> Displacement<Point<T1, T2>> for Point<T1, T2>
220where
221 T1: Displacement<T1, Output = T1>,
222 T2: Displacement<T2, Output = T2>,
223{
224 type Output = Vector2<T1, T2>;
225
226 /// The `displace` function calculates the displacement between two points in Rust.
227 ///
228 /// Arguments:
229 ///
230 /// * `other`: The `other` parameter in the `displace` method is a reference to another `Point`
231 /// object with the same generic types `T1` and `T2` as the current `Point` object.
232 #[inline]
233 fn displace(&self, other: &Point<T1, T2>) -> Self::Output {
234 Self::Output::new(
235 self.xcoord.displace(&other.xcoord),
236 self.ycoord.displace(&other.ycoord),
237 )
238 }
239}
240
241// impl<T1, T2> Hull<Point<T1, T2>> for Point<T1, T2>
242// where
243// T1: Hull<T1, Output=Interval<T1>>,
244// T2: Hull<T2, Output=Interval<T2>>,
245// {
246// type Output = Point<Interval<T1>, Interval<T2>>;
247// fn hull_with(&self, other: &Point<T1, T2>) -> Self::Output {
248// Self::Output::new(
249// self.xcoord.hull_with(&other.xcoord),
250// self.ycoord.hull_with(&other.ycoord),
251// )
252// }
253// }
254
255/// The above code is implementing a trait called `Hull` for the `Point` struct in Rust. The `Hull`
256/// trait defines a method `hull_with` that calculates the hull (convex hull, for example) of two
257/// points. The implementation specifies that the output type of the hull operation on two `Point`
258/// instances is a new `Point` with the hull operation applied to the x and y coordinates of the points.
259/// The implementation also specifies that the hull operation is applied to the generic types `T1` and
260/// `T2` where `T1` and `T
261impl<T1, T2> Hull<Point<T1, T2>> for Point<T1, T2>
262where
263 T1: Hull<T1>,
264 T2: Hull<T2>,
265{
266 type Output = Point<T1::Output, T2::Output>;
267
268 /// The function `hull_with` calculates the hull with another `Point` object by combining their x
269 /// and y coordinates.
270 ///
271 /// Arguments:
272 ///
273 /// * `other`: The `other` parameter in the `hull_with` method is a reference to another `Point`
274 /// struct with the same generic types `T1` and `T2` as the current `Point` struct. It is used to
275 /// combine the coordinates of the current `Point` with the coordinates
276 #[inline]
277 fn hull_with(&self, other: &Point<T1, T2>) -> Self::Output {
278 Self::Output::new(
279 self.xcoord.hull_with(&other.xcoord),
280 self.ycoord.hull_with(&other.ycoord),
281 )
282 }
283}
284
285/// The above Rust code is implementing an `Intersect` trait for the `Point` struct. The `Intersect`
286/// trait is defined for two generic types `T1` and `T2`, and it requires that `T1` and `T2` implement
287/// the `Intersect` trait themselves.
288impl<T1, T2> Intersect<Point<T1, T2>> for Point<T1, T2>
289where
290 T1: Intersect<T1>,
291 T2: Intersect<T2>,
292{
293 type Output = Point<T1::Output, T2::Output>;
294
295 /// The `intersect_with` function takes another `Point` as input and returns a new `Point` with
296 /// intersected coordinates.
297 ///
298 /// Arguments:
299 ///
300 /// * `other`: The `other` parameter in the `intersect_with` method is a reference to another
301 /// `Point` struct with the same generic types `T1` and `T2` as the current `Point` struct. It is
302 /// used to compare and intersect the `xcoord` and `ycoord`
303 #[inline]
304 fn intersect_with(&self, other: &Point<T1, T2>) -> Self::Output {
305 Self::Output::new(
306 self.xcoord.intersect_with(&other.xcoord),
307 self.ycoord.intersect_with(&other.ycoord),
308 )
309 }
310}
311
312macro_rules! forward_xf_xf_binop {
313 (impl $imp:ident, $method:ident) => {
314 impl<'a, 'b, T1: Clone + Num, T2: Clone + Num> $imp<&'b Vector2<T1, T2>>
315 for &'a Point<T1, T2>
316 {
317 type Output = Point<T1, T2>;
318
319 #[inline]
320 fn $method(self, other: &Vector2<T1, T2>) -> Self::Output {
321 self.clone().$method(other.clone())
322 }
323 }
324 };
325}
326
327macro_rules! forward_xf_val_binop {
328 (impl $imp:ident, $method:ident) => {
329 impl<'a, T1: Clone + Num, T2: Clone + Num> $imp<Vector2<T1, T2>> for &'a Point<T1, T2> {
330 type Output = Point<T1, T2>;
331
332 #[inline]
333 fn $method(self, other: Vector2<T1, T2>) -> Self::Output {
334 self.clone().$method(other)
335 }
336 }
337 };
338}
339
340/// The above code is a Rust macro definition that creates an implementation for a binary operation on a
341/// custom type `Point<T1, T2>` and a reference to `Vector2<T1, T2>`. The macro is used to generate
342/// implementations for various traits and methods for the specified types. In this case, it generates
343/// an implementation for a specific binary operation method specified by the input parameters ``
344/// and ``.
345macro_rules! forward_val_xf_binop {
346 (impl $imp:ident, $method:ident) => {
347 /// The above code is implementing a trait for a specific type in Rust. The trait being
348 /// implemented is not explicitly mentioned in the code snippet, but based on the syntax used
349 /// (`impl Trait for Type`), it appears to be a custom trait defined elsewhere in the codebase.
350 /// The code is implementing the trait for a specific type `Point<T1, T2>`, where `T1` and `T2`
351 /// are generic types that must implement the `Clone` and `Num` traits.
352 impl<'a, T1: Clone + Num, T2: Clone + Num> $imp<&'a Vector2<T1, T2>> for Point<T1, T2> {
353 type Output = Point<T1, T2>;
354
355 /// The function implements a method that performs a specific operation on two Vector2
356 /// instances in Rust.
357 ///
358 /// Arguments:
359 ///
360 /// * `other`: The `other` parameter in the code snippet represents a reference to a
361 /// `Vector2` struct with generic types `T1` and `T2`. This parameter is used as the input
362 /// for the method being called on `self`.
363 #[inline]
364 fn $method(self, other: &Vector2<T1, T2>) -> Self::Output {
365 self.$method(other.clone())
366 }
367 }
368 };
369}
370
371macro_rules! forward_all_binop {
372 (impl $imp:ident, $method:ident) => {
373 forward_xf_xf_binop!(impl $imp, $method);
374 forward_xf_val_binop!(impl $imp, $method);
375 forward_val_xf_binop!(impl $imp, $method);
376 };
377}
378
379// arithmetic
380forward_all_binop!(impl Add, add);
381
382// (a, b) + (c, d) == (a + c), (b + d)
383impl<T1: Clone + Num, T2: Clone + Num> Add<Vector2<T1, T2>> for Point<T1, T2> {
384 type Output = Self;
385
386 /// Translate a new Point
387 ///
388 /// # Examples
389 ///
390 /// ```
391 /// use physdes::point::Point;
392 /// use physdes::vector2::Vector2;
393 ///
394 /// assert_eq!(Point::new(3, 4) + Vector2::new(5, 3), Point::new(8, 7));
395 /// assert_eq!(Point::new(3, 4) + Vector2::new(-5, -3), Point::new(-2, 1));
396 /// assert_eq!(Point::new(3, 4) + Vector2::new(5, -3), Point::new(8, 1));
397 /// assert_eq!(Point::new(3, 4) + Vector2::new(-5, 3), Point::new(-2, 7));
398 /// assert_eq!(Point::new(3, 4) + Vector2::new(0, 0), Point::new(3, 4));
399 /// assert_eq!(Point::new(3, 4) + Vector2::new(0, 5), Point::new(3, 9));
400 /// ```
401 #[inline]
402 fn add(self, other: Vector2<T1, T2>) -> Self::Output {
403 Self::Output::new(self.xcoord + other.x_, self.ycoord + other.y_)
404 }
405}
406
407forward_all_binop!(impl Sub, sub);
408
409/// (a, b) - (c, d) == (a - c), (b - d)
410/// The above Rust code snippet is implementing the subtraction operation for a Point struct. It defines
411/// the implementation of the Sub trait for subtracting a Vector2 from a Point. The code defines the
412/// behavior of subtracting a Vector2 from a Point to get a new Point with updated coordinates.
413impl<T1: Clone + Num, T2: Clone + Num> Sub<Vector2<T1, T2>> for Point<T1, T2> {
414 type Output = Self;
415
416 /// Translate a new Point
417 ///
418 /// # Examples
419 ///
420 /// ```
421 /// use physdes::point::Point;
422 /// use physdes::vector2::Vector2;
423 /// assert_eq!(Point::new(3, 4) - Vector2::new(5, 3), Point::new(-2, 1));
424 /// assert_eq!(Point::new(3, 4) - Vector2::new(-5, -3), Point::new(8, 7));
425 /// assert_eq!(Point::new(3, 4) - Vector2::new(5, -3), Point::new(-2, 7));
426 /// assert_eq!(Point::new(3, 4) - Vector2::new(-5, 3), Point::new(8, 1));
427 /// assert_eq!(Point::new(3, 4) - Vector2::new(0, 0), Point::new(3, 4));
428 /// assert_eq!(Point::new(3, 4) - Vector2::new(0, 5), Point::new(3, -1));
429 /// assert_eq!(Point::new(3, 4) - Vector2::new(5, 0), Point::new(-2, 4));
430 /// ```
431 #[inline]
432 fn sub(self, other: Vector2<T1, T2>) -> Self::Output {
433 Self::Output::new(self.xcoord - other.x_, self.ycoord - other.y_)
434 }
435}
436
437macro_rules! forward_xf_xf_binop2 {
438 (impl $imp:ident, $method:ident) => {
439 impl<'a, 'b, T1: Clone + Num, T2: Clone + Num> $imp<&'b Point<T1, T2>>
440 for &'a Point<T1, T2>
441 {
442 type Output = Vector2<T1, T2>;
443
444 #[inline]
445 fn $method(self, other: &Point<T1, T2>) -> Self::Output {
446 self.clone().$method(other.clone())
447 }
448 }
449 };
450}
451
452macro_rules! forward_xf_val_binop2 {
453 (impl $imp:ident, $method:ident) => {
454 impl<'a, T1: Clone + Num, T2: Clone + Num> $imp<Point<T1, T2>> for &'a Point<T1, T2> {
455 type Output = Vector2<T1, T2>;
456
457 #[inline]
458 fn $method(self, other: Point<T1, T2>) -> Self::Output {
459 self.clone().$method(other)
460 }
461 }
462 };
463}
464
465macro_rules! forward_val_xf_binop2 {
466 (impl $imp:ident, $method:ident) => {
467 impl<'a, T1: Clone + Num, T2: Clone + Num> $imp<&'a Point<T1, T2>> for Point<T1, T2> {
468 type Output = Vector2<T1, T2>;
469
470 #[inline]
471 fn $method(self, other: &Point<T1, T2>) -> Self::Output {
472 self.$method(other.clone())
473 }
474 }
475 };
476}
477
478macro_rules! forward_all_binop2 {
479 (impl $imp:ident, $method:ident) => {
480 forward_xf_xf_binop2!(impl $imp, $method);
481 forward_xf_val_binop2!(impl $imp, $method);
482 forward_val_xf_binop2!(impl $imp, $method);
483 };
484}
485
486// arithmetic
487forward_all_binop2!(impl Sub, sub);
488
489/// The above code is implementing the subtraction operation for a custom Point struct in Rust. It
490/// defines the behavior of subtracting one Point from another Point, resulting in a Vector2
491/// representing the displacement between the two points. The `sub` function takes two Point objects as
492/// input and returns a Vector2 object with the x and y coordinates calculated by subtracting the
493/// corresponding coordinates of the two points. The code also includes examples demonstrating the usage
494/// of the subtraction operation with different scenarios.
495impl<T1: Clone + Num, T2: Clone + Num> Sub for Point<T1, T2> {
496 type Output = Vector2<T1, T2>;
497
498 /// Displacement of two Points
499 ///
500 /// Arguments:
501 ///
502 /// * `other`: The `other` parameter is of the same type as `self` and represents the other object
503 /// that you want to subtract from `self`.
504 ///
505 /// # Examples
506 ///
507 /// ```
508 /// use physdes::point::Point;
509 /// use physdes::vector2::Vector2;
510 ///
511 /// assert_eq!(Point::new(3, 4) - Point::new(5, 3), Vector2::new(-2, 1));
512 /// assert_eq!(Point::new(3, 4) - Point::new(-5, -3), Vector2::new(8, 7));
513 /// assert_eq!(Point::new(3, 4) - Point::new(5, -3), Vector2::new(-2, 7));
514 /// assert_eq!(Point::new(3, 4) - Point::new(-5, 3), Vector2::new(8, 1));
515 /// assert_eq!(Point::new(3, 4) - Point::new(0, 0), Vector2::new(3, 4));
516 #[inline]
517 fn sub(self, other: Self) -> Self::Output {
518 Self::Output::new(self.xcoord - other.xcoord, self.ycoord - other.ycoord)
519 }
520}
521
522// Op Assign
523
524mod opassign {
525 use core::ops::{AddAssign, SubAssign};
526
527 use num_traits::NumAssign;
528
529 use crate::Point;
530 use crate::Vector2;
531
532 /// The above code is implementing the `AddAssign` trait for a custom type `Point<T1, T2>`. This
533 /// implementation allows instances of `Point<T1, T2>` to be added to instances of `Vector2<T1, T2>`
534 /// using the `+=` operator. Inside the `add_assign` function, the `xcoord` and `ycoord` fields of
535 /// the `Point` instance are updated by adding the corresponding `x_` and `y_` fields of the
536 /// `Vector2` instance.
537 impl<T1: Clone + NumAssign, T2: Clone + NumAssign> AddAssign<Vector2<T1, T2>> for Point<T1, T2> {
538 /// The `add_assign` function in Rust adds the x and y coordinates of another Vector2 to the
539 /// current Vector2.
540 ///
541 /// Arguments:
542 ///
543 /// * `other`: The `other` parameter in the `add_assign` function is of type `Vector2<T1, T2>`.
544 /// It represents another instance of the `Vector2` struct with potentially different generic
545 /// types `T1` and `T2`.
546 #[inline]
547 fn add_assign(&mut self, other: Vector2<T1, T2>) {
548 self.xcoord += other.x_;
549 self.ycoord += other.y_;
550 }
551 }
552
553 /// The above code is implementing the `SubAssign` trait for a custom type `Point<T1, T2>`. This
554 /// implementation allows instances of `Point` to be subtracted by instances of `Vector2<T1, T2>`
555 /// using the `-=` operator. Inside the implementation, it subtracts the `x_` and `y_` components of
556 /// the `other` vector from the `xcoord` and `ycoord` components of the `Point` respectively.
557 impl<T1: Clone + NumAssign, T2: Clone + NumAssign> SubAssign<Vector2<T1, T2>> for Point<T1, T2> {
558 /// The function `sub_assign` subtracts the `x_` and `y_` components of another `Vector2` from
559 /// the `xcoord` and `ycoord` components of the current `Vector2`.
560 ///
561 /// Arguments:
562 ///
563 /// * `other`: The `other` parameter in the `sub_assign` function is of type `Vector2<T1, T2>`.
564 /// It represents another instance of the `Vector2` struct with potentially different generic
565 /// types `T1` and `T2`. This parameter is used to subtract the `x_
566 #[inline]
567 fn sub_assign(&mut self, other: Vector2<T1, T2>) {
568 self.xcoord -= other.x_;
569 self.ycoord -= other.y_;
570 }
571 }
572
573 macro_rules! forward_op_assign {
574 (impl $imp:ident, $method:ident) => {
575 impl<'a, T1: Clone + NumAssign, T2: Clone + NumAssign> $imp<&'a Vector2<T1, T2>>
576 for Point<T1, T2>
577 {
578 #[inline]
579 fn $method(&mut self, other: &Vector2<T1, T2>) {
580 self.$method(other.clone())
581 }
582 }
583 };
584 }
585
586 forward_op_assign!(impl AddAssign, add_assign);
587 forward_op_assign!(impl SubAssign, sub_assign);
588}
589
590/// The above code is implementing the `Neg` trait for a custom type `Point<T1, T2>`. This
591/// implementation allows for negating instances of the `Point` type. The `Neg` trait requires defining
592/// an associated type `Output` and implementing the `neg` method which returns the negated version of
593/// the `Point` instance by negating its `xcoord` and `ycoord` values.
594impl<T1: Clone + Num + Neg<Output = T1>, T2: Clone + Num + Neg<Output = T2>> Neg for Point<T1, T2> {
595 type Output = Self;
596
597 /// Negate a Points
598 ///
599 /// # Examples
600 ///
601 /// ```
602 /// use physdes::point::Point;
603 ///
604 /// assert_eq!(-Point::new(3, 4), Point::new(-3, -4));
605 /// assert_eq!(-Point::new(0, 0), Point::new(0, 0));
606 #[inline]
607 fn neg(self) -> Self::Output {
608 Self::Output::new(-self.xcoord, -self.ycoord)
609 }
610}
611
612/// The above code is implementing the `Neg` trait for a reference to a `Point<T1, T2>` struct in Rust.
613/// The `Neg` trait is used for the negation operation (unary minus) on a value.
614impl<T1: Clone + Num + Neg<Output = T1>, T2: Clone + Num + Neg<Output = T2>> Neg
615 for &Point<T1, T2>
616{
617 type Output = Point<T1, T2>;
618
619 /// The function `neg` returns the negation of the cloned value.
620 #[inline]
621 fn neg(self) -> Self::Output {
622 -self.clone()
623 }
624}
625
626#[cfg(test)]
627fn hash<T: hash::Hash>(x: &T) -> u64 {
628 use std::collections::hash_map::RandomState;
629 use std::hash::{BuildHasher, Hasher};
630 let mut hasher = <RandomState as BuildHasher>::Hasher::new();
631 x.hash(&mut hasher);
632 hasher.finish()
633}
634
635#[cfg(test)]
636mod test {
637 #![allow(non_upper_case_globals)]
638
639 use super::*;
640 use crate::generic::Overlap;
641 use crate::interval::Interval;
642
643 pub const _0_0p: Point<i32, i32> = Point {
644 xcoord: 0,
645 ycoord: 0,
646 };
647 pub const _1_0p: Point<i32, i32> = Point {
648 xcoord: 1,
649 ycoord: 0,
650 };
651 pub const _1_1p: Point<i32, i32> = Point {
652 xcoord: 1,
653 ycoord: 1,
654 };
655 pub const _0_1p: Point<i32, i32> = Point {
656 xcoord: 0,
657 ycoord: 1,
658 };
659 pub const _neg1_1p: Point<i32, i32> = Point {
660 xcoord: -1,
661 ycoord: 1,
662 };
663 // pub const all_consts: [Point<i32, i32>; 4] = [_0_0p, _1_0p, _1_1p, _neg1_1p];
664 pub const _4_2p: Point<i32, i32> = Point {
665 xcoord: 4,
666 ycoord: 2,
667 };
668
669 #[test]
670 fn test_consts() {
671 // check our constants are what Point::new creates
672 fn test(c: Point<i32, i32>, r: i32, i: i32) {
673 assert_eq!(c, Point::new(r, i));
674 }
675 test(_0_0p, 0, 0);
676 test(_1_0p, 1, 0);
677 test(_1_1p, 1, 1);
678 test(_neg1_1p, -1, 1);
679 }
680
681 #[test]
682 fn test_hash() {
683 let a = Point::new(0i32, 0i32);
684 let b = Point::new(1i32, 0i32);
685 let c = Point::new(0i32, 1i32);
686 assert!(hash(&a) != hash(&b));
687 assert!(hash(&b) != hash(&c));
688 assert!(hash(&c) != hash(&a));
689 }
690
691 #[test]
692 fn test_overlap() {
693 let a = Point::new(0i32, 0i32);
694 let b = Point::new(1i32, 0i32);
695 assert!(!a.overlaps(&b));
696 }
697
698 #[test]
699 fn test_contain() {
700 let a = Point::new(0i32, 0i32);
701 let b = Point::new(1i32, 0i32);
702 assert!(!a.contains(&b));
703 }
704
705 #[test]
706 fn test_min_dist_with() {
707 let a = Point::new(3i32, 5i32);
708 let b = Point::new(6i32, 4i32);
709 assert_eq!(a.min_dist_with(&b), 4);
710 }
711
712 #[test]
713 fn test_add() {
714 let a = Point::new(0i32, 0i32);
715 let b = Point::new(1i32, 0i32);
716 let v = Vector2::new(5i32, 6i32);
717 assert_eq!(a, a + v - v);
718 assert_eq!(b, b - v + v);
719 }
720
721 #[test]
722 fn test_sub() {
723 let a = Point::new(0i32, 0i32);
724 let b = Point::new(1i32, 0i32);
725 let v = Vector2::new(5i32, 6i32);
726 assert_eq!(a, a - v + v);
727 assert_eq!(b, b + v - v);
728 }
729
730 #[test]
731 fn test_neg() {
732 let a = Point::new(0i32, 0i32);
733 let b = Point::new(1i32, 0i32);
734 let c = Point::new(0i32, 1i32);
735 assert_eq!(a, -(-a));
736 assert_eq!(b, -(-b));
737 assert_eq!(c, -(-c));
738 }
739
740 #[test]
741 fn test_add_assign() {
742 let mut a = Point::new(1i32, 0i32);
743 let b = Point::new(6i32, 6i32);
744 let v = Vector2::new(5i32, 6i32);
745 a += v;
746 assert_eq!(a, b);
747 }
748
749 #[test]
750 fn test_sub_assign() {
751 let mut a = Point::new(1i32, 0i32);
752 let b = Point::new(-4i32, -6i32);
753 let v = Vector2::new(5i32, 6i32);
754 a -= v;
755 assert_eq!(a, b);
756 }
757
758 #[test]
759 fn test_neg_assign() {
760 let mut a = Point::new(1i32, 0i32);
761 let b = Point::new(-1i32, 0i32);
762 let c = Point::new(1i32, 0i32);
763 a = -a;
764 assert_eq!(a, b);
765 a = -a;
766 assert_eq!(a, c);
767 }
768
769 #[test]
770 fn test_point() {
771 let a = Point::new(4, 8);
772 let b = Point::new(5, 6);
773 assert!(a < b);
774 assert!(a <= b);
775 assert_ne!(b, a);
776 }
777
778 #[test]
779 fn test_point2() {
780 let a = Point::new(3, 4);
781 let r = Point::new(Interval::new(3, 4), Interval::new(5, 6)); // Rectangle
782 assert!(!r.contains(&a));
783 assert!(r.contains(&Point::new(4, 5)));
784 assert!(!r.overlaps(&a));
785 assert!(r.overlaps(&Point::new(4, 5)));
786 assert!(r.overlaps(&Point::new(4, 6)));
787 // assert_eq!(r.intersect_with(&Point::new(4, 5)), Point::new(Interval::new(4, 4), Interval::new(5, 5)));
788 }
789
790 #[test]
791 fn test_transform() {
792 let mut a = Point::new(3, 5);
793 let b = Vector2::new(5, 7);
794 assert_eq!(a + b, Point::new(8, 12));
795 assert_eq!(a - b, Point::new(-2, -2));
796 a += b;
797 assert_eq!(a, Point::new(8, 12));
798 a -= b;
799 assert_eq!(a, Point::new(3, 5));
800 assert_eq!(a.flip(), Point::new(5, 3));
801 }
802
803 #[test]
804 fn test_displacement() {
805 let a = Point::new(3, 5);
806 let b = Point::new(5, 7);
807 let c = Point::new(7, 8);
808 assert_eq!(a.displace(&b), Vector2::new(-2, -2));
809 assert_eq!(a.displace(&c), Vector2::new(-4, -3));
810 assert_eq!(b.displace(&c), Vector2::new(-2, -1));
811 }
812
813 #[test]
814 fn test_enlarge() {
815 let _a = Point::new(3, 5);
816 // assert_eq!(a.enlarge_with(2), Point::new(Interval::new(1, 5), Interval::new(3, 7)));
817 }
818
819 #[test]
820 fn test_hull() {
821 let a = Point::new(3, 5);
822 let b = Point::new(5, 7);
823 assert_eq!(
824 a.hull_with(&b),
825 Point::new(Interval::new(3, 5), Interval::new(5, 7))
826 );
827 }
828
829 #[test]
830 fn test_min_dist_with2() {
831 let a = Point::new(3, 5);
832 let b = Point::new(5, 7);
833 assert_eq!(a.min_dist_with(&b), 4);
834 }
835}