/**
 *  Caractérisation de la notion usuelle de point en geometrie dans un espace en
 *  deux dimensions. C'est a dire un objet caracterise par une abcisse et une
 *  ordonnee.
 *
 * @author     Marc Champesme
 * @version    18 février 2002
 * @version    11 mars 2004
 */

public class Point {
	private int x;
	private int y;


	/**
	 *  Initialise un point de coordonees (0, 0)
	 */
	//@ ensures isOrigine();
	public Point() {
		// Cette methode pourrait aussi bien etre vide, puisque les champs
		// de type int sont initialises a zero par defaut
		x = y = 0;
	}


	/**
	 *  Initialise un point dont l'abcisse et l'odonnee sont identiques et egales a
	 *  la valeur donnee en parametre
	 *
	 * @param  xy  La valeur de l'abcisse et de l'ordonnee du nouveau point
	 */
	//@ ensures (getX() == xy) && (getY() == xy);
	public Point(int xy) {
		x = y = xy;
	}


	/**
	 *  Initialise un point dont l'abcisse et l'odonnee sont donnees en parametre.
	 *
	 * @param  x  Description of Parameter
	 * @param  y  Description of Parameter
	 */
	//@ ensures    (getX() == x) && (getY() == y);
	public Point(int x, int y) {
		this.x = x;
		this.y = y;
	}


	/**
	 *  Clonage d'un point.
	 *
	 * @param  unPoint  le point a cloner
	 */
	/*@ requires unPoint != null;
	  @ ensures this.equals(unPoint);
	  @*/
	public Point(Point unPoint) {
		this(unPoint.getX(), unPoint.getY());
	}


	/**
	 *  Test d'égalité
	 *
	 * @param  obj      Description of the Parameter
	 * @return          true si les deux points ont les memes coordonnées false
	 *      sinon
	 */
	/*@ also
	  @ ensures ((obj == null) || !(\typeof(obj) == \type(Point))) ==> (\result == false);
	  @ ensures ((obj != null) && (\typeof(obj) == \type(Point))) ==>
	  @ 		\result ==  (getX() == ((Point) obj).getX())
	  @			&& (getY() == ((Point) obj).getY());
	  @ pure
	  @*/
	public boolean equals(Object obj) {
		if (!(obj instanceof Point)) {
			return false;
		}
		Point unPoint = (Point) obj;
		return (getX() == unPoint.getX() && getY() == unPoint.getY());
	}




	/**
	 *  Renvoie l'abcisse du point
	 *
	 * @return    L'abcisse du point
	 */
	//@ pure
	public int getX() {
		return x;
	}


	/**
	 *  Renvoie l'ordonnee du point
	 *
	 * @return    L'ordonnee du point
	 */
	//@ pure
	public int getY() {
		return y;
	}


	/**
	 *  Cree un nouveau point symetrique du point courant par rapport a l'axe des
	 *  ordonnees
	 *
	 * @return    Un point symetrique
	 */
	/*@ ensures    \fresh(\result);
	  @ ensures    \result.getX() == -getX();
	  @ ensures    \result.getY() == getY();
	  @ pure
	  @*/
	public Point symetrie() {
		return (new Point(-x, y));
	}


	/**
	 *  Cree un nouveau point par translation de deltaX selon l'axe des abcisses et
	 *  de deltaY selon l'axe des ordonnées.
	 *
	 * @param  deltaX  valeur a ajouter a l'abcisse
	 * @param  deltaY  valeur a ajouter a l'ordonnées
	 * @return         Description of the Return Value
	 */
	/*@
	  @ ensures	\fresh(\result);
	  @ ensures	\result.getX() == getX() + deltaX;
	  @ ensures	\result.getY() == getY() + deltaY;
	  @ pure
	  @*/
	public Point translater(int deltaX, int deltaY) {
		return new Point(x + deltaX, y + deltaY);
	}


	/**
	 *  Teste si le point courant est l'origine du repère.
	 *
	 * @return    Vrai si le point est l'origine du repère, faux sinon.
	 */
	/*@ ensures \result == ((getX() == 0) && (getY() == 0));
	  @ pure
	  @*/
	public boolean isOrigine() {
		return (x == 0) && (y == 0);
	}


	/**
	 *  Calcule la distance du point courant au point passé en argument.
	 *
	 * @param  autrePoint  Point dont on souhaite connaitre la distance du point
	 *      courant
	 * @return             Distance du point courant au point autrePoint
	 */
	/*@ requires autrePoint != null;
	  @ pure
	  @*/
	public double distanceA(Point autrePoint) {
		double dx;
		double dy;

		dx = getX() - autrePoint.getX();
		dy = getY() - autrePoint.getY();
		return Math.sqrt(dx * dx + dy * dy);
	}


	/**
	 *  Description of the Method
	 *
	 * @return    Description of the Return Value
	 */
	/*@ also
	  @ ensures \result != null;
	  @ pure
	  @*/
	public String toString() {
		return "(" + x + ", " + y + ")";
	}
}

