import java.lang.Math.*; import java.util.*; /** * Un cubo que representa una de las piezas del cubo rubik completo. * Contiene informacion de la ubicacion espacial de sus ocho vertices * y sus caras. * @author Carlos Cortes */ public class Pieza implements Comparable { /** * Punto desde donde son vistas las piezas por el observador (la camara). */ private static Point3D vista; /** * Arreglo con los ocho vertices del cubo que representa esta Pieza. */ private Point3D[] vertice = {null,null,null,null,null,null,null,null}; /** * Arreglo con las 12 Cara3D (dos triangulos por cada cara cuadrada). */ private Cara3D[] cara = {null,null,null,null,null,null, null,null,null,null,null,null}; /** * Determina la orientacion de la Pieza (rotaciones). */ private Ejes3D eje; /** * Crea e inicializa una Pieza. * @param x posicion en x * @param y posicion en y * @param z posicion en z * @param a color de la cara que mira arriba * @param i color de la cara que mira izquieda * @param f color de la cara que mira frente * @param d color de la cara que mira derecha * @param t color de la cara que mira atras * @param b color de la cara que mira abajo */ public Pieza(int x, int y, int z, int a, int i, int f, int d, int t, int b) { vertice[0] = new Point3D(x*2-.94f, y*2-.94f, z*2-.94f); vertice[1] = new Point3D(x*2+.94f, y*2-.94f, z*2-.94f); vertice[2] = new Point3D(x*2+.94f, y*2+.94f, z*2-.94f); vertice[3] = new Point3D(x*2-.94f, y*2+.94f, z*2-.94f); vertice[4] = new Point3D(x*2-.94f, y*2-.94f, z*2+.94f); vertice[5] = new Point3D(x*2+.94f, y*2-.94f, z*2+.94f); vertice[6] = new Point3D(x*2+.94f, y*2+.94f, z*2+.94f); vertice[7] = new Point3D(x*2-.94f, y*2+.94f, z*2+.94f); cara[0] = new Cara3D(this, 4, 5, 6, a); cara[1] = new Cara3D(this, 6, 7, 4, a); cara[2] = new Cara3D(this, 0, 1, 5, i); cara[3] = new Cara3D(this, 5, 4, 0, i); cara[4] = new Cara3D(this, 1, 2, 6, f); cara[5] = new Cara3D(this, 6, 5, 1, f); cara[6] = new Cara3D(this, 2, 3, 7, d); cara[7] = new Cara3D(this, 7, 6, 2, d); cara[8] = new Cara3D(this, 3, 0, 4, t); cara[9] = new Cara3D(this, 4, 7, 3, t); cara[10] = new Cara3D(this, 0, 3, 2, b); cara[11] = new Cara3D(this, 2, 1, 0, b); eje = new Ejes3D(); } /** * Usado por clone(). */ private Pieza(Point3D[] ve, Cara3D[] ca, Ejes3D ej) { vertice = ve; cara = ca; eje = ej; } /** * Cambia la referencia punto desde donde son vistas las Piezas. * @param _v Nuevo punto de vista. */ public static void setVista(Point3D _v) { vista = _v; } /** * Retorna el arraglo de vertices de esta Pieza. * @return El arraglo de vertices de esta Pieza. */ public Point3D[] getVerticeArray() { return vertice; } /** * Retorna el arraglo de caras de esta Pieza. * @return El arraglo de caras de esta Pieza. */ public Cara3D[] getCaraArray() { return cara; } /** * Retorna los ejes de esta Pieza. * @return Los ejes de esta Pieza. */ public Ejes3D getEjes() { return eje; } /** * Retorna un Point3D que indica el punto central de esta pieza en el * espacio 3D. * @return Un Point3D que indica el punto central de esta pieza en el * espacio 3D. */ public Point3D getCentro() { float _x=0, _y=0, _z=0; Point3D pTemp; for (int j=0; j<8; j++) { pTemp = vertice[j].clone(); pTemp.normalizar(eje); _x += pTemp.getX(); _y += pTemp.getY(); _z += pTemp.getZ(); } _x /= 8; _y /= 8; _z /= 8; Point3D centro = new Point3D(_x, _y, _z); return centro; } /** * Rota los ejes de esta Pieza sobre el eje X. * @param giro grados del giro en sentido horario. */ public void rotar_X(float giro) { float vy, vz; vy = (float)Math.cos(Math.PI*giro/180); vz = (float)Math.sin(Math.PI*giro/180); eje = new Ejes3D(new Point3D(1, 0, 0), new Point3D(0, vy, vz), new Point3D(0, -vz, vy)); } /** * Rota los ejes de esta Pieza sobre el eje Y. * @param giro grados del giro en sentido horario. */ public void rotar_Y(float giro) { float vx, vz; vx = (float)Math.cos(Math.PI*giro/180); vz = (float)Math.sin(Math.PI*giro/180); eje = new Ejes3D(new Point3D( vx, 0, -vz), new Point3D( 0, 1, 0), new Point3D( vz, 0, vx)); } /** * Rota los ejes de esta Pieza sobre el eje Z. * @param giro grados del giro en sentido horario. */ public void rotar_Z(float giro) { float vx, vy; vx = (float)Math.cos(Math.PI*giro/180); vy = (float)Math.sin(Math.PI*giro/180); eje = new Ejes3D(new Point3D( vx, vy, 0), new Point3D(-vy, vx, 0), new Point3D( 0, 0, 1)); } /** * Rota esta pieza para hacer que sus ejes coincidan con los ejes canonicos. */ public void normalizar() { for (int i=0; i<8; i++) vertice[i].normalizar(eje); resetEjes(); } /** * Invoca el metodo 'ajustar()' de los ejes de esta pieza y luego normaliza * esta pieza. Sirve para evitar que se acumulen errores en los giros de la * Pieza. Por ejemplo despues de hacer muchos giros de 90 grados, se iran * acumulando errores por el redondeo a float, que harian que despues de * muchos giros, las piezas se vean chuecas. */ public void ajustar() { eje.ajustar(); normalizar(); } /** * Devuelve los ejes de la pieza a sus orientaciones canonicas. */ public void resetEjes() { eje = new Ejes3D(); } /** * Crea una copia de esta Pieza. * @return Una copia de esta Pieza. */ public Pieza clone() { Point3D[] ve = {null,null,null,null,null,null,null,null}; Cara3D[] ca = {null,null,null,null,null,null,null,null,null,null,null,null}; Ejes3D ej; int i; for (i=0; i<8; i++) ve[i] = vertice[i].clone(); for (i=0; i<12; i++) ca[i] = cara[i].clone(); ej = eje.clone(); Pieza nueva = new Pieza(ve, ca, ej); for (i=0; i<12; i++) nueva.getCaraArray()[i].setPieza(nueva); return nueva; } /** * Compara la distancia de las piezas respecto a la camara, * la mas lejana va primero. */ public int compareTo(Pieza otra) { Point3D posEsta = getCentro(); Point3D posOtra = otra.getCentro(); posEsta.menos(Pieza.vista); posOtra.menos(Pieza.vista); float d1 = posEsta.getMagnitud(); float d2 = posOtra.getMagnitud(); if (d1 == d2) return 0; if (d1 > d2) return -1; else return 1; } }