package ch.epfl.maze.util; /** * Immutable 2-dimensional vector (x, y). */ 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(); } }