Home | History | Annotate | Line # | Download | only in nurbtess
      1 /*
      2 ** License Applicability. Except to the extent portions of this file are
      3 ** made subject to an alternative license as permitted in the SGI Free
      4 ** Software License B, Version 1.1 (the "License"), the contents of this
      5 ** file are subject only to the provisions of the License. You may not use
      6 ** this file except in compliance with the License. You may obtain a copy
      7 ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
      8 ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
      9 **
     10 ** http://oss.sgi.com/projects/FreeB
     11 **
     12 ** Note that, as provided in the License, the Software is distributed on an
     13 ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
     14 ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
     15 ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
     16 ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
     17 **
     18 ** Original Code. The Original Code is: OpenGL Sample Implementation,
     19 ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
     20 ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
     21 ** Copyright in any portions created by third parties is as indicated
     22 ** elsewhere herein. All Rights Reserved.
     23 **
     24 ** Additional Notice Provisions: The application programming interfaces
     25 ** established by SGI in conjunction with the Original Code are The
     26 ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
     27 ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
     28 ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
     29 ** Window System(R) (Version 1.3), released October 19, 1998. This software
     30 ** was created using the OpenGL(R) version 1.2.1 Sample Implementation
     31 ** published by SGI, but has not been independently verified as being
     32 ** compliant with the OpenGL(R) version 1.2.1 Specification.
     33 **
     34 */
     35 /*
     36 */
     37 
     38 #include <stdlib.h>
     39 #include <stdio.h>
     40 #include "gluos.h"
     41 #include "glimports.h"
     42 #include "zlassert.h"
     43 
     44 #include "monoTriangulation.h"
     45 #include "polyUtil.h" /*for area*/
     46 #include "partitionX.h"
     47 #include "monoPolyPart.h"
     48 
     49 
     50 
     51 extern  directedLine*  polygonConvert(directedLine* polygon);
     52 
     53 /*poly is NOT deleted
     54  */
     55 void monoTriangulationOpt(directedLine* poly, primStream* pStream)
     56 {
     57   Int n_cusps;
     58   Int n_edges = poly->numEdges();
     59   directedLine** cusps = (directedLine**) malloc(sizeof(directedLine*)*n_edges);
     60   assert(cusps);
     61   findInteriorCuspsX(poly, n_cusps, cusps);
     62   if(n_cusps ==0) //u monotine
     63     {
     64       monoTriangulationFun(poly, compV2InX, pStream);
     65     }
     66   else if(n_cusps == 1) // one interior cusp
     67     {
     68       directedLine* new_polygon = polygonConvert(cusps[0]);
     69       directedLine* other = findDiagonal_singleCuspX(new_polygon);
     70       //<other> should NOT be null unless there are self-intersecting
     71       //trim curves. In that case, we don't want to core dump, instead,
     72       //we triangulate anyway, and print out error message.
     73       if(other == NULL)
     74 	{
     75 	  monoTriangulationFun(poly, compV2InX, pStream);
     76 	}
     77       else
     78 	{
     79 	  directedLine* ret_p1;
     80 	  directedLine* ret_p2;
     81 
     82 	  new_polygon->connectDiagonal_2slines(new_polygon, other,
     83 					       &ret_p1,
     84 					       &ret_p2,
     85 					       new_polygon);
     86 
     87 	  monoTriangulationFun(ret_p1, compV2InX, pStream);
     88 	  monoTriangulationFun(ret_p2, compV2InX, pStream);
     89 
     90 	  ret_p1->deleteSinglePolygonWithSline();
     91 	  ret_p2->deleteSinglePolygonWithSline();
     92 	}
     93     }
     94   else
     95     {
     96       //we need a general partitionX funtion (supposed to be in partitionX.C,
     97       //not implemented yet. XXX
     98       monoTriangulationFun(poly, compV2InY, pStream);
     99     }
    100 
    101   free(cusps);
    102 }
    103 
    104 void monoTriangulationRecOpt(Real* topVertex, Real* botVertex,
    105 			     vertexArray* left_chain, Int left_current,
    106 			     vertexArray* right_chain, Int right_current,
    107 			     primStream* pStream)
    108 {
    109   Int i,j;
    110   Int n_left = left_chain->getNumElements();
    111   Int n_right = right_chain->getNumElements();
    112   if(left_current>= n_left-1 ||
    113      right_current>= n_right-1)
    114     {
    115       monoTriangulationRec(topVertex, botVertex, left_chain, left_current,
    116 			   right_chain, right_current, pStream);
    117       return;
    118     }
    119   //now both left and right  have at least two vertices each.
    120   Real left_v = left_chain->getVertex(left_current)[1];
    121   Real right_v = right_chain->getVertex(right_current)[1];
    122 
    123   if(left_v <= right_v) //first left vertex is below right
    124     {
    125       //find the last vertex of right which is above or equal to left
    126       for(j=right_current; j<=n_right-1; j++)
    127 	{
    128 	  if(right_chain->getVertex(j)[1] < left_v)
    129 	    break;
    130 	}
    131       monoTriangulationRecGen(topVertex, left_chain->getVertex(left_current),
    132 			      left_chain, left_current, left_current,
    133 			      right_chain, right_current, j-1,
    134 			      pStream);
    135       monoTriangulationRecOpt(right_chain->getVertex(j-1),
    136 			      botVertex,
    137 			      left_chain, left_current,
    138 			      right_chain, j,
    139 			      pStream);
    140     }
    141   else //first right vertex is strictly below left
    142     {
    143       //find the last vertex of left which is strictly above right
    144       for(i=left_current; i<=n_left-1; i++)
    145 	{
    146 	  if(left_chain->getVertex(i)[1] <= right_v)
    147 	    break;
    148 	}
    149       monoTriangulationRecGen(topVertex, right_chain->getVertex(right_current),
    150 			      left_chain, left_current, i-1,
    151 			      right_chain, right_current, right_current,
    152 			      pStream);
    153       monoTriangulationRecOpt(left_chain->getVertex(i-1),
    154 			      botVertex,
    155 			      left_chain, i,
    156 			      right_chain, right_current,
    157 			      pStream);
    158     }
    159 }
    160 
    161 
    162 void monoTriangulationRecGenTBOpt(Real* topVertex, Real* botVertex,
    163 			  vertexArray* inc_chain, Int inc_current, Int inc_end,
    164 			  vertexArray* dec_chain, Int dec_current, Int dec_end,
    165 			  primStream* pStream)
    166 {
    167   pStream->triangle(topVertex, inc_chain->getVertex(inc_current), dec_chain->getVertex(dec_current));
    168 
    169 /*printf("**(%f,%f)\n", inc_chain->getArray()[0][0],inc_chain->getArray()[0][1]);*/
    170   triangulateXYMonoTB(inc_end-inc_current+1, inc_chain->getArray()+inc_current,  dec_end-dec_current+1,  dec_chain->getArray()+dec_current, pStream);
    171 
    172   pStream->triangle(botVertex, dec_chain->getVertex(dec_end), inc_chain->getVertex(inc_end));
    173 }
    174 
    175 
    176 /*n_left>=1
    177  *n_right>=1
    178  *the strip is going top to bottom. compared to the funtion
    179  * triangulateXYmono()
    180  */
    181 void triangulateXYMonoTB(Int n_left, Real** leftVerts,
    182 		       Int n_right, Real** rightVerts,
    183 		       primStream* pStream)
    184 {
    185 
    186 
    187   Int i,j,k,l;
    188   Real* topMostV;
    189 
    190   assert(n_left>=1 && n_right>=1);
    191   if(leftVerts[0][1] >= rightVerts[0][1])
    192     {
    193       i=1;
    194       j=0;
    195       topMostV = leftVerts[0];
    196     }
    197   else
    198     {
    199       i=0;
    200       j=1;
    201       topMostV = rightVerts[0];
    202     }
    203 
    204   while(1)
    205     {
    206       if(i >= n_left) /*case1: no more in left*/
    207 	{
    208 
    209 	  if(j<n_right-1) /*at least two vertices in right*/
    210 	    {
    211 	      pStream->begin();
    212 	      pStream->insert(topMostV);
    213 	      for(k=n_right-1; k>=j; k--)
    214 		pStream->insert(rightVerts[j]);
    215 
    216 	      pStream->end(PRIMITIVE_STREAM_FAN);
    217 
    218 	    }
    219 
    220 	  break;
    221 	}
    222       else if(j>= n_right) /*case2: no more in right*/
    223 	{
    224 
    225 	  if(i<n_left-1) /*at least two vertices in left*/
    226 	    {
    227 	      pStream->begin();
    228 	      pStream->insert(topMostV);
    229 
    230 	      for(k=i; k<n_left; k++)
    231 		pStream->insert(leftVerts[k]);
    232 
    233 	      pStream->end(PRIMITIVE_STREAM_FAN);
    234 	    }
    235 
    236 	  break;
    237 	}
    238       else /* case3: neither is empty, plus the topMostV, there is at least one triangle to output*/
    239 	{
    240 
    241 	  if(leftVerts[i][1] >=  rightVerts[j][1])
    242 	    {
    243 	      pStream->begin();
    244 	      pStream->insert(rightVerts[j]); /*the origin of this fan*/
    245 
    246 	      pStream->insert(topMostV);
    247 
    248 	      /*find the last k>=i such that
    249 	       *leftverts[k][1] >= rightverts[j][1]
    250 	       */
    251 	      k=i;
    252 	      while(k<n_left)
    253 		{
    254 		  if(leftVerts[k][1] < rightVerts[j][1])
    255 		    break;
    256 		  k++;
    257 		}
    258 	      k--;
    259 	      for(l=i; l<=k; l++)
    260 		{
    261 		  pStream->insert(leftVerts[l]);
    262 		}
    263 
    264 	      pStream->end(PRIMITIVE_STREAM_FAN);
    265 	      //update i for next loop
    266 	      i = k+1;
    267 	      topMostV = leftVerts[k];
    268 
    269 	    }
    270 	  else /*leftVerts[i][1] < rightVerts[j][1]*/
    271 	    {
    272 	      pStream->begin();
    273 	      pStream->insert(leftVerts[i]);/*the origion of this fan*/
    274 
    275 	      /*find the last k>=j such that
    276 	       *rightverts[k][1] > leftverts[i][1]*/
    277 	      k=j;
    278 	      while(k< n_right)
    279 		{
    280 		  if(rightVerts[k][1] <= leftVerts[i][1])
    281 		    break;
    282 		  k++;
    283 		}
    284 	      k--;
    285 
    286 	      for(l=k; l>= j; l--)
    287 		pStream->insert(rightVerts[l]);
    288 
    289 	      pStream->insert(topMostV);
    290 	      pStream->end(PRIMITIVE_STREAM_FAN);
    291 	      j=k+1;
    292 	      topMostV = rightVerts[j-1];
    293 	    }
    294 	}
    295     }
    296 }
    297 
    298 static int chainConvex(vertexArray* inc_chain, Int inc_current, Int inc_end)
    299 {
    300   Int i;
    301   //if there are no more than 2 vertices, return 1
    302   if(inc_current >= inc_end-1) return 1;
    303   for(i=inc_current; i<= inc_end-2; i++)
    304     {
    305       if(area(inc_chain->getVertex(i), inc_chain->getVertex(i+1), inc_chain->getVertex(i+2)) <0)
    306 	return 0;
    307     }
    308   return 1;
    309 }
    310 
    311 static int chainConcave(vertexArray* dec_chain, Int dec_current, Int dec_end)
    312 {
    313   Int i;
    314   //if there are no more than 2 vertices, return 1
    315   if(dec_current >= dec_end -1) return 1;
    316   for(i=dec_current; i<=dec_end-2; i++)
    317     {
    318       if(area(dec_chain->getVertex(i), dec_chain->getVertex(i+1), dec_chain->getVertex(i+2)) >0)
    319 	return 0;
    320     }
    321   return 1;
    322 }
    323 
    324 void monoTriangulationRecGenInU(Real* topVertex, Real* botVertex,
    325 				vertexArray* inc_chain, Int inc_current, Int inc_end,
    326 				vertexArray* dec_chain, Int dec_current, Int dec_end,
    327 				primStream* pStream)
    328 {
    329 
    330 }
    331 
    332 void  monoTriangulationRecGenOpt(Real* topVertex, Real* botVertex,
    333 				 vertexArray* inc_chain, Int inc_current, Int inc_end,
    334 				 vertexArray* dec_chain, Int dec_current, Int dec_end,
    335 				 primStream* pStream)
    336 {
    337   Int i;
    338   //copy this to a polygon: directedLine Lioop
    339   sampledLine* sline;
    340   directedLine* dline;
    341   directedLine* poly;
    342 
    343   if(inc_current <= inc_end) //at least one vertex in inc_chain
    344     {
    345       sline = new sampledLine(topVertex, inc_chain->getVertex(inc_current));
    346       poly = new directedLine(INCREASING, sline);
    347       for(i=inc_current; i<=inc_end-1; i++)
    348 	{
    349 	  sline = new sampledLine(inc_chain->getVertex(i), inc_chain->getVertex(i+1));
    350 	  dline = new directedLine(INCREASING, sline);
    351 	  poly->insert(dline);
    352 	}
    353       sline = new sampledLine(inc_chain->getVertex(inc_end), botVertex);
    354       dline = new directedLine(INCREASING, sline);
    355       poly->insert(dline);
    356     }
    357   else //inc_chian is empty
    358     {
    359       sline = new sampledLine(topVertex, botVertex);
    360       dline = new directedLine(INCREASING, sline);
    361       poly = dline;
    362     }
    363 
    364   assert(poly != NULL);
    365 
    366   if(dec_current <= dec_end) //at least on vertex in dec_Chain
    367     {
    368       sline = new sampledLine(botVertex, dec_chain->getVertex(dec_end));
    369       dline = new directedLine(INCREASING, sline);
    370       poly->insert(dline);
    371       for(i=dec_end; i>dec_current; i--)
    372 	{
    373 	  sline = new sampledLine(dec_chain->getVertex(i), dec_chain->getVertex(i-1));
    374 	  dline = new directedLine(INCREASING, sline);
    375 	  poly->insert(dline);
    376 	}
    377       sline = new sampledLine(dec_chain->getVertex(dec_current), topVertex);
    378       dline = new directedLine(INCREASING, sline);
    379       poly->insert(dline);
    380     }
    381   else //dec_chain  is empty
    382     {
    383       sline = new sampledLine(botVertex, topVertex);
    384       dline = new directedLine(INCREASING, sline);
    385       poly->insert(dline);
    386     }
    387 
    388   {
    389     Int n_cusps;
    390     Int n_edges = poly->numEdges();
    391     directedLine** cusps = (directedLine**) malloc(sizeof(directedLine*)*n_edges);
    392     assert(cusps);
    393     findInteriorCuspsX(poly, n_cusps, cusps);
    394 
    395     if(n_cusps ==0) //u monotine
    396       {
    397 	monoTriangulationFun(poly, compV2InX, pStream);
    398       }
    399     else if(n_cusps == 1) // one interior cusp
    400       {
    401 	directedLine* new_polygon = polygonConvert(cusps[0]);
    402 	directedLine* other = findDiagonal_singleCuspX(new_polygon);
    403 	  //<other> should NOT be null unless there are self-intersecting
    404           //trim curves. In that case, we don't want to core dump, instead,
    405           //we triangulate anyway, and print out error message.
    406 	  if(other == NULL)
    407 	    {
    408 	      monoTriangulationFun(poly, compV2InX, pStream);
    409 	    }
    410 	  else
    411 	    {
    412 	      directedLine* ret_p1;
    413 	      directedLine* ret_p2;
    414 
    415 	      new_polygon->connectDiagonal_2slines(new_polygon, other,
    416 						   &ret_p1,
    417 						   &ret_p2,
    418 						   new_polygon);
    419 
    420 	      monoTriangulationFun(ret_p1, compV2InX, pStream);
    421 	      monoTriangulationFun(ret_p2, compV2InX, pStream);
    422 
    423 	      ret_p1->deleteSinglePolygonWithSline();
    424 	      ret_p2->deleteSinglePolygonWithSline();
    425 	    }
    426       }
    427     else
    428       {
    429 	//we need a general partitionX funtion (supposed to be in partitionX.C,
    430 	//not implemented yet. XXX
    431 	//monoTriangulationFun(poly, compV2InY, pStream);
    432 
    433 	directedLine* new_polygon = polygonConvert(poly);
    434 	directedLine* list = monoPolyPart(new_polygon);
    435 	for(directedLine* temp = list; temp != NULL; temp = temp->getNextPolygon())
    436 	  {
    437 	    monoTriangulationFun(temp, compV2InX, pStream);
    438 	  }
    439 	//clean up
    440 	list->deletePolygonListWithSline();
    441 
    442       }
    443 
    444     free(cusps);
    445     /*
    446       if(numInteriorCuspsX(poly) == 0) //is u monotone
    447 	monoTriangulationFun(poly, compV2InX, pStream);
    448       else //it is not u motone
    449 	monoTriangulationFun(poly, compV2InY, pStream);
    450 	*/
    451     //clean up space
    452     poly->deleteSinglePolygonWithSline();
    453     return;
    454   }
    455 
    456   //apparently the following code is not reachable,
    457   //it is for test purpose
    458   if(inc_current > inc_end || dec_current>dec_end)
    459     {
    460     monoTriangulationRecGen(topVertex, botVertex, inc_chain, inc_current, inc_end,
    461 			    dec_chain, dec_current, dec_end,
    462 			    pStream);
    463     return;
    464   }
    465 
    466 
    467   if(
    468      area(dec_chain->getVertex(dec_current),
    469 	  topVertex,
    470 	  inc_chain->getVertex(inc_current)) >=0
    471      && chainConvex(inc_chain, inc_current, inc_end)
    472      && chainConcave(dec_chain, dec_current, dec_end)
    473      && area(inc_chain->getVertex(inc_end), botVertex, dec_chain->getVertex(dec_end)) >=0
    474      )
    475     {
    476       monoTriangulationRecFunGen(topVertex, botVertex,
    477 				 inc_chain, inc_current, inc_end,
    478 				 dec_chain, dec_current, dec_end,
    479 				 compV2InX, pStream);
    480     }
    481   else
    482     {
    483       monoTriangulationRecGen(topVertex, botVertex, inc_chain, inc_current, inc_end,
    484 			      dec_chain, dec_current, dec_end,
    485 			      pStream);
    486     }
    487 }
    488 
    489 /*if inc_current>inc_end, then inc_chain has no points to be considered
    490  *same for dec_chain
    491  */
    492 void monoTriangulationRecGen(Real* topVertex, Real* botVertex,
    493 			  vertexArray* inc_chain, Int inc_current, Int inc_end,
    494 			  vertexArray* dec_chain, Int dec_current, Int dec_end,
    495 			  primStream* pStream)
    496 {
    497   Real** inc_array ;
    498   Real** dec_array ;
    499   Int i;
    500 
    501   if(inc_current > inc_end && dec_current>dec_end)
    502     return;
    503   else if(inc_current>inc_end) /*no more vertices on inc_chain*/
    504     {
    505       dec_array = dec_chain->getArray();
    506       reflexChain rChain(100,0);
    507       /*put the top vertex into the reflex chain*/
    508       rChain.processNewVertex(topVertex, pStream);
    509       /*process all the vertices on the dec_chain*/
    510       for(i=dec_current; i<=dec_end; i++){
    511 	rChain.processNewVertex(dec_array[i], pStream);
    512       }
    513       /*process the bottom vertex*/
    514       rChain.processNewVertex(botVertex, pStream);
    515     }
    516   else if(dec_current> dec_end) /*no more vertices on dec_chain*/
    517     {
    518       inc_array = inc_chain->getArray();
    519 
    520       reflexChain rChain(100,1);
    521       /*put the top vertex into the reflex chain*/
    522       rChain.processNewVertex(topVertex, pStream);
    523       /*process all the vertices on the inc_chain*/
    524       for(i=inc_current; i<=inc_end; i++){
    525 	rChain.processNewVertex(inc_array[i], pStream);
    526       }
    527       /*process the bottom vertex*/
    528       rChain.processNewVertex(botVertex, pStream);
    529     }
    530   else /*neither chain is empty*/
    531     {
    532       inc_array = inc_chain -> getArray();
    533       dec_array = dec_chain -> getArray();
    534 
    535       /*if top of inc_chain is 'lower' than top of dec_chain, process all the
    536        *vertices on the dec_chain which are higher than top of inc_chain
    537        */
    538       if(compV2InY(inc_array[inc_current], dec_array[dec_current]) <= 0)
    539 	{
    540 
    541 	  reflexChain rChain(100, 0);
    542 	  rChain.processNewVertex(topVertex, pStream);
    543 	  for(i=dec_current; i<=dec_end; i++)
    544 	    {
    545 	      if(compV2InY(inc_array[inc_current], dec_array[i]) <= 0)
    546 		rChain.processNewVertex(dec_array[i], pStream);
    547 	      else
    548 		break;
    549 	    }
    550 	  rChain.outputFan(inc_array[inc_current], pStream);
    551 	  monoTriangulationRecGen(dec_array[i-1], botVertex,
    552 			       inc_chain, inc_current, inc_end,
    553 			       dec_chain, i, dec_end,
    554 			       pStream);
    555 	}
    556       else /*compV2InY(inc_array[inc_current], dec_array[dec_current]) > 0*/
    557 	{
    558 
    559 	  reflexChain rChain(100, 1);
    560 	  rChain.processNewVertex(topVertex, pStream);
    561 	  for(i=inc_current; i<=inc_end; i++)
    562 	    {
    563 	      if(compV2InY(inc_array[i], dec_array[dec_current]) >0)
    564 		rChain.processNewVertex(inc_array[i], pStream);
    565 	      else
    566 		break;
    567 	    }
    568 	  rChain.outputFan(dec_array[dec_current], pStream);
    569 	  monoTriangulationRecGen(inc_array[i-1], botVertex,
    570 			       inc_chain, i, inc_end,
    571 			       dec_chain, dec_current,dec_end,
    572 			       pStream);
    573 	}
    574     }/*end case neither is empty*/
    575 }
    576 
    577 void monoTriangulationFun(directedLine* monoPolygon, Int (*compFun)(Real*, Real*), primStream* pStream)
    578 {
    579   Int i;
    580   /*find the top vertex, bottom vertex, inccreasing chain, and decreasing chain,
    581    *then call monoTriangulationRec
    582    */
    583   directedLine* tempV;
    584   directedLine* topV;
    585   directedLine* botV;
    586   topV = botV = monoPolygon;
    587   for(tempV = monoPolygon->getNext(); tempV != monoPolygon; tempV = tempV->getNext())
    588     {
    589       if(compFun(topV->head(), tempV->head())<0) {
    590 	topV = tempV;
    591       }
    592       if(compFun(botV->head(), tempV->head())>0) {
    593 	botV = tempV;
    594       }
    595     }
    596 
    597   /*creat increase and decrease chains*/
    598   vertexArray inc_chain(20); /*this is a dynamic array*/
    599   for(i=1; i<=topV->get_npoints()-2; i++) { /*the first vertex is the top vertex which doesn't belong to inc_chain*/
    600     inc_chain.appendVertex(topV->getVertex(i));
    601   }
    602   for(tempV = topV->getNext(); tempV != botV; tempV = tempV->getNext())
    603     {
    604       for(i=0; i<=tempV->get_npoints()-2; i++){
    605 	inc_chain.appendVertex(tempV->getVertex(i));
    606       }
    607     }
    608 
    609   vertexArray dec_chain(20);
    610   for(tempV = topV->getPrev(); tempV != botV; tempV = tempV->getPrev())
    611     {
    612       for(i=tempV->get_npoints()-2; i>=0; i--){
    613 	dec_chain.appendVertex(tempV->getVertex(i));
    614       }
    615     }
    616   for(i=botV->get_npoints()-2; i>=1; i--){
    617     dec_chain.appendVertex(tempV->getVertex(i));
    618   }
    619 
    620   if (!(0 == inc_chain.getNumElements() && 0 == dec_chain.getNumElements())) {
    621      monoTriangulationRecFun(topV->head(), botV->head(), &inc_chain, 0,
    622                              &dec_chain, 0, compFun, pStream);
    623   }
    624 }
    625 
    626 void monoTriangulation(directedLine* monoPolygon, primStream* pStream)
    627 {
    628   Int i;
    629   /*find the top vertex, bottom vertex, inccreasing chain, and decreasing chain,
    630    *then call monoTriangulationRec
    631    */
    632   directedLine* tempV;
    633   directedLine* topV;
    634   directedLine* botV;
    635   topV = botV = monoPolygon;
    636   for(tempV = monoPolygon->getNext(); tempV != monoPolygon; tempV = tempV->getNext())
    637     {
    638       if(compV2InY(topV->head(), tempV->head())<0) {
    639 	topV = tempV;
    640       }
    641       if(compV2InY(botV->head(), tempV->head())>0) {
    642 	botV = tempV;
    643       }
    644     }
    645   /*creat increase and decrease chains*/
    646   vertexArray inc_chain(20); /*this is a dynamic array*/
    647   for(i=1; i<=topV->get_npoints()-2; i++) { /*the first vertex is the top vertex which doesn't belong to inc_chain*/
    648     inc_chain.appendVertex(topV->getVertex(i));
    649   }
    650   for(tempV = topV->getNext(); tempV != botV; tempV = tempV->getNext())
    651     {
    652       for(i=0; i<=tempV->get_npoints()-2; i++){
    653 	inc_chain.appendVertex(tempV->getVertex(i));
    654       }
    655     }
    656 
    657   vertexArray dec_chain(20);
    658   for(tempV = topV->getPrev(); tempV != botV; tempV = tempV->getPrev())
    659     {
    660       for(i=tempV->get_npoints()-2; i>=0; i--){
    661 	dec_chain.appendVertex(tempV->getVertex(i));
    662       }
    663     }
    664   for(i=botV->get_npoints()-2; i>=1; i--){
    665     dec_chain.appendVertex(tempV->getVertex(i));
    666   }
    667 
    668   monoTriangulationRec(topV->head(), botV->head(), &inc_chain, 0, &dec_chain, 0, pStream);
    669 
    670 }
    671 
    672 /*the chain could be increasing or decreasing, although we use the
    673  * name inc_chain.
    674  *the argument  is_increase_chain indicates whether this chain
    675  *is increasing (left chain in V-monotone case) or decreaing (right chain
    676  *in V-monotone case).
    677  */
    678 void monoTriangulation2(Real* topVertex, Real* botVertex,
    679 			vertexArray* inc_chain, Int inc_smallIndex,
    680 			Int inc_largeIndex,
    681 			Int is_increase_chain,
    682 			primStream* pStream)
    683 {
    684   assert( inc_chain != NULL);
    685   Real** inc_array ;
    686 
    687   if(inc_smallIndex > inc_largeIndex)
    688     return; //no triangles
    689   if(inc_smallIndex == inc_largeIndex)
    690     {
    691       if(is_increase_chain)
    692 	pStream->triangle(inc_chain->getVertex(inc_smallIndex), botVertex, topVertex);
    693       else
    694 	pStream->triangle(inc_chain->getVertex(inc_smallIndex), topVertex, botVertex);
    695       return;
    696     }
    697   Int i;
    698 
    699   if(is_increase_chain && botVertex[1] == inc_chain->getVertex(inc_largeIndex)[1])
    700     {
    701       pStream->triangle(botVertex, inc_chain->getVertex(inc_largeIndex-1),
    702 			inc_chain->getVertex(inc_largeIndex));
    703       monoTriangulation2(topVertex, botVertex, inc_chain, inc_smallIndex,
    704 			 inc_largeIndex-1,
    705 			 is_increase_chain,
    706 			 pStream);
    707       return;
    708     }
    709   else if( (!is_increase_chain) && topVertex[1] == inc_chain->getVertex(inc_smallIndex)[1])
    710     {
    711       pStream->triangle(topVertex, inc_chain->getVertex(inc_smallIndex+1),
    712 			inc_chain->getVertex(inc_smallIndex));
    713       monoTriangulation2(topVertex, botVertex, inc_chain, inc_smallIndex+1,
    714 			 inc_largeIndex, is_increase_chain, pStream);
    715       return ;
    716     }
    717 
    718   inc_array = inc_chain->getArray();
    719 
    720   reflexChain rChain(20,is_increase_chain); /*1 means the chain is increasing*/
    721 
    722   rChain.processNewVertex(topVertex, pStream);
    723 
    724   for(i=inc_smallIndex; i<=inc_largeIndex; i++){
    725     rChain.processNewVertex(inc_array[i], pStream);
    726   }
    727   rChain.processNewVertex(botVertex, pStream);
    728 
    729 }
    730 
    731 /*if compFun == compV2InY, top to bottom: V-monotone
    732  *if compFun == compV2InX, right to left: U-monotone
    733  */
    734 void monoTriangulationRecFunGen(Real* topVertex, Real* botVertex,
    735 			  vertexArray* inc_chain, Int inc_current, Int inc_end,
    736 			  vertexArray* dec_chain, Int dec_current, Int dec_end,
    737 			  Int  (*compFun)(Real*, Real*),
    738 			  primStream* pStream)
    739 {
    740   assert( inc_chain != NULL && dec_chain != NULL);
    741   assert( ! (inc_current> inc_end &&
    742 	     dec_current> dec_end));
    743   /*
    744   Int inc_nVertices;
    745   Int dec_nVertices;
    746   */
    747   Real** inc_array ;
    748   Real** dec_array ;
    749   Int i;
    750   assert( ! ( (inc_chain==NULL) && (dec_chain==NULL)));
    751 
    752   if(inc_current> inc_end) /*no more vertices on inc_chain*/
    753     {
    754 
    755       dec_array = dec_chain->getArray();
    756       reflexChain rChain(20,0);
    757       /*put the top vertex into the reflex chain*/
    758       rChain.processNewVertex(topVertex, pStream);
    759       /*process all the vertices on the dec_chain*/
    760       for(i=dec_current; i<=dec_end; i++){
    761 	rChain.processNewVertex(dec_array[i], pStream);
    762       }
    763       /*process the bottom vertex*/
    764       rChain.processNewVertex(botVertex, pStream);
    765 
    766     }
    767   else if(dec_current> dec_end) /*no more vertices on dec_chain*/
    768     {
    769       inc_array = inc_chain->getArray();
    770       reflexChain rChain(20,1);
    771       /*put the top vertex into the reflex chain*/
    772       rChain.processNewVertex(topVertex, pStream);
    773       /*process all the vertices on the inc_chain*/
    774       for(i=inc_current; i<=inc_end; i++){
    775 	rChain.processNewVertex(inc_array[i], pStream);
    776       }
    777       /*process the bottom vertex*/
    778       rChain.processNewVertex(botVertex, pStream);
    779     }
    780   else /*neither chain is empty*/
    781     {
    782       inc_array = inc_chain -> getArray();
    783       dec_array = dec_chain -> getArray();
    784 
    785       /*if top of inc_chain is 'lower' than top of dec_chain, process all the
    786        *vertices on the dec_chain which are higher than top of inc_chain
    787        */
    788       if(compFun(inc_array[inc_current], dec_array[dec_current]) <= 0)
    789 	{
    790 
    791 	  reflexChain rChain(20, 0);
    792 	  rChain.processNewVertex(topVertex, pStream);
    793 	  for(i=dec_current; i<=dec_end; i++)
    794 	    {
    795 	      if(compFun(inc_array[inc_current], dec_array[i]) <= 0)
    796 		rChain.processNewVertex(dec_array[i], pStream);
    797 	      else
    798 		break;
    799 	    }
    800 	  rChain.outputFan(inc_array[inc_current], pStream);
    801 	  monoTriangulationRecFunGen(dec_array[i-1], botVertex,
    802 			       inc_chain, inc_current, inc_end,
    803 			       dec_chain, i, dec_end,
    804 			       compFun,
    805 			       pStream);
    806 	}
    807       else /*compFun(inc_array[inc_current], dec_array[dec_current]) > 0*/
    808 	{
    809 
    810 	  reflexChain rChain(20, 1);
    811 	  rChain.processNewVertex(topVertex, pStream);
    812 	  for(i=inc_current; i<=inc_end; i++)
    813 	    {
    814 	      if(compFun(inc_array[i], dec_array[dec_current]) >0)
    815 		rChain.processNewVertex(inc_array[i], pStream);
    816 	      else
    817 		break;
    818 	    }
    819 	  rChain.outputFan(dec_array[dec_current], pStream);
    820 	  monoTriangulationRecFunGen(inc_array[i-1], botVertex,
    821 			       inc_chain, i,inc_end,
    822 			       dec_chain, dec_current,dec_end,
    823 			       compFun,
    824 			       pStream);
    825 	}
    826     }/*end case neither is empty*/
    827 }
    828 
    829 /*if compFun == compV2InY, top to bottom: V-monotone
    830  *if compFun == compV2InX, right to left: U-monotone
    831  */
    832 void monoTriangulationRecFun(Real* topVertex, Real* botVertex,
    833 			  vertexArray* inc_chain, Int inc_current,
    834 			  vertexArray* dec_chain, Int dec_current,
    835 			  Int  (*compFun)(Real*, Real*),
    836 			  primStream* pStream)
    837 {
    838   assert( inc_chain != NULL && dec_chain != NULL);
    839   assert( ! (inc_current>=inc_chain->getNumElements() &&
    840 	     dec_current>=dec_chain->getNumElements()));
    841   Int inc_nVertices;
    842   Int dec_nVertices;
    843   Real** inc_array ;
    844   Real** dec_array ;
    845   Int i;
    846   assert( ! ( (inc_chain==NULL) && (dec_chain==NULL)));
    847 
    848   if(inc_current>=inc_chain->getNumElements()) /*no more vertices on inc_chain*/
    849     {
    850 
    851       dec_array = dec_chain->getArray();
    852       dec_nVertices = dec_chain->getNumElements();
    853       reflexChain rChain(20,0);
    854       /*put the top vertex into the reflex chain*/
    855       rChain.processNewVertex(topVertex, pStream);
    856       /*process all the vertices on the dec_chain*/
    857       for(i=dec_current; i<dec_nVertices; i++){
    858 	rChain.processNewVertex(dec_array[i], pStream);
    859       }
    860       /*process the bottom vertex*/
    861       rChain.processNewVertex(botVertex, pStream);
    862 
    863     }
    864   else if(dec_current>= dec_chain->getNumElements()) /*no more vertices on dec_chain*/
    865     {
    866       inc_array = inc_chain->getArray();
    867       inc_nVertices= inc_chain->getNumElements();
    868       reflexChain rChain(20,1);
    869       /*put the top vertex into the reflex chain*/
    870       rChain.processNewVertex(topVertex, pStream);
    871       /*process all the vertices on the inc_chain*/
    872       for(i=inc_current; i<inc_nVertices; i++){
    873 	rChain.processNewVertex(inc_array[i], pStream);
    874       }
    875       /*process the bottom vertex*/
    876       rChain.processNewVertex(botVertex, pStream);
    877     }
    878   else /*neither chain is empty*/
    879     {
    880       inc_array = inc_chain -> getArray();
    881       dec_array = dec_chain -> getArray();
    882       inc_nVertices= inc_chain->getNumElements();
    883       dec_nVertices= dec_chain->getNumElements();
    884       /*if top of inc_chain is 'lower' than top of dec_chain, process all the
    885        *vertices on the dec_chain which are higher than top of inc_chain
    886        */
    887       if(compFun(inc_array[inc_current], dec_array[dec_current]) <= 0)
    888 	{
    889 
    890 	  reflexChain rChain(20, 0);
    891 	  rChain.processNewVertex(topVertex, pStream);
    892 	  for(i=dec_current; i<dec_nVertices; i++)
    893 	    {
    894 	      if(compFun(inc_array[inc_current], dec_array[i]) <= 0)
    895 		rChain.processNewVertex(dec_array[i], pStream);
    896 	      else
    897 		break;
    898 	    }
    899 	  rChain.outputFan(inc_array[inc_current], pStream);
    900 	  monoTriangulationRecFun(dec_array[i-1], botVertex,
    901 			       inc_chain, inc_current,
    902 			       dec_chain, i,
    903 			       compFun,
    904 			       pStream);
    905 	}
    906       else /*compFun(inc_array[inc_current], dec_array[dec_current]) > 0*/
    907 	{
    908 
    909 	  reflexChain rChain(20, 1);
    910 	  rChain.processNewVertex(topVertex, pStream);
    911 	  for(i=inc_current; i<inc_nVertices; i++)
    912 	    {
    913 	      if(compFun(inc_array[i], dec_array[dec_current]) >0)
    914 		rChain.processNewVertex(inc_array[i], pStream);
    915 	      else
    916 		break;
    917 	    }
    918 	  rChain.outputFan(dec_array[dec_current], pStream);
    919 	  monoTriangulationRecFun(inc_array[i-1], botVertex,
    920 			       inc_chain, i,
    921 			       dec_chain, dec_current,
    922 			       compFun,
    923 			       pStream);
    924 	}
    925     }/*end case neither is empty*/
    926 }
    927 
    928 
    929 void monoTriangulationRec(Real* topVertex, Real* botVertex,
    930 			  vertexArray* inc_chain, Int inc_current,
    931 			  vertexArray* dec_chain, Int dec_current,
    932 			  primStream* pStream)
    933 {
    934   assert( inc_chain != NULL && dec_chain != NULL);
    935   assert( ! (inc_current>=inc_chain->getNumElements() &&
    936 	     dec_current>=dec_chain->getNumElements()));
    937   Int inc_nVertices;
    938   Int dec_nVertices;
    939   Real** inc_array ;
    940   Real** dec_array ;
    941   Int i;
    942   assert( ! ( (inc_chain==NULL) && (dec_chain==NULL)));
    943 
    944   if(inc_current>=inc_chain->getNumElements()) /*no more vertices on inc_chain*/
    945     {
    946 
    947       dec_array = dec_chain->getArray();
    948       dec_nVertices = dec_chain->getNumElements();
    949       reflexChain rChain(20,0);
    950       /*put the top vertex into the reflex chain*/
    951       rChain.processNewVertex(topVertex, pStream);
    952       /*process all the vertices on the dec_chain*/
    953       for(i=dec_current; i<dec_nVertices; i++){
    954 	rChain.processNewVertex(dec_array[i], pStream);
    955       }
    956       /*process the bottom vertex*/
    957       rChain.processNewVertex(botVertex, pStream);
    958 
    959     }
    960   else if(dec_current>= dec_chain->getNumElements()) /*no more vertices on dec_chain*/
    961     {
    962       inc_array = inc_chain->getArray();
    963       inc_nVertices= inc_chain->getNumElements();
    964       reflexChain rChain(20,1);
    965       /*put the top vertex into the reflex chain*/
    966       rChain.processNewVertex(topVertex, pStream);
    967       /*process all the vertices on the inc_chain*/
    968       for(i=inc_current; i<inc_nVertices; i++){
    969 	rChain.processNewVertex(inc_array[i], pStream);
    970       }
    971       /*process the bottom vertex*/
    972       rChain.processNewVertex(botVertex, pStream);
    973     }
    974   else /*neither chain is empty*/
    975     {
    976       inc_array = inc_chain -> getArray();
    977       dec_array = dec_chain -> getArray();
    978       inc_nVertices= inc_chain->getNumElements();
    979       dec_nVertices= dec_chain->getNumElements();
    980       /*if top of inc_chain is 'lower' than top of dec_chain, process all the
    981        *vertices on the dec_chain which are higher than top of inc_chain
    982        */
    983       if(compV2InY(inc_array[inc_current], dec_array[dec_current]) <= 0)
    984 	{
    985 
    986 	  reflexChain rChain(20, 0);
    987 	  rChain.processNewVertex(topVertex, pStream);
    988 	  for(i=dec_current; i<dec_nVertices; i++)
    989 	    {
    990 	      if(compV2InY(inc_array[inc_current], dec_array[i]) <= 0)
    991 		rChain.processNewVertex(dec_array[i], pStream);
    992 	      else
    993 		break;
    994 	    }
    995 	  rChain.outputFan(inc_array[inc_current], pStream);
    996 	  monoTriangulationRec(dec_array[i-1], botVertex,
    997 			       inc_chain, inc_current,
    998 			       dec_chain, i,
    999 			       pStream);
   1000 	}
   1001       else /*compV2InY(inc_array[inc_current], dec_array[dec_current]) > 0*/
   1002 	{
   1003 
   1004 	  reflexChain rChain(20, 1);
   1005 	  rChain.processNewVertex(topVertex, pStream);
   1006 	  for(i=inc_current; i<inc_nVertices; i++)
   1007 	    {
   1008 	      if(compV2InY(inc_array[i], dec_array[dec_current]) >0)
   1009 		rChain.processNewVertex(inc_array[i], pStream);
   1010 	      else
   1011 		break;
   1012 	    }
   1013 	  rChain.outputFan(dec_array[dec_current], pStream);
   1014 	  monoTriangulationRec(inc_array[i-1], botVertex,
   1015 			       inc_chain, i,
   1016 			       dec_chain, dec_current,
   1017 			       pStream);
   1018 	}
   1019     }/*end case neither is empty*/
   1020 }
   1021 
   1022 
   1023 
   1024 /* the name here assumes that the polygon is Y-monotone, but
   1025  *this function also works for X-monotone polygons.
   1026  * a monotne polygon consists of two extrem verteices: topVertex and botVertex, and
   1027  *two monotone chains: inc_chain, and dec_chain. The edges of the increasing chain (inc_chain)
   1028  *is ordered by following pointer: next, while  the edges of the decreasing chain (dec_chain)
   1029  *is ordered by following pointer: prev
   1030  * inc_index index the vertex which is the toppest of the inc_chain which we are handling currently.
   1031  * dec_index index the vertex which is the toppest of the dec_chain which we are handling currently.
   1032  */
   1033 void monoTriangulationRec(directedLine* inc_chain, Int inc_index,
   1034 			  directedLine* dec_chain, Int dec_index,
   1035 			  directedLine* topVertex, Int top_index,
   1036 			  directedLine* botVertex,
   1037 			  primStream* pStream)
   1038 {
   1039   Int i;
   1040   directedLine *temp, *oldtemp = NULL;
   1041   Int tempIndex, oldtempIndex = 0;
   1042 
   1043   assert(inc_chain != NULL && dec_chain != NULL);
   1044 
   1045   if(inc_chain == botVertex) {
   1046     reflexChain rChain(20, 0);
   1047     rChain.processNewVertex(topVertex->getVertex(top_index), pStream);
   1048     for(i=dec_index; i< dec_chain->get_npoints(); i++){
   1049       rChain.processNewVertex(dec_chain->getVertex(i), pStream);
   1050     }
   1051     for(temp = dec_chain->getPrev(); temp != botVertex; temp = temp->getPrev())
   1052       {
   1053 	for(i=0; i<temp->get_npoints(); i++){
   1054 	  rChain.processNewVertex(temp->getVertex(i), pStream);
   1055 	}
   1056       }
   1057   }
   1058   else if(dec_chain==botVertex) {
   1059     reflexChain rChain(20, 1);
   1060     rChain.processNewVertex(topVertex->getVertex(top_index), pStream);
   1061     for(i=inc_index; i< inc_chain->get_npoints(); i++){
   1062       rChain.processNewVertex(inc_chain->getVertex(i), pStream);
   1063     }
   1064     for(temp = inc_chain->getPrev(); temp != botVertex; temp = temp->getNext())
   1065       {
   1066 	for(i=0; i<temp->get_npoints(); i++){
   1067 	  rChain.processNewVertex(temp->getVertex(i), pStream);
   1068 	}
   1069       }
   1070   }
   1071   else /*neither reached the bottom*/{
   1072     if(compV2InY(inc_chain->getVertex(inc_index), dec_chain->getVertex(dec_index)) <=0) {
   1073       reflexChain rChain(20, 0);
   1074       rChain.processNewVertex(topVertex -> getVertex(top_index), pStream);
   1075       temp = dec_chain;
   1076       tempIndex = dec_index;
   1077       while( compV2InY(inc_chain->getVertex(inc_index), temp->getVertex(tempIndex))<=0) {
   1078 	oldtemp = temp;
   1079 	oldtempIndex = tempIndex;
   1080 	rChain.processNewVertex(temp->getVertex(tempIndex), pStream);
   1081 
   1082 	if(tempIndex == temp->get_npoints()-1){
   1083 	  tempIndex = 0;
   1084 	  temp = temp->getPrev();
   1085 	}
   1086 	else{
   1087 	  tempIndex++;
   1088 	}
   1089       }
   1090       rChain.outputFan(inc_chain->getVertex(inc_index), pStream);
   1091       monoTriangulationRec(inc_chain, inc_index, temp, tempIndex, oldtemp, oldtempIndex, botVertex, pStream);
   1092     }
   1093     else /* >0*/ {
   1094       reflexChain rChain(20, 1);
   1095       rChain.processNewVertex(topVertex -> getVertex(top_index), pStream);
   1096       temp = inc_chain;
   1097       tempIndex = inc_index;
   1098       while( compV2InY(temp->getVertex(tempIndex), dec_chain->getVertex(dec_index))>0){
   1099 	oldtemp = temp;
   1100 	oldtempIndex = tempIndex;
   1101 	rChain.processNewVertex(temp->getVertex(tempIndex), pStream);
   1102 
   1103 	if(tempIndex == temp->get_npoints()-1){
   1104 	  tempIndex = 0;
   1105 	  temp = temp->getNext();
   1106 	}
   1107 	else{
   1108 	  tempIndex++;
   1109 	}
   1110       }
   1111       rChain.outputFan(dec_chain->getVertex(dec_index), pStream);
   1112       monoTriangulationRec(temp, tempIndex, dec_chain, dec_index, oldtemp, oldtempIndex, botVertex, pStream);
   1113     }
   1114   } /*end case neither reached the bottom*/
   1115 }
   1116 
   1117 /***************************vertexArray begin here**********************************/
   1118 vertexArray::vertexArray(Real2* vertices, Int nVertices)
   1119 {
   1120   Int i;
   1121   size = index = nVertices;
   1122   array = (Real**) malloc(sizeof(Real*) * nVertices);
   1123   assert(array);
   1124   for(i=0; i<nVertices; i++)
   1125     {
   1126       array[i] = vertices[i];
   1127       array[i] = vertices[i];
   1128     }
   1129 }
   1130 
   1131 vertexArray::vertexArray(Int s)
   1132 {
   1133   size = s;
   1134   array = (Real**) malloc(sizeof(Real*) * s);
   1135   assert(array);
   1136   index = 0;
   1137 }
   1138 
   1139 vertexArray::~vertexArray()
   1140 {
   1141   free(array);
   1142 }
   1143 
   1144 void vertexArray::appendVertex(Real* ptr)
   1145 {
   1146   Int i;
   1147   if(index >= size){
   1148     Real** temp = (Real**) malloc(sizeof(Real*) * (2*size +1));
   1149     assert(temp);
   1150     for(i=0; i<index; i++)
   1151       temp[i] = array[i];
   1152     free(array);
   1153     array = temp;
   1154     size = 2*size+1;
   1155   }
   1156   array[index++] = ptr;
   1157 }
   1158 
   1159 void vertexArray::print()
   1160 {
   1161   printf("vertex Array:index=%i, size=%i\n", index, size);
   1162   for(Int i=0; i<index; i++)
   1163     {
   1164       printf("(%f,%f) ", array[i][0], array[i][1]);
   1165     }
   1166   printf("\n");
   1167 }
   1168 
   1169 /*find the first i such that array[i][1] >= v
   1170  * and array[i+1][1] <v
   1171  * if index == 0 (the array is empty, return -1.
   1172  * if v is above all, return -1.
   1173  * if v is below all, return index-1.
   1174  */
   1175 Int vertexArray::findIndexAbove(Real v)
   1176 {
   1177   Int i;
   1178   if(index == 0)
   1179     return -1;
   1180   else if(array[0][1] < v)
   1181     return -1;
   1182   else
   1183     {
   1184       for(i=1; i<index; i++)
   1185 	{
   1186 	  if(array[i][1] < v)
   1187 	    break;
   1188 	}
   1189       return i-1;
   1190     }
   1191 }
   1192 
   1193 /*find the first i<=endIndex such that array[i][1] <= v
   1194  * and array[i-1][1] > v
   1195  *if sartIndex>endIndex, then return endIndex+1.
   1196  *otherwise, startIndex<=endIndex, it is assumed that
   1197  * 0<=startIndex<=endIndex<index.
   1198  * if v is below all, return endIndex+1
   1199  * if v is above all, return startIndex.
   1200  */
   1201 Int vertexArray::findIndexBelowGen(Real v, Int startIndex, Int endIndex)
   1202 {
   1203   Int i;
   1204   if(startIndex > endIndex)
   1205     return endIndex+1;
   1206   else if(array[endIndex][1] >  v)
   1207     return endIndex+1;
   1208   else //now array[endIndex][1] <= v
   1209     {
   1210       for(i=endIndex-1; i>=startIndex; i--)
   1211 	{
   1212 	  if(array[i][1] > v)
   1213 	    break;
   1214 	}
   1215       return i+1;
   1216     }
   1217 }
   1218 
   1219 /*find the first i<=endIndex such that array[i-1][1] >= v
   1220  * and array[i][1] < v
   1221  *if sartIndex>endIndex, then return endIndex+1.
   1222  *otherwise, startIndex<=endIndex, it is assumed that
   1223  * 0<=startIndex<=endIndex<index.
   1224  * if v is below or equal to all, return endIndex+1
   1225  * if v is strictly above all, return startIndex.
   1226  */
   1227 Int vertexArray::findIndexStrictBelowGen(Real v, Int startIndex, Int endIndex)
   1228 {
   1229   Int i;
   1230   if(startIndex > endIndex)
   1231     return endIndex+1;
   1232   else if(array[endIndex][1] >=  v)
   1233     return endIndex+1;
   1234   else //now array[endIndex][1] < v
   1235     {
   1236       for(i=endIndex-1; i>=startIndex; i--)
   1237 	{
   1238 	  if(array[i][1] >= v)
   1239 	    break;
   1240 	}
   1241       return i+1;
   1242     }
   1243 }
   1244 
   1245 /*find the first i>startIndex such that array[i-1][1] > v
   1246  * and array[i][1] >=v
   1247  *if sartIndex>endIndex, then return startIndex-1.
   1248  *otherwise, startIndex<=endIndex, it is assumed that
   1249  * 0<=startIndex<=endIndex<index.
   1250  * if v is strictly above all, return startIndex-1
   1251  * if v is strictly below all, return endIndex.
   1252  */
   1253 Int vertexArray::findIndexFirstAboveEqualGen(Real v, Int startIndex, Int endIndex)
   1254 {
   1255 
   1256   Int i;
   1257   if(startIndex > endIndex)
   1258     return startIndex-1;
   1259   else if(array[startIndex][1] < v)
   1260     return startIndex-1;
   1261   else //now array[startIndex][1] >= v
   1262     {
   1263 
   1264       for(i=startIndex; i<=endIndex; i++)
   1265 	{
   1266 	  if(array[i][1] <= v)
   1267 	    break;
   1268 	}
   1269       if(i>endIndex) // v is strictly below all
   1270 	return endIndex;
   1271       else if(array[i][1] == v)
   1272 	return i;
   1273       else
   1274 	return i-1;
   1275     }
   1276 
   1277 }
   1278 
   1279 
   1280 /*find the first i>=startIndex such that array[i][1] >= v
   1281  * and array[i+1][1] <v
   1282  *if sartIndex>endIndex, then return startIndex-1.
   1283  *otherwise, startIndex<=endIndex, it is assumed that
   1284  * 0<=startIndex<=endIndex<index.
   1285  * if v is above all, return startIndex-1
   1286  * if v is below all, return endIndex.
   1287  */
   1288 Int vertexArray::findIndexAboveGen(Real v, Int startIndex, Int endIndex)
   1289 {
   1290   Int i;
   1291   if(startIndex > endIndex)
   1292     return startIndex-1;
   1293   else if(array[startIndex][1] < v)
   1294     return startIndex-1;
   1295   else //now array[startIndex][1] >= v
   1296     {
   1297       for(i=startIndex+1; i<=endIndex; i++)
   1298 	{
   1299 	  if(array[i][1] < v)
   1300 	    break;
   1301 	}
   1302       return i-1;
   1303     }
   1304 }
   1305 
   1306 Int vertexArray::findDecreaseChainFromEnd(Int begin, Int end)
   1307 {
   1308   Int i = end;
   1309   Real prevU = array[i][0];
   1310   Real thisU;
   1311   for(i=end-1; i>=begin; i--){
   1312     thisU = array[i][0];
   1313     if(thisU < prevU)
   1314       prevU = thisU;
   1315     else
   1316       break;
   1317   }
   1318   return i;
   1319 }
   1320 
   1321 //if(V(start) == v, return start, other wise return the
   1322 //last i so that V(i)==v
   1323 Int vertexArray::skipEqualityFromStart(Real v, Int start, Int end)
   1324 {
   1325   Int i;
   1326   if(array[start][1] != v)
   1327     return start;
   1328   //now array[start][1] == v
   1329   for(i=start+1; i<= end; i++)
   1330     if(array[i][1] != v)
   1331       break;
   1332   return i-1;
   1333 }
   1334 
   1335 
   1336 /***************************vertexArray end****************************************/
   1337 
   1338 
   1339 
   1340 /***************************relfex chain stuff begin here*****************************/
   1341 
   1342 reflexChain::reflexChain(Int size, Int is_increasing)
   1343 {
   1344   queue = (Real2*) malloc(sizeof(Real2) * size);
   1345   assert(queue);
   1346   index_queue = 0;
   1347   size_queue = size;
   1348   isIncreasing = is_increasing;
   1349 }
   1350 
   1351 reflexChain::~reflexChain()
   1352 {
   1353   free(queue);
   1354 }
   1355 
   1356 /*put (u,v) at the end of the queue
   1357  *pay attention to space
   1358  */
   1359 void reflexChain::insert(Real u, Real v)
   1360 {
   1361   Int i;
   1362   if(index_queue >= size_queue) {
   1363     Real2 *temp = (Real2*) malloc(sizeof(Real2) * (2*size_queue+1));
   1364     assert(temp);
   1365 
   1366     /*copy*/
   1367     for(i=0; i<index_queue; i++){
   1368       temp[i][0] = queue[i][0];
   1369       temp[i][1] = queue[i][1];
   1370     }
   1371 
   1372     free(queue);
   1373     queue = temp;
   1374     size_queue = 2*size_queue + 1;
   1375   }
   1376 
   1377   queue[index_queue][0] = u;
   1378   queue[index_queue][1] = v;
   1379   index_queue ++;
   1380 }
   1381 
   1382 void reflexChain::insert(Real v[2])
   1383 {
   1384   insert(v[0], v[1]);
   1385 }
   1386 
   1387 /*
   1388 static Real area(Real A[2], Real B[2], Real C[2])
   1389 {
   1390   Real Bx, By, Cx, Cy;
   1391   Bx = B[0] - A[0];
   1392   By = B[1] - A[1];
   1393   Cx = C[0] - A[0];
   1394   Cy = C[1] - A[1];
   1395   return Bx*Cy - Cx*By;
   1396 }
   1397 */
   1398 
   1399 /*the chain is reflex, and the vertex v is
   1400  *on the other side of the chain, so that
   1401  *we can outout the fan with v as the
   1402  *the center
   1403  */
   1404 void reflexChain::outputFan(Real v[2], primStream* pStream)
   1405 {
   1406   Int i;
   1407   pStream->begin();
   1408   pStream->insert(v);
   1409   if(isIncreasing) {
   1410     for(i=0; i<index_queue; i++)
   1411       pStream->insert(queue[i]);
   1412   }
   1413   else {
   1414     for(i=index_queue-1; i>=0; i--)
   1415       pStream->insert(queue[i]);
   1416   }
   1417   pStream->end(PRIMITIVE_STREAM_FAN);
   1418 }
   1419 
   1420 void reflexChain::processNewVertex(Real v[2], primStream* pStream)
   1421 {
   1422   Int i,j,k;
   1423   Int isReflex;
   1424   /*if there are at most one vertex in the queue, then simply insert
   1425    */
   1426   if(index_queue <=1){
   1427     insert(v);
   1428     return;
   1429   }
   1430 
   1431   /*there are at least two vertices in the queue*/
   1432   j=index_queue-1;
   1433 
   1434   for(i=j; i>=1; i--) {
   1435     if(isIncreasing) {
   1436       isReflex = (area(queue[i-1], queue[i], v) <= 0.0);
   1437     }
   1438     else /*decreasing*/{
   1439       isReflex = (area(v, queue[i], queue[i-1]) <= 0.0);
   1440     }
   1441     if(isReflex) {
   1442       break;
   1443     }
   1444   }
   1445 
   1446   /*
   1447    *if i<j then vertices: i+1--j are convex
   1448    * output triangle fan:
   1449    *  v, and queue[i], i+1, ..., j
   1450    */
   1451   if(i<j)
   1452     {
   1453       pStream->begin();
   1454       pStream->insert(v);
   1455       if(isIncreasing) {
   1456 	for(k=i; k<=j; k++)
   1457 	  pStream->insert(queue[k]);
   1458       }
   1459       else {
   1460 	for(k=j; k>=i; k--)
   1461 	  pStream->insert(queue[k]);
   1462       }
   1463 
   1464       pStream->end(PRIMITIVE_STREAM_FAN);
   1465     }
   1466 
   1467   /*delete vertices i+1--j from the queue*/
   1468   index_queue = i+1;
   1469   /*finally insert v at the end of the queue*/
   1470   insert(v);
   1471 
   1472 }
   1473 
   1474 void reflexChain::print()
   1475 {
   1476   Int i;
   1477   printf("reflex chain: isIncreasing=%i\n", isIncreasing);
   1478   for(i=0; i<index_queue; i++) {
   1479     printf("(%f,%f) ", queue[i][0], queue[i][1]);
   1480   }
   1481   printf("\n");
   1482 }
   1483