import java.awt.*;
import java.awt.geom.*;
import java.lang.Math;
import java.util.*;
import java.lang.*;
import java.text.*;


/**
* <strong>Clase que Implementa la representacion de un rectangulo en un 
* entorno bi-dimensional.<strong>
* @author Thomas Genet
*/
class Circulo extends Forma
{
/*
* Elipse usada para dibujar el Circulo.
*/
private Ellipse2D.Double elipse;

/*
*Contiene el punto central del Circulo.
*/
private Point centro;
/*
*Contiene el radio del Circulo.
*/
private double radio;
/**
*Formato usado para visualizar las coordenadas del centro en el metodo
* toString.
*/
private DecimalFormat miformato = new DecimalFormat("###.###");
private static final int NUMBER_OF_SQUARE = 4;
/**
* Index del cuadradito verde de seleccion en el arreglo greenSquare.
*/
private static final int RIGHT_SQUARE = 0;
private static final int LEFT_SQUARE = 1;
private static final int  DOWN_SQUARE = 2;
private static final int TOP_SQUARE = 3;

/**
* Arreglo de Rectangle2D que contiene los cuadraditos verdes de selección
*del Circulo.
*/
private Rectangle2D[] greenSquare;


/**Constructor
* Construye un Circulo de centro (0;0) del radio dado en parametro.
*@param r Radio del circulo.
*/
public Circulo(double r)
{
centro = new Point (0, 0);
radio = r;
}


/**Constructor
* Construye un Circulo de centro center y de radio r.
* @param center Punto central del circulo.
* @param r Radio del circulo.
*/
public Circulo (Point center, double r)
{
centro = new Point (center.X, center.Y);
radio = r;
elipse = new Ellipse2D.Double(center.X - radio, center.Y - radio,
2 * radio, 2 * radio);
}
  

/**
* Metodo que dibuja el Circulo en el Graphics2D dado en parametro.
* @param g2d Graphics2D donde el Circulo se dibuja.
*/
 public void paintComponent(Graphics2D g2d)
    {
    elipse.setFrame(centro.X - radio, centro.Y - radio, 2 * radio, 2 * radio);
    g2d.draw(elipse);
    }

/**
* Metodo que permite cambiar el valor del radio del Circulo al valor dado en
* parametro.
* @param r Nuevo valor del radio del Circulo.
*/
public void setRadio (double r)
{
radio = r;
elipse.setFrame(centro.X - radio, centro.Y - radio, 2 * radio, 2 * radio);
}
/**
* Metodo que permite acceder al centro del circulo.
* @return el punto central del circulo.
*/
public Point centro()
{
return centro;
}

/**
* Metodo que permite acceder al radio del circulo.
* @return el radio del circulo.
*/
public double radio()
{
return radio;
}

/**
* Describe el circulo en un String.
* @return Una string segun el formato:"Este es un Circulo:
* centro("+centro.X+";"+centro.Y+"), Radio = "+radio.
*/
public String toString()
{
String str = new String("Este es un Circulo:centro"
+ centro.toString() + ", Radio=" + radio);
return str;
}

/** Escala el circulo respecto al punto c en un factor dado.
* @param c Punto respecto del cual se hace el escalamiento.
* @param factor Factor usado en el escalamiento. >1 corresponde a amplificación,
*<1 corresponde a reducción.
*/
public void escalar (Point c, double factor)
{
centro.escalar(c, factor);
radio = radio * factor;
}

/**Traslada el circulo dedesplazandolo en sentido X e Y.
* @param deltaX desplazamiento en sentido horizontal.
* @param deltaY desplazamiento en sentido vertical.
*/
public void trasladar(double deltaX, double deltaY)
{
centro.X += deltaX;
centro.Y += deltaY;
}

/** Rota el circulo respecto al punto c en un ángulo dado.
* @param c Punto respecto del cual se hace la rotación.
* @param deltaAngulo ángulo de rotación en radianes.
*/
public void rotar(Point c, double deltaAngulo)
{ 
centro.rotar(c, deltaAngulo);
}

/**Compara la forma dada en parametro con el Circulo.
*@param f Forma comparada con el circulo.
*@return True si la forma es un circulo identico al circulo pendiente,
*False sino.
*/
public boolean equals (Forma f)
{
if (this == f) return true;

if (f == null) return false;

if (getClass() != f.getClass()) return false;

Circulo otro = (Circulo)f;

return ((centro.equals(otro.centro())) && (radio == otro.radio()));
}


/**Duplica el Circulo.
*@return Un Circulo identico al Circulo pendiente.
*/
public Forma clone()
{
Circulo copia = new Circulo(radio);

copia.centro = centro.clone();

return copia;
}

/**
* Metodo que dibuja 4 cuadraditos sobre el Circulo para mostrar que este está
* seleccionado.
* @param g Graphics donde se dibujan los 4 cuadraditos.
*/
public void select (Graphics g)
{
g.setColor(Color.green);
greenSquare = new Rectangle2D[NUMBER_OF_SQUARE];
greenSquare[RIGHT_SQUARE] = new Rectangle2D.Double((centro.X + radio - 2),
(centro.Y - 2), SIZE_OF_SQUARE, SIZE_OF_SQUARE);
greenSquare[LEFT_SQUARE] = new Rectangle2D.Double((centro.X - radio - 2),
(centro.Y - 2), SIZE_OF_SQUARE, SIZE_OF_SQUARE);
greenSquare[DOWN_SQUARE] = new Rectangle2D.Double((centro.X - 2),
(centro.Y + radio - 2), SIZE_OF_SQUARE, SIZE_OF_SQUARE);
greenSquare[TOP_SQUARE] = new Rectangle2D.Double((centro.X - 2),
(centro.Y - radio - 2), SIZE_OF_SQUARE, SIZE_OF_SQUARE);
Graphics2D g2 = (Graphics2D) g;
for (int i = 0; i < greenSquare.length; i++)
g2.draw(greenSquare[i]);
g.setColor(Color.black);
}

/**
* Metodo que permite saber si el punto dado en parametro pertenece a uno de los
* cuadraditos de seleccion del Circulo. 
* @return True si el punto dado en parametro pertenece a uno de los cuadraditos
* de seleccion del Circulo, False sino.
*/
public boolean isItInAGreenSquare(Point p)
{
Point2D p2 = new Point2D.Double(p.X, p.Y);
for (int i = 0; i < greenSquare.length; i++)
if (greenSquare[i].contains(p2))
return true;
return false;
}

/**
* Metodo que permite saber si el punto dado en parametro pertenece
* al circulo.
* @param punto Punto cuya coordenadas son revisadas para comprobar si 
* pertenecen o no al Circulo.
* @return True si punto hace parte del Circulo, False sino.
*/
public boolean isSelected(Point punto)
{
Linea linea = new Linea (centro, punto);

return ((linea.getDistancia() >= radio - 2)
&& (linea.getDistancia() <= radio + 2));
}
 

}
