summaryrefslogtreecommitdiff
path: root/src/ch/epfl/maze/util/Vector2D.java
blob: 52e1e55881c4c95f5a6953c013c084f6e57fa309 (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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
package ch.epfl.maze.util;

/**
 * Immutable 2-dimensional vector (<i>x</i>, <i>y</i>).
 */
public final class Vector2D {

    /* shift constant to compute the hash */
    private static final int SHIFT = 1000;

    private static final int ZERO = 0;

    /* 2-dimension coordinates */
    private final int mX, mY;

    /**
     * Constructs a 2-dimensional vector.
     *
     * @param x Horizontal coordinate
     * @param y Vertical coordinate
     */
    public Vector2D(int x, int y) {
        mX = x;
        mY = y;
    }

    /**
     * Constructs a 2-dimensional zero vector.
     */
    public Vector2D() {
        this(Vector2D.ZERO, Vector2D.ZERO);
    }

    /**
     * Adds two coordinates to the vector.
     *
     * @param x Horizontal coordinate to add
     * @param y Vertical coordinate to add
     * @return The result of an addition with two coordinates
     */
    public Vector2D add(int x, int y) {
        return new Vector2D(mX + x, mY + y);
    }

    /**
     * Adds a vector to the vector.
     *
     * @param v Vector to add
     * @return The result of the addition with the vector
     */
    public Vector2D add(Vector2D v) {
        return add(v.mX, v.mY);
    }

    /**
     * Subtracts two coordinates to the vector.
     *
     * @param x Horizontal coordinate to subtract
     * @param y Vertical coordinate to subtract
     * @return The result of the subtraction with the vector
     */
    public Vector2D sub(int x, int y) {
        return new Vector2D(mX - x, mY - y);
    }

    /**
     * Subtracts a vector to the vector.
     *
     * @param v Vector to subtract
     * @return The result of the subtraction with the vector
     */
    public Vector2D sub(Vector2D v) {
        return sub(v.mX, v.mY);
    }

    /**
     * Negates the vector.
     *
     * @return The negated version of the vector
     */
    public Vector2D negate() {
        return new Vector2D(-mX, -mY);
    }

    /**
     * Multiplies the coordinates of the vector by a scalar.
     *
     * @param scalar Number to multiply the coordinates with
     * @return The result of the multiplication with a scalar
     */
    public Vector2D mul(int scalar) {
        return new Vector2D(scalar * mX, scalar * mY);
    }

    /**
     * Divides the coordinates of the vector by a scalar.
     *
     * @param scalar Number to divide the coordinates with
     * @return The result of the division with a scalar
     */
    public Vector2D div(int scalar) {
        return new Vector2D(scalar / mX, scalar / mY);
    }

    /**
     * Normalizes the vector.
     *
     * @return The normalized version of the vector
     */
    public Vector2D normalize() {
        double dist = dist();
        return new Vector2D((int) (mX / dist), (int) (mY / dist));
    }

    /**
     * The Euclidean distance of the vector.
     *
     * @return The length of the vector
     */
    public double dist() {
        return Math.sqrt(mX * mX + mY * mY);
    }

    /**
     * Adds a direction to the vector
     *
     * @param d Direction to add
     * @return The result of the addition with the direction
     */
    public Vector2D addDirectionTo(Direction d) {
        switch (d) {
            case UP:
                return new Vector2D(mX, mY - 1);

            case DOWN:
                return new Vector2D(mX, mY + 1);

            case LEFT:
                return new Vector2D(mX - 1, mY);

            case RIGHT:
                return new Vector2D(mX + 1, mY);

            case NONE:
            default:
                return new Vector2D(mX, mY);
        }
    }

    /**
     * Converts the vector to the closest corresponding direction.
     *
     * @return The closest direction corresponding to the vector
     */
    public Direction toDirection() {
        Vector2D normal = this.normalize();

        if (normal.mX == 0 && normal.mY == 1) {
            return Direction.DOWN;
        } else if (normal.mX == 0 && normal.mY == -1) {
            return Direction.UP;
        } else if (normal.mX == 1 && normal.mY == 0) {
            return Direction.RIGHT;
        } else if (normal.mX == -1 && normal.mY == 0) {
            return Direction.LEFT;
        } else {
            return Direction.NONE;
        }
    }

    /**
     * Returns the horizontal coordinate of the vector.
     *
     * @return x-coordinate of the vector
     */
    public int getX() {
        return mX;
    }

    /**
     * Returns the vertical coordinate of the vector.
     *
     * @return y-coordinate of the vector
     */
    public int getY() {
        return mY;
    }

    @Override
    public String toString() {
        return "(" + mX + ", " + mY + ")";
    }

    @Override
    public int hashCode() {
        return mX * SHIFT + mY;
    }

    @Override
    public boolean equals(Object o) {
        if (o == null) {
            return false;
        }
        if (o.getClass() != this.getClass()) {
            return false;
        }

        return o.hashCode() == this.hashCode();
    }

}