arcs/algorithms/
translate.rs

1use crate::{
2    algorithms::AffineTransformable,
3    components::{BoundingBox, DrawingObject, Geometry, Viewport},
4    Arc, Transform, Vector,
5};
6
7/// Something which can be moved around "rigidly" in *Drawing Space*.
8pub trait Translate {
9    /// Translate this object in-place.
10    fn translate(&mut self, displacement: Vector);
11
12    /// A convenience method for getting a translated copy of this object.
13    fn translated(&self, displacement: Vector) -> Self
14    where
15        Self: Sized + Clone,
16    {
17        let mut clone = self.clone();
18        clone.translate(displacement);
19
20        clone
21    }
22}
23
24impl<A: AffineTransformable> Translate for A {
25    fn translate(&mut self, displacement: Vector) {
26        self.transform(Transform::create_translation(
27            displacement.x,
28            displacement.y,
29        ));
30    }
31}
32
33impl Translate for Arc {
34    fn translate(&mut self, displacement: Vector) {
35        *self = Arc::from_centre_radius(
36            self.centre().translated(displacement),
37            self.radius(),
38            self.start_angle(),
39            self.sweep_angle(),
40        );
41    }
42}
43
44impl Translate for BoundingBox {
45    fn translate(&mut self, displacement: Vector) {
46        *self = BoundingBox::new_unchecked(
47            self.bottom_left().translated(displacement),
48            self.top_right().translated(displacement),
49        );
50    }
51}
52
53impl Translate for Viewport {
54    fn translate(&mut self, displacement: Vector) {
55        self.centre.translate(displacement);
56    }
57}
58
59impl Translate for Geometry {
60    fn translate(&mut self, displacement: Vector) {
61        match self {
62            Geometry::Point(ref mut point) => point.translate(displacement),
63            Geometry::Line(ref mut line) => line.translate(displacement),
64            Geometry::Arc(ref mut arc) => arc.translate(displacement),
65        }
66    }
67}
68
69impl Translate for DrawingObject {
70    fn translate(&mut self, displacement: Vector) {
71        self.geometry.translate(displacement);
72    }
73}
74
75#[cfg(test)]
76mod tests {
77    use super::*;
78    use crate::Point;
79
80    #[test]
81    fn translate_point() {
82        let original = Point::new(3.0, 4.0);
83        let delta = Vector::new(-5.0, 2.5);
84
85        let got = original.translated(delta);
86
87        assert_eq!(got, original + delta);
88    }
89
90    #[test]
91    fn translate_bounding_box() {
92        let first = Point::new(-2.0, 1.5);
93        let second = Point::new(4.0, 3.7);
94        let displacement = Vector::new(1.0, -1.0);
95        let original = BoundingBox::new(first, second);
96
97        let expected = BoundingBox::new(
98            Point::new(-2.0 + 1.0, 1.5 + -1.0),
99            Point::new(4.0 + 1.0, 3.7 + -1.0),
100        );
101        let actual = original.translated(displacement);
102
103        assert_eq!(actual, expected);
104    }
105}