import java.util.ArrayList;
public class PolygonTriangulation {
	
	static final float EPSILON=0.0000000001f;
	
	static public float Area(float[] contour) {
		int n = contour.length;
		float A = 0.0f;
		
		for(int p = n - 3, q = 0; q < n; p=q, q+=3)
		{
			A += contour[p] * contour[q+1] - contour[q] * contour[p+1];
		}
		return A * 0.5f;
	}

	static public boolean InsideTriangle(float Ax,float Ay,float Bx,float By,float Cx,float Cy,float Px,float Py){
		float ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy;
		float cCROSSap, bCROSScp, aCROSSbp;
		
		ax = Cx - Bx;  ay = Cy - By;
		bx = Ax - Cx;  by = Ay - Cy;
		cx = Bx - Ax;  cy = By - Ay;
		apx= Px - Ax;  apy= Py - Ay;
		bpx= Px - Bx;  bpy= Py - By;
		cpx= Px - Cx;  cpy= Py - Cy;
		
		aCROSSbp = ax * bpy - ay * bpx;
		cCROSSap = cx * apy - cy * apx;
		bCROSScp = bx * cpy - by * cpx;

		return ((aCROSSbp >= 0.0f) && (bCROSScp >= 0.0f) && (cCROSSap >= 0.0f));
	}

	static public boolean Snip(float[] contour, int u, int v, int w, int n, int[] V) {
		int p;
		float Ax, Ay, Bx, By, Cx, Cy, Px, Py;
		
		Ax = contour[V[u]];
		Ay = contour[V[u+1]];
		
		Bx = contour[V[v]];
		By = contour[V[v+1]];
		
		Cx = contour[V[w]];
		Cy = contour[V[w+1]];
		
		if ( EPSILON > (((Bx-Ax)*(Cy-Ay)) - ((By-Ay)*(Cx-Ax))) ){
			return false;
		}
		
		for (p = 0; p < n; p++)
		{
			if( (p == u/2) || (p == v/2) || (p == w/2) ){
				continue;
			}
			
			Px = contour[V[p*2]];
			Py = contour[V[(p*2)+1]];
			
			if (InsideTriangle(Ax,Ay,Bx,By,Cx,Cy,Px,Py)){
				return false;
			}
		}
		return true;
	}
	
	//Brings in 3D vertex float array but processes it as 2D only.
	static public int[] Process(float[] contour) {
		//Pre-return list
		ArrayList<Integer> vertexArray = new ArrayList<Integer>();
		
		/* allocate and initialize list of Vertices in polygon */
		int n = contour.length;
		if ( n/3 < 3 )
			return null;

		//The (n/3)*2 occurs as we are removing the z coordinate from the mix
		int[] V = new int[(n/3)*2];

		/* we want a counter-clockwise polygon in V */
		if (0.0f < Area(contour)){
			for (int s = 0, v = 0; v < n-1; s+=2, v += 3){
				V[s] = v;
				V[s + 1] = v + 1;
			}
		}
		else{
			for(int s = 0, v = 0; v < n-1; s += 2, v += 3){
				V[s] = (n - 1) - (v + 2);
				V[s + 1] = (n - 1) - (v + 1);
			}
		}
		
		int nv = n/3;

		/*  remove nv-2 Vertices, creating 1 triangle every time */
		int count = 2 * nv;   /* error detection */

		for(int v = nv - 1; nv > 2;)
		{
			/* if we loop, it is probably a non-simple polygon */
			if (0 >= (count--))
			{
				//** Triangulate: ERROR - probable bad polygon!
				return null;
			}
			
			/* three consecutive vertices in current polygon, <u,v,w> */
			int u = v;
			if (nv <= u)
				u = 0;		/* previous */
			v = u + 1;
			if (nv <= v)
				v = 0;		/* new v    */
			int w = v + 1;
			if (nv <= w)
				w = 0;		/* next     */

			if (Snip(contour, u*2, v*2, w*2, nv, V))
			{
				vertexArray.add(V[u*2]/3);
				vertexArray.add(V[v*2]/3);
				vertexArray.add(V[w*2]/3);
				
				// remove v from remaining polygon
				for(int s = v * 2, t = (v * 2) + 2; t < (nv * 2); s += 2, t += 2){
					V[s] = V[t];
					V[s+1] = V[t+1];
				}
				nv--;
				
				// reset error detection counter
				count = 2 * nv;
			}
		}
		//Convert ArrayList into short array
		int[] index = new int[vertexArray.size()];
		for(int i = 0; i < vertexArray.size(); i++){
			index[i] = vertexArray.get(i);
		}
		return index;
	}
}