summaryrefslogtreecommitdiffstats
path: root/svgbob/src/loc.rs
blob: fa83d11b84ca0a0ad4559889c9c533e7ef9d54f0 (plain)
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
use std::cmp::Ordering;
use location::Location;
use location::Direction::{Top,Bottom,Left,Right,TopLeft,TopRight,BottomLeft,BottomRight};

/// Location of Block relative to the Grid
/// This the equivalent to the cell cation in the grid
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq)]
pub struct Loc {
    pub x: i32,
    pub y: i32,
}

impl Ord for Loc{
    fn cmp(&self, other:&Loc) -> Ordering{
        if let Some(order) = self.partial_cmp(other){
            return order
        }
        Ordering::Less
    }
}

impl Loc {
    pub fn new(x: i32, y: i32) -> Loc {
        Loc { x: x, y: y }
    }

    pub fn from_location(&self, location: &Location) -> Loc {
        let mut loc = self.clone();
        for &(ref direction, step) in &location.0 {
            for _ in 0..step {
                match *direction {
                    TopLeft => {
                        loc = loc.top().left();
                    }
                    Top => {
                        loc = loc.top();
                    }
                    TopRight => {
                        loc = loc.top().right();
                    }
                    Left => {
                        loc = loc.left();
                    }
                    Right => {
                        loc = loc.right();
                    }
                    BottomLeft => {
                        loc = loc.bottom().left();
                    }
                    Bottom => {
                        loc = loc.bottom();
                    }
                    BottomRight => {
                        loc = loc.bottom().right();
                    }
                };
            }
        }
        loc
    }

    pub fn top(&self) -> Loc {
        Loc {
            x: self.x,
            y: self.y - 1,
        }
    }
    pub fn left(&self) -> Loc {
        Loc {
            x: self.x - 1,
            y: self.y,
        }
    }
    pub fn in_left(&self, step: i32) -> Loc{
        Loc{
            x: self.x - step,
            y: self.y
        }
    }
    pub fn bottom(&self) -> Loc {
        Loc {
            x: self.x,
            y: self.y + 1,
        }
    }
    pub fn right(&self) -> Loc {
        Loc {
            x: self.x + 1,
            y: self.y,
        }
    }

    pub fn in_right(&self, step: i32) -> Loc {
        Loc{
            x: self.x + step,
            y: self.y
        }
    }

    pub fn top_left(&self) -> Loc {
        Loc {
            x: self.x - 1,
            y: self.y - 1,
        }
    }

    pub fn top_right(&self) -> Loc {
        Loc {
            x: self.x + 1,
            y: self.y - 1,
        }
    }

    pub fn bottom_left(&self) -> Loc {
        Loc {
            x: self.x - 1,
            y: self.y + 1,
        }
    }

    pub fn bottom_right(&self) -> Loc {
        Loc {
            x: self.x + 1,
            y: self.y + 1,
        }
    }

    /// make a lower and upper bound loc with
    /// ry units top + ry units bottom
    /// rx units left + rx units right
    pub fn get_range(&self, rx: i32, ry: i32) -> (Loc, Loc) {
        let loc1 = Loc::new(self.x - rx, self.y - ry);
        let loc2 = Loc::new(self.x + rx, self.y + ry);
        (loc1, loc2)
    }
}