sampleMonoPoly.cc revision f220fa62
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 "gluos.h"
39#include <stdlib.h>
40#include <stdio.h>
41#include <math.h>
42
43#ifndef max
44#define max(a,b) ((a>b)? a:b)
45#endif
46#ifndef min
47#define min(a,b) ((a>b)? b:a)
48#endif
49
50#include <GL/gl.h>
51
52#include "glimports.h"
53#include "zlassert.h"
54#include "sampleMonoPoly.h"
55#include "sampleComp.h"
56#include "polyDBG.h"
57#include "partitionX.h"
58
59
60#define ZERO 0.00001
61
62//#define  MYDEBUG
63
64//#define SHORTEN_GRID_LINE
65//see work/newtess/internal/test/problems
66
67
68/*split a polygon so that each vertex correcpond to one edge
69 *the head of the first edge of the returned plygon must be the head of the first
70 *edge of the origianl polygon. This is crucial for the code in sampleMonoPoly function
71 */
72 directedLine*  polygonConvert(directedLine* polygon)
73{
74  int i;
75  directedLine* ret;
76  sampledLine* sline;
77  sline = new sampledLine(2);
78  sline->setPoint(0, polygon->getVertex(0));
79  sline->setPoint(1, polygon->getVertex(1));
80  ret=new directedLine(INCREASING, sline);
81  for(i=1; i<= polygon->get_npoints()-2; i++)
82    {
83      sline = new sampledLine(2);
84      sline->setPoint(0, polygon->getVertex(i));
85      sline->setPoint(1, polygon->getVertex(i+1));
86      ret->insert(new directedLine(INCREASING, sline));
87    }
88
89  for(directedLine *temp = polygon->getNext(); temp != polygon; temp = temp->getNext())
90    {
91      for(i=0; i<= temp->get_npoints()-2; i++)
92	{
93	  sline = new sampledLine(2);
94	  sline->setPoint(0, temp->getVertex(i));
95	  sline->setPoint(1, temp->getVertex(i+1));
96	  ret->insert(new directedLine(INCREASING, sline));
97	}
98    }
99  return ret;
100}
101
102void triangulateConvexPolyVertical(directedLine* topV, directedLine* botV, primStream *pStream)
103{
104  Int i,j;
105  Int n_leftVerts;
106  Int n_rightVerts;
107  Real** leftVerts;
108  Real** rightVerts;
109  directedLine* tempV;
110  n_leftVerts = 0;
111  for(tempV = topV; tempV != botV; tempV = tempV->getNext())
112    {
113      n_leftVerts += tempV->get_npoints();
114    }
115  n_rightVerts=0;
116  for(tempV = botV; tempV != topV; tempV = tempV->getNext())
117    {
118      n_rightVerts += tempV->get_npoints();
119    }
120
121  Real2* temp_leftVerts = (Real2 *) malloc(sizeof(Real2) * n_leftVerts);
122  assert(temp_leftVerts);
123  Real2* temp_rightVerts = (Real2 *) malloc(sizeof(Real2) * n_rightVerts);
124  assert(temp_rightVerts);
125
126  leftVerts = (Real**) malloc(sizeof(Real2*) * n_leftVerts);
127  assert(leftVerts);
128  rightVerts = (Real**) malloc(sizeof(Real2*) * n_rightVerts);
129  assert(rightVerts);
130  for(i=0; i<n_leftVerts; i++)
131    leftVerts[i] = temp_leftVerts[i];
132  for(i=0; i<n_rightVerts; i++)
133    rightVerts[i] = temp_rightVerts[i];
134
135  i=0;
136  for(tempV = topV; tempV != botV; tempV = tempV->getNext())
137    {
138      for(j=1; j<tempV->get_npoints(); j++)
139	{
140	  leftVerts[i][0] = tempV->getVertex(j)[0];
141	  leftVerts[i][1] = tempV->getVertex(j)[1];
142	  i++;
143	}
144    }
145  n_leftVerts = i;
146  i=0;
147  for(tempV = topV->getPrev(); tempV != botV->getPrev(); tempV = tempV->getPrev())
148    {
149      for(j=tempV->get_npoints()-1; j>=1; j--)
150	{
151	  rightVerts[i][0] = tempV->getVertex(j)[0];
152	  rightVerts[i][1] = tempV->getVertex(j)[1];
153	  i++;
154	}
155    }
156  n_rightVerts = i;
157  triangulateXYMonoTB(n_leftVerts, leftVerts, n_rightVerts, rightVerts, pStream);
158  free(leftVerts);
159  free(rightVerts);
160  free(temp_leftVerts);
161  free(temp_rightVerts);
162}
163
164void triangulateConvexPolyHoriz(directedLine* leftV, directedLine* rightV, primStream *pStream)
165{
166  Int i,j;
167  Int n_lowerVerts;
168  Int n_upperVerts;
169  Real2 *lowerVerts;
170  Real2 *upperVerts;
171  directedLine* tempV;
172  n_lowerVerts=0;
173  for(tempV = leftV; tempV != rightV; tempV = tempV->getNext())
174    {
175      n_lowerVerts += tempV->get_npoints();
176    }
177  n_upperVerts=0;
178  for(tempV = rightV; tempV != leftV; tempV = tempV->getNext())
179    {
180      n_upperVerts += tempV->get_npoints();
181    }
182  lowerVerts = (Real2 *) malloc(sizeof(Real2) * n_lowerVerts);
183  assert(n_lowerVerts);
184  upperVerts = (Real2 *) malloc(sizeof(Real2) * n_upperVerts);
185  assert(n_upperVerts);
186  i=0;
187  for(tempV = leftV; tempV != rightV; tempV = tempV->getNext())
188    {
189      for(j=0; j<tempV->get_npoints(); j++)
190	{
191	  lowerVerts[i][0] = tempV->getVertex(j)[0];
192	  lowerVerts[i][1] = tempV->getVertex(j)[1];
193	  i++;
194	}
195    }
196  i=0;
197  for(tempV = leftV->getPrev(); tempV != rightV->getPrev(); tempV = tempV->getPrev())
198    {
199      for(j=tempV->get_npoints()-1; j>=0; j--)
200	{
201	  upperVerts[i][0] = tempV->getVertex(j)[0];
202	  upperVerts[i][1] = tempV->getVertex(j)[1];
203	  i++;
204	}
205    }
206  triangulateXYMono(n_upperVerts, upperVerts, n_lowerVerts, lowerVerts, pStream);
207  free(lowerVerts);
208  free(upperVerts);
209}
210void triangulateConvexPoly(directedLine* polygon, Int ulinear, Int vlinear, primStream* pStream)
211{
212  /*find left, right, top , bot
213    */
214  directedLine* tempV;
215  directedLine* topV;
216  directedLine* botV;
217  directedLine* leftV;
218  directedLine* rightV;
219  topV = botV = polygon;
220
221  for(tempV = polygon->getNext(); tempV != polygon; tempV = tempV->getNext())
222    {
223      if(compV2InY(topV->head(), tempV->head())<0) {
224
225	topV = tempV;
226      }
227      if(compV2InY(botV->head(), tempV->head())>0) {
228
229	botV = tempV;
230      }
231    }
232  //find leftV
233  for(tempV = topV; tempV != botV; tempV = tempV->getNext())
234    {
235      if(tempV->tail()[0] >= tempV->head()[0])
236	break;
237    }
238  leftV = tempV;
239  //find rightV
240  for(tempV = botV; tempV != topV; tempV = tempV->getNext())
241    {
242      if(tempV->tail()[0] <= tempV->head()[0])
243	break;
244    }
245  rightV = tempV;
246  if(vlinear)
247    {
248      triangulateConvexPolyHoriz( leftV, rightV, pStream);
249    }
250  else if(ulinear)
251    {
252      triangulateConvexPolyVertical(topV, botV, pStream);
253    }
254  else
255    {
256      if(DBG_is_U_direction(polygon))
257	{
258	  triangulateConvexPolyHoriz( leftV, rightV, pStream);
259	}
260      else
261	triangulateConvexPolyVertical(topV, botV, pStream);
262    }
263}
264
265/*for debug purpose*/
266void drawCorners(
267		 Real* topV, Real* botV,
268		 vertexArray* leftChain,
269		 vertexArray* rightChain,
270		 gridBoundaryChain* leftGridChain,
271		 gridBoundaryChain* rightGridChain,
272		 Int gridIndex1,
273		 Int gridIndex2,
274		 Int leftCornerWhere,
275		 Int leftCornerIndex,
276		 Int rightCornerWhere,
277		 Int rightCornerIndex,
278		 Int bot_leftCornerWhere,
279		 Int bot_leftCornerIndex,
280		 Int bot_rightCornerWhere,
281		 Int bot_rightCornerIndex)
282{
283  Real* leftCornerV;
284  Real* rightCornerV;
285  Real* bot_leftCornerV;
286  Real* bot_rightCornerV;
287
288  if(leftCornerWhere == 1)
289    leftCornerV = topV;
290  else if(leftCornerWhere == 0)
291    leftCornerV = leftChain->getVertex(leftCornerIndex);
292  else
293    leftCornerV = rightChain->getVertex(leftCornerIndex);
294
295  if(rightCornerWhere == 1)
296    rightCornerV = topV;
297  else if(rightCornerWhere == 0)
298    rightCornerV = leftChain->getVertex(rightCornerIndex);
299  else
300    rightCornerV = rightChain->getVertex(rightCornerIndex);
301
302  if(bot_leftCornerWhere == 1)
303    bot_leftCornerV = botV;
304  else if(bot_leftCornerWhere == 0)
305    bot_leftCornerV = leftChain->getVertex(bot_leftCornerIndex);
306  else
307    bot_leftCornerV = rightChain->getVertex(bot_leftCornerIndex);
308
309  if(bot_rightCornerWhere == 1)
310    bot_rightCornerV = botV;
311  else if(bot_rightCornerWhere == 0)
312    bot_rightCornerV = leftChain->getVertex(bot_rightCornerIndex);
313  else
314    bot_rightCornerV = rightChain->getVertex(bot_rightCornerIndex);
315
316  Real topGridV = leftGridChain->get_v_value(gridIndex1);
317  Real topGridU1 = leftGridChain->get_u_value(gridIndex1);
318  Real topGridU2 = rightGridChain->get_u_value(gridIndex1);
319  Real botGridV = leftGridChain->get_v_value(gridIndex2);
320  Real botGridU1 = leftGridChain->get_u_value(gridIndex2);
321  Real botGridU2 = rightGridChain->get_u_value(gridIndex2);
322
323  glBegin(GL_LINE_STRIP);
324  glVertex2fv(leftCornerV);
325  glVertex2f(topGridU1, topGridV);
326  glEnd();
327
328  glBegin(GL_LINE_STRIP);
329  glVertex2fv(rightCornerV);
330  glVertex2f(topGridU2, topGridV);
331  glEnd();
332
333  glBegin(GL_LINE_STRIP);
334  glVertex2fv(bot_leftCornerV);
335  glVertex2f(botGridU1, botGridV);
336  glEnd();
337
338  glBegin(GL_LINE_STRIP);
339  glVertex2fv(bot_rightCornerV);
340  glVertex2f(botGridU2, botGridV);
341  glEnd();
342
343
344}
345
346void toVertexArrays(directedLine* topV, directedLine* botV, vertexArray& leftChain, vertexArray& rightChain)
347{
348  Int i;
349  directedLine* tempV;
350  for(i=1; i<=topV->get_npoints()-2; i++) { /*the first vertex is the top vertex which doesn't belong to inc_chain*/
351    leftChain.appendVertex(topV->getVertex(i));
352  }
353  for(tempV = topV->getNext(); tempV != botV; tempV = tempV->getNext())
354    {
355      for(i=0; i<=tempV->get_npoints()-2; i++){
356	leftChain.appendVertex(tempV->getVertex(i));
357      }
358    }
359
360  for(tempV = topV->getPrev(); tempV != botV; tempV = tempV->getPrev())
361    {
362      for(i=tempV->get_npoints()-2; i>=0; i--){
363	rightChain.appendVertex(tempV->getVertex(i));
364      }
365    }
366  for(i=botV->get_npoints()-2; i>=1; i--){
367    rightChain.appendVertex(tempV->getVertex(i));
368  }
369}
370
371
372void findTopAndBot(directedLine* polygon, directedLine*& topV, directedLine*& botV)
373{
374  assert(polygon);
375  directedLine* tempV;
376  topV = botV = polygon;
377   for(tempV = polygon->getNext(); tempV != polygon; tempV = tempV->getNext())
378    {
379      if(compV2InY(topV->head(), tempV->head())<0) {
380	topV = tempV;
381      }
382      if(compV2InY(botV->head(), tempV->head())>0) {
383	botV = tempV;
384      }
385    }
386}
387
388void findGridChains(directedLine* topV, directedLine* botV,
389		    gridWrap* grid,
390		    gridBoundaryChain*& leftGridChain,
391		    gridBoundaryChain*& rightGridChain)
392{
393  /*find the first(top) and the last (bottom) grid line which intersect the
394   *this polygon
395   */
396  Int firstGridIndex; /*the index in the grid*/
397  Int lastGridIndex;
398
399  firstGridIndex = (Int) ((topV->head()[1] - grid->get_v_min()) / (grid->get_v_max() - grid->get_v_min()) * (grid->get_n_vlines()-1));
400
401  if(botV->head()[1] < grid->get_v_min())
402    lastGridIndex = 0;
403  else
404    lastGridIndex  = (Int) ((botV->head()[1] - grid->get_v_min()) / (grid->get_v_max() - grid->get_v_min()) * (grid->get_n_vlines()-1)) + 1;
405
406  /*find the interval inside  the polygon for each gridline*/
407  Int *leftGridIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1));
408  assert(leftGridIndices);
409  Int *rightGridIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1));
410  assert(rightGridIndices);
411  Int *leftGridInnerIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1));
412  assert(leftGridInnerIndices);
413  Int *rightGridInnerIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1));
414  assert(rightGridInnerIndices);
415
416  findLeftGridIndices(topV, firstGridIndex, lastGridIndex, grid,  leftGridIndices, leftGridInnerIndices);
417
418  findRightGridIndices(topV, firstGridIndex, lastGridIndex, grid,  rightGridIndices, rightGridInnerIndices);
419
420  leftGridChain =  new gridBoundaryChain(grid, firstGridIndex, firstGridIndex-lastGridIndex+1, leftGridIndices, leftGridInnerIndices);
421
422  rightGridChain = new gridBoundaryChain(grid, firstGridIndex, firstGridIndex-lastGridIndex+1, rightGridIndices, rightGridInnerIndices);
423
424  free(leftGridIndices);
425  free(rightGridIndices);
426  free(leftGridInnerIndices);
427  free(rightGridInnerIndices);
428}
429
430void findDownCorners(Real *botVertex,
431		   vertexArray *leftChain, Int leftChainStartIndex, Int leftChainEndIndex,
432		   vertexArray *rightChain, Int rightChainStartIndex, Int rightChainEndIndex,
433		   Real v,
434		   Real uleft,
435		   Real uright,
436		   Int& ret_leftCornerWhere, /*0: left chain, 1: topvertex, 2: rightchain*/
437		   Int& ret_leftCornerIndex, /*useful when ret_leftCornerWhere == 0 or 2*/
438		   Int& ret_rightCornerWhere, /*0: left chain, 1: topvertex, 2: rightchain*/
439		   Int& ret_rightCornerIndex /*useful when ret_leftCornerWhere == 0 or 2*/
440		   )
441{
442#ifdef MYDEBUG
443printf("*************enter find donw corner\n");
444printf("finddownCorner: v=%f, uleft=%f, uright=%f\n", v, uleft, uright);
445printf("(%i,%i,%i,%i)\n", leftChainStartIndex, leftChainEndIndex,rightChainStartIndex, rightChainEndIndex);
446printf("left chain is\n");
447leftChain->print();
448printf("right chain is\n");
449rightChain->print();
450#endif
451
452  assert(v > botVertex[1]);
453  Real leftGridPoint[2];
454  leftGridPoint[0] = uleft;
455  leftGridPoint[1] = v;
456  Real rightGridPoint[2];
457  rightGridPoint[0] = uright;
458  rightGridPoint[1] = v;
459
460  Int i;
461  Int index1, index2;
462
463  index1 = leftChain->findIndexBelowGen(v, leftChainStartIndex, leftChainEndIndex);
464  index2 = rightChain->findIndexBelowGen(v, rightChainStartIndex, rightChainEndIndex);
465
466  if(index2 <= rightChainEndIndex) //index2 was found above
467    index2 = rightChain->skipEqualityFromStart(v, index2, rightChainEndIndex);
468
469  if(index1>leftChainEndIndex && index2 > rightChainEndIndex) /*no point below v on left chain or right chain*/
470    {
471
472      /*the botVertex is the only vertex below v*/
473      ret_leftCornerWhere = 1;
474      ret_rightCornerWhere = 1;
475    }
476  else if(index1>leftChainEndIndex ) /*index2 <= rightChainEndIndex*/
477    {
478
479      ret_rightCornerWhere = 2; /*on right chain*/
480      ret_rightCornerIndex = index2;
481
482
483      Real tempMin = rightChain->getVertex(index2)[0];
484      Int tempI = index2;
485      for(i=index2+1; i<= rightChainEndIndex; i++)
486	if(rightChain->getVertex(i)[0] < tempMin)
487	  {
488	    tempI = i;
489	    tempMin = rightChain->getVertex(i)[0];
490	  }
491
492
493      //we consider whether we can use botVertex as left corner. First check
494      //if (leftGirdPoint, botVertex) interesects right chian or not.
495     if(DBG_intersectChain(rightChain, rightChainStartIndex,rightChainEndIndex,
496				    leftGridPoint, botVertex))
497       {
498	 ret_leftCornerWhere = 2;//right
499	 ret_leftCornerIndex = index2; //should use tempI???
500       }
501     else if(botVertex[0] < tempMin)
502       ret_leftCornerWhere = 1; //bot
503     else
504       {
505	 ret_leftCornerWhere = 2; //right
506	 ret_leftCornerIndex = tempI;
507       }
508    }
509  else if(index2> rightChainEndIndex) /*index1<=leftChainEndIndex*/
510    {
511      ret_leftCornerWhere = 0; /*left chain*/
512      ret_leftCornerIndex = index1;
513
514      /*find the vertex on the left chain with the maximum u,
515       *either this vertex or the botvertex can be used as the right corner
516       */
517
518      Int tempI;
519      //skip those points which are equal to v. (avoid degeneratcy)
520      for(tempI = index1; tempI <= leftChainEndIndex; tempI++)
521	if(leftChain->getVertex(tempI)[1] < v)
522	  break;
523      if(tempI > leftChainEndIndex)
524	ret_rightCornerWhere = 1;
525      else
526	{
527	  Real tempMax = leftChain->getVertex(tempI)[0];
528	  for(i=tempI; i<= leftChainEndIndex; i++)
529	    if(leftChain->getVertex(i)[0] > tempMax)
530	      {
531		tempI = i;
532		tempMax = leftChain->getVertex(i)[0];
533	      }
534
535
536
537	  //we consider whether we can use botVertex as a corner. So first we check
538	  //whether (rightGridPoint, botVertex) interescts the left chain or not.
539	  if(DBG_intersectChain(leftChain, leftChainStartIndex,leftChainEndIndex,
540				    rightGridPoint, botVertex))
541	    {
542	      ret_rightCornerWhere = 0;
543	      ret_rightCornerIndex = index1; //should use tempI???
544	    }
545	  else if(botVertex[0] > tempMax)
546	    {
547
548              ret_rightCornerWhere = 1;
549	    }
550	  else
551	    {
552	      ret_rightCornerWhere = 0;
553	      ret_rightCornerIndex = tempI;
554	    }
555	}
556
557    }
558  else /*index1<=leftChainEndIndex and index2 <=rightChainEndIndex*/
559    {
560      if(leftChain->getVertex(index1)[1] >= rightChain->getVertex(index2)[1]) /*left point above right point*/
561	{
562	  ret_leftCornerWhere = 0; /*on left chain*/
563	  ret_leftCornerIndex = index1;
564
565	  Real tempMax;
566	  Int tempI;
567
568	  tempI = index1;
569	  tempMax = leftChain->getVertex(index1)[0];
570
571	  /*find the maximum u for all the points on the left above the right point index2*/
572	  for(i=index1+1; i<= leftChainEndIndex; i++)
573	    {
574	      if(leftChain->getVertex(i)[1] < rightChain->getVertex(index2)[1])
575		break;
576
577	      if(leftChain->getVertex(i)[0]>tempMax)
578		{
579		  tempI = i;
580		  tempMax = leftChain->getVertex(i)[0];
581		}
582	    }
583	  //we consider if we can use rightChain(index2) as right corner
584	  //we check if (rightChain(index2), rightGidPoint) intersecs left chain or not.
585	  if(DBG_intersectChain(leftChain, leftChainStartIndex,leftChainEndIndex, rightGridPoint, rightChain->getVertex(index2)))
586	    {
587	      ret_rightCornerWhere = 0;
588	      ret_rightCornerIndex = index1; //should use tempI???
589	    }
590	  else if(tempMax >= rightChain->getVertex(index2)[0] ||
591	     tempMax >= uright
592	     )
593	    {
594
595	      ret_rightCornerWhere = 0; /*on left Chain*/
596	      ret_rightCornerIndex = tempI;
597	    }
598	  else
599	    {
600	      ret_rightCornerWhere = 2; /*on right chain*/
601	      ret_rightCornerIndex = index2;
602	    }
603	}
604      else /*left below right*/
605	{
606	  ret_rightCornerWhere = 2; /*on the right*/
607	  ret_rightCornerIndex = index2;
608
609	  Real tempMin;
610	  Int tempI;
611
612	  tempI = index2;
613	  tempMin = rightChain->getVertex(index2)[0];
614
615	  /*find the minimum u for all the points on the right above the left poitn index1*/
616	  for(i=index2+1; i<= rightChainEndIndex; i++)
617	    {
618	      if( rightChain->getVertex(i)[1] < leftChain->getVertex(index1)[1])
619		break;
620	      if(rightChain->getVertex(i)[0] < tempMin)
621		{
622		  tempI = i;
623		  tempMin = rightChain->getVertex(i)[0];
624		}
625	    }
626
627	  //we consider if we can use leftchain(index1) as left corner.
628	  //we check if (leftChain(index1) intersects right chian or not
629	  if(DBG_intersectChain(rightChain, rightChainStartIndex, rightChainEndIndex, leftGridPoint, leftChain->getVertex(index1)))
630	    {
631	      ret_leftCornerWhere = 2;
632	      ret_leftCornerIndex = index2; //should use tempI???
633	      }
634	  else if(tempMin <= leftChain->getVertex(index1)[0] ||
635	     tempMin <= uleft)
636	    {
637	      ret_leftCornerWhere = 2; /* on right chain*/
638	      ret_leftCornerIndex = tempI;
639	    }
640	  else
641	    {
642	      ret_leftCornerWhere = 0; /*on left chain*/
643	      ret_leftCornerIndex = index1;
644	    }
645	}
646    }
647
648}
649
650
651void findUpCorners(Real *topVertex,
652		   vertexArray *leftChain, Int leftChainStartIndex, Int leftChainEndIndex,
653		   vertexArray *rightChain, Int rightChainStartIndex, Int rightChainEndIndex,
654		   Real v,
655		   Real uleft,
656		   Real uright,
657		   Int& ret_leftCornerWhere, /*0: left chain, 1: topvertex, 2: rightchain*/
658		   Int& ret_leftCornerIndex, /*useful when ret_leftCornerWhere == 0 or 2*/
659		   Int& ret_rightCornerWhere, /*0: left chain, 1: topvertex, 2: rightchain*/
660		   Int& ret_rightCornerIndex /*useful when ret_leftCornerWhere == 0 or 2*/
661		   )
662{
663#ifdef MYDEBUG
664printf("***********enter findUpCorners\n");
665#endif
666
667  assert(v < topVertex[1]);
668  Real leftGridPoint[2];
669  leftGridPoint[0] = uleft;
670  leftGridPoint[1] = v;
671  Real rightGridPoint[2];
672  rightGridPoint[0] = uright;
673  rightGridPoint[1] = v;
674
675  Int i;
676  Int index1, index2;
677
678  index1 = leftChain->findIndexFirstAboveEqualGen(v, leftChainStartIndex, leftChainEndIndex);
679
680
681  index2 = rightChain->findIndexFirstAboveEqualGen(v, rightChainStartIndex, rightChainEndIndex);
682
683  if(index2>= leftChainStartIndex)  //index2 was found above
684    index2 = rightChain->skipEqualityFromStart(v, index2, rightChainEndIndex);
685
686  if(index1<leftChainStartIndex && index2 <rightChainStartIndex) /*no point above v on left chain or right chain*/
687    {
688      /*the topVertex is the only vertex above v*/
689      ret_leftCornerWhere = 1;
690      ret_rightCornerWhere = 1;
691    }
692  else if(index1<leftChainStartIndex ) /*index2 >= rightChainStartIndex*/
693    {
694      ret_rightCornerWhere = 2; /*on right chain*/
695      ret_rightCornerIndex = index2;
696
697      //find the minimum u on right top, either that, or top, or right[index2] is the left corner
698      Real tempMin = rightChain->getVertex(index2)[0];
699      Int tempI = index2;
700      for(i=index2-1; i>=rightChainStartIndex; i--)
701	if(rightChain->getVertex(i)[0] < tempMin)
702	  {
703	    tempMin = rightChain->getVertex(i)[0];
704	    tempI = i;
705	  }
706      //chech whether (leftGridPoint, top) intersects rightchai,
707      //if yes, use right corner as left corner
708      //if not, use top or right[tempI] as left corner
709      if(DBG_intersectChain(rightChain, rightChainStartIndex, rightChainEndIndex,
710			leftGridPoint, topVertex))
711	{
712	  ret_leftCornerWhere = 2; //rightChain
713	  ret_leftCornerIndex = index2;
714	}
715      else if(topVertex[0] < tempMin)
716	ret_leftCornerWhere = 1; /*topvertex*/
717      else
718	{
719	  ret_leftCornerWhere = 2; //right chain
720	  ret_leftCornerIndex = tempI;
721	}
722
723    }
724  else if(index2< rightChainStartIndex) /*index1>=leftChainStartIndex*/
725    {
726      ret_leftCornerWhere = 0; /*left chain*/
727      ret_leftCornerIndex = index1;
728
729      //find the maximum u on the left top section. either that or topvertex, or left[index1]  is the right corner
730      Real tempMax = leftChain->getVertex(index1)[0];
731      Int tempI = index1;
732
733      for(i=index1-1; i>=leftChainStartIndex; i--){
734
735	if(leftChain->getVertex(i)[0] > tempMax)
736	  {
737
738	    tempMax = leftChain->getVertex(i)[0];
739	    tempI = i;
740	  }
741      }
742      //check whether (rightGridPoint, top) intersects leftChain or not
743      //if yes, we use leftCorner as the right corner
744      //if not, we use either top or left[tempI] as the right corner
745      if(DBG_intersectChain(leftChain, leftChainStartIndex,leftChainEndIndex,
746			    rightGridPoint, topVertex))
747	 {
748	   ret_rightCornerWhere = 0; //left chan
749	   ret_rightCornerIndex = index1;
750	 }
751      else if(topVertex[0] > tempMax)
752	ret_rightCornerWhere = 1;//topVertex
753      else
754	{
755	  ret_rightCornerWhere = 0;//left chain
756	  ret_rightCornerIndex = tempI;
757	}
758    }
759  else /*index1>=leftChainStartIndex and index2 >=rightChainStartIndex*/
760    {
761      if(leftChain->getVertex(index1)[1] <= rightChain->getVertex(index2)[1]) /*left point below right point*/
762	{
763	  ret_leftCornerWhere = 0; /*on left chain*/
764	  ret_leftCornerIndex = index1;
765
766	  Real tempMax;
767	  Int tempI;
768
769	  tempI = index1;
770	  tempMax = leftChain->getVertex(index1)[0];
771
772	  /*find the maximum u for all the points on the left below the right point index2*/
773	  for(i=index1-1; i>= leftChainStartIndex; i--)
774	    {
775	      if(leftChain->getVertex(i)[1] > rightChain->getVertex(index2)[1])
776		break;
777
778	      if(leftChain->getVertex(i)[0]>tempMax)
779		{
780		  tempI = i;
781		  tempMax = leftChain->getVertex(i)[0];
782		}
783	    }
784	  //chek whether (rightChain(index2), rightGridPoint) intersects leftchian or not
785	  if(DBG_intersectChain(leftChain, leftChainStartIndex, leftChainEndIndex, rightGridPoint, rightChain->getVertex(index2)))
786	     {
787	       ret_rightCornerWhere = 0;
788	       ret_rightCornerIndex = index1;
789	     }
790	  else if(tempMax >= rightChain->getVertex(index2)[0] ||
791	     tempMax >= uright)
792	    {
793	      ret_rightCornerWhere = 0; /*on left Chain*/
794	      ret_rightCornerIndex = tempI;
795	    }
796	  else
797	    {
798	      ret_rightCornerWhere = 2; /*on right chain*/
799	      ret_rightCornerIndex = index2;
800	    }
801	}
802      else /*left above right*/
803	{
804	  ret_rightCornerWhere = 2; /*on the right*/
805	  ret_rightCornerIndex = index2;
806
807	  Real tempMin;
808	  Int tempI;
809
810	  tempI = index2;
811	  tempMin = rightChain->getVertex(index2)[0];
812
813	  /*find the minimum u for all the points on the right below the left poitn index1*/
814	  for(i=index2-1; i>= rightChainStartIndex; i--)
815	    {
816	      if( rightChain->getVertex(i)[1] > leftChain->getVertex(index1)[1])
817		break;
818	      if(rightChain->getVertex(i)[0] < tempMin)
819		{
820		  tempI = i;
821		  tempMin = rightChain->getVertex(i)[0];
822		}
823	    }
824          //check whether (leftGRidPoint,left(index1)) interesect right chain
825	  if(DBG_intersectChain(rightChain, rightChainStartIndex, rightChainEndIndex,
826				leftGridPoint, leftChain->getVertex(index1)))
827	    {
828	      ret_leftCornerWhere = 2; //right
829	      ret_leftCornerIndex = index2;
830	    }
831	  else if(tempMin <= leftChain->getVertex(index1)[0] ||
832	     tempMin <= uleft)
833	    {
834	      ret_leftCornerWhere = 2; /* on right chain*/
835	      ret_leftCornerIndex = tempI;
836	    }
837	  else
838	    {
839	      ret_leftCornerWhere = 0; /*on left chain*/
840	      ret_leftCornerIndex = index1;
841	    }
842	}
843    }
844#ifdef MYDEBUG
845printf("***********leave findUpCorners\n");
846#endif
847}
848
849//return 1 if neck exists, 0 othewise
850Int findNeckF(vertexArray *leftChain, Int botLeftIndex,
851	      vertexArray *rightChain, Int botRightIndex,
852	      gridBoundaryChain* leftGridChain,
853	      gridBoundaryChain* rightGridChain,
854	      Int gridStartIndex,
855	      Int& neckLeft,
856	      Int& neckRight)
857{
858/*
859printf("enter findNeckF, botleft, botright=%i,%i,gstartindex=%i\n",botLeftIndex,botRightIndex,gridStartIndex);
860printf("leftChain is\n");
861leftChain->print();
862printf("rightChain is\n");
863rightChain->print();
864*/
865
866  Int lowerGridIndex; //the grid below leftChain and rightChian vertices
867  Int i;
868  Int n_vlines = leftGridChain->get_nVlines();
869  Real v;
870  if(botLeftIndex >= leftChain->getNumElements() ||
871     botRightIndex >= rightChain->getNumElements())
872    return 0; //no neck exists
873
874  v=min(leftChain->getVertex(botLeftIndex)[1], rightChain->getVertex(botRightIndex)[1]);
875
876
877
878
879  for(i=gridStartIndex; i<n_vlines; i++)
880    if(leftGridChain->get_v_value(i) <= v &&
881       leftGridChain->getUlineIndex(i)<= rightGridChain->getUlineIndex(i))
882      break;
883
884  lowerGridIndex = i;
885
886  if(lowerGridIndex == n_vlines) //the two trm vertex are higher than all gridlines
887    return 0;
888  else
889    {
890      Int botLeft2, botRight2;
891/*
892printf("leftGridChain->get_v_)value=%f\n",leftGridChain->get_v_value(lowerGridIndex), botLeftIndex);
893printf("leftChain->get_vertex(0)=(%f,%f)\n", leftChain->getVertex(0)[0],leftChain->getVertex(0)[1]);
894printf("leftChain->get_vertex(1)=(%f,%f)\n", leftChain->getVertex(1)[0],leftChain->getVertex(1)[1]);
895printf("leftChain->get_vertex(2)=(%f,%f)\n", leftChain->getVertex(2)[0],leftChain->getVertex(2)[1]);
896*/
897      botLeft2 = leftChain->findIndexFirstAboveEqualGen(leftGridChain->get_v_value(lowerGridIndex), botLeftIndex, leftChain->getNumElements()-1) -1 ;
898
899/*
900printf("botLeft2=%i\n", botLeft2);
901printf("leftChain->getNumElements=%i\n", leftChain->getNumElements());
902*/
903
904      botRight2 = rightChain->findIndexFirstAboveEqualGen(leftGridChain->get_v_value(lowerGridIndex), botRightIndex, rightChain->getNumElements()-1) -1;
905      if(botRight2 < botRightIndex) botRight2=botRightIndex;
906
907      if(botLeft2 < botLeftIndex) botLeft2 = botLeftIndex;
908
909      assert(botLeft2 >= botLeftIndex);
910      assert(botRight2 >= botRightIndex);
911      //find nectLeft so that it is th erightmost vertex on letChain
912
913      Int tempI = botLeftIndex;
914      Real temp = leftChain->getVertex(tempI)[0];
915      for(i=botLeftIndex+1; i<= botLeft2; i++)
916	if(leftChain->getVertex(i)[0] > temp)
917	  {
918	    temp = leftChain->getVertex(i)[0];
919	    tempI = i;
920	  }
921      neckLeft = tempI;
922
923      tempI = botRightIndex;
924      temp = rightChain->getVertex(tempI)[0];
925      for(i=botRightIndex+1; i<= botRight2; i++)
926	if(rightChain->getVertex(i)[0] < temp)
927	  {
928	    temp = rightChain->getVertex(i)[0];
929	    tempI = i;
930	  }
931      neckRight = tempI;
932      return 1;
933    }
934}
935
936
937
938/*find i>=botLeftIndex,j>=botRightIndex so that
939 *(leftChain[i], rightChain[j]) is a neck.
940 */
941void findNeck(vertexArray *leftChain, Int botLeftIndex,
942	      vertexArray *rightChain, Int botRightIndex,
943	      Int& leftLastIndex, /*left point of the neck*/
944	      Int& rightLastIndex /*right point of the neck*/
945	      )
946{
947  assert(botLeftIndex < leftChain->getNumElements() &&
948     botRightIndex < rightChain->getNumElements());
949
950  /*now the neck exists for sure*/
951
952  if(leftChain->getVertex(botLeftIndex)[1] <= rightChain->getVertex(botRightIndex)[1]) //left below right
953    {
954
955      leftLastIndex = botLeftIndex;
956
957      /*find i so that rightChain[i][1] >= leftchainbotverte[1], and i+1<
958       */
959      rightLastIndex=rightChain->findIndexAboveGen(leftChain->getVertex(botLeftIndex)[1], botRightIndex+1, rightChain->getNumElements()-1);
960    }
961  else  //left above right
962    {
963
964      rightLastIndex = botRightIndex;
965
966      leftLastIndex = leftChain->findIndexAboveGen(rightChain->getVertex(botRightIndex)[1],
967						  botLeftIndex+1,
968						  leftChain->getNumElements()-1);
969    }
970}
971
972
973
974void findLeftGridIndices(directedLine* topEdge, Int firstGridIndex, Int lastGridIndex, gridWrap* grid,  Int* ret_indices, Int* ret_innerIndices)
975{
976
977  Int i,k,isHoriz = 0;
978  Int n_ulines = grid->get_n_ulines();
979  Real uMin = grid->get_u_min();
980  Real uMax = grid->get_u_max();
981  /*
982  Real vMin = grid->get_v_min();
983  Real vMax = grid->get_v_max();
984  */
985  Real slop = 0.0, uinterc;
986
987#ifdef SHORTEN_GRID_LINE
988  //uintercBuf stores all the interction u value for each grid line
989  //notice that lastGridIndex<= firstGridIndex
990  Real *uintercBuf = (Real *) malloc (sizeof(Real) * (firstGridIndex-lastGridIndex+1));
991  assert(uintercBuf);
992#endif
993
994  /*initialization to make vtail bigger than grid->...*/
995  directedLine* dLine = topEdge;
996  Real vtail = grid->get_v_value(firstGridIndex) + 1.0;
997  Real tempMaxU = grid->get_u_min();
998
999
1000  /*for each grid line*/
1001  for(k=0, i=firstGridIndex; i>=lastGridIndex; i--, k++)
1002    {
1003
1004      Real grid_v_value = grid->get_v_value(i);
1005
1006      /*check whether this grid line is below the current trim edge.*/
1007      if(vtail > grid_v_value)
1008	{
1009	  /*since the grid line is below the trim edge, we
1010	   *find the trim edge which will contain the trim line
1011	   */
1012	  while( (vtail=dLine->tail()[1]) > grid_v_value){
1013
1014	    tempMaxU = max(tempMaxU, dLine->tail()[0]);
1015	    dLine = dLine -> getNext();
1016	  }
1017
1018	  if( fabs(dLine->head()[1] - vtail) < ZERO)
1019	    isHoriz = 1;
1020	  else
1021	    {
1022	      isHoriz = 0;
1023	      slop = (dLine->head()[0] - dLine->tail()[0]) / (dLine->head()[1]-vtail);
1024	    }
1025	}
1026
1027      if(isHoriz)
1028	{
1029	  uinterc = max(dLine->head()[0], dLine->tail()[0]);
1030	}
1031      else
1032	{
1033	  uinterc = slop * (grid_v_value - vtail) + dLine->tail()[0];
1034	}
1035
1036      tempMaxU = max(tempMaxU, uinterc);
1037
1038      if(uinterc < uMin && uinterc >= uMin - ZERO)
1039	uinterc = uMin;
1040      if(uinterc > uMax && uinterc <= uMax + ZERO)
1041	uinterc = uMax;
1042
1043#ifdef SHORTEN_GRID_LINE
1044      uintercBuf[k] = uinterc;
1045#endif
1046
1047      assert(uinterc >= uMin && uinterc <= uMax);
1048       if(uinterc == uMax)
1049         ret_indices[k] = n_ulines-1;
1050       else
1051	 ret_indices[k] = (Int)(((uinterc-uMin)/(uMax - uMin)) * (n_ulines-1)) + 1;
1052      if(ret_indices[k] >= n_ulines)
1053	ret_indices[k] = n_ulines-1;
1054
1055
1056      ret_innerIndices[k] = (Int)(((tempMaxU-uMin)/(uMax - uMin)) * (n_ulines-1)) + 1;
1057
1058      /*reinitialize tempMaxU for next grdiLine*/
1059      tempMaxU = uinterc;
1060    }
1061#ifdef SHORTEN_GRID_LINE
1062  //for each grid line, compare the left grid point with the
1063  //intersection point. If the two points are too close, then
1064  //we should move the grid point one grid to the right
1065  //and accordingly we should update the inner index.
1066  for(k=0, i=firstGridIndex; i>=lastGridIndex; i--, k++)
1067    {
1068      //check gridLine i
1069      //check ret_indices[k]
1070      Real a = grid->get_u_value(ret_indices[k]-1);
1071      Real b = grid->get_u_value(ret_indices[k]);
1072      assert(uintercBuf[k] >= a && uintercBuf < b);
1073      if( (b-uintercBuf[k]) <= 0.2 * (b-a)) //interc is very close to b
1074	{
1075	  ret_indices[k]++;
1076	}
1077
1078      //check ret_innerIndices[k]
1079      if(k>0)
1080	{
1081	  if(ret_innerIndices[k] < ret_indices[k-1])
1082	    ret_innerIndices[k] = ret_indices[k-1];
1083	  if(ret_innerIndices[k] < ret_indices[k])
1084	    ret_innerIndices[k] = ret_indices[k];
1085	}
1086    }
1087  //clean up
1088  free(uintercBuf);
1089#endif
1090}
1091
1092void findRightGridIndices(directedLine* topEdge, Int firstGridIndex, Int lastGridIndex, gridWrap* grid,  Int* ret_indices, Int* ret_innerIndices)
1093{
1094
1095  Int i,k;
1096  Int n_ulines = grid->get_n_ulines();
1097  Real uMin = grid->get_u_min();
1098  Real uMax = grid->get_u_max();
1099  /*
1100  Real vMin = grid->get_v_min();
1101  Real vMax = grid->get_v_max();
1102  */
1103  Real slop = 0.0, uinterc;
1104
1105#ifdef SHORTEN_GRID_LINE
1106  //uintercBuf stores all the interction u value for each grid line
1107  //notice that firstGridIndex >= lastGridIndex
1108  Real *uintercBuf = (Real *) malloc (sizeof(Real) * (firstGridIndex-lastGridIndex+1));
1109  assert(uintercBuf);
1110#endif
1111
1112  /*initialization to make vhead bigger than grid->v_value...*/
1113  directedLine* dLine = topEdge->getPrev();
1114  Real vhead = dLine->tail()[1];
1115  Real tempMinU = grid->get_u_max();
1116
1117  /*for each grid line*/
1118  for(k=0, i=firstGridIndex; i>=lastGridIndex; i--, k++)
1119    {
1120
1121      Real grid_v_value = grid->get_v_value(i);
1122
1123
1124      /*check whether this grid line is below the current trim edge.*/
1125      if(vhead >= grid_v_value)
1126	{
1127	  /*since the grid line is below the tail of the trim edge, we
1128	   *find the trim edge which will contain the trim line
1129	   */
1130	  while( (vhead=dLine->head()[1]) > grid_v_value){
1131	    tempMinU = min(tempMinU, dLine->head()[0]);
1132	    dLine = dLine -> getPrev();
1133	  }
1134
1135	  /*skip the equality in the case of degenerat case: horizontal */
1136	  while(dLine->head()[1] == grid_v_value)
1137	    dLine = dLine->getPrev();
1138
1139	  assert( dLine->tail()[1] != dLine->head()[1]);
1140	  slop = (dLine->tail()[0] - dLine->head()[0]) / (dLine->tail()[1]-dLine->head()[1]);
1141	  /*
1142	   if(dLine->tail()[1] == vhead)
1143	     isHoriz = 1;
1144	     else
1145	    {
1146	      isHoriz = 0;
1147	      slop = (dLine->tail()[0] - dLine->head()[0]) / (dLine->tail()[1]-vhead);
1148	    }
1149	    */
1150	}
1151	uinterc = slop * (grid_v_value - dLine->head()[1]) + dLine->head()[0];
1152
1153      //in case unterc is outside of the grid due to floating point
1154      if(uinterc < uMin)
1155	uinterc = uMin;
1156      else if(uinterc > uMax)
1157	uinterc = uMax;
1158
1159#ifdef SHORTEN_GRID_LINE
1160      uintercBuf[k] = uinterc;
1161#endif
1162
1163      tempMinU = min(tempMinU, uinterc);
1164
1165      assert(uinterc >= uMin && uinterc <= uMax);
1166
1167      if(uinterc == uMin)
1168	ret_indices[k] = 0;
1169      else
1170	ret_indices[k] = (int)ceil((((uinterc-uMin)/(uMax - uMin)) * (n_ulines-1))) -1;
1171/*
1172if(ret_indices[k] >= grid->get_n_ulines())
1173  {
1174  printf("ERROR3\n");
1175  exit(0);
1176}
1177if(ret_indices[k] < 0)
1178  {
1179  printf("ERROR4\n");
1180  exit(0);
1181}
1182*/
1183      ret_innerIndices[k] = (int)ceil ((((tempMinU-uMin)/(uMax - uMin)) * (n_ulines-1))) -1;
1184
1185      tempMinU = uinterc;
1186    }
1187#ifdef SHORTEN_GRID_LINE
1188  //for each grid line, compare the left grid point with the
1189  //intersection point. If the two points are too close, then
1190  //we should move the grid point one grid to the right
1191  //and accordingly we should update the inner index.
1192  for(k=0, i=firstGridIndex; i>=lastGridIndex; i--, k++)
1193    {
1194      //check gridLine i
1195      //check ret_indices[k]
1196      Real a = grid->get_u_value(ret_indices[k]);
1197      Real b = grid->get_u_value(ret_indices[k]+1);
1198      assert(uintercBuf[k] > a && uintercBuf <= b);
1199      if( (uintercBuf[k]-a) <= 0.2 * (b-a)) //interc is very close to a
1200	{
1201	  ret_indices[k]--;
1202	}
1203
1204      //check ret_innerIndices[k]
1205      if(k>0)
1206	{
1207	  if(ret_innerIndices[k] > ret_indices[k-1])
1208	    ret_innerIndices[k] = ret_indices[k-1];
1209	  if(ret_innerIndices[k] > ret_indices[k])
1210	    ret_innerIndices[k] = ret_indices[k];
1211	}
1212    }
1213  //clean up
1214  free(uintercBuf);
1215#endif
1216}
1217
1218
1219void sampleMonoPoly(directedLine* polygon, gridWrap* grid, Int ulinear, Int vlinear, primStream* pStream, rectBlockArray* rbArray)
1220{
1221/*
1222{
1223grid->print();
1224polygon->writeAllPolygons("zloutputFile");
1225exit(0);
1226}
1227*/
1228
1229if(grid->get_n_ulines() == 2 ||
1230   grid->get_n_vlines() == 2)
1231{
1232  if(ulinear && grid->get_n_ulines() == 2)
1233    {
1234      monoTriangulationFun(polygon, compV2InY, pStream);
1235      return;
1236    }
1237  else if(DBG_isConvex(polygon) && polygon->numEdges() >=4)
1238     {
1239       triangulateConvexPoly(polygon, ulinear, vlinear, pStream);
1240       return;
1241     }
1242  else if(vlinear || DBG_is_U_direction(polygon))
1243    {
1244      Int n_cusps;//num interior cusps
1245      Int n_edges = polygon->numEdges();
1246      directedLine** cusps = (directedLine**) malloc(sizeof(directedLine*) * n_edges);
1247      assert(cusps);
1248      findInteriorCuspsX(polygon, n_cusps, cusps);
1249
1250      if(n_cusps == 0) //u_monotone
1251	{
1252
1253	  monoTriangulationFun(polygon, compV2InX, pStream);
1254
1255          free(cusps);
1256          return;
1257	}
1258      else if(n_cusps == 1) //one interior cusp
1259	{
1260
1261	  directedLine* new_polygon = polygonConvert(cusps[0]);
1262
1263	  directedLine* other = findDiagonal_singleCuspX( new_polygon);
1264
1265
1266
1267	  //<other> should NOT be null unless there are self-intersecting
1268          //trim curves. In that case, we don't want to core dump, instead,
1269          //we triangulate anyway, and print out error message.
1270	  if(other == NULL)
1271	    {
1272	      monoTriangulationFun(polygon, compV2InX, pStream);
1273	      free(cusps);
1274	      return;
1275	    }
1276
1277	  directedLine* ret_p1;
1278	  directedLine* ret_p2;
1279
1280	  new_polygon->connectDiagonal_2slines(new_polygon, other,
1281					   &ret_p1,
1282					   &ret_p2,
1283					   new_polygon);
1284
1285	  monoTriangulationFun(ret_p1, compV2InX, pStream);
1286	  monoTriangulationFun(ret_p2, compV2InX, pStream);
1287
1288	  ret_p1->deleteSinglePolygonWithSline();
1289	  ret_p2->deleteSinglePolygonWithSline();
1290
1291          free(cusps);
1292          return;
1293         }
1294     free(cusps);
1295     }
1296}
1297
1298  /*find the top and bottom of the polygon. It is supposed to be
1299   *a V-monotone polygon
1300   */
1301
1302  directedLine* tempV;
1303  directedLine* topV;
1304  directedLine* botV;
1305  topV = botV = polygon;
1306
1307  for(tempV = polygon->getNext(); tempV != polygon; tempV = tempV->getNext())
1308    {
1309      if(compV2InY(topV->head(), tempV->head())<0) {
1310
1311	topV = tempV;
1312      }
1313      if(compV2InY(botV->head(), tempV->head())>0) {
1314
1315	botV = tempV;
1316      }
1317    }
1318
1319  /*find the first(top) and the last (bottom) grid line which intersect the
1320   *this polygon
1321   */
1322  Int firstGridIndex; /*the index in the grid*/
1323  Int lastGridIndex;
1324  firstGridIndex = (Int) ((topV->head()[1] - grid->get_v_min()) / (grid->get_v_max() - grid->get_v_min()) * (grid->get_n_vlines()-1));
1325  lastGridIndex  = (Int) ((botV->head()[1] - grid->get_v_min()) / (grid->get_v_max() - grid->get_v_min()) * (grid->get_n_vlines()-1)) + 1;
1326
1327
1328  /*find the interval inside  the polygon for each gridline*/
1329  Int *leftGridIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1));
1330  assert(leftGridIndices);
1331  Int *rightGridIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1));
1332  assert(rightGridIndices);
1333  Int *leftGridInnerIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1));
1334  assert(leftGridInnerIndices);
1335  Int *rightGridInnerIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1));
1336  assert(rightGridInnerIndices);
1337
1338  findLeftGridIndices(topV, firstGridIndex, lastGridIndex, grid,  leftGridIndices, leftGridInnerIndices);
1339
1340  findRightGridIndices(topV, firstGridIndex, lastGridIndex, grid,  rightGridIndices, rightGridInnerIndices);
1341
1342  gridBoundaryChain leftGridChain(grid, firstGridIndex, firstGridIndex-lastGridIndex+1, leftGridIndices, leftGridInnerIndices);
1343
1344  gridBoundaryChain rightGridChain(grid, firstGridIndex, firstGridIndex-lastGridIndex+1, rightGridIndices, rightGridInnerIndices);
1345
1346
1347
1348//  leftGridChain.draw();
1349//  leftGridChain.drawInner();
1350//  rightGridChain.draw();
1351//  rightGridChain.drawInner();
1352  /*(1) determine the grid boundaries (left and right).
1353   *(2) process polygon  into two monotone chaines: use vertexArray
1354   *(3) call sampleMonoPolyRec
1355   */
1356
1357  /*copy the two chains into vertexArray datastructure*/
1358  Int i;
1359  vertexArray leftChain(20); /*this is a dynamic array*/
1360  for(i=1; i<=topV->get_npoints()-2; i++) { /*the first vertex is the top vertex which doesn't belong to inc_chain*/
1361    leftChain.appendVertex(topV->getVertex(i));
1362  }
1363  for(tempV = topV->getNext(); tempV != botV; tempV = tempV->getNext())
1364    {
1365      for(i=0; i<=tempV->get_npoints()-2; i++){
1366	leftChain.appendVertex(tempV->getVertex(i));
1367      }
1368    }
1369
1370  vertexArray rightChain(20);
1371  for(tempV = topV->getPrev(); tempV != botV; tempV = tempV->getPrev())
1372    {
1373      for(i=tempV->get_npoints()-2; i>=0; i--){
1374	rightChain.appendVertex(tempV->getVertex(i));
1375      }
1376    }
1377  for(i=botV->get_npoints()-2; i>=1; i--){
1378    rightChain.appendVertex(tempV->getVertex(i));
1379  }
1380
1381  sampleMonoPolyRec(topV->head(),
1382		    botV->head(),
1383		    &leftChain,
1384		    0,
1385		    &rightChain,
1386		    0,
1387		    &leftGridChain,
1388		    &rightGridChain,
1389		    0,
1390		    pStream,
1391		    rbArray);
1392
1393
1394  /*cleanup space*/
1395  free(leftGridIndices);
1396  free(rightGridIndices);
1397  free(leftGridInnerIndices);
1398  free(rightGridInnerIndices);
1399}
1400
1401void sampleMonoPolyRec(
1402		       Real* topVertex,
1403		       Real* botVertex,
1404		       vertexArray* leftChain,
1405		       Int leftStartIndex,
1406		       vertexArray* rightChain,
1407		       Int rightStartIndex,
1408		       gridBoundaryChain* leftGridChain,
1409		       gridBoundaryChain* rightGridChain,
1410		       Int gridStartIndex,
1411		       primStream* pStream,
1412		       rectBlockArray* rbArray)
1413{
1414
1415  /*find the first connected component, and the four corners.
1416   */
1417  Int index1, index2; /*the first and last grid line of the first connected component*/
1418
1419  if(topVertex[1] <= botVertex[1])
1420    return;
1421
1422  /*find i so that the grid line is below the top vertex*/
1423  Int i=gridStartIndex;
1424  while (i < leftGridChain->get_nVlines())
1425    {
1426      if(leftGridChain->get_v_value(i) < topVertex[1])
1427	break;
1428      i++;
1429    }
1430
1431  /*find the first connected component starting with i*/
1432  /*find index1 so that left_uline_index <= right_uline_index, that is, this
1433   *grid line contains at least one inner grid point
1434   */
1435  index1=i;
1436  int num_skipped_grid_lines=0;
1437  while(index1 < leftGridChain->get_nVlines())
1438    {
1439      if(leftGridChain->getUlineIndex(index1) <= rightGridChain->getUlineIndex(index1))
1440	break;
1441      num_skipped_grid_lines++;
1442      index1++;
1443    }
1444
1445
1446
1447  if(index1 >= leftGridChain->get_nVlines()) /*no grid line exists which has inner point*/
1448    {
1449      /*stop recursion, ...*/
1450      /*monotone triangulate it...*/
1451//      printf("no grid line exists\n");
1452/*
1453      monoTriangulationRecOpt(topVertex, botVertex, leftChain, leftStartIndex,
1454			   rightChain, rightStartIndex, pStream);
1455*/
1456
1457if(num_skipped_grid_lines <2)
1458  {
1459    monoTriangulationRecGenOpt(topVertex, botVertex, leftChain, leftStartIndex,
1460			       leftChain->getNumElements()-1,
1461			       rightChain, rightStartIndex,
1462			       rightChain->getNumElements()-1,
1463			       pStream);
1464  }
1465else
1466  {
1467    //the optimum way to triangulate is top-down since this polygon
1468    //is narrow-long.
1469    monoTriangulationRec(topVertex, botVertex, leftChain, leftStartIndex,
1470			 rightChain, rightStartIndex, pStream);
1471  }
1472
1473/*
1474      monoTriangulationRec(topVertex, botVertex, leftChain, leftStartIndex,
1475			   rightChain, rightStartIndex, pStream);
1476*/
1477
1478/*      monoTriangulationRecGenTBOpt(topVertex, botVertex,
1479				   leftChain, leftStartIndex, leftChain->getNumElements()-1,
1480				   rightChain, rightStartIndex, rightChain->getNumElements()-1,
1481				   pStream);*/
1482
1483
1484
1485    }
1486  else
1487    {
1488
1489      /*find index2 so that left_inner_index <= right_inner_index holds until index2*/
1490      index2=index1+1;
1491      if(index2 < leftGridChain->get_nVlines())
1492	while(leftGridChain->getInnerIndex(index2) <= rightGridChain->getInnerIndex(index2))
1493	  {
1494	    index2++;
1495	    if(index2 >= leftGridChain->get_nVlines())
1496	      break;
1497	  }
1498
1499      index2--;
1500
1501
1502
1503      /*the neck*/
1504      Int neckLeftIndex;
1505      Int neckRightIndex;
1506
1507      /*the four corners*/
1508      Int up_leftCornerWhere;
1509      Int up_leftCornerIndex;
1510      Int up_rightCornerWhere;
1511      Int up_rightCornerIndex;
1512      Int down_leftCornerWhere;
1513      Int down_leftCornerIndex;
1514      Int down_rightCornerWhere;
1515      Int down_rightCornerIndex;
1516
1517      Real* tempBotVertex; /*the bottom vertex for this component*/
1518      Real* nextTopVertex=NULL; /*for the recursion*/
1519      Int nextLeftStartIndex=0;
1520      Int nextRightStartIndex=0;
1521
1522      /*find the points below the grid line index2 on both chains*/
1523      Int botLeftIndex = leftChain->findIndexStrictBelowGen(
1524						      leftGridChain->get_v_value(index2),
1525						      leftStartIndex,
1526						      leftChain->getNumElements()-1);
1527      Int botRightIndex = rightChain->findIndexStrictBelowGen(
1528							rightGridChain->get_v_value(index2),
1529							rightStartIndex,
1530							rightChain->getNumElements()-1);
1531      /*if either botLeftIndex>= numelements,
1532       *        or botRightIndex >= numelemnet,
1533       *then there is no neck exists. the bottom vertex is botVertex,
1534       */
1535      if(! findNeckF(leftChain, botLeftIndex, rightChain, botRightIndex,
1536		   leftGridChain, rightGridChain, index2, neckLeftIndex, neckRightIndex))
1537	 /*
1538      if(botLeftIndex == leftChain->getNumElements() ||
1539	 botRightIndex == rightChain->getNumElements())
1540	 */
1541	{
1542#ifdef MYDEBUG
1543	  printf("neck NOT exists, botRightIndex=%i\n", botRightIndex);
1544#endif
1545
1546	  tempBotVertex =  botVertex;
1547	  nextTopVertex = botVertex;
1548	  botLeftIndex = leftChain->getNumElements()-1;
1549	  botRightIndex = rightChain->getNumElements()-1;
1550	}
1551      else /*neck exists*/
1552	{
1553#ifdef MYDEBUG
1554	  printf("neck exists\n");
1555#endif
1556
1557          /*
1558	  findNeck(leftChain, botLeftIndex,
1559		   rightChain, botRightIndex,
1560		   neckLeftIndex,
1561		   neckRightIndex);
1562		   */
1563#ifdef MYDEBUG
1564printf("neck is found, neckLeftIndex=%i, neckRightIndex=%i\n", neckLeftIndex, neckRightIndex);
1565glBegin(GL_LINES);
1566glVertex2fv(leftChain->getVertex(neckLeftIndex));
1567glVertex2fv(rightChain->getVertex(neckRightIndex));
1568glEnd();
1569#endif
1570
1571	  if(leftChain->getVertex(neckLeftIndex)[1] <= rightChain->getVertex(neckRightIndex)[1])
1572	    {
1573	      tempBotVertex = leftChain->getVertex(neckLeftIndex);
1574	      botLeftIndex = neckLeftIndex-1;
1575	      botRightIndex = neckRightIndex;
1576	      nextTopVertex = rightChain->getVertex(neckRightIndex);
1577	      nextLeftStartIndex = neckLeftIndex;
1578	      nextRightStartIndex = neckRightIndex+1;
1579	    }
1580	  else
1581	    {
1582	      tempBotVertex = rightChain->getVertex(neckRightIndex);
1583	      botLeftIndex = neckLeftIndex;
1584	      botRightIndex = neckRightIndex-1;
1585	      nextTopVertex = leftChain->getVertex(neckLeftIndex);
1586	      nextLeftStartIndex = neckLeftIndex+1;
1587	      nextRightStartIndex = neckRightIndex;
1588	    }
1589	}
1590
1591      findUpCorners(topVertex,
1592		    leftChain,
1593		    leftStartIndex, botLeftIndex,
1594		    rightChain,
1595		    rightStartIndex, botRightIndex,
1596		    leftGridChain->get_v_value(index1),
1597		    leftGridChain->get_u_value(index1),
1598		    rightGridChain->get_u_value(index1),
1599		    up_leftCornerWhere,
1600		    up_leftCornerIndex,
1601		    up_rightCornerWhere,
1602		    up_rightCornerIndex);
1603
1604      findDownCorners(tempBotVertex,
1605		      leftChain,
1606		      leftStartIndex, botLeftIndex,
1607		      rightChain,
1608		      rightStartIndex, botRightIndex,
1609		      leftGridChain->get_v_value(index2),
1610		      leftGridChain->get_u_value(index2),
1611		      rightGridChain->get_u_value(index2),
1612		      down_leftCornerWhere,
1613		      down_leftCornerIndex,
1614		      down_rightCornerWhere,
1615		      down_rightCornerIndex);
1616#ifdef MYDEBUG
1617      printf("find corners done, down_leftwhere=%i, down_righwhere=%i,\n",down_leftCornerWhere, down_rightCornerWhere );
1618      printf("find corners done, up_leftwhere=%i, up_righwhere=%i,\n",up_leftCornerWhere, up_rightCornerWhere );
1619      printf("find corners done, up_leftindex=%i, up_righindex=%i,\n",up_leftCornerIndex, up_rightCornerIndex );
1620      printf("find corners done, down_leftindex=%i, down_righindex=%i,\n",down_leftCornerIndex, down_rightCornerIndex );
1621#endif
1622
1623/*
1624      drawCorners(topVertex,
1625		  tempBotVertex,
1626		  leftChain,
1627		  rightChain,
1628		  leftGridChain,
1629		  rightGridChain,
1630		  index1,
1631		  index2,
1632		  up_leftCornerWhere,
1633		  up_leftCornerIndex,
1634		  up_rightCornerWhere,
1635		  up_rightCornerIndex,
1636		  down_leftCornerWhere,
1637		  down_leftCornerIndex,
1638		  down_rightCornerWhere,
1639		  down_rightCornerIndex);
1640*/
1641
1642
1643      sampleConnectedComp(topVertex, tempBotVertex,
1644			  leftChain,
1645			  leftStartIndex, botLeftIndex,
1646			  rightChain,
1647			  rightStartIndex, botRightIndex,
1648			  leftGridChain,
1649			  rightGridChain,
1650			  index1, index2,
1651			  up_leftCornerWhere,
1652			  up_leftCornerIndex,
1653			  up_rightCornerWhere,
1654			  up_rightCornerIndex,
1655			  down_leftCornerWhere,
1656			  down_leftCornerIndex,
1657			  down_rightCornerWhere,
1658			  down_rightCornerIndex,
1659			  pStream,
1660			  rbArray
1661			  );
1662
1663      /*recursion*/
1664
1665      sampleMonoPolyRec(
1666			nextTopVertex,
1667			botVertex,
1668			leftChain,
1669			nextLeftStartIndex,
1670			rightChain,
1671			nextRightStartIndex,
1672			leftGridChain,
1673			rightGridChain,
1674			index2+1,
1675			pStream, rbArray);
1676
1677
1678    }
1679
1680}
1681
1682void sampleLeftStrip(vertexArray* leftChain,
1683		     Int topLeftIndex,
1684		     Int botLeftIndex,
1685		     gridBoundaryChain* leftGridChain,
1686		     Int leftGridChainStartIndex,
1687		     Int leftGridChainEndIndex,
1688		     primStream* pStream
1689		     )
1690{
1691  assert(leftChain->getVertex(topLeftIndex)[1] > leftGridChain->get_v_value(leftGridChainStartIndex));
1692  assert(leftChain->getVertex(topLeftIndex+1)[1] <= leftGridChain->get_v_value(leftGridChainStartIndex));
1693  assert(leftChain->getVertex(botLeftIndex)[1] <= leftGridChain->get_v_value(leftGridChainEndIndex));
1694  assert(leftChain->getVertex(botLeftIndex-1)[1] > leftGridChain->get_v_value(leftGridChainEndIndex));
1695
1696  /*
1697   *(1)find the last grid line which doesn'; pass below
1698   * this first edge, sample this region: one trim edge and
1699   * possily multiple grid lines.
1700   */
1701  Real *upperVert, *lowerVert; /*the end points of the first trim edge*/
1702  upperVert = leftChain->getVertex(topLeftIndex);
1703  lowerVert = leftChain->getVertex(topLeftIndex+1);
1704
1705  Int index = leftGridChainStartIndex;
1706  while(leftGridChain->get_v_value(index) >= lowerVert[1]){
1707    index++;
1708    if(index > leftGridChainEndIndex)
1709      break;
1710  }
1711  index--;
1712
1713  sampleLeftSingleTrimEdgeRegion(upperVert, lowerVert,
1714				 leftGridChain,
1715				 leftGridChainStartIndex,
1716				 index,
1717				 pStream);
1718  sampleLeftStripRec(leftChain, topLeftIndex+1, botLeftIndex,
1719		     leftGridChain, index, leftGridChainEndIndex,
1720		     pStream);
1721
1722}
1723
1724void sampleLeftStripRec(vertexArray* leftChain,
1725		     Int topLeftIndex,
1726		     Int botLeftIndex,
1727		     gridBoundaryChain* leftGridChain,
1728		     Int leftGridChainStartIndex,
1729		     Int leftGridChainEndIndex,
1730			primStream* pStream
1731		     )
1732{
1733  /*now top left trim vertex is below the top grid line.
1734   */
1735  /*stop condition: if topLeftIndex >= botLeftIndex, then stop.
1736   */
1737  if(topLeftIndex >= botLeftIndex)
1738    return;
1739
1740  /*find the last trim vertex which is above the second top grid line:
1741   * index1.
1742   *and sampleLeftOneGridStep(leftchain, topLeftIndex, index1, leftGridChain,
1743   * leftGridChainStartIndex).
1744   * index1 could be equal to topLeftIndex.
1745   */
1746  Real secondGridChainV = leftGridChain->get_v_value(leftGridChainStartIndex+1);
1747  assert(leftGridChainStartIndex < leftGridChainEndIndex);
1748  Int index1 = topLeftIndex;
1749  while(leftChain->getVertex(index1)[1] > secondGridChainV)
1750    index1++;
1751  index1--;
1752
1753  sampleLeftOneGridStep(leftChain, topLeftIndex, index1, leftGridChain, leftGridChainStartIndex, pStream);
1754
1755
1756  /*
1757   * Let the next trim vertex be nextTrimVertIndex (which should be
1758   *  below the second grid line).
1759   * Find the last grid line index2 which is above nextTrimVert.
1760   * sampleLeftSingleTrimEdgeRegion(uppervert[2], lowervert[2],
1761   *                      leftGridChain, leftGridChainStartIndex+1, index2).
1762   */
1763  Real *uppervert, *lowervert;
1764  uppervert = leftChain->getVertex(index1);
1765  lowervert = leftChain->getVertex(index1+1);
1766  Int index2 = leftGridChainStartIndex+1;
1767
1768  while(leftGridChain->get_v_value(index2) >= lowervert[1])
1769    {
1770      index2++;
1771      if(index2 > leftGridChainEndIndex)
1772	break;
1773    }
1774  index2--;
1775  sampleLeftSingleTrimEdgeRegion(uppervert, lowervert, leftGridChain, leftGridChainStartIndex+1, index2,  pStream);
1776
1777   /* sampleLeftStripRec(leftChain,
1778                        nextTrimVertIndex,
1779                        botLeftIndex,
1780                        leftGridChain,
1781			index2,
1782                        leftGridChainEndIndex
1783			)
1784   *
1785   */
1786  sampleLeftStripRec(leftChain, index1+1, botLeftIndex, leftGridChain, index2, leftGridChainEndIndex, pStream);
1787
1788}
1789
1790
1791/***************begin RecF***********************/
1792/* the gridlines from leftGridChainStartIndex to
1793 * leftGridChainEndIndex are assumed to form a
1794 * connected component.
1795 * the trim vertex of topLeftIndex is assumed to
1796 * be below the first gridline, and the tim vertex
1797 * of botLeftIndex is assumed to be above the last
1798 * grid line.
1799 * If botLeftIndex < topLeftIndex, then no connected componeent exists, and this funcion returns without
1800 * outputing any triangles.
1801 * Otherwise botLeftIndex >= topLeftIndex, there is at least one triangle to output.
1802 */
1803void sampleLeftStripRecF(vertexArray* leftChain,
1804		     Int topLeftIndex,
1805		     Int botLeftIndex,
1806		     gridBoundaryChain* leftGridChain,
1807		     Int leftGridChainStartIndex,
1808		     Int leftGridChainEndIndex,
1809			primStream* pStream
1810		     )
1811{
1812  /*now top left trim vertex is below the top grid line.
1813   */
1814  /*stop condition: if topLeftIndex > botLeftIndex, then stop.
1815   */
1816  if(topLeftIndex > botLeftIndex)
1817    return;
1818
1819  /*if there is only one grid Line, return.*/
1820
1821  if(leftGridChainStartIndex>=leftGridChainEndIndex)
1822    return;
1823
1824
1825  assert(leftChain->getVertex(topLeftIndex)[1] <= leftGridChain->get_v_value(leftGridChainStartIndex) &&
1826	 leftChain->getVertex(botLeftIndex)[1] >= leftGridChain->get_v_value(leftGridChainEndIndex));
1827
1828  /*firs find the first trim vertex which is below or equal to the second top grid line:
1829   * index1.
1830   */
1831  Real secondGridChainV = leftGridChain->get_v_value(leftGridChainStartIndex+1);
1832
1833
1834  Int index1 = topLeftIndex;
1835
1836  while(leftChain->getVertex(index1)[1] > secondGridChainV){
1837    index1++;
1838    if(index1>botLeftIndex)
1839      break;
1840  }
1841
1842  /*now leftChain->getVertex(index-1)[1] > secondGridChainV and
1843   *    leftChain->getVertex(index)[1] <= secondGridChainV
1844   *If equality holds, then we should include the vertex index1, otherwise we include only index1-1, to
1845   *perform sampleOneGridStep.
1846   */
1847  if(index1>botLeftIndex)
1848    index1--;
1849  else if(leftChain->getVertex(index1)[1] < secondGridChainV)
1850    index1--;
1851
1852  /*now we have leftChain->getVertex(index1)[1] >= secondGridChainV, and
1853   *  leftChain->getVertex(index1+1)[1] <= secondGridChainV
1854   */
1855
1856
1857  sampleLeftOneGridStep(leftChain, topLeftIndex, index1, leftGridChain, leftGridChainStartIndex, pStream);
1858
1859
1860  /*if leftChain->getVertex(index1)[1] == secondGridChainV, then we can recursively do the rest.
1861   */
1862  if(leftChain->getVertex(index1)[1] == secondGridChainV)
1863    {
1864
1865      sampleLeftStripRecF(leftChain, index1, botLeftIndex,leftGridChain, leftGridChainStartIndex+1, leftGridChainEndIndex, pStream);
1866    }
1867  else if(index1 < botLeftIndex)
1868    {
1869
1870      /* Otherwise, we have leftChain->getVertex(index1)[1] > secondGridChainV,
1871       * let the next trim vertex be nextTrimVertIndex (which should be  strictly
1872       *  below the second grid line).
1873       * Find the last grid line index2 which is above nextTrimVert.
1874       * sampleLeftSingleTrimEdgeRegion(uppervert[2], lowervert[2],
1875       *                      leftGridChain, leftGridChainStartIndex+1, index2).
1876       */
1877      Real *uppervert, *lowervert;
1878      uppervert = leftChain->getVertex(index1);
1879      lowervert = leftChain->getVertex(index1+1); //okay since index1<botLeftIndex
1880      Int index2 = leftGridChainStartIndex+1;
1881
1882
1883      while(leftGridChain->get_v_value(index2) >= lowervert[1])
1884	{
1885	  index2++;
1886	  if(index2 > leftGridChainEndIndex)
1887	    break;
1888	}
1889      index2--;
1890
1891
1892      sampleLeftSingleTrimEdgeRegion(uppervert, lowervert, leftGridChain, leftGridChainStartIndex+1, index2,  pStream);
1893
1894      /*recursion*/
1895
1896      sampleLeftStripRecF(leftChain, index1+1, botLeftIndex, leftGridChain, index2, leftGridChainEndIndex, pStream);
1897    }
1898
1899}
1900
1901/***************End RecF***********************/
1902
1903/*sample the left area in between one trim edge and multiple grid lines.
1904 * all the grid lines should be in between the two end poins of the
1905 *trim edge.
1906 */
1907void sampleLeftSingleTrimEdgeRegion(Real upperVert[2], Real lowerVert[2],
1908				    gridBoundaryChain* gridChain,
1909				    Int beginIndex,
1910				    Int endIndex,
1911				    primStream* pStream)
1912{
1913  Int i,j,k;
1914
1915  vertexArray vArray(endIndex-beginIndex+1);
1916  vArray.appendVertex(gridChain->get_vertex(beginIndex));
1917
1918  for(k=1, i=beginIndex+1; i<=endIndex; i++, k++)
1919    {
1920      vArray.appendVertex(gridChain->get_vertex(i));
1921
1922      /*output the fan of the grid points of the (i)th and (i-1)th grid line.
1923       */
1924      if(gridChain->getUlineIndex(i) < gridChain->getUlineIndex(i-1))
1925	{
1926	  pStream->begin();
1927	  pStream->insert(gridChain->get_vertex(i-1));
1928	  for(j=gridChain->getUlineIndex(i); j<= gridChain->getUlineIndex(i-1); j++)
1929	    pStream->insert(gridChain->getGrid()->get_u_value(j), gridChain->get_v_value(i));
1930	  pStream->end(PRIMITIVE_STREAM_FAN);
1931	}
1932      else if(gridChain->getUlineIndex(i) > gridChain->getUlineIndex(i-1))
1933	{
1934	  pStream->begin();
1935	  pStream->insert(gridChain->get_vertex(i));
1936	  for(j=gridChain->getUlineIndex(i); j>= gridChain->getUlineIndex(i-1); j--)
1937	    pStream->insert(gridChain->getGrid()->get_u_value(j), gridChain->get_v_value(i-1));
1938	  pStream->end(PRIMITIVE_STREAM_FAN);
1939	}
1940      /*otherwisem, the two are equal, so there is no fan to outout*/
1941    }
1942
1943  monoTriangulation2(upperVert, lowerVert, &vArray, 0, endIndex-beginIndex,
1944		     0, /*decreasing chain*/
1945		     pStream);
1946}
1947
1948/*return i, such that from begin to i-1 the chain is strictly u-monotone.
1949 */
1950Int findIncreaseChainFromBegin(vertexArray* chain, Int begin ,Int end)
1951{
1952  Int i=begin;
1953  Real prevU = chain->getVertex(i)[0];
1954  Real thisU;
1955  for(i=begin+1; i<=end; i++){
1956    thisU = chain->getVertex(i)[0];
1957
1958    if(prevU < thisU){
1959      prevU = thisU;
1960    }
1961    else
1962      break;
1963  }
1964  return i;
1965}
1966
1967/*check whether there is a vertex whose v value is strictly
1968 *inbetween vup vbelow
1969 *if no middle exists return -1, else return the idnex.
1970 */
1971Int checkMiddle(vertexArray* chain, Int begin, Int end,
1972		Real vup, Real vbelow)
1973{
1974  Int i;
1975  for(i=begin; i<=end; i++)
1976    {
1977      if(chain->getVertex(i)[1] < vup && chain->getVertex(i)[1]>vbelow)
1978	return i;
1979    }
1980  return -1;
1981}
1982
1983/*the degenerat case of sampleLeftOneGridStep*/
1984void sampleLeftOneGridStepNoMiddle(vertexArray* leftChain,
1985				   Int beginLeftIndex,
1986				   Int endLeftIndex,
1987				   gridBoundaryChain* leftGridChain,
1988				   Int leftGridChainStartIndex,
1989				   primStream* pStream)
1990{
1991  /*since there is no middle, there is at most one point which is on the
1992   *second grid line, there could be multiple points on the first (top)
1993   *grid line.
1994   */
1995
1996  leftGridChain->leftEndFan(leftGridChainStartIndex+1, pStream);
1997
1998  monoTriangulation2(leftGridChain->get_vertex(leftGridChainStartIndex),
1999		     leftGridChain->get_vertex(leftGridChainStartIndex+1),
2000		     leftChain,
2001		     beginLeftIndex,
2002		     endLeftIndex,
2003		     1, //is increase chain.
2004		     pStream);
2005}
2006
2007
2008
2009/*sampling the left area in between two grid lines.
2010 */
2011void sampleLeftOneGridStep(vertexArray* leftChain,
2012		  Int beginLeftIndex,
2013		  Int endLeftIndex,
2014		  gridBoundaryChain* leftGridChain,
2015		  Int leftGridChainStartIndex,
2016		  primStream* pStream
2017		  )
2018{
2019  if(checkMiddle(leftChain, beginLeftIndex, endLeftIndex,
2020		 leftGridChain->get_v_value(leftGridChainStartIndex),
2021		 leftGridChain->get_v_value(leftGridChainStartIndex+1))<0)
2022
2023    {
2024
2025      sampleLeftOneGridStepNoMiddle(leftChain, beginLeftIndex, endLeftIndex, leftGridChain, leftGridChainStartIndex, pStream);
2026      return;
2027    }
2028
2029  //copy into a polygon
2030  {
2031    directedLine* poly = NULL;
2032    sampledLine* sline;
2033    directedLine* dline;
2034    gridWrap* grid = leftGridChain->getGrid();
2035    Real vert1[2];
2036    Real vert2[2];
2037    Int i;
2038
2039    Int innerInd = leftGridChain->getInnerIndex(leftGridChainStartIndex+1);
2040    Int upperInd = leftGridChain->getUlineIndex(leftGridChainStartIndex);
2041    Int lowerInd = leftGridChain->getUlineIndex(leftGridChainStartIndex+1);
2042    Real upperV = leftGridChain->get_v_value(leftGridChainStartIndex);
2043    Real lowerV = leftGridChain->get_v_value(leftGridChainStartIndex+1);
2044
2045    //the upper gridline
2046    vert1[1] = vert2[1] = upperV;
2047    for(i=innerInd;	i>upperInd;	i--)
2048      {
2049	vert1[0]=grid->get_u_value(i);
2050	vert2[0]=grid->get_u_value(i-1);
2051	sline = new sampledLine(vert1, vert2);
2052	dline = new directedLine(INCREASING, sline);
2053	if(poly == NULL)
2054	  poly = dline;
2055	else
2056	  poly->insert(dline);
2057      }
2058
2059    //the edge connecting upper grid with left chain
2060    vert1[0] = grid->get_u_value(upperInd);
2061    vert1[1] = upperV;
2062    sline = new sampledLine(vert1, leftChain->getVertex(beginLeftIndex));
2063    dline = new directedLine(INCREASING, sline);
2064    if(poly == NULL)
2065      poly = dline;
2066    else
2067      poly->insert(dline);
2068
2069    //the left chain
2070    for(i=beginLeftIndex; i<endLeftIndex; i++)
2071      {
2072	sline = new sampledLine(leftChain->getVertex(i), leftChain->getVertex(i+1));
2073	dline = new directedLine(INCREASING, sline);
2074	poly->insert(dline);
2075      }
2076
2077    //the edge connecting left chain with lower gridline
2078    vert2[0] = grid->get_u_value(lowerInd);
2079    vert2[1] = lowerV;
2080    sline = new sampledLine(leftChain->getVertex(endLeftIndex), vert2);
2081    dline = new directedLine(INCREASING, sline);
2082    poly->insert(dline);
2083
2084    //the lower grid line
2085    vert1[1] = vert2[1] = lowerV;
2086    for(i=lowerInd; i<innerInd; i++)
2087      {
2088	vert1[0] = grid->get_u_value(i);
2089	vert2[0] = grid->get_u_value(i+1);
2090	sline = new sampledLine(vert1, vert2);
2091	dline = new directedLine(INCREASING, sline);
2092	poly->insert(dline);
2093      }
2094
2095    //the vertical grid line segement
2096    vert1[0]=vert2[0] = grid->get_u_value(innerInd);
2097    vert2[1]=upperV;
2098    vert1[1]=lowerV;
2099    sline=new sampledLine(vert1, vert2);
2100    dline=new directedLine(INCREASING, sline);
2101    poly->insert(dline);
2102    monoTriangulationOpt(poly, pStream);
2103    //cleanup
2104    poly->deleteSinglePolygonWithSline();
2105    return;
2106  }
2107
2108
2109
2110
2111
2112  Int i;
2113  if(1/*leftGridChain->getUlineIndex(leftGridChainStartIndex) >=
2114     leftGridChain->getUlineIndex(leftGridChainStartIndex+1)*/
2115     ) /*the second grid line is beyond the first one to the left*/
2116    {
2117      /*find the maximal U-monotone chain
2118       * of endLeftIndex, endLeftIndex-1, ...,
2119       */
2120      i=endLeftIndex;
2121      Real prevU = leftChain->getVertex(i)[0];
2122      for(i=endLeftIndex-1; i>=beginLeftIndex; i--){
2123	Real thisU = leftChain->getVertex(i)[0];
2124	if( prevU < thisU){
2125	  prevU = thisU;
2126	}
2127	else
2128	  break;
2129      }
2130      /*from endLeftIndex to i+1 is strictly U- monotone */
2131      /*if i+1==endLeftIndex and the vertex and leftchain is on the second gridline, then
2132       *we should use 2 vertices on the leftchain. If we only use one (endLeftIndex), then we
2133       *we would output degenerate triangles
2134       */
2135      if(i+1 == endLeftIndex && leftChain->getVertex(endLeftIndex)[1] == leftGridChain->get_v_value(1+leftGridChainStartIndex))
2136	i--;
2137
2138      Int j = beginLeftIndex/*endLeftIndex*/+1;
2139
2140
2141      if(leftGridChain->getInnerIndex(leftGridChainStartIndex+1) > leftGridChain->getUlineIndex(leftGridChainStartIndex))
2142	{
2143	  j = findIncreaseChainFromBegin(leftChain, beginLeftIndex, i+1/*endLeftIndex*/);
2144
2145	  Int temp = beginLeftIndex;
2146	  /*now from begin to j-1 is strictly u-monotone*/
2147	  /*if j-1 is on the first grid line, then we want to skip to the vertex which is strictly
2148	   *below the grid line. This vertexmust exist since there is a 'corner turn' inbetween the two grid lines
2149	   */
2150	  if(j-1 == beginLeftIndex)
2151	    {
2152	      while(leftChain->getVertex(j-1)[1] == leftGridChain->get_v_value(leftGridChainStartIndex))
2153		j++;
2154
2155	      Real vert[2];
2156	      vert[0] = leftGridChain->get_u_value(leftGridChainStartIndex);
2157	      vert[1] = leftGridChain->get_v_value(leftGridChainStartIndex);
2158
2159	      monoTriangulation2(
2160				 vert/*leftChain->getVertex(beginLeftIndex)*/,
2161				 leftChain->getVertex(j-1),
2162				 leftChain,
2163				 beginLeftIndex,
2164				 j-2,
2165				 1,
2166				 pStream //increase chain
2167				 );
2168
2169	      temp = j-1;
2170	    }
2171
2172	  stripOfFanLeft(leftChain, j-1, temp/*beginLeftIndex*/, leftGridChain->getGrid(),
2173			 leftGridChain->getVlineIndex(leftGridChainStartIndex),
2174			 leftGridChain->getUlineIndex(leftGridChainStartIndex),
2175			 leftGridChain->getInnerIndex(leftGridChainStartIndex+1),
2176			 pStream,
2177			 1 /*the grid line is above the trim line*/
2178			 );
2179	}
2180
2181      stripOfFanLeft(leftChain, endLeftIndex, i+1, leftGridChain->getGrid(),
2182		     leftGridChain->getVlineIndex(leftGridChainStartIndex+1),
2183		     leftGridChain->getUlineIndex(leftGridChainStartIndex+1),
2184		     leftGridChain->getInnerIndex(leftGridChainStartIndex+1),
2185		     pStream,
2186		     0 /*the grid line is below the trim lines*/
2187		     );
2188
2189      /*monotone triangulate the remaining left chain togther with the
2190       *two vertices on the two grid v-lines.
2191       */
2192      Real vert[2][2];
2193      vert[0][0]=vert[1][0] = leftGridChain->getInner_u_value(leftGridChainStartIndex+1);
2194      vert[0][1] = leftGridChain->get_v_value(leftGridChainStartIndex);
2195      vert[1][1] = leftGridChain->get_v_value(leftGridChainStartIndex+1);
2196
2197//      vertexArray right(vert, 2);
2198
2199      monoTriangulation2(
2200			 &vert[0][0], /*top vertex */
2201			 &vert[1][0], /*bottom vertex*/
2202			 leftChain,
2203			 /*beginLeftIndex*/j-1,
2204			 i+1,
2205			 1, /*an increasing chain*/
2206			 pStream);
2207    }
2208  else /*the second one is shorter than the first one to the left*/
2209    {
2210      /*find the maximal U-monotone chain of beginLeftIndex, beginLeftIndex+1,...,
2211       */
2212      i=beginLeftIndex;
2213      Real prevU = leftChain->getVertex(i)[0];
2214      for(i=beginLeftIndex+1; i<=endLeftIndex; i++){
2215	Real thisU = leftChain->getVertex(i)[0];
2216
2217	if(prevU < thisU){
2218	  prevU = thisU;
2219	}
2220	else
2221	  break;
2222      }
2223      /*from beginLeftIndex to i-1 is strictly U-monotone*/
2224
2225
2226      stripOfFanLeft(leftChain, i-1, beginLeftIndex, leftGridChain->getGrid(),
2227			 leftGridChain->getVlineIndex(leftGridChainStartIndex),
2228			 leftGridChain->getUlineIndex(leftGridChainStartIndex),
2229			 leftGridChain->getUlineIndex(leftGridChainStartIndex+1),
2230			 pStream,
2231		         1 /*the grid line is above the trim lines*/
2232			 );
2233      /*monotone triangulate the remaining left chain together with the
2234       *two vertices on the two grid v-lines.
2235       */
2236      Real vert[2][2];
2237      vert[0][0]=vert[1][0] = leftGridChain->get_u_value(leftGridChainStartIndex+1);
2238      vert[0][1] = leftGridChain->get_v_value(leftGridChainStartIndex);
2239      vert[1][1] = leftGridChain->get_v_value(leftGridChainStartIndex+1);
2240
2241      vertexArray right(vert, 2);
2242
2243      monoTriangulation2(
2244			 &vert[0][0], //top vertex
2245			 &vert[1][0], //bottom vertex
2246			 leftChain,
2247			 i-1,
2248			 endLeftIndex,
2249			 1, /*an increase chain*/
2250			 pStream);
2251
2252    }
2253}
2254
2255/*n_upper>=1
2256 *n_lower>=1
2257 */
2258void triangulateXYMono(Int n_upper, Real upperVerts[][2],
2259		       Int n_lower, Real lowerVerts[][2],
2260		       primStream* pStream)
2261{
2262  Int i,j,k,l;
2263  Real* leftMostV;
2264
2265  assert(n_upper>=1 && n_lower>=1);
2266  if(upperVerts[0][0] <= lowerVerts[0][0])
2267    {
2268      i=1;
2269      j=0;
2270      leftMostV = upperVerts[0];
2271    }
2272  else
2273    {
2274      i=0;
2275      j=1;
2276      leftMostV = lowerVerts[0];
2277    }
2278
2279  while(1)
2280    {
2281      if(i >= n_upper) /*case1: no more in upper*/
2282	{
2283
2284	  if(j<n_lower-1) /*at least two vertices in lower*/
2285	    {
2286	      pStream->begin();
2287	      pStream->insert(leftMostV);
2288	      while(j<n_lower){
2289		pStream->insert(lowerVerts[j]);
2290		j++;
2291	      }
2292	      pStream->end(PRIMITIVE_STREAM_FAN);
2293	    }
2294
2295	  break;
2296	}
2297      else if(j>= n_lower) /*case2: no more in lower*/
2298	{
2299
2300	  if(i<n_upper-1) /*at least two vertices in upper*/
2301	    {
2302	      pStream->begin();
2303	      pStream->insert(leftMostV);
2304
2305	      for(k=n_upper-1; k>=i; k--)
2306		pStream->insert(upperVerts[k]);
2307
2308	      pStream->end(PRIMITIVE_STREAM_FAN);
2309	    }
2310
2311	  break;
2312	}
2313      else /* case3: neither is empty, plus the leftMostV, there is at least one triangle to output*/
2314	{
2315
2316	  if(upperVerts[i][0] <= lowerVerts[j][0])
2317	    {
2318	      pStream->begin();
2319	      pStream->insert(lowerVerts[j]); /*the origin of this fan*/
2320
2321	      /*find the last k>=i such that
2322	       *upperverts[k][0] <= lowerverts[j][0]
2323	       */
2324	      k=i;
2325	      while(k<n_upper)
2326		{
2327		  if(upperVerts[k][0] > lowerVerts[j][0])
2328		    break;
2329		  k++;
2330		}
2331	      k--;
2332	      for(l=k; l>=i; l--)/*the reverse is for two-face lighting*/
2333		{
2334		  pStream->insert(upperVerts[l]);
2335		}
2336	      pStream->insert(leftMostV);
2337
2338	      pStream->end(PRIMITIVE_STREAM_FAN);
2339	      //update i for next loop
2340	      i = k+1;
2341	      leftMostV = upperVerts[k];
2342
2343	    }
2344	  else /*upperVerts[i][0] > lowerVerts[j][0]*/
2345	    {
2346	      pStream->begin();
2347	      pStream->insert(upperVerts[i]);/*the origion of this fan*/
2348	      pStream->insert(leftMostV);
2349	      /*find the last k>=j such that
2350	       *lowerverts[k][0] < upperverts[i][0]*/
2351	      k=j;
2352	      while(k< n_lower)
2353		{
2354		  if(lowerVerts[k][0] >= upperVerts[i][0])
2355		    break;
2356		  pStream->insert(lowerVerts[k]);
2357		  k++;
2358		}
2359	      pStream->end(PRIMITIVE_STREAM_FAN);
2360	      j=k;
2361	      leftMostV = lowerVerts[j-1];
2362	    }
2363	}
2364    }
2365}
2366
2367
2368void stripOfFanLeft(vertexArray* leftChain,
2369		    Int largeIndex,
2370		    Int smallIndex,
2371		    gridWrap* grid,
2372		    Int vlineIndex,
2373		    Int ulineSmallIndex,
2374		    Int ulineLargeIndex,
2375		    primStream* pStream,
2376		    Int gridLineUp /*1 if the grid line is above the trim lines*/
2377		     )
2378{
2379  assert(largeIndex >= smallIndex);
2380
2381  Real grid_v_value;
2382  grid_v_value = grid->get_v_value(vlineIndex);
2383
2384  Real2* trimVerts=(Real2*) malloc(sizeof(Real2)* (largeIndex-smallIndex+1));
2385  assert(trimVerts);
2386
2387
2388  Real2* gridVerts=(Real2*) malloc(sizeof(Real2)* (ulineLargeIndex-ulineSmallIndex+1));
2389  assert(gridVerts);
2390
2391  Int k,i;
2392  if(gridLineUp) /*trim line is below grid line, so trim vertices are going right when index increases*/
2393    for(k=0, i=smallIndex; i<=largeIndex; i++, k++)
2394      {
2395      trimVerts[k][0] = leftChain->getVertex(i)[0];
2396      trimVerts[k][1] = leftChain->getVertex(i)[1];
2397    }
2398  else
2399    for(k=0, i=largeIndex; i>=smallIndex; i--, k++)
2400      {
2401	trimVerts[k][0] = leftChain->getVertex(i)[0];
2402	trimVerts[k][1] = leftChain->getVertex(i)[1];
2403      }
2404
2405  for(k=0, i=ulineSmallIndex; i<= ulineLargeIndex; i++, k++)
2406    {
2407      gridVerts[k][0] = grid->get_u_value(i);
2408      gridVerts[k][1] = grid_v_value;
2409    }
2410
2411  if(gridLineUp)
2412    triangulateXYMono(
2413		      ulineLargeIndex-ulineSmallIndex+1, gridVerts,
2414		      largeIndex-smallIndex+1, trimVerts,
2415		      pStream);
2416  else
2417    triangulateXYMono(largeIndex-smallIndex+1, trimVerts,
2418		      ulineLargeIndex-ulineSmallIndex+1, gridVerts,
2419		      pStream);
2420  free(trimVerts);
2421  free(gridVerts);
2422}
2423
2424
2425
2426
2427
2428