viernes, 9 de septiembre de 2011

Ejercicio "Figuras geométricas"

Este ejercicio lo realizamos a lo largo de varias semanas, añadiendo funciones, creando clases nuevas y realizando algunos ejercicios con las figuras que se añadirán en entradas posteriores.

Dada la clase abstracta* "Figura", añadirle varias funciones de desplazamiento, una función que permita consultar su posición y dos funciones que permitan modificar directamente las coordenadas.

public abstract class Figura implements Serializable {
    protected  Point posicion;
    public Figura(int a, int b) {
    posicion= new Point(a,b);}
    public abstract float area();
    public abstract float perimetro();
    public abstract int alto();
    public abstract int ancho();
    public abstract void dibujar(Graphics g);
    public abstract void guardar(OutputStream out) throws IOException;
    public abstract void cargar(InputStream in) throws IOException;
    public void arr(int incremento){
        this.posicion.y -= incremento;
    }
    public void abj(int incremento){
        this.posicion.y += incremento;
    }
    public void izq(int incremento){
        this.posicion.x -= incremento;
    }
    public void der(int incremento){
        this.posicion.x += incremento;
    }
    public Point posicion(){
        Point aux = new Point(posicion);
        return aux;
    }
    public void set_y(int pos_y){
        this.posicion.y = pos_y;
    }
    public void set_x(int pos_x){
        this.posicion.x = pos_x;
    }
}

Crear la clase (excepción) "FiguraFormatException", que hereda de "IllegalArgumentException" y se lanzará si en la función Cargar, se lee del flujo una figura que no es la indicada.

public class FiguraFormatException extends IllegalArgumentException{
    public FiguraFormatException() {
    }
    public FiguraFormatException(String string) {
        super(string);
    }
}

Dadas las clases "Triangulo", "Elipse", "Circulo", "Rectangulo" y "Cuadrado", que heredan de la clase abstracta "Figura", añadir un constructor que reciba un InputStream, que tendrá los datos adecuados para inicializar la figura. Además, se sobreescribirán las funciones abstractas de la clase "Figura".

CLASE Triangulo

public class Triangulo extends Figura {
    protected int lado1, lado2, lado3;
    private int lx, altura;
    public Triangulo(int a, int b, int c, int d, int e) {
        super(a, b);
        int elMayor = (c > d & c > e) ? c : ((d > e) ? d : e);
        if (elMayor >= (c + d + e - elMayor)) {
            throw new IllegalArgumentException("Los lados del triangulo son imposibles");
        }
        lado1 = c;
        lado2 = d;
        lado3 = e;
        lx = (lado2 * lado2 - lado3 * lado3 - lado1 * lado1) / (2 * lado1);
        altura = (int) Math.sqrt(lado3 * lado3 - lx * lx);
    }
    public Triangulo(InputStream in) throws IOException {
        super(0, 0);
        cargar(in);
    }
    public void guardar(OutputStream out) throws IOException {
        DataOutputStream escribir = new DataOutputStream(out);
        escribir.writeUTF("figuras.Triangulo");
        escribir.writeInt(posicion.x);
        escribir.writeInt(posicion.y);
        escribir.writeInt(lado1);
        escribir.writeInt(lado2);
        escribir.writeInt(lado3);
        escribir.flush();
    }
    public void cargar(InputStream in) throws IOException {
        DataInputStream leer = new DataInputStream(in);
        String figura;
        figura = leer.readUTF();
        if (!figura.equals("figuras.Triangulo")) {
            throw new FiguraFormatException();
        }
        posicion.x = leer.readInt();
        posicion.y = leer.readInt();
        lado1 = leer.readInt();
        lado2 = leer.readInt();
        lado3 = leer.readInt();
        lx = (lado2 * lado2 - lado3 * lado3 - lado1 * lado1) / (2 * lado1);
        altura = (int) Math.sqrt(lado3 * lado3 - lx * lx);
    }
    public float area() {
        return (lado1 * altura) / 2;
    }
    public float perimetro() {
        return lado1 + lado2 + lado3;
    }
    public int alto() {
        return altura;
    }
    public int ancho() {
        return lado1;
    }
    public void dibujar(Graphics g) {
        Color cActual = g.getColor();
        int[] xPuntos = {posicion.x,
            posicion.x + lado1,
            posicion.x + lado1 + lx};
        int[] yPuntos = {posicion.y,
            posicion.y,
            posicion.y + altura};
        g.fillPolygon(xPuntos, yPuntos, 3);
        g.setColor(Color.white);
        g.drawPolygon(xPuntos, yPuntos, 3);
        g.setColor(cActual);
    }
}

CLASE Elipse

public class Elipse extends Figura {
    public final static float PI = 3.1415F;
    protected int dMenor, dMayor;
    public Elipse(int a, int b, int c, int d) {
        super(a, b);
        dMenor = c;
        dMayor = d;
    }
    public Elipse(InputStream in) throws IOException {
        super(0, 0);
        this.cargar(in);
    }
    public void guardar(OutputStream out) throws IOException {
        DataOutputStream escribir = new DataOutputStream(out);
        escribir.writeUTF("figuras.Elipse");
        escribir.writeInt(posicion.x);
        escribir.writeInt(posicion.y);
        escribir.writeInt(dMenor);
        escribir.writeInt(dMayor);
        escribir.flush();
    }
    public void cargar(InputStream in) throws IOException {
        DataInputStream leer = new DataInputStream(in);
        if (!leer.readUTF().equals("figuras.Elipse")) {
            throw new FiguraFormatException();
        }
        posicion.x = leer.readInt();
        posicion.y = leer.readInt();
        dMenor = leer.readInt();
        dMayor = leer.readInt();
    }
    public float area() {
        return PI * dMenor * dMayor;
    }
    public float perimetro() {
        return PI * (dMenor + dMayor);
    }
    public int alto() {
        return dMayor;
    }
    public int ancho() {
        return dMenor;
    }
    public void dibujar(Graphics g) {
        Color cActual = g.getColor();
        g.fillOval(posicion.x, posicion.y, dMenor, dMayor);
        g.setColor(Color.white);
        g.drawOval(posicion.x, posicion.y, dMenor, dMayor);
        g.setColor(cActual);
    }
}

CLASE Circulo

public class Circulo extends Elipse {
    public Circulo(int a, int b, int d) {
        super(a, b, d, d);
    }
    public Circulo(InputStream is) throws IOException {
        super(0, 0, 0, 0);
        //Si se produce una IOException, se borrarán los datos del objeto Circulo
        cargar(is);
    }
    @Override
    public void guardar(OutputStream os) throws IOException {
        DataOutputStream dos = new DataOutputStream(os);
        dos.writeUTF("figuras.Circulo");
        dos.writeInt(posicion.x);
        dos.writeInt(posicion.y);
        dos.writeInt(dMayor);
        dos.flush();
    }
    @Override
    public void cargar(InputStream is) throws IOException {
        DataInputStream dis = new DataInputStream(is);

        if (!dis.readUTF().equals("figuras.Circulo")) {
            throw new FiguraFormatException();
        }
        posicion = new Point(dis.readInt(), dis.readInt());
        dMayor = dis.readInt();
        dMenor = dMayor;
    }
}

CLASE Rectangulo

public class Rectangulo extends Figura {
    protected int lado1, lado2;
    public Rectangulo(int a,int b,int c,int d) {
        super(a,b);
        lado1=c;
        lado2=d; }
    public Rectangulo(InputStream in) throws IOException {
        super(0,0);
        this.cargar(in);
    }
    public float area() {
        return lado1*lado2;
    }
    public float perimetro() {
        return lado1*2+lado2*2;
    }
    public int alto() {
        return lado2;
    }
    public int ancho() {
        return lado1;
    }
    public void dibujar(Graphics g) {
        Color cActual=g.getColor();
        g.fillRect(posicion.x,posicion.y,lado1,lado2);
        g.setColor(Color.white);
        g.drawRect(posicion.x,posicion.y,lado1,lado2);
        g.setColor(cActual);
    }
    public void guardar (OutputStream out) throws IOException{
        DataOutputStream dos = new DataOutputStream(out);
        dos.writeUTF("figuras.Rectangulo");
        dos.writeInt((int) super.posicion().getX());
        dos.writeInt((int) super.posicion().getY());
        dos.writeInt(lado1);
        dos.writeInt(lado2);
        dos.flush();
    }
    public void cargar (InputStream in) throws IOException{
        DataInputStream dis = new DataInputStream(in);
        if(!dis.readUTF().equals("figuras.Rectangulo")) {
            throw new FiguraFormatException("La figura no es un rectángulo.");
        }
        super.set_x(dis.readInt());
        super.set_y(dis.readInt());
        lado1=dis.readInt();
        lado2=dis.readInt();
    }
}

CLASE Cuadrado

public class Cuadrado extends Rectangulo {
    public Cuadrado(int a, int b, int c) {
        super(a, b, c, c);
    }
    public Cuadrado(InputStream in) throws IOException {
        super(0, 0, 0, 0);
        cargar(in);
    }
    @Override
    public void guardar(OutputStream out) throws IOException {
        DataOutputStream escribe = new DataOutputStream(out);
        escribe.writeUTF("figuras.Cuadrado");
        escribe.writeInt(posicion.x);
        escribe.writeInt(posicion.y);
        escribe.writeInt(this.alto());
        escribe.flush();
    }
    @Override
    public void cargar(InputStream in) throws IOException {
        DataInputStream lee = new DataInputStream(in);
        if (!lee.readUTF().equals("figuras.Cuadrado")) {
            throw new FiguraFormatException();
        }
        posicion.x = lee.readInt();
        posicion.y = lee.readInt();
        lado1 = lee.readInt();
        lado2 = lado1;
    }
}

Crear las clases "TEquilatero" que hereda de "Triangulo" y "Coche" que hereda de "Figura".

La clase "TEquilatero":
  • Es un triángulo con los tres lados iguales.

La clase "Coche":

  • Estará formada por dos círculos (ruedas) y un rectángulo.
  • Su posición la indicará la esquina superior izquierda.
  • Los círculos tendrán el mismo tamaño que la altura del rectángulo.
    • Si la suma de los dos diámetros es mayor a la longitud del rectángulo, entonces el diámetro será la mitad de la longitud.
CLASE TEquilatero

public class TEquilatero extends Triangulo {
    public TEquilatero(int a, int b, int c) {
        super(a, b, c, c, c);
    }
    public TEquilatero(InputStream in) throws IOException {
        super(0, 0, 0, 0, 0);
        cargar(in);
    }
    @Override
    public void cargar(InputStream into) throws IOException {
        DataInputStream di = new DataInputStream(into);
        if (!di.readUTF().equals("figuras.TEquilatero")) {
            throw new FiguraFormatException();
        }
        posicion.x = di.readInt();
        posicion.y = di.readInt();
        lado1 = di.readInt();
    }
    @Override
    public void guardar(OutputStream o) throws IOException {
        DataOutputStream out = new DataOutputStream(o);
        out.writeUTF("figuras.TEquilatero");
        out.writeInt(posicion.x);
        out.writeInt(posicion.y);
        out.writeInt(lado1);
        out.flush();
    }
}

CLASE Coche

public class Coche extends Figura {
    private Rectangulo chasis;
    private Circulo rueda1, rueda2;
    public Coche(int a, int b, int alto, int ancho) {
        super(a, b);
        if (alto <= ancho) {
            chasis = new Rectangulo(a, b, ancho, alto / 2);
            rueda1 = new Circulo(a, b + chasis.alto(), alto / 2);
            rueda2 = new Circulo(a + ancho - alto / 2, b + chasis.alto(), alto / 2);
        } else {
            chasis = new Rectangulo(a, b, ancho, alto - (ancho / 2));
            rueda1 = new Circulo(a, b + chasis.alto(), ancho / 2);
            rueda2 = new Circulo(a + ancho / 2, b + chasis.alto(), ancho / 2);
        }
    }
    public Coche(InputStream in)throws IOException{
        super(0,0);
        this.cargar(in);
    }
    @Override
    public float area() {
        return chasis.area() + rueda1.area() + rueda2.area();
    }
    @Override
    public float perimetro() {
        return chasis.perimetro() + rueda1.perimetro() + rueda2.perimetro();
    }
    @Override
    public int alto() {
        return chasis.alto() + rueda1.alto();
    }
    @Override
    public int ancho() {
        return chasis.ancho();
    }
    @Override
    public void dibujar(Graphics g) {
        chasis.dibujar(g);
        rueda1.dibujar(g);
        rueda2.dibujar(g);
    }
    @Override
    public void arr(int incremento) {
        super.arr(incremento);
        chasis.arr(incremento);
        rueda1.arr(incremento);
        rueda2.arr(incremento);
    }
    @Override
    public void abj(int incremento) {
        super.abj(incremento);
        chasis.abj(incremento);
        rueda1.abj(incremento);
        rueda2.abj(incremento);
    }
    @Override
    public void izq(int incremento) {
        super.izq(incremento);
        chasis.izq(incremento);
        rueda1.izq(incremento);
        rueda2.izq(incremento);
    }
    @Override
    public void der(int incremento) {
        super.der(incremento);
        chasis.der(incremento);
        rueda1.der(incremento);
        rueda2.der(incremento);
    }
    @Override
    public void set_y(int pos_y) {
        super.set_y(pos_y);
        chasis.set_y(pos_y);
        rueda1.set_y(pos_y + chasis.alto());
        rueda2.set_y(pos_y + chasis.alto());
    }
    @Override
    public void set_x(int pos_x) {
        super.set_x(pos_x);
        chasis.set_x(pos_x);
        rueda1.set_x(pos_x);
        rueda2.set_x(pos_x + chasis.ancho() - rueda2.ancho());
    }
    public void guardar(OutputStream out) throws IOException {
        DataOutputStream escribe = new DataOutputStream(out);
        escribe.writeUTF("figuras.Coche");
        escribe.writeInt(posicion.x);
        escribe.writeInt(posicion.y);
        escribe.flush();
        rueda1.guardar(out);
        rueda2.guardar(out);
        chasis.guardar(out);

    }
    public void cargar(InputStream in) throws IOException {
        DataInputStream leer = new DataInputStream(in);
        String clase;
        if (!(clase=leer.readUTF()).equals("figuras.Coche")) {
            throw new FiguraFormatException("La figura no es un coche. Se ha leído: "+clase);
        }
        posicion.x = (leer.readInt());
        posicion.y = (leer.readInt());
        rueda1 = new Circulo(in);
        rueda2 = new Circulo(in);
        chasis = new Rectangulo(in);
    }
}

* Una clase será abstracta cuando no queremos que se puedan crear objetos de esa clase. Sus funciones pueden ser abstractas, en este caso, las clases que hereden de una abstracta pueden sobreescribir esas funciones o dejarla abstracta (la clase hija será también abstracta). Una clase abstracta también puede tener funciones no abstractas, es decir, que tengan código.

3 comentarios:

  1. muchas gracias esta excelente!
    tal vez me ayudas con la clase main para correr todas las clases?

    ResponderEliminar
  2. Genial. Muchas gracias por tu aporte. Es realmente muy didáctico.

    ResponderEliminar