/********************************************************************/
/*   STRIPE: converting a polygonal model to triangle strips    
     Francine Evans, 1996.
     SUNY @ Stony Brook
     Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/

/*---------------------------------------------------------------------*/
/*	STRIPE: ties.c
     This file will contain all the routines used to determine the next face if there
	is a tie
*/
/*---------------------------------------------------------------------*/

#include <stdlib.h>
#include "polverts.h"
#include "ties.h"
#include "sturctsex.h"
#include "triangulatex.h"
#include "options.h"
#include "common.h"
#include "util.h"

#define MAX_TIE 60
int ties_array[60];
int last = 0;

void Clear_Ties()
{
	/*	Clear the buffer, because we do not have the tie
		any more that we had before */
	last = 0;
}

void Add_Ties(int id)
{
	/*	We have a tie to add to the buffer */
	ties_array[last++] = id;
}

int Alternate_Tie()
{
	/*	Alternate in what we choose to break the tie 
		We are just alternating between the first and
		second thing that we found
	*/
	static int x = 0;
	register int t;
	
	t = ties_array[x];
	x++;
	if (x == 2)
		x = 0;
	return t;
}

int Random_Tie()
{
	/*	Randomly choose the next face with which
		to break the tie
	*/
	register int num;

	num = rand();
	while (num >= last)
		num = num/20;
	return (ties_array[num]);
}

int Look_Ahead(int id)
{
	/*	Look ahead at this face and save the minimum
		adjacency of all the faces that are adjacent to
		this face.
	*/
	return Min_Adj(id);
}

int Random_Look(int id[],int count)
{
	/*	We had a tie within a tie in the lookahead, 
		break it randomly 
	*/
	register int num;

	num = rand();
	while (num >= count)
		num = num/20;
	return (id[num]);
}


int Look_Ahead_Tie()
{
	/*	Look ahead and find the face to go to that
		will give the least number of adjacencies
	*/
	int id[60],t,x,f=0,min = 60;

	for (x = 0; x < last; x++)
	{
		t = Look_Ahead(ties_array[x]);
		/*	We have a tie */
		if (t == min)
			id[f++] = ties_array[x];
		if (t < min)
		{
			f = 0;
			min = t;
			id[f++] = ties_array[x];
		}
	}
	/*	No tie within the tie */
	if ( f == 1)
		return id[0];
	/*	Or ties, but we are at the end of strips */
	if (min == 0)
		return id[0];
	return (Random_Look(id,f));
}


int Sequential_Tri(int *index)
{
    /*  We have a triangle and need to break the ties at it.
        We will choose the edge that is sequential. There
        is definitely one since we know we have a triangle
        and that there is a tie and there are only 2 edges
        for the tie.
    */
    int e1,e2,e3,output1,output2,output3,output4;

    /*  e2 and e3 are the input edge to the triangle */
    Last_Edge(&e1,&e2,&e3,0);
    
    if ((e2 == 0) && (e3 == 0))
        /*  Starting the strip, don't need to do this */
        return ties_array[0];

    /*  For the 2 ties find the edge adjacent to face id */
    Get_EdgeEx(&output1,&output2,index,ties_array[0],3,0,0);
    Get_EdgeEx(&output3,&output4,index,ties_array[1],3,0,0);

    if ((output1 == e3) || (output2 == e3))
        return ties_array[0];
    if ((output3 == e3) || (output4 == e3))
        return ties_array[1];
    printf("There is an error trying to break sequential triangle \n");
}

int Sequential_Quad(int *index,	int triangulate)
{
    /*  We have a quad that need to break its ties, we will try
        and choose a side that is sequential, otherwise use lookahead
    */
    int output1,output2,x,e1,e2,e3;

    /*  e2 and e3 are the input edge to the quad */
    Last_Edge(&e1,&e2,&e3,0);

    /*  No input edge */
    if ((e2 == 0) && (e3 == 0))
        return ties_array[0];

	/*  Go through the ties and see if there is a sequential one */
    for (x = 0; x < last; x++)
	{
        Get_EdgeEx(&output1,&output2,index,ties_array[x],4,0,0);
        /*  Partial and whole triangulation will have different requirements */
        if (((output1 == e3) || (output2 == e3)) && (triangulate == PARTIAL))
            return ties_array[x];
        if (((output1 != e3) && (output1 != e2) &&
                (output2 != e3) && (output2 != e2)))
            return ties_array[x];
    }
    /*  There was not a tie that was sequential */
	return Look_Ahead_Tie();
}

void Whole_Output(int in1,int in2, int *index, int size, int *out1, int *out2)
{
    /*  Used to sequentially break ties in the whole triangulation for polygons
        greater than 4 sides. We will find the output edge that is good
        for sequential triangulation.
    */

    int half;
    
    /*  Put the input edge first in the list */
    Rearrange_IndexEx(index,size);

    if (!(EVEN(size)))
    {
        if (*(index) == in1)
            half = size/2 ;
        else
            half = size/2 +1;
    }
    else
        half = size/2;

    *out1 = *(index+half);
    *out2 = *(index+half+1);
}

int Sequential_Poly(int size, int *index, int triangulate)
{
    /*  We have a polygon of greater than 4 sides and wish to break the
        tie in the most sequential manner.
    */

    int x,output1,output2,e1,e2,e3,saved1=-1,saved2=-1,output3,output4;
    
    /*  e2 and e3 are the input edge to the quad */
    Last_Edge(&e1,&e2,&e3,0);

    /*  If we are using whole, find the output edge that is sequential */
    if (triangulate == WHOLE)
        Whole_Output(e2,e3,index,size,&output3,&output4);

    /*  No input edge */
    if ((e2 == 0) && (e3 == 0))
        return ties_array[0];
    
    for (x = 0; x < last ; x++)
    {
        Get_EdgeEx(&output1,&output2,index,ties_array[x],size,0,0);
        /*  Partial that can be removed in just one triangle */
        if (((output1 == e3) || (output2 == e3)) && (triangulate == PARTIAL))
            saved1 = ties_array[x];
        /*  Partial removed in more than one triangle */
        if ((output1 != e3) && (output1 != e2) && (output2 != e3) && (output2 != e2) &&
            (triangulate == PARTIAL) && (saved2 != -1))
            saved2 = ties_array[x];
        /*  Whole is not so easy, since the whole polygon must be done. Given
            an input edge there is only one way to come out, approximately half
            way around the polygon.
        */
        if (((output1 == output3) && (output2 == output4)) ||
            ((output1 == output4) && (output2 == output3)) &&
            (triangulate == WHOLE))
            return ties_array[x];
    }
    
    if (saved1 != -1)
        return saved1;
    if (saved2 != -1)
        return saved2;
    
    /*  There was not a tie that was sequential */
    return Look_Ahead_Tie();
}

int Sequential_Tie(int face_id, int triangulate)
{
    /*  Break the tie by choosing the face that will
        not give us a swap and is sequential. If there
        is not one, then do the lookahead to break the
        tie.
    */
    /*  Separate into 3 cases for simplicity, if the current
        polygon has 3 sides, 4 sides or if the sides were 
        greater. We can do the smaller cases faster, so that
        is why I separated the cases.
    */

     ListHead *pListFace;
	PF_FACES face;

    /*	Get the polygon with id face_id */
	pListFace  = PolFaces[face_id];
	face = (PF_FACES) PeekList(pListFace,LISTHEAD,0);

     if (face->nPolSize == 3)
        return(Sequential_Tri(face->pPolygon));
     if (face->nPolSize == 4)
        return(Sequential_Quad(face->pPolygon,triangulate));
     else
        return(Sequential_Poly(face->nPolSize,face->pPolygon,triangulate));

}

int Get_Next_Face(int t, int face_id, int triangulate)
{
	/*	Get the next face depending on what
		the user specified
	*/
	
	/*	Did not have a tie, don't do anything */
	if (last == 1)
		return(ties_array[0]);
	if (t == RANDOM)
		return Random_Tie();
	if (t == ALTERNATE)
		return Alternate_Tie();
	if (t == LOOK)
		return Look_Ahead_Tie();
     if (t == SEQUENTIAL)
        return Sequential_Tie(face_id,triangulate);

	printf("Illegal option specified for ties, using first \n");
     return (ties_array[0]);
}