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  */
monoTriangulationOpt(directedLine * poly,primStream * pStream)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 
monoTriangulationRecOpt(Real * topVertex,Real * botVertex,vertexArray * left_chain,Int left_current,vertexArray * right_chain,Int right_current,primStream * pStream)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 
monoTriangulationRecGenTBOpt(Real * topVertex,Real * botVertex,vertexArray * inc_chain,Int inc_current,Int inc_end,vertexArray * dec_chain,Int dec_current,Int dec_end,primStream * pStream)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  */
triangulateXYMonoTB(Int n_left,Real ** leftVerts,Int n_right,Real ** rightVerts,primStream * pStream)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 
chainConvex(vertexArray * inc_chain,Int inc_current,Int inc_end)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 
chainConcave(vertexArray * dec_chain,Int dec_current,Int dec_end)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 
monoTriangulationRecGenInU(Real * topVertex,Real * botVertex,vertexArray * inc_chain,Int inc_current,Int inc_end,vertexArray * dec_chain,Int dec_current,Int dec_end,primStream * pStream)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 
monoTriangulationRecGenOpt(Real * topVertex,Real * botVertex,vertexArray * inc_chain,Int inc_current,Int inc_end,vertexArray * dec_chain,Int dec_current,Int dec_end,primStream * pStream)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  */
monoTriangulationRecGen(Real * topVertex,Real * botVertex,vertexArray * inc_chain,Int inc_current,Int inc_end,vertexArray * dec_chain,Int dec_current,Int dec_end,primStream * pStream)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 
monoTriangulationFun(directedLine * monoPolygon,Int (* compFun)(Real *,Real *),primStream * pStream)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 
monoTriangulation(directedLine * monoPolygon,primStream * pStream)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  */
monoTriangulation2(Real * topVertex,Real * botVertex,vertexArray * inc_chain,Int inc_smallIndex,Int inc_largeIndex,Int is_increase_chain,primStream * pStream)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  */
monoTriangulationRecFunGen(Real * topVertex,Real * botVertex,vertexArray * inc_chain,Int inc_current,Int inc_end,vertexArray * dec_chain,Int dec_current,Int dec_end,Int (* compFun)(Real *,Real *),primStream * pStream)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  */
monoTriangulationRecFun(Real * topVertex,Real * botVertex,vertexArray * inc_chain,Int inc_current,vertexArray * dec_chain,Int dec_current,Int (* compFun)(Real *,Real *),primStream * pStream)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 
monoTriangulationRec(Real * topVertex,Real * botVertex,vertexArray * inc_chain,Int inc_current,vertexArray * dec_chain,Int dec_current,primStream * pStream)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  */
monoTriangulationRec(directedLine * inc_chain,Int inc_index,directedLine * dec_chain,Int dec_index,directedLine * topVertex,Int top_index,directedLine * botVertex,primStream * pStream)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**********************************/
vertexArray(Real2 * vertices,Int nVertices)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 
vertexArray(Int s)1131 vertexArray::vertexArray(Int s)
1132 {
1133   size = s;
1134   array = (Real**) malloc(sizeof(Real*) * s);
1135   assert(array);
1136   index = 0;
1137 }
1138 
~vertexArray()1139 vertexArray::~vertexArray()
1140 {
1141   free(array);
1142 }
1143 
appendVertex(Real * ptr)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 
print()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  */
findIndexAbove(Real v)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  */
findIndexBelowGen(Real v,Int startIndex,Int endIndex)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  */
findIndexStrictBelowGen(Real v,Int startIndex,Int endIndex)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  */
findIndexFirstAboveEqualGen(Real v,Int startIndex,Int endIndex)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  */
findIndexAboveGen(Real v,Int startIndex,Int endIndex)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 
findDecreaseChainFromEnd(Int begin,Int end)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
skipEqualityFromStart(Real v,Int start,Int end)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 
reflexChain(Int size,Int is_increasing)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 
~reflexChain()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  */
insert(Real u,Real v)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 
insert(Real v[2])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  */
outputFan(Real v[2],primStream * pStream)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 
processNewVertex(Real v[2],primStream * pStream)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 
print()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