Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / glu / sgi / libnurbs / nurbtess / monoTriangulation.cc
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 }