1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
use crate::{
    primitives::{Arc, Line, Point},
    Vector,
};

/// Something which can be moved around "rigidly" in *Drawing Space*.
pub trait Translate {
    fn translate(&mut self, displacement: Vector);

    fn translated(&self, displacement: Vector) -> Self
    where
        Self: Sized + Clone,
    {
        let mut clone = self.clone();
        clone.translate(displacement);

        clone
    }
}

impl<'t, T: Translate + ?Sized> Translate for &'t mut T {
    fn translate(&mut self, displacement: Vector) {
        (*self).translate(displacement);
    }
}

impl Translate for Vector {
    fn translate(&mut self, displacement: Vector) { *self += displacement; }
}

impl Translate for Point {
    fn translate(&mut self, displacement: Vector) {
        self.location += displacement;
    }
}

impl Translate for Line {
    fn translate(&mut self, displacement: Vector) {
        self.start += displacement;
        self.end += displacement;
    }
}

impl Translate for Arc {
    fn translate(&mut self, displacement: Vector) {
        *self = Arc::from_centre_radius(
            self.centre() + displacement,
            self.radius(),
            self.start_angle(),
            self.sweep_angle(),
        );
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn vector() {
        let original = Vector::new(3.0, 4.0);
        let delta = Vector::new(-5.0, 2.5);

        let got = original.translated(delta);

        assert_eq!(got, original + delta);
    }
}