/*
** License Applicability. Except to the extent portions of this file are
** made subject to an alternative license as permitted in the SGI Free
** Software License B, Version 1.1 (the "License"), the contents of this
** file are subject only to the provisions of the License. You may not use
** this file except in compliance with the License. You may obtain a copy
** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
** 
** http://oss.sgi.com/projects/FreeB
** 
** Note that, as provided in the License, the Software is distributed on an
** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
** 
** Original Code. The Original Code is: OpenGL Sample Implementation,
** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
** Copyright in any portions created by third parties is as indicated
** elsewhere herein. All Rights Reserved.
** 
** Additional Notice Provisions: The application programming interfaces
** established by SGI in conjunction with the Original Code are The
** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
** Window System(R) (Version 1.3), released October 19, 1998. This software
** was created using the OpenGL(R) version 1.2.1 Sample Implementation
** published by SGI, but has not been independently verified as being
** compliant with the OpenGL(R) version 1.2.1 Specification.
**
** $Date: 2012/03/29 17:22:18 $ $Revision: 1.1.1.1 $
*/
/*
** $Header: /cvs/bao-parsec/pkgs/libs/mesa/src/src/glu/sgi/libnurbs/internals/monoTriangulationBackend.cc,v 1.1.1.1 2012/03/29 17:22:18 uid42307 Exp $
*/

#include "monoTriangulation.h"
#include "polyUtil.h"
#include "backend.h"
#include "arc.h"

void reflexChain::outputFan(Real v[2], Backend* backend)
{
  Int i;
  /*
  TrimVertex trimVert;
  */
  backend->bgntfan();

  /*
  trimVert.param[0]=v[0];
  trimVert.param[1]=v[1];
  backend->tmeshvert(&trimVert);
  */
  backend->tmeshvert(v[0], v[1]);

  if(isIncreasing) {
    for(i=0; i<index_queue; i++)
      {
	/*
	trimVert.param[0]=queue[i][0];
	trimVert.param[1]=queue[i][1];
	backend->tmeshvert(&trimVert);
	*/
	backend->tmeshvert(queue[i][0], queue[i][1]);
      }
  }
  else {
    for(i=index_queue-1; i>=0; i--)
      {
	/*
	trimVert.param[0]=queue[i][0];
	trimVert.param[1]=queue[i][1];
	backend->tmeshvert(&trimVert);
	*/
	backend->tmeshvert(queue[i][0], queue[i][1]);
      }
  }
  backend->endtfan();
}

void reflexChain::processNewVertex(Real v[2], Backend* backend)
{
  Int i,j,k;
  Int isReflex;
  /*TrimVertex trimVert;*/
  /*if there are at most one vertex in the queue, then simply insert
   */
  if(index_queue <=1){
    insert(v);
    return;
  }
  
  /*there are at least two vertices in the queue*/
  j=index_queue-1;
  
  for(i=j; i>=1; i--) {
    if(isIncreasing) {
      isReflex = (area(queue[i-1], queue[i], v) <= 0.0);
    }
    else /*decreasing*/{
      isReflex = (area(v, queue[i], queue[i-1]) <= 0.0);	  
    }
    if(isReflex) {
      break;
    }
  }

  /*
   *if i<j then vertices: i+1--j are convex
   * output triangle fan: 
   *  v, and queue[i], i+1, ..., j
   */
  if(i<j) 
    {
      backend->bgntfan();
      /*
      trimVert.param[0]=v[0];
      trimVert.param[1]=v[1];
      backend->tmeshvert(& trimVert);
      */
      backend->tmeshvert(v[0], v[1]);

      if(isIncreasing) {
	for(k=i; k<=j; k++)
	  {
	    /*
	    trimVert.param[0]=queue[k][0];
	    trimVert.param[1]=queue[k][1];
	    backend->tmeshvert(& trimVert);
	    */
	    backend->tmeshvert(queue[k][0], queue[k][1]);
	  }
      }
      else {
	for(k=j; k>=i; k--)
	  {
	    /*
	    trimVert.param[0]=queue[k][0];
	    trimVert.param[1]=queue[k][1];
	    backend->tmeshvert(& trimVert);
	    */
	    backend->tmeshvert(queue[k][0], queue[k][1]);
	  }
      }
      
      backend->endtfan();
    }

  /*delete vertices i+1--j from the queue*/
  index_queue = i+1;
  /*finally insert v at the end of the queue*/
  insert(v);

}


void monoTriangulationRec(Real* topVertex, Real* botVertex, 
			  vertexArray* inc_chain, Int inc_current,
			  vertexArray* dec_chain, Int dec_current,
			  Backend* backend)
{
  assert( inc_chain != NULL && dec_chain != NULL);
  assert( ! (inc_current>=inc_chain->getNumElements() &&
	     dec_current>=dec_chain->getNumElements()));
  Int inc_nVertices;
  Int dec_nVertices;
  Real** inc_array ;
  Real** dec_array ;
  Int i;
  assert( ! ( (inc_chain==NULL) && (dec_chain==NULL)));

  if(inc_current>=inc_chain->getNumElements()) /*no more vertices on inc_chain*/
    {

      dec_array = dec_chain->getArray();
      dec_nVertices = dec_chain->getNumElements();      
      reflexChain rChain(20,0);
      /*put the top vertex into the reflex chain*/
      rChain.processNewVertex(topVertex, backend);
      /*process all the vertices on the dec_chain*/
      for(i=dec_current; i<dec_nVertices; i++){
	rChain.processNewVertex(dec_array[i], backend);
      }
      /*process the bottom vertex*/
      rChain.processNewVertex(botVertex, backend);

    }
  else if(dec_current>= dec_chain->getNumElements()) /*no more vertices on dec_chain*/
    {
      inc_array = inc_chain->getArray();
      inc_nVertices= inc_chain->getNumElements();
      reflexChain rChain(20,1);
      /*put the top vertex into the reflex chain*/
      rChain.processNewVertex(topVertex, backend);
      /*process all the vertices on the inc_chain*/
      for(i=inc_current; i<inc_nVertices; i++){
	rChain.processNewVertex(inc_array[i], backend);
      }
      /*process the bottom vertex*/
      rChain.processNewVertex(botVertex, backend);
    }
  else /*neither chain is empty*/
    {
      inc_array = inc_chain -> getArray();
      dec_array = dec_chain -> getArray();
      inc_nVertices= inc_chain->getNumElements();
      dec_nVertices= dec_chain->getNumElements();
      /*if top of inc_chain is 'lower' than top of dec_chain, process all the 
       *vertices on the dec_chain which are higher than top of inc_chain
       */
      if(compV2InY(inc_array[inc_current], dec_array[dec_current]) <= 0)
	{

	  reflexChain rChain(20, 0);
	  rChain.processNewVertex(topVertex, backend);
	  for(i=dec_current; i<dec_nVertices; i++)
	    {
	      if(compV2InY(inc_array[inc_current], dec_array[i]) <= 0)
		rChain.processNewVertex(dec_array[i], backend);
	      else 
		break;
	    }
	  rChain.outputFan(inc_array[inc_current], backend);
	  monoTriangulationRec(dec_array[i-1], botVertex, 
			       inc_chain, inc_current,
			       dec_chain, i,
			       backend);
	}
      else /*compV2InY(inc_array[inc_current], dec_array[dec_current]) > 0*/
	{

	  reflexChain rChain(20, 1);
	  rChain.processNewVertex(topVertex, backend);
	  for(i=inc_current; i<inc_nVertices; i++)
	    {
	      if(compV2InY(inc_array[i], dec_array[dec_current]) >0)		
		rChain.processNewVertex(inc_array[i], backend);	      
	      else
		break;
	    }
	  rChain.outputFan(dec_array[dec_current], backend);
	  monoTriangulationRec(inc_array[i-1], botVertex, 
			       inc_chain, i,
			       dec_chain, dec_current,
			       backend);
	}
    }/*end case neither is empty*/
}


void monoTriangulationFunBackend(Arc_ptr loop, Int (*compFun)(Real*, Real*), Backend* backend)
{
  Int i;
  /*find the top vertex, bottom vertex, inccreasing chain, and decreasing chain,
   *then call monoTriangulationRec
   */
  Arc_ptr tempV;
  Arc_ptr topV;
  Arc_ptr botV;
  topV = botV = loop;
  for(tempV = loop->next; tempV != loop; tempV = tempV->next)
    {
      if(compFun(topV->tail(), tempV->tail())<0) {
	topV = tempV;
      }
      if(compFun(botV->tail(), tempV->tail())>0) {
	botV = tempV;
      }
    }

  /*creat increase and decrease chains*/
  vertexArray inc_chain(20); /*this is a dynamic array*/
  for(i=1; i<=topV->pwlArc->npts-2; i++) { /*the first vertex is the top vertex which doesn't belong to inc_chain*/
    inc_chain.appendVertex(topV->pwlArc->pts[i].param);
  }
  for(tempV = topV->next; tempV != botV; tempV = tempV->next)
    {
      for(i=0; i<=tempV->pwlArc->npts-2; i++){
	inc_chain.appendVertex(tempV->pwlArc->pts[i].param);
      }
    }
  
  vertexArray dec_chain(20);
  for(tempV = topV->prev; tempV != botV; tempV = tempV->prev)
    {
      for(i=tempV->pwlArc->npts-2; i>=0; i--){
	dec_chain.appendVertex(tempV->pwlArc->pts[i].param);
      }
    }
  for(i=botV->pwlArc->npts-2; i>=1; i--){ 
    dec_chain.appendVertex(tempV->pwlArc->pts[i].param);
  }
  
  monoTriangulationRecFunBackend(topV->tail(), botV->tail(), &inc_chain, 0, &dec_chain, 0, compFun, backend);

}  

/*if compFun == compV2InY, top to bottom: V-monotone
 *if compFun == compV2InX, right to left: U-monotone
 */
void monoTriangulationRecFunBackend(Real* topVertex, Real* botVertex, 
			  vertexArray* inc_chain, Int inc_current,
			  vertexArray* dec_chain, Int dec_current,
			  Int  (*compFun)(Real*, Real*),
			  Backend* backend)
{
  assert( inc_chain != NULL && dec_chain != NULL);
  assert( ! (inc_current>=inc_chain->getNumElements() &&
	     dec_current>=dec_chain->getNumElements()));
  Int inc_nVertices;
  Int dec_nVertices;
  Real** inc_array ;
  Real** dec_array ;
  Int i;
  assert( ! ( (inc_chain==NULL) && (dec_chain==NULL)));

  if(inc_current>=inc_chain->getNumElements()) /*no more vertices on inc_chain*/
    {

      dec_array = dec_chain->getArray();
      dec_nVertices = dec_chain->getNumElements();      
      reflexChain rChain(20,0);
      /*put the top vertex into the reflex chain*/
      rChain.processNewVertex(topVertex, backend);
      /*process all the vertices on the dec_chain*/
      for(i=dec_current; i<dec_nVertices; i++){
	rChain.processNewVertex(dec_array[i], backend);
      }
      /*process the bottom vertex*/
      rChain.processNewVertex(botVertex, backend);

    }
  else if(dec_current>= dec_chain->getNumElements()) /*no more vertices on dec_chain*/
    {
      inc_array = inc_chain->getArray();
      inc_nVertices= inc_chain->getNumElements();
      reflexChain rChain(20,1);
      /*put the top vertex into the reflex chain*/
      rChain.processNewVertex(topVertex, backend);
      /*process all the vertices on the inc_chain*/
      for(i=inc_current; i<inc_nVertices; i++){
	rChain.processNewVertex(inc_array[i], backend);
      }
      /*process the bottom vertex*/
      rChain.processNewVertex(botVertex, backend);
    }
  else /*neither chain is empty*/
    {
      inc_array = inc_chain -> getArray();
      dec_array = dec_chain -> getArray();
      inc_nVertices= inc_chain->getNumElements();
      dec_nVertices= dec_chain->getNumElements();
      /*if top of inc_chain is 'lower' than top of dec_chain, process all the 
       *vertices on the dec_chain which are higher than top of inc_chain
       */
      if(compFun(inc_array[inc_current], dec_array[dec_current]) <= 0)
	{

	  reflexChain rChain(20, 0);
	  rChain.processNewVertex(topVertex, backend);
	  for(i=dec_current; i<dec_nVertices; i++)
	    {
	      if(compFun(inc_array[inc_current], dec_array[i]) <= 0)
		rChain.processNewVertex(dec_array[i], backend);
	      else 
		break;
	    }
	  rChain.outputFan(inc_array[inc_current], backend);
	  monoTriangulationRecFunBackend(dec_array[i-1], botVertex, 
			       inc_chain, inc_current,
			       dec_chain, i,
			       compFun,
			       backend);
	}
      else /*compFun(inc_array[inc_current], dec_array[dec_current]) > 0*/
	{

	  reflexChain rChain(20, 1);
	  rChain.processNewVertex(topVertex, backend);
	  for(i=inc_current; i<inc_nVertices; i++)
	    {
	      if(compFun(inc_array[i], dec_array[dec_current]) >0)		
		rChain.processNewVertex(inc_array[i], backend);	      
	      else
		break;
	    }
	  rChain.outputFan(dec_array[dec_current], backend);
	  monoTriangulationRecFunBackend(inc_array[i-1], botVertex, 
			       inc_chain, i,
			       dec_chain, dec_current,
			       compFun,
			       backend);
	}
    }/*end case neither is empty*/
}
