
import java.text.*;
import java.util.*;
import java.lang.*;

/**<strong> Clase que implementa la representation de puntos 
*bi-dimensionales.<strong>
*Contiene varios metodos usados en la manipulacion de formas geometricas.
*@author Thomas Genet
*/

public class Point
{
/**
*Contiene la coordenada X del punto en el sistema cartesiano.
*/
public double X = 0;
/**
*Contiene la coordenada Y del punto en el sistema cartesiano.
*/
public double Y = 0;
/*
*formato usado para visualizar las coordenadas y para hacer comparaciones.
*/
private DecimalFormat miformato = new DecimalFormat("###.###");

/**
*Constructor que usa las coordenadas cartesianas.
*Construye un punto ubiquado en las coordenadas dadas en parametros.
*@param x Coordenada X en el sistema cartesiano.
*@param y Coordenada Y en el sistema cartesiano.
*/
public Point(double x, double y)
{
this.X = x;
this.Y = y;
}


/**
* Construye un punto identico al Point dado en parametro.
* @param p Point cuyas coordinadas son usadas para crear al nuevo punto.
*/
public Point(java.awt.Point p)
{
this.X = (double)p.getX();
this.Y = (double)p.getY();
}

/**
* Construye un punto identico al punto dado en parametro.
* @param p Punto que contiene las carasteristicas del nuevo punto.
*/
public Point(Point p)
{
this.X = p.X;
this.Y = p.Y;
}

/**Compara el punto dado en parametro con el punto pendiente.
*@param p Punto comparado con el punto pendiente.
*@return True si los dos puntos son iguales, False sino.
*/
public boolean equals (Point p)
{
/*
*Comproba si los dos puntos tienen la misma referencia.
*/
if (this == p) return true; 

if (p == null) return false; //Comproba que existe un punto dado en parametro.
//Comproba si los dos elementos son de la misma clase.
if (getClass() != p.getClass()) return false; 

Point otro = (Point)p;

/*
*Si una coordenada esta igual a -0, la fijamos igual a 0.
*/
if (miformato.format(this.X).equals("-0")) X = 0;
if (miformato.format(this.Y).equals("-0")) X = 0;
if (miformato.format(otro.X).equals("-0")) otro.X = 0;
if (miformato.format(otro.Y).equals("-0")) otro.Y = 0;

/*
*Para comparar las coordenadas de los dos puntos, usamos el formato "miformato"
*para redondear las coordenadas.
*/

return (miformato.format(this.X).equals(miformato.format(otro.X)))
&& (miformato.format(this.Y).equals(miformato.format(otro.Y)));
}

/**Escala le distancia entre el punto pendiente y el punto especificado
* del factor dado
* @param centro Punto respecto del cual se hace el escalamiento de la distancia.
* @param factor Factor usado en el escalamiento de la distancia. >1 corresponde
* a amplificación, <1 corresponde a reducción.
*/
public void escalar (Point centro, double factor)
{
X = centro.X + (this.X - centro.X) * factor;
Y = centro.Y + (this.Y - centro.Y) * factor;
}
/** Rota el punto respecto al punto especificado en un ángulo dado.
* @param centro Punto respecto del cual se hace la rotación.
* @param deltaAngulo ángulo de rotación en radianes.
*/
public void rotar(Point centro, double deltaAngulo)
{
/**
*Creamos una linea entre el punto pendiente y el centro de la rotacion.
*/
Linea lin = new Linea (centro, this);
/*
*Pendiente de esta linea.
*/
double pendiente = lin.getPendiente();

/*
*La pendiente "angulo" de la linea entre el centro de la rotacion y el punto
*que buscamos se obtiene sumando la pendiente de L y el angulo de la rotacion.
*/
double angulo = pendiente + deltaAngulo;
/*
*Expresamos angulo entre -2*Pi y 2*Pi.
*/
while (angulo > (2 * Math.PI)) angulo -= 2 * Math.PI;
while (angulo < (-2 * Math.PI)) angulo += 2 * Math.PI;

/*
*Se usa las coordinadas polares del punto con respecto al punto centro para
*efectuar la rotacion.
*/
X = -lin.getDistancia() * Math.sin(angulo) + centro.X;
Y = lin.getDistancia() * Math.cos(angulo) + centro.Y;
}

/**
* Describe el punto en un String.
* @return Una Sring segun el formato:"Esto es un punto: (" + X + ";" + Y) + ")".
*/
public String toString ()
{
/**
*Usamos el formato "miformato" para visualizar las coordenadas
*redondeadas del punto.
*/
String str = new String("(" + miformato.format(X) + ";"
+ miformato.format(Y) + ")");
return str;
}

/**
* Duplica el punto.
* @return un punto identico al punto pendiente.
*/
public Point clone()
{
Point copia = new Point(X , Y);
return copia;
}

}
