import java.awt.*;
/**
 * Ravnina v 3D prostoru.
 */
public class Ravnina {
	Matrix3D pmat = new Matrix3D();
	Polygon p = new Polygon();   
    Tocka tp[];
    
    /**
     * Polje oglisc poligona ravnine v 3D prostoru.
     */
    public Tocka op[];
	
	/** 
	 * Krajevni vektor prve tocke v poligonu ravnine. 
	 */
    public Vektor V;
	
	/** 
	 * Normalni enotski vektor ravnine. 
	 */
    public Vektor n;
    
    /**
     * Doloci ravnino podano s tremi tockami. Inicializira
     * poligon ravnine kot paralelogram skozi te tri tocke.
     *@param P  polje treh tock
     */
    public Ravnina(Tocka P[]) {
        Vektor V1 = new Vektor(P[0],P[1]);
        Vektor V2 = new Vektor(P[0],P[2]);

        V = new Vektor(P[0]);	// krajevni vektor do prve tocke
        n = new Vektor();		// enotski vektor normale ravnine
        n.vektProd(V1,V2);
        n.normVekt();
        
    	// model ravnine kot oglisca poligona:
    	op = new Tocka[5];
        op[0] = new Tocka(P[0]);
        op[1] = new Tocka(P[1]);
        op[2] = new Tocka(V1.x + V2.x + V.x, 
        			 	  V1.y + V2.y + V.y,
        				  V1.z + V2.z + V.z);
        op[3] = new Tocka(P[2]);
        op[4] = new Tocka(P[0]);
   		
   		/*** poligon bi moral biti dolocen kot presek ravnine z
   			 mejnim kvadrom, ki je dolocen s tockama Dp in Dn! ***/
		
		// transformacija ravnine vzporedno ravnini xy:
		double alfa,beta,d = Math.sqrt(n.y * n.y + n.z * n.z);
		
		if(d == 0) alfa = 0;
		else { alfa = (n.z >= 0) ? Math.asin(n.y / d) * 180 / Math.PI :
    	         			    180 - Math.asin(n.y / d) * 180 / Math.PI;
		}
  		beta = Math.asin(-n.x) * 180 / Math.PI;
		
	 	pmat.unit();
		pmat.xrot(-alfa);
		pmat.yrot(beta);
      
		// transformiran poligon:
		tp = pmat.transform(op,5);

		// inicializacija dvodim. poligona:
		for(int i=0; i<5; i++) {
			p.addPoint((int)tp[i].x,(int)tp[i].y);
		}
	}

    /**
     * Doloci ravnino podano s poligonom. Podani poligon 
     * vzame kot poligon ravnine v 3D prostoru.
     *@param P  polje tock poligona
     *@param stt  stevilo tock v poligonu (P.length)
     */
    public Ravnina(Tocka P[],int stt) {
        Vektor V1 = new Vektor(P[0],P[1]);
        Vektor V2 = new Vektor(P[0],P[2]);

        V = new Vektor(P[0]);	// krajevni vektor do prve tocke
        n = new Vektor();		// enotski vektor normale ravnine
        n.vektProd(V1,V2);
        n.normVekt();
        
    	// model ravnine kot oglisca poligona:
    	op = new Tocka[stt];
		System.arraycopy(P,0,op,0,stt);

   		/*** poligon bi moral biti dolocen kot presek ravnine z
   			 mejnim kvadrom, ki je dolocen s tockama Dp in Dn! ***/
		
		// transformacija ravnine vzporedno ravnini xy:
		double alfa,beta,d = Math.sqrt(n.y * n.y + n.z * n.z);
		
		if(d == 0) alfa = 0;
		else { alfa = (n.z >= 0) ? Math.asin(n.y / d) * 180 / Math.PI :
    	         			    180 - Math.asin(n.y / d) * 180 / Math.PI;
		}
  		beta = Math.asin(-n.x) * 180 / Math.PI;
		
	 	pmat.unit();
		pmat.xrot(-alfa);
		pmat.yrot(beta);
      
		// transformiran poligon:
		tp = pmat.transform(op,stt);

		// inicializacija dvodim. poligona:
		for(int i=0; i<stt; i++) {
			p.addPoint((int)tp[i].x,(int)tp[i].y);
		}
	}
	
	/**
	 * Testira ali lezi tocka znotraj poligona ravnine.
	 * Vrne <code>true</code>, ce lezi znotraj poligona, drugace 
	 * vrne <code>false</code>.
	 *@param T  testirana tocka
	 */
	public boolean inside(Tocka T) {
		Tocka cht = pmat.transform(T);
        // tocka na robu je del poligona:
		int chx = (int)((cht.x < 0) ? (cht.x + 0.1f):(cht.x - 0.1f));
		int chy = (int)((cht.y < 0) ? (cht.y + 0.1f):(cht.y - 0.1f));

		return p.inside(chx,chy); 
	}

	/**
	 * Izrise poligon ravnine v 3D prostoru.
	 *@param g  graficni kontekst kamor naj izrise
	 *@param x0  x koordinata izhodisca na canvasu
	 *@param y0  y koordinata izhodisca na canvasu
	 *@param mat  matrika 3D transformacij
	 *@param c  barva s katero naj izrise
	 */
	public void draw3D(Graphics g,int x0,int y0,Matrix3D mat,Color c) {
		int x[] = new int[5];
		int y[] = new int[5];
        
        g.setColor(c);

		Tocka tt[] = mat.transform(op,op.length);
		
		for(int i=0; i<5; i++) {
			x[i] = (int)tt[i].x + x0;
			y[i] = -(int)tt[i].y + y0;
		}
		g.drawPolygon(x,y,5);
    }		
}
