package com.project.shared.data; import java.io.Serializable; import com.google.gwt.user.client.rpc.IsSerializable; import com.project.shared.interfaces.ICloneable; public class Point2D implements Serializable, IsSerializable, ICloneable<Point2D> { private static final long serialVersionUID = 1L; /** x = 0, y = 0 */ public static final Point2D zero = new Point2D(0, 0); /** x = 1, y = 1 */ public static final Point2D ones = new Point2D(1, 1); // These should have been 'final', but then they will not be serialized. private int _x; private int _y; public Point2D() { this._x = 0; this._y = 0; } public Point2D(int x, int y) { this._x = x; this._y = y; } public Point2D(Point2D pos) { this(pos.getX(), pos.getY()); } public Point2D getAbs() { return new Point2D(Math.abs(this._x), Math.abs(this._y)); } public int getX() { return this._x; } public int getY() { return this._y; } @Override public boolean equals(Object other) { if (null == other) { return false; } if (other.getClass() != this.getClass()) { return false; } Point2D otherPoint = (Point2D) other; return ((this._x == otherPoint._x) && (this._y == otherPoint._y)); } @Override public int hashCode() { return (this._x * 51 + this._y * 37) * 13; } public Point2D minus(Point2D other) { return new Point2D(this._x - other._x, this._y - other._y); } public Point2D mulCoords(double xMul, double yMul) { return new Point2D((int) Math.round(this._x * xMul), (int) Math.round(this._y * yMul)); } public Point2D mul(double scalar) { return new Point2D((int) Math.round(this._x * scalar), (int) Math.round(this._y * scalar)); } public Point2D plus(Point2D other) { return new Point2D(this._x + other._x, this._y + other._y); } public int dotProduct(Point2D other) { return (this._x * other._x + this._y * other._y); } /*** * Returns x*x + y*y. Equivalent to point.dotProduct(point) or point.getRadius() squared. * @return */ public int getPower() { return this.dotProduct(this); } /** * Returns x + y (equivalent to p.{@link #dotProduct}({@link #ones})) */ public int sumCoords() { return this._x + this._y; } public double getRadians() { return Math.atan2(this._y, this._x); } public double getRadius() { return Math.sqrt(this.getPower()); } /** * Returns max(x, y) */ public int getMaxCoord() { return Math.max(this._x, this._y); } public Point2D getRotated(double radians) { return this.getRotated(radians, 0, 0); } /** * Returns the result of rotating this point by 90 degrees. * This method is much faster than using {@link #getRotated(double)} or its variants for these angles. * @param times Number of times to rotate by 90 degrees. */ public Point2D getRotatedBy90Deg() { return new Point2D(-this._y, this._x); } /** * Returns the result of rotating the point around the given axis point */ public Point2D getRotated(double radians, Point2D axisOffset) { int tx = axisOffset.getX(); int ty = axisOffset.getY(); return getRotated(radians, tx, ty); } private Point2D getRotated(double radians, int tx, int ty) { double cos = Math.cos(radians); double sin = Math.sin(radians); int sx = this._x - tx; int sy = this._y - ty; return new Point2D((int) Math.round(sx * cos - sy * sin + tx), (int) Math.round(sx * sin + sy * cos + ty)); } public static Point2D fromPolar(double radius, double radians) { return new Point2D((int)Math.round(radius * Math.cos(radians)), (int) Math.round(radius * Math.sin(radians))); } public static Point2D max(Point2D first, Point2D other) { return new Point2D(Math.max(first._x, other._x), Math.max(first._y, other._y)); } public static Point2D min(Point2D first, Point2D other) { return new Point2D(Math.min(first._x, other._x), Math.min(first._y, other._y)); } /** * Returns a new point which is this point's coordinates limited to be at least <code>min</code> and at most * <code>max</code>, with priority to being more than <code>min</code> */ public Point2D limitTo(Point2D min, Point2D max) { return Point2D.max(min, Point2D.min(this, max)); } @Override public String toString() { return "Point2D(x=" + this.getX() + ", y=" + this.getY() + ")"; } /** * Returns a vector in the same direction with unit size. */ public Point2D getNormalized() { return this.getNormalized(1); } /** * Returns a vector in the same direction with the given size. */ public Point2D getNormalized(double size) { if ((0 == this._x) && (0 == this._y)) { return new Point2D(0, 0); } return this.mul(size/this.getRadius()); } /** * Returns a unit normal (unit orthogonal vector) to this one. * In other words, a vector that is perpendicular to this and has radius = 1. */ public Point2D getUnitNormal() { Point2D normalized = this.getNormalized(); return new Point2D(-normalized.getY(), normalized.getX()); } @Override public Point2D getClone() { return new Point2D(this); } }