import java.lang.*;
import Vertex2D;

class planeEquation
{
	protected float A[], B[], C[];
	protected float Ap[], Bp[], Cp[];
	protected float Area; // actually twice the area
		
	/**
	 * void constructor
	 *
	 */
	public planeEquation( )
	{
	}
	
	/**
	 * constructor, takes 3 vertices of the 3angle
	 *
	 */
	public planeEquation(Vertex2D v[])
	{
		A=new float[3];
		B=new float[3];
		C=new float[3];
		Ap=new float[4];
		Bp=new float[4];
		Cp=new float[4];
		
		Area = get2Area(v);		// calculate the triangle area
		
		A[0]=getA(v[0], v[1]);	// calculate the edge equation coeffs
		B[0]=getB(v[0], v[1]);
		C[0]=getC(v[0], v[1], A[0], B[0]);
		A[1]=getA(v[1], v[2]);
		B[1]=getB(v[1], v[2]);
		C[1]=getC(v[1], v[2], A[1], B[1]);
		A[2]=getA(v[2], v[0]);
		B[2]=getB(v[2], v[0]);
		C[2]=getC(v[2], v[0], A[2], B[2]);
		
		Ap=getAp(v);
		Bp=getBp(v);
		Cp=getCp(v);
	}
	
	/**
	 * Returns 2x the area of the 3angle
	 *
	 */
	private float get2Area(Vertex2D v[])
	{
//		return(v[0].x*(v[1].y-v[2].y)+v[1].x*(v[2].y-v[1].y)+v[2].x*(v[0].y-v[1].y));
		return(det3(v[0].x,v[1].x,v[2].x,v[0].y,v[1].y,v[2].y,1.0f,1.0f,1.0f));
	}
	
	private float getA(Vertex2D v0, Vertex2D v1)
	{
		return (v0.y-v1.y);
	}
	
	private float getB(Vertex2D v0, Vertex2D v1)
	{
		return (v1.x-v0.x);
	}
	
	private float getC(Vertex2D v0, Vertex2D v1)
	{
		return(-((v0.y-v1.y)*(v0.x+v1.x)+(v1.x-v0.x)*(v0.y+v1.y))/2);
	}
	
	private float getC(Vertex2D v0, Vertex2D v1, float A, float B)
	{
		return(-(A*(v0.x+v1.x)+B*(v0.y+v1.y))/2);
	}
	
	private float [] getAp(Vertex2D v[])
	{
		float a[]=new float[4];
		int alpha[], r[], g[], b[];
		
		alpha = new int[3];
		r=new int[3];
		g=new int[3];
		b=new int[3];
		
		for(int i=0;i<3;i++)
		{
			alpha[i]=(v[i].argb>>24)&0xFF;
			r[i]=(v[i].argb>>16)&0xFF;
			g[i]=(v[i].argb>>8)&0xFF;
			b[i]=(v[i].argb)&0xFF;
		}
			
		a[0] = (A[1]*b[0] + A[2]*b[1] + A[0]*b[2])/Area;
		a[1] = (A[1]*g[0] + A[2]*g[1] + A[0]*g[2])/Area;
		a[2] = (A[1]*r[0] + A[2]*r[1] + A[0]*r[2])/Area;
		a[3] = (A[1]*alpha[0] + A[2]*alpha[1] + A[0]*alpha[2])/Area;

		return a;
	}

	private float [] getBp(Vertex2D v[])
	{
		float a[]=new float[4];
		int alpha[], r[], g[], b[];
		
		alpha = new int[3];
		r=new int[3];
		g=new int[3];
		b=new int[3];
		
		for(int i=0;i<3;i++)
		{
			alpha[i]=(v[i].argb>>24)&0xFF;
			r[i]=(v[i].argb>>16)&0xFF;
			g[i]=(v[i].argb>>8)&0xFF;
			b[i]=(v[i].argb)&0xFF;
		}
			
		a[0] = (B[1]*b[0] + B[2]*b[1] + B[0]*b[2])/Area;
		a[1] = (B[1]*g[0] + B[2]*g[1] + B[0]*g[2])/Area;
		a[2] = (B[1]*r[0] + B[2]*r[1] + B[0]*r[2])/Area;
		a[3] = (B[1]*alpha[0] + B[2]*alpha[1] + B[0]*alpha[2])/Area;

		return a;
	}

	private float [] getCp(Vertex2D v[])
	{
		float a[]=new float[4];
		int alpha[], r[], g[], b[];
		
		alpha = new int[3];
		r=new int[3];
		g=new int[3];
		b=new int[3];
		
		for(int i=0;i<3;i++)
		{
			alpha[i]=(v[i].argb>>24)&0xFF;
			r[i]=(v[i].argb>>16)&0xFF;
			g[i]=(v[i].argb>>8)&0xFF;
			b[i]=(v[i].argb)&0xFF;
		}
			
		a[0] = (C[1]*b[0] + C[2]*b[1] + C[0]*b[2])/Area;
		a[1] = (C[1]*g[0] + C[2]*g[1] + C[0]*g[2])/Area;
		a[2] = (C[1]*r[0] + C[2]*r[1] + C[0]*r[2])/Area;
		a[3] = (C[1]*alpha[0] + C[2]*alpha[1] + C[0]*alpha[2])/Area;
		
		return a;
	}
		
	private float det3(float a, float b, float c, float d, float e, float f,
						float g, float h, float i)
	{
		return(a*(e*i-h*f)-b*(d*i-g*f)+c*(d*h-g*e));
	}
	
	public int computeColor(int x, int y)
	{
		int a, r, g, b, col;
		
		b=Math.round((Ap[0]*x)+(Bp[0]*y)+Cp[0]);
		g=Math.round((Ap[1]*x)+(Bp[1]*y)+Cp[1]);
		r=Math.round((Ap[2]*x)+(Bp[2]*y)+Cp[2]);
		a=Math.round((Ap[3]*x)+(Bp[3]*y)+Cp[3]);
		
		col=((a<<24)&0xFF000000)|((r<<16)&0x00FF0000)|((g<<8)&0x0000FF00)|(b&0x000000FF);
//		col+=(r<<16)& 0x00FF0000;
//		col+=(g<<8) & 0x0000FF00;
//		col+= b     & 0x000000FF;
		
		return col;
	}
}	
