1f220fa62Smrg/*
2f220fa62Smrg** License Applicability. Except to the extent portions of this file are
3f220fa62Smrg** made subject to an alternative license as permitted in the SGI Free
4f220fa62Smrg** Software License B, Version 1.1 (the "License"), the contents of this
5f220fa62Smrg** file are subject only to the provisions of the License. You may not use
6f220fa62Smrg** this file except in compliance with the License. You may obtain a copy
7f220fa62Smrg** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
8f220fa62Smrg** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
9f220fa62Smrg**
10f220fa62Smrg** http://oss.sgi.com/projects/FreeB
11f220fa62Smrg**
12f220fa62Smrg** Note that, as provided in the License, the Software is distributed on an
13f220fa62Smrg** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
14f220fa62Smrg** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
15f220fa62Smrg** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
16f220fa62Smrg** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
17f220fa62Smrg**
18f220fa62Smrg** Original Code. The Original Code is: OpenGL Sample Implementation,
19f220fa62Smrg** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
20f220fa62Smrg** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
21f220fa62Smrg** Copyright in any portions created by third parties is as indicated
22f220fa62Smrg** elsewhere herein. All Rights Reserved.
23f220fa62Smrg**
24f220fa62Smrg** Additional Notice Provisions: The application programming interfaces
25f220fa62Smrg** established by SGI in conjunction with the Original Code are The
26f220fa62Smrg** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
27f220fa62Smrg** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
28f220fa62Smrg** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
29f220fa62Smrg** Window System(R) (Version 1.3), released October 19, 1998. This software
30f220fa62Smrg** was created using the OpenGL(R) version 1.2.1 Sample Implementation
31f220fa62Smrg** published by SGI, but has not been independently verified as being
32f220fa62Smrg** compliant with the OpenGL(R) version 1.2.1 Specification.
33f220fa62Smrg**
34f220fa62Smrg*/
35f220fa62Smrg/*
36f220fa62Smrg*/
37f220fa62Smrg
38f220fa62Smrg#include <stdlib.h>
39f220fa62Smrg#include <stdio.h>
40f220fa62Smrg#include <math.h>
41f220fa62Smrg#include "zlassert.h"
42f220fa62Smrg#include "sampleCompTop.h"
43f220fa62Smrg#include "sampleCompRight.h"
44f220fa62Smrg
45f220fa62Smrg#define max(a,b) ((a>b)? a:b)
46f220fa62Smrg
47f220fa62Smrg//return : index_small, and index_large,
48f220fa62Smrg//from [small, large] is strictly U-monotne,
49f220fa62Smrg//from [large+1, end] is <u
50f220fa62Smrg//and vertex[large][0] is >= u
51f220fa62Smrg//if eveybody is <u, the large = start-1.
52f220fa62Smrg//otherwise both large and small are meaningful and we have start<=small<=large<=end
53f220fa62Smrgvoid findTopLeftSegment(vertexArray* leftChain,
54f220fa62Smrg                        Int leftStart,
55f220fa62Smrg                        Int leftEnd,
56f220fa62Smrg                        Real u,
57f220fa62Smrg                        Int& ret_index_small,
58f220fa62Smrg                        Int& ret_index_large
59f220fa62Smrg                        )
60f220fa62Smrg{
61f220fa62Smrg  Int i;
62f220fa62Smrg  assert(leftStart <= leftEnd);
63f220fa62Smrg  for(i=leftEnd; i>= leftStart; i--)
64f220fa62Smrg    {
65f220fa62Smrg      if(leftChain->getVertex(i)[0] >= u)
66f220fa62Smrg        break;
67f220fa62Smrg    }
68f220fa62Smrg  ret_index_large = i;
69f220fa62Smrg  if(ret_index_large >= leftStart)
70f220fa62Smrg    {
71f220fa62Smrg      for(i=ret_index_large; i>leftStart; i--)
72f220fa62Smrg        {
73f220fa62Smrg          if(leftChain->getVertex(i-1)[0] <= leftChain->getVertex(i)[0])
74f220fa62Smrg            break;
75f220fa62Smrg        }
76f220fa62Smrg      ret_index_small = i;
77f220fa62Smrg    }
78f220fa62Smrg}
79f220fa62Smrg
80f220fa62Smrgvoid findTopRightSegment(vertexArray* rightChain,
81f220fa62Smrg                         Int rightStart,
82f220fa62Smrg                         Int rightEnd,
83f220fa62Smrg                         Real u,
84f220fa62Smrg                         Int& ret_index_small,
85f220fa62Smrg                         Int& ret_index_large)
86f220fa62Smrg{
87f220fa62Smrg  Int i;
88f220fa62Smrg  assert(rightStart<=rightEnd);
89f220fa62Smrg  for(i=rightEnd; i>=rightStart; i--)
90f220fa62Smrg    {
91f220fa62Smrg      if(rightChain->getVertex(i)[0] <= u)
92f220fa62Smrg        break;
93f220fa62Smrg    }
94f220fa62Smrg  ret_index_large = i;
95f220fa62Smrg  if(ret_index_large >= rightStart)
96f220fa62Smrg    {
97f220fa62Smrg      for(i=ret_index_large; i>rightStart;i--)
98f220fa62Smrg        {
99f220fa62Smrg          if(rightChain->getVertex(i-1)[0] >= rightChain->getVertex(i)[0])
100f220fa62Smrg	    break;
101f220fa62Smrg        }
102f220fa62Smrg      ret_index_small = i;
103f220fa62Smrg    }
104f220fa62Smrg}
105f220fa62Smrg
106f220fa62Smrg
107f220fa62Smrgvoid sampleTopRightWithGridLinePost(Real* topVertex,
108f220fa62Smrg				   vertexArray* rightChain,
109f220fa62Smrg				   Int rightStart,
110f220fa62Smrg				   Int segIndexSmall,
111f220fa62Smrg				   Int segIndexLarge,
112f220fa62Smrg				   Int rightEnd,
113f220fa62Smrg				   gridWrap* grid,
114f220fa62Smrg				   Int gridV,
115f220fa62Smrg				   Int leftU,
116f220fa62Smrg				   Int rightU,
117f220fa62Smrg				   primStream* pStream)
118f220fa62Smrg{
119f220fa62Smrg  //the possible section which is to the right of rightU
120f220fa62Smrg  if(segIndexLarge < rightEnd)
121f220fa62Smrg    {
122f220fa62Smrg      Real *tempTop;
123f220fa62Smrg      if(segIndexLarge >= rightStart)
124f220fa62Smrg        tempTop = rightChain->getVertex(segIndexLarge);
125f220fa62Smrg      else
126f220fa62Smrg        tempTop = topVertex;
127f220fa62Smrg      Real tempBot[2];
128f220fa62Smrg      tempBot[0] = grid->get_u_value(rightU);
129f220fa62Smrg      tempBot[1] = grid->get_v_value(gridV);
130f220fa62SmrgmonoTriangulationRecGenOpt(tempTop, tempBot,
131f220fa62Smrg			   NULL, 1,0,
132f220fa62Smrg			   rightChain, segIndexLarge+1, rightEnd,
133f220fa62Smrg			   pStream);
134f220fa62Smrg/*
135f220fa62Smrg      monoTriangulation2(tempTop, tempBot,
136f220fa62Smrg                         rightChain,
137f220fa62Smrg                         segIndexLarge+1,
138f220fa62Smrg                         rightEnd,
139f220fa62Smrg                         0, //a decrease  chian
140f220fa62Smrg                         pStream);
141f220fa62Smrg*/
142f220fa62Smrg
143f220fa62Smrg    }
144f220fa62Smrg
145f220fa62Smrg  //the possible section which is strictly Umonotone
146f220fa62Smrg  if(segIndexLarge >= rightStart)
147f220fa62Smrg    {
148f220fa62Smrg      stripOfFanRight(rightChain, segIndexLarge, segIndexSmall, grid, gridV, leftU, rightU, pStream, 0);
149f220fa62Smrg      Real tempBot[2];
150f220fa62Smrg      tempBot[0] = grid->get_u_value(leftU);
151f220fa62Smrg      tempBot[1] = grid->get_v_value(gridV);
152f220fa62Smrg      monoTriangulation2(topVertex, tempBot, rightChain, rightStart, segIndexSmall, 0, pStream);
153f220fa62Smrg    }
154f220fa62Smrg  else //the topVertex forms a fan with the grid points
155f220fa62Smrg    grid->outputFanWithPoint(gridV, leftU, rightU, topVertex, pStream);
156f220fa62Smrg}
157f220fa62Smrg
158f220fa62Smrgvoid sampleTopRightWithGridLine(Real* topVertex,
159f220fa62Smrg                                vertexArray* rightChain,
160f220fa62Smrg                                Int rightStart,
161f220fa62Smrg                                Int rightEnd,
162f220fa62Smrg                                gridWrap* grid,
163f220fa62Smrg                                Int gridV,
164f220fa62Smrg                                Int leftU,
165f220fa62Smrg                                Int rightU,
166f220fa62Smrg                                primStream* pStream
167f220fa62Smrg                                )
168f220fa62Smrg{
169f220fa62Smrg  //if right chian is empty, then there is only one topVertex with one grid line
170f220fa62Smrg  if(rightEnd < rightStart){
171f220fa62Smrg    grid->outputFanWithPoint(gridV, leftU, rightU, topVertex, pStream);
172f220fa62Smrg    return;
173f220fa62Smrg  }
174f220fa62Smrg
175f220fa62Smrg  Int segIndexSmall = 0, segIndexLarge;
176f220fa62Smrg  findTopRightSegment(rightChain,
177f220fa62Smrg                      rightStart,
178f220fa62Smrg                      rightEnd,
179f220fa62Smrg                      grid->get_u_value(rightU),
180f220fa62Smrg                      segIndexSmall,
181f220fa62Smrg                      segIndexLarge
182f220fa62Smrg                      );
183f220fa62Smrg  sampleTopRightWithGridLinePost(topVertex, rightChain,
184f220fa62Smrg				 rightStart,
185f220fa62Smrg				 segIndexSmall,
186f220fa62Smrg				 segIndexLarge,
187f220fa62Smrg				 rightEnd,
188f220fa62Smrg				 grid,
189f220fa62Smrg				 gridV,
190f220fa62Smrg				 leftU,
191f220fa62Smrg				 rightU,
192f220fa62Smrg				 pStream);
193f220fa62Smrg}
194f220fa62Smrg
195f220fa62Smrg
196f220fa62Smrgvoid sampleTopLeftWithGridLinePost(Real* topVertex,
197f220fa62Smrg				   vertexArray* leftChain,
198f220fa62Smrg				   Int leftStart,
199f220fa62Smrg				   Int segIndexSmall,
200f220fa62Smrg				   Int segIndexLarge,
201f220fa62Smrg				   Int leftEnd,
202f220fa62Smrg				   gridWrap* grid,
203f220fa62Smrg				   Int gridV,
204f220fa62Smrg				   Int leftU,
205f220fa62Smrg				   Int rightU,
206f220fa62Smrg				   primStream* pStream)
207f220fa62Smrg{
208f220fa62Smrg  //the possible section which is to the left of leftU
209f220fa62Smrg
210f220fa62Smrg  if(segIndexLarge < leftEnd)
211f220fa62Smrg    {
212f220fa62Smrg      Real *tempTop;
213f220fa62Smrg      if(segIndexLarge >= leftStart)
214f220fa62Smrg        tempTop = leftChain->getVertex(segIndexLarge);
215f220fa62Smrg      else
216f220fa62Smrg        tempTop = topVertex;
217f220fa62Smrg      Real tempBot[2];
218f220fa62Smrg      tempBot[0] = grid->get_u_value(leftU);
219f220fa62Smrg      tempBot[1] = grid->get_v_value(gridV);
220f220fa62Smrg
221f220fa62Smrg      monoTriangulation2(tempTop, tempBot,
222f220fa62Smrg                         leftChain,
223f220fa62Smrg                         segIndexLarge+1,
224f220fa62Smrg                         leftEnd,
225f220fa62Smrg                         1, //a increase  chian
226f220fa62Smrg                         pStream);
227f220fa62Smrg    }
228f220fa62Smrg
229f220fa62Smrg  //the possible section which is strictly Umonotone
230f220fa62Smrg  if(segIndexLarge >= leftStart)
231f220fa62Smrg    {
232f220fa62Smrg      //if there are grid points which are to the right of topV,
233f220fa62Smrg      //then we should use topVertex to form a fan with these points to
234f220fa62Smrg      //optimize the triangualtion
235f220fa62Smrg      int do_optimize=1;
236f220fa62Smrg      if(topVertex[0] >= grid->get_u_value(rightU))
237f220fa62Smrg	do_optimize = 0;
238f220fa62Smrg      else
239f220fa62Smrg	{
240f220fa62Smrg	  //we also have to make sure that topVertex are the right most vertex
241f220fa62Smrg          //on the chain.
242f220fa62Smrg	  int i;
243f220fa62Smrg	  for(i=leftStart; i<=segIndexSmall; i++)
244f220fa62Smrg	    if(leftChain->getVertex(i)[0] >= topVertex[0])
245f220fa62Smrg	      {
246f220fa62Smrg		do_optimize = 0;
247f220fa62Smrg		break;
248f220fa62Smrg	      }
249f220fa62Smrg	}
250f220fa62Smrg
251f220fa62Smrg      if(do_optimize)
252f220fa62Smrg	{
253f220fa62Smrg	  //find midU so that grid->get_u_value(midU) >= topVertex[0]
254f220fa62Smrg	  //and               grid->get_u_value(midU-1) < topVertex[0]
255f220fa62Smrg	  int midU=rightU;
256f220fa62Smrg	  while(grid->get_u_value(midU) >= topVertex[0])
257f220fa62Smrg	    {
258f220fa62Smrg	      midU--;
259f220fa62Smrg	      if(midU < leftU)
260f220fa62Smrg		break;
261f220fa62Smrg	    }
262f220fa62Smrg	  midU++;
263f220fa62Smrg
264f220fa62Smrg	  grid->outputFanWithPoint(gridV, midU, rightU, topVertex, pStream);
265f220fa62Smrg	  stripOfFanLeft(leftChain, segIndexLarge, segIndexSmall, grid, gridV, leftU, midU, pStream, 0);
266f220fa62Smrg	  Real tempBot[2];
267f220fa62Smrg	  tempBot[0] = grid->get_u_value(midU);
268f220fa62Smrg	  tempBot[1] = grid->get_v_value(gridV);
269f220fa62Smrg	  monoTriangulation2(topVertex, tempBot, leftChain, leftStart, segIndexSmall, 1, pStream);
270f220fa62Smrg	}
271f220fa62Smrg      else //not optimize
272f220fa62Smrg	{
273f220fa62Smrg
274f220fa62Smrg	  stripOfFanLeft(leftChain, segIndexLarge, segIndexSmall, grid, gridV, leftU, rightU, pStream, 0);
275f220fa62Smrg	  Real tempBot[2];
276f220fa62Smrg	  tempBot[0] = grid->get_u_value(rightU);
277f220fa62Smrg	  tempBot[1] = grid->get_v_value(gridV);
278f220fa62Smrg	  monoTriangulation2(topVertex, tempBot, leftChain, leftStart, segIndexSmall, 1, pStream);
279f220fa62Smrg	}
280f220fa62Smrg    }
281f220fa62Smrg  else //the topVertex forms a fan with the grid points
282f220fa62Smrg    grid->outputFanWithPoint(gridV, leftU, rightU, topVertex, pStream);
283f220fa62Smrg}
284f220fa62Smrg
285f220fa62Smrg
286f220fa62Smrgvoid sampleTopLeftWithGridLine(Real* topVertex,
287f220fa62Smrg                                vertexArray* leftChain,
288f220fa62Smrg                                Int leftStart,
289f220fa62Smrg                                Int leftEnd,
290f220fa62Smrg                                gridWrap* grid,
291f220fa62Smrg                                Int gridV,
292f220fa62Smrg                                Int leftU,
293f220fa62Smrg                                Int rightU,
294f220fa62Smrg                                primStream* pStream
295f220fa62Smrg                                )
296f220fa62Smrg{
297f220fa62Smrg  Int segIndexSmall = 0, segIndexLarge;
298f220fa62Smrg  //if left chain is empty, then there is only one top vertex with one grid
299f220fa62Smrg  //  line
300f220fa62Smrg  if(leftEnd < leftStart) {
301f220fa62Smrg    grid->outputFanWithPoint(gridV, leftU, rightU, topVertex, pStream);
302f220fa62Smrg    return;
303f220fa62Smrg  }
304f220fa62Smrg  findTopLeftSegment(leftChain,
305f220fa62Smrg                      leftStart,
306f220fa62Smrg                      leftEnd,
307f220fa62Smrg                      grid->get_u_value(leftU),
308f220fa62Smrg                      segIndexSmall,
309f220fa62Smrg                      segIndexLarge
310f220fa62Smrg                      );
311f220fa62Smrg  sampleTopLeftWithGridLinePost(topVertex,
312f220fa62Smrg				leftChain,
313f220fa62Smrg				leftStart,
314f220fa62Smrg				segIndexSmall,
315f220fa62Smrg				segIndexLarge,
316f220fa62Smrg				leftEnd,
317f220fa62Smrg				grid,
318f220fa62Smrg				gridV,
319f220fa62Smrg			        leftU,
320f220fa62Smrg				rightU,
321f220fa62Smrg				pStream);
322f220fa62Smrg}
323f220fa62Smrg
324f220fa62Smrg
325f220fa62Smrg//return 1 if saprator exits, 0 otherwise
326f220fa62SmrgInt findTopSeparator(vertexArray* leftChain,
327f220fa62Smrg		     Int leftStartIndex,
328f220fa62Smrg		     Int leftEndIndex,
329f220fa62Smrg		     vertexArray* rightChain,
330f220fa62Smrg		     Int rightStartIndex,
331f220fa62Smrg		     Int rightEndIndex,
332f220fa62Smrg		     Int& ret_sep_left,
333f220fa62Smrg		     Int& ret_sep_right)
334f220fa62Smrg{
335f220fa62Smrg
336f220fa62Smrg  Int oldLeftI, oldRightI, newLeftI, newRightI;
337f220fa62Smrg  Int i,j,k;
338f220fa62Smrg  Real leftMax /*= leftChain->getVertex(leftEndIndex)[0]*/;
339f220fa62Smrg  Real rightMin /*= rightChain->getVertex(rightEndIndex)[0]*/;
340f220fa62Smrg  if(leftChain->getVertex(leftEndIndex)[1] > rightChain->getVertex(rightEndIndex)[1]) //left higher
341f220fa62Smrg    {
342f220fa62Smrg      oldLeftI = leftEndIndex+1;
343f220fa62Smrg      oldRightI = rightEndIndex;
344f220fa62Smrg      leftMax =  leftChain->getVertex(leftEndIndex)[0] - Real(1.0); //initilza to left of leftU
345f220fa62Smrg      rightMin = rightChain->getVertex(rightEndIndex)[0];
346f220fa62Smrg    }
347f220fa62Smrg  else
348f220fa62Smrg    {
349f220fa62Smrg      oldLeftI = leftEndIndex;
350f220fa62Smrg      oldRightI = rightEndIndex+1;
351f220fa62Smrg      leftMax =  leftChain->getVertex(leftEndIndex)[0];
352f220fa62Smrg      rightMin = rightChain->getVertex(rightEndIndex)[0] + Real(1.0);
353f220fa62Smrg    }
354f220fa62Smrg
355f220fa62Smrg  //i: the current working leftChain index,
356f220fa62Smrg  //j: the current working rightChain index,
357f220fa62Smrg  //if left(i) is higher than right(j), then the two chains beloew right(j) are separated.
358f220fa62Smrg  //else the two chains below left(i) are separeated.
359f220fa62Smrg  i=leftEndIndex;
360f220fa62Smrg  j=rightEndIndex;
361f220fa62Smrg  while(1)
362f220fa62Smrg    {
363f220fa62Smrg      newLeftI = oldLeftI;
364f220fa62Smrg      newRightI = oldRightI;
365f220fa62Smrg
366f220fa62Smrg      if(i<leftStartIndex) //left chain is done, go through remining right chain.
367f220fa62Smrg	{
368f220fa62Smrg	  for(k=j-1; k>= rightStartIndex; k--)
369f220fa62Smrg	    {
370f220fa62Smrg	      if(rightChain->getVertex(k)[0] > leftMax) //no conflict
371f220fa62Smrg		{
372f220fa62Smrg		  //update oldRightI if necessary
373f220fa62Smrg		  if(rightChain->getVertex(k)[0] < rightMin)
374f220fa62Smrg		    {
375f220fa62Smrg		      rightMin = rightChain->getVertex(k)[0];
376f220fa62Smrg		      oldRightI = k;
377f220fa62Smrg		    }
378f220fa62Smrg		}
379f220fa62Smrg	      else  //there is a conflict
380f220fa62Smrg		break; //the for-loop. below right(k-1) is seperated: oldLeftI, oldRightI.
381f220fa62Smrg	    }
382f220fa62Smrg	  break; //the while loop
383f220fa62Smrg	}
384f220fa62Smrg      else if(j<rightStartIndex) //rightChain is done
385f220fa62Smrg	{
386f220fa62Smrg	  for(k=i-1; k>= leftStartIndex; k--)
387f220fa62Smrg	    {
388f220fa62Smrg	      if(leftChain->getVertex(k)[0] < rightMin) //no conflict
389f220fa62Smrg		{
390f220fa62Smrg		  //update oldLeftI if necessary
391f220fa62Smrg		  if(leftChain->getVertex(k)[0] > leftMax)
392f220fa62Smrg		    {
393f220fa62Smrg		      leftMax = leftChain->getVertex(k)[0];
394f220fa62Smrg		      oldLeftI = k;
395f220fa62Smrg		    }
396f220fa62Smrg		}
397f220fa62Smrg	      else //there is a conflict
398f220fa62Smrg		break; //the for loop
399f220fa62Smrg	    }
400f220fa62Smrg	  break; //the while loop
401f220fa62Smrg	}
402f220fa62Smrg      else if(leftChain->getVertex(i)[1] > rightChain->getVertex(j)[1]) //left hgiher
403f220fa62Smrg	{
404f220fa62Smrg	  if(leftChain->getVertex(i)[0] > leftMax) //update leftMax and newLeftI.
405f220fa62Smrg	    {
406f220fa62Smrg	      leftMax = leftChain->getVertex(i)[0];
407f220fa62Smrg	      newLeftI = i;
408f220fa62Smrg	    }
409f220fa62Smrg	  for(k=j-1; k>= rightStartIndex; k--) //update rightMin and newRightI.
410f220fa62Smrg	    {
411f220fa62Smrg	      if(rightChain->getVertex(k)[1] > leftChain->getVertex(i)[1])
412f220fa62Smrg		break;
413f220fa62Smrg	      if(rightChain->getVertex(k)[0] < rightMin)
414f220fa62Smrg		{
415f220fa62Smrg		  rightMin = rightChain->getVertex(k)[0];
416f220fa62Smrg		  newRightI = k;
417f220fa62Smrg		}
418f220fa62Smrg	    }
419f220fa62Smrg	  j = k; //next working j, since j will be higher than i in next loop
420f220fa62Smrg	  if(leftMax >= rightMin) //there is a conflict
421f220fa62Smrg	    break;
422f220fa62Smrg	  else //still no conflict
423f220fa62Smrg	    {
424f220fa62Smrg	      oldLeftI = newLeftI;
425f220fa62Smrg	      oldRightI = newRightI;
426f220fa62Smrg	    }
427f220fa62Smrg	}
428f220fa62Smrg      else //right higher
429f220fa62Smrg	{
430f220fa62Smrg	  if(rightChain->getVertex(j)[0] < rightMin)
431f220fa62Smrg	    {
432f220fa62Smrg	      rightMin = rightChain->getVertex(j)[0];
433f220fa62Smrg	      newRightI = j;
434f220fa62Smrg	    }
435f220fa62Smrg	  for(k=i-1; k>= leftStartIndex; k--)
436f220fa62Smrg	    {
437f220fa62Smrg	      if(leftChain->getVertex(k)[1] > rightChain->getVertex(j)[1])
438f220fa62Smrg		break;
439f220fa62Smrg	      if(leftChain->getVertex(k)[0] > leftMax)
440f220fa62Smrg		{
441f220fa62Smrg		  leftMax = leftChain->getVertex(k)[0];
442f220fa62Smrg		  newLeftI = k;
443f220fa62Smrg		}
444f220fa62Smrg	    }
445f220fa62Smrg	  i = k; //next working i, since i will be higher than j next loop
446f220fa62Smrg
447f220fa62Smrg	  if(leftMax >= rightMin) //there is a conflict
448f220fa62Smrg	    break;
449f220fa62Smrg	  else //still no conflict
450f220fa62Smrg	    {
451f220fa62Smrg	      oldLeftI = newLeftI;
452f220fa62Smrg	      oldRightI = newRightI;
453f220fa62Smrg	    }
454f220fa62Smrg	}
455f220fa62Smrg    }//end of while loop
456f220fa62Smrg  //now oldLeftI and oldRightI are the desired separeator index, notice that there are not necessarily valid
457f220fa62Smrg  if(oldLeftI > leftEndIndex || oldRightI > rightEndIndex)
458f220fa62Smrg    return 0;
459f220fa62Smrg  else
460f220fa62Smrg    {
461f220fa62Smrg      ret_sep_left = oldLeftI;
462f220fa62Smrg      ret_sep_right = oldRightI;
463f220fa62Smrg      return 1;
464f220fa62Smrg    }
465f220fa62Smrg}
466f220fa62Smrg
467f220fa62Smrg
468f220fa62Smrgvoid sampleCompTop(Real* topVertex,
469f220fa62Smrg                   vertexArray* leftChain,
470f220fa62Smrg                   Int leftStartIndex,
471f220fa62Smrg                   vertexArray* rightChain,
472f220fa62Smrg                   Int rightStartIndex,
473f220fa62Smrg                   gridBoundaryChain* leftGridChain,
474f220fa62Smrg                   gridBoundaryChain* rightGridChain,
475f220fa62Smrg                   Int gridIndex1,
476f220fa62Smrg                   Int up_leftCornerWhere,
477f220fa62Smrg                   Int up_leftCornerIndex,
478f220fa62Smrg                   Int up_rightCornerWhere,
479f220fa62Smrg                   Int up_rightCornerIndex,
480f220fa62Smrg                   primStream* pStream)
481f220fa62Smrg{
482f220fa62Smrg  if(up_leftCornerWhere == 1 && up_rightCornerWhere == 1) //the top is topVertex with possible grid points
483f220fa62Smrg    {
484f220fa62Smrg      leftGridChain->getGrid()->outputFanWithPoint(leftGridChain->getVlineIndex(gridIndex1),
485f220fa62Smrg						   leftGridChain->getUlineIndex(gridIndex1),
486f220fa62Smrg						   rightGridChain->getUlineIndex(gridIndex1),
487f220fa62Smrg						   topVertex,
488f220fa62Smrg						   pStream);
489f220fa62Smrg      return;
490f220fa62Smrg    }
491f220fa62Smrg
492f220fa62Smrg  else if(up_leftCornerWhere != 0)
493f220fa62Smrg    {
494f220fa62Smrg      Real* tempTop;
495f220fa62Smrg      Int tempRightStart;
496f220fa62Smrg      if(up_leftCornerWhere == 1){
497f220fa62Smrg	tempRightStart = rightStartIndex;
498f220fa62Smrg	tempTop = topVertex;
499f220fa62Smrg      }
500f220fa62Smrg      else
501f220fa62Smrg	{
502f220fa62Smrg	  tempRightStart = up_leftCornerIndex+1;
503f220fa62Smrg	  tempTop = rightChain->getVertex(up_leftCornerIndex);
504f220fa62Smrg	}
505f220fa62Smrg      sampleTopRightWithGridLine(tempTop, rightChain, tempRightStart, up_rightCornerIndex,
506f220fa62Smrg				 rightGridChain->getGrid(),
507f220fa62Smrg				 leftGridChain->getVlineIndex(gridIndex1),
508f220fa62Smrg				 leftGridChain->getUlineIndex(gridIndex1),
509f220fa62Smrg				 rightGridChain->getUlineIndex(gridIndex1),
510f220fa62Smrg				 pStream);
511f220fa62Smrg    }
512f220fa62Smrg  else if(up_rightCornerWhere != 2)
513f220fa62Smrg    {
514f220fa62Smrg      Real* tempTop;
515f220fa62Smrg      Int tempLeftStart;
516f220fa62Smrg      if(up_rightCornerWhere == 1)
517f220fa62Smrg	{
518f220fa62Smrg	  tempLeftStart = leftStartIndex;
519f220fa62Smrg	  tempTop = topVertex;
520f220fa62Smrg	}
521f220fa62Smrg      else //0
522f220fa62Smrg	{
523f220fa62Smrg	  tempLeftStart = up_rightCornerIndex+1;
524f220fa62Smrg	  tempTop = leftChain->getVertex(up_rightCornerIndex);
525f220fa62Smrg	}
526f220fa62Smrg/*
527f220fa62Smrg      sampleTopLeftWithGridLine(tempTop, leftChain, tempLeftStart, up_leftCornerIndex,
528f220fa62Smrg				leftGridChain->getGrid(),
529f220fa62Smrg				 leftGridChain->getVlineIndex(gridIndex1),
530f220fa62Smrg				 leftGridChain->getUlineIndex(gridIndex1),
531f220fa62Smrg				 rightGridChain->getUlineIndex(gridIndex1),
532f220fa62Smrg				 pStream);
533f220fa62Smrg*/
534f220fa62Smrg      sampleCompTopSimple(topVertex,
535f220fa62Smrg			  leftChain,
536f220fa62Smrg			  leftStartIndex,
537f220fa62Smrg			  rightChain,
538f220fa62Smrg			  rightStartIndex,
539f220fa62Smrg			  leftGridChain,
540f220fa62Smrg			  rightGridChain,
541f220fa62Smrg			  gridIndex1,
542f220fa62Smrg			  up_leftCornerWhere,
543f220fa62Smrg			  up_leftCornerIndex,
544f220fa62Smrg			  up_rightCornerWhere,
545f220fa62Smrg			  up_rightCornerIndex,
546f220fa62Smrg			  pStream);
547f220fa62Smrg    }
548f220fa62Smrg  else //up_leftCornerWhere == 0, up_rightCornerWhere == 2.
549f220fa62Smrg    {
550f220fa62Smrg      sampleCompTopSimple(topVertex,
551f220fa62Smrg			  leftChain,
552f220fa62Smrg			  leftStartIndex,
553f220fa62Smrg			  rightChain,
554f220fa62Smrg			  rightStartIndex,
555f220fa62Smrg			  leftGridChain,
556f220fa62Smrg			  rightGridChain,
557f220fa62Smrg			  gridIndex1,
558f220fa62Smrg			  up_leftCornerWhere,
559f220fa62Smrg			  up_leftCornerIndex,
560f220fa62Smrg			  up_rightCornerWhere,
561f220fa62Smrg			  up_rightCornerIndex,
562f220fa62Smrg			  pStream);
563f220fa62Smrg      return;
564f220fa62Smrg#ifdef NOT_REACHABLE //code is not reachable, for test purpose only
565f220fa62Smrg      //the following code is trying to do some optimization, but not quite working, also see sampleCompBot.C:
566f220fa62Smrg      Int sep_left, sep_right;
567f220fa62Smrg      if(findTopSeparator(leftChain,
568f220fa62Smrg			  leftStartIndex,
569f220fa62Smrg			  up_leftCornerIndex,
570f220fa62Smrg			  rightChain,
571f220fa62Smrg			  rightStartIndex,
572f220fa62Smrg			  up_rightCornerIndex,
573f220fa62Smrg			  sep_left,
574f220fa62Smrg			  sep_right)
575f220fa62Smrg	 ) //separator exists
576f220fa62Smrg	{
577f220fa62Smrg
578f220fa62Smrg	  if( leftChain->getVertex(sep_left)[0] >= leftGridChain->get_u_value(gridIndex1) &&
579f220fa62Smrg	     rightChain->getVertex(sep_right)[0] <= rightGridChain->get_u_value(gridIndex1))
580f220fa62Smrg	    {
581f220fa62Smrg	      Int gridSep;
582f220fa62Smrg	      Int segLeftSmall, segLeftLarge, segRightSmall, segRightLarge;
583f220fa62Smrg	      Int valid=1; //whether the gridStep is valid or not.
584f220fa62Smrg	      findTopLeftSegment(leftChain,
585f220fa62Smrg				 sep_left,
586f220fa62Smrg				 up_leftCornerIndex,
587f220fa62Smrg				 leftGridChain->get_u_value(gridIndex1),
588f220fa62Smrg				 segLeftSmall,
589f220fa62Smrg				 segLeftLarge);
590f220fa62Smrg	      findTopRightSegment(rightChain,
591f220fa62Smrg				 sep_right,
592f220fa62Smrg				 up_rightCornerIndex,
593f220fa62Smrg				 rightGridChain->get_u_value(gridIndex1),
594f220fa62Smrg				 segRightSmall,
595f220fa62Smrg				 segRightLarge);
596f220fa62Smrg	      if(leftChain->getVertex(segLeftSmall)[1] >= rightChain->getVertex(segRightSmall)[1])
597f220fa62Smrg		{
598f220fa62Smrg		  gridSep = rightGridChain->getUlineIndex(gridIndex1);
599f220fa62Smrg		  while(leftGridChain->getGrid()->get_u_value(gridSep) > leftChain->getVertex(segLeftSmall)[0])
600f220fa62Smrg		    gridSep--;
601f220fa62Smrg		  if(segLeftSmall<segLeftLarge)
602f220fa62Smrg		    if(leftGridChain->getGrid()->get_u_value(gridSep) < leftChain->getVertex(segLeftSmall+1)[0])
603f220fa62Smrg		      {
604f220fa62Smrg			valid = 0;
605f220fa62Smrg		      }
606f220fa62Smrg		}
607f220fa62Smrg	      else
608f220fa62Smrg		{
609f220fa62Smrg		  gridSep = leftGridChain->getUlineIndex(gridIndex1);
610f220fa62Smrg		  while(leftGridChain->getGrid()->get_u_value(gridSep) < rightChain->getVertex(segRightSmall)[0])
611f220fa62Smrg		    gridSep++;
612f220fa62Smrg		  if(segRightSmall<segRightLarge)
613f220fa62Smrg		    if(leftGridChain->getGrid()->get_u_value(gridSep) > rightChain->getVertex(segRightSmall+1)[0])
614f220fa62Smrg		      {
615f220fa62Smrg			valid = 0;
616f220fa62Smrg		      }
617f220fa62Smrg		}
618f220fa62Smrg
619f220fa62Smrg	      if(! valid)
620f220fa62Smrg		{
621f220fa62Smrg		  sampleCompTopSimple(topVertex,
622f220fa62Smrg				      leftChain,
623f220fa62Smrg				      leftStartIndex,
624f220fa62Smrg				      rightChain,
625f220fa62Smrg				      rightStartIndex,
626f220fa62Smrg				      leftGridChain,
627f220fa62Smrg				      rightGridChain,
628f220fa62Smrg				      gridIndex1,
629f220fa62Smrg				      up_leftCornerWhere,
630f220fa62Smrg				      up_leftCornerIndex,
631f220fa62Smrg				      up_rightCornerWhere,
632f220fa62Smrg				      up_rightCornerIndex,
633f220fa62Smrg				      pStream);
634f220fa62Smrg		}
635f220fa62Smrg	      else
636f220fa62Smrg		{
637f220fa62Smrg		  sampleTopLeftWithGridLinePost(leftChain->getVertex(segLeftSmall),
638f220fa62Smrg						leftChain,
639f220fa62Smrg						segLeftSmall+1,
640f220fa62Smrg						segLeftSmall+1,
641f220fa62Smrg						segLeftLarge,
642f220fa62Smrg						up_leftCornerIndex,
643f220fa62Smrg						leftGridChain->getGrid(),
644f220fa62Smrg						leftGridChain->getVlineIndex(gridIndex1),
645f220fa62Smrg						leftGridChain->getUlineIndex(gridIndex1),
646f220fa62Smrg						gridSep,
647f220fa62Smrg						pStream);
648f220fa62Smrg		  sampleTopRightWithGridLinePost(rightChain->getVertex(segRightSmall),
649f220fa62Smrg						 rightChain,
650f220fa62Smrg						 segRightSmall+1,
651f220fa62Smrg						 segRightSmall+1,
652f220fa62Smrg						 segRightLarge,
653f220fa62Smrg						 up_rightCornerIndex,
654f220fa62Smrg						 leftGridChain->getGrid(),
655f220fa62Smrg						 leftGridChain->getVlineIndex(gridIndex1),
656f220fa62Smrg						 gridSep,
657f220fa62Smrg						 rightGridChain->getUlineIndex(gridIndex1),
658f220fa62Smrg						 pStream);
659f220fa62Smrg		  Real tempBot[2];
660f220fa62Smrg		  tempBot[0] = leftGridChain->getGrid()->get_u_value(gridSep);
661f220fa62Smrg		  tempBot[1] = leftGridChain->get_v_value(gridIndex1);
662f220fa62Smrg		  monoTriangulationRecGen(topVertex, tempBot,
663f220fa62Smrg					  leftChain, leftStartIndex, segLeftSmall,
664f220fa62Smrg					  rightChain, rightStartIndex, segRightSmall,
665f220fa62Smrg					  pStream);
666f220fa62Smrg		}
667f220fa62Smrg	    }//end if both sides have vetices inside the gridboundary points
668f220fa62Smrg	  else if(leftChain->getVertex(sep_left)[0] >= leftGridChain->get_u_value(gridIndex1)) //left is in, right is nout
669f220fa62Smrg	    {
670f220fa62Smrg
671f220fa62Smrg	      Int segLeftSmall, segLeftLarge;
672f220fa62Smrg	      findTopLeftSegment(leftChain,
673f220fa62Smrg				 sep_left,
674f220fa62Smrg				 up_leftCornerIndex,
675f220fa62Smrg				 leftGridChain->get_u_value(gridIndex1),
676f220fa62Smrg				 segLeftSmall,
677f220fa62Smrg				 segLeftLarge);
678f220fa62Smrg	      assert(segLeftLarge >= sep_left);
679f220fa62Smrg              monoTriangulation2(leftChain->getVertex(segLeftLarge),
680f220fa62Smrg				 leftGridChain->get_vertex(gridIndex1),
681f220fa62Smrg				 leftChain,
682f220fa62Smrg				 segLeftLarge+1,
683f220fa62Smrg				 up_leftCornerIndex,
684f220fa62Smrg				 1, //a increase chain,
685f220fa62Smrg				 pStream);
686f220fa62Smrg
687f220fa62Smrg	      stripOfFanLeft(leftChain, segLeftLarge, segLeftSmall,
688f220fa62Smrg			     leftGridChain->getGrid(),
689f220fa62Smrg			     leftGridChain->getVlineIndex(gridIndex1),
690f220fa62Smrg			     leftGridChain->getUlineIndex(gridIndex1),
691f220fa62Smrg			     rightGridChain->getUlineIndex(gridIndex1),
692f220fa62Smrg			     pStream, 0);
693f220fa62Smrg
694f220fa62Smrg
695f220fa62Smrg	      monoTriangulationRecGen(topVertex, rightGridChain->get_vertex(gridIndex1),
696f220fa62Smrg				      leftChain, leftStartIndex, segLeftSmall,
697f220fa62Smrg				      rightChain, rightStartIndex, up_rightCornerIndex,
698f220fa62Smrg				      pStream);
699f220fa62Smrg	    }//end left in right out
700f220fa62Smrg	  else if(rightChain->getVertex(sep_right)[0] <= rightGridChain->get_u_value(gridIndex1))
701f220fa62Smrg	    {
702f220fa62Smrg	      Int segRightSmall, segRightLarge;
703f220fa62Smrg	      findTopRightSegment(rightChain,
704f220fa62Smrg				 sep_right,
705f220fa62Smrg				 up_rightCornerIndex,
706f220fa62Smrg				 rightGridChain->get_u_value(gridIndex1),
707f220fa62Smrg				 segRightSmall,
708f220fa62Smrg				 segRightLarge);
709f220fa62Smrg	      assert(segRightLarge>=sep_right);
710f220fa62Smrg	      monoTriangulation2(rightChain->getVertex(segRightLarge),
711f220fa62Smrg				 rightGridChain->get_vertex(gridIndex1),
712f220fa62Smrg				 rightChain,
713f220fa62Smrg				 segRightLarge+1,
714f220fa62Smrg				 up_rightCornerIndex,
715f220fa62Smrg				 0, //a decrease chain
716f220fa62Smrg				 pStream);
717f220fa62Smrg	      stripOfFanRight(rightChain, segRightLarge, segRightSmall,
718f220fa62Smrg			      rightGridChain->getGrid(),
719f220fa62Smrg			      rightGridChain->getVlineIndex(gridIndex1),
720f220fa62Smrg			      leftGridChain->getUlineIndex(gridIndex1),
721f220fa62Smrg			      rightGridChain->getUlineIndex(gridIndex1),
722f220fa62Smrg			      pStream, 0);
723f220fa62Smrg
724f220fa62Smrg
725f220fa62Smrg	      monoTriangulationRecGen(topVertex, leftGridChain->get_vertex(gridIndex1),
726f220fa62Smrg				      leftChain, leftStartIndex, up_leftCornerIndex,
727f220fa62Smrg				      rightChain, rightStartIndex,segRightSmall,
728f220fa62Smrg				      pStream);
729f220fa62Smrg
730f220fa62Smrg	    }//end left out rigth in
731f220fa62Smrg	  else //left out , right out
732f220fa62Smrg	    {
733f220fa62Smrg
734f220fa62Smrg	      sampleCompTopSimple(topVertex,
735f220fa62Smrg				  leftChain,
736f220fa62Smrg				  leftStartIndex,
737f220fa62Smrg				  rightChain,
738f220fa62Smrg				  rightStartIndex,
739f220fa62Smrg				  leftGridChain,
740f220fa62Smrg				  rightGridChain,
741f220fa62Smrg				  gridIndex1,
742f220fa62Smrg				  up_leftCornerWhere,
743f220fa62Smrg				  up_leftCornerIndex,
744f220fa62Smrg				  up_rightCornerWhere,
745f220fa62Smrg				  up_rightCornerIndex,
746f220fa62Smrg				  pStream);
747f220fa62Smrg	    }//end leftout, right out
748f220fa62Smrg	}//end if separator exixts.
749f220fa62Smrg      else //no separator
750f220fa62Smrg	{
751f220fa62Smrg
752f220fa62Smrg	  sampleCompTopSimple(topVertex,
753f220fa62Smrg			    leftChain,
754f220fa62Smrg			      leftStartIndex,
755f220fa62Smrg			      rightChain,
756f220fa62Smrg			      rightStartIndex,
757f220fa62Smrg			      leftGridChain,
758f220fa62Smrg			      rightGridChain,
759f220fa62Smrg			      gridIndex1,
760f220fa62Smrg			    up_leftCornerWhere,
761f220fa62Smrg			      up_leftCornerIndex,
762f220fa62Smrg			      up_rightCornerWhere,
763f220fa62Smrg			      up_rightCornerIndex,
764f220fa62Smrg			    pStream);
765f220fa62Smrg	}
766f220fa62Smrg#endif
767f220fa62Smrg    }//end if 0,2
768f220fa62Smrg}//end if the function
769f220fa62Smrg
770f220fa62Smrg
771f220fa62Smrgstatic void sampleCompTopSimpleOpt(gridWrap* grid,
772f220fa62Smrg				   Int gridV,
773f220fa62Smrg				   Real* topVertex, Real* botVertex,
774f220fa62Smrg				   vertexArray* inc_chain, Int inc_current, Int inc_end,
775f220fa62Smrg				   vertexArray* dec_chain, Int dec_current, Int dec_end,
776f220fa62Smrg				   primStream* pStream)
777f220fa62Smrg{
778f220fa62Smrg  if(gridV <= 0 || dec_end<dec_current || inc_end <inc_current)
779f220fa62Smrg    {
780f220fa62Smrg      monoTriangulationRecGenOpt(topVertex, botVertex,
781f220fa62Smrg				 inc_chain, inc_current, inc_end,
782f220fa62Smrg				 dec_chain, dec_current, dec_end,
783f220fa62Smrg				 pStream);
784f220fa62Smrg      return;
785f220fa62Smrg    }
786f220fa62Smrg  if(grid->get_v_value(gridV+1) >= topVertex[1])
787f220fa62Smrg    {
788f220fa62Smrg      monoTriangulationRecGenOpt(topVertex, botVertex,
789f220fa62Smrg				 inc_chain, inc_current, inc_end,
790f220fa62Smrg				 dec_chain, dec_current, dec_end,
791f220fa62Smrg				 pStream);
792f220fa62Smrg      return;
793f220fa62Smrg    }
794f220fa62Smrg Int i,j,k;
795f220fa62Smrg  Real currentV = grid->get_v_value(gridV+1);
796f220fa62Smrg  if(inc_chain->getVertex(inc_end)[1] <= currentV &&
797f220fa62Smrg     dec_chain->getVertex(dec_end)[1] < currentV)
798f220fa62Smrg    {
799f220fa62Smrg      //find i bottom up so that inc_chain[i]<= curentV and inc_chain[i-1] > currentV,
800f220fa62Smrg      //find j botom up so that dec_chain[j] < currentV and dec_chain[j-1] >= currentV
801f220fa62Smrg      for(i=inc_end; i >= inc_current; i--)
802f220fa62Smrg	{
803f220fa62Smrg	  if(inc_chain->getVertex(i)[1] > currentV)
804f220fa62Smrg	    break;
805f220fa62Smrg	}
806f220fa62Smrg      i++;
807f220fa62Smrg      for(j=dec_end; j >= dec_current; j--)
808f220fa62Smrg	{
809f220fa62Smrg	  if(dec_chain->getVertex(j)[1] >= currentV)
810f220fa62Smrg	    break;
811f220fa62Smrg	}
812f220fa62Smrg      j++;
813f220fa62Smrg     if(inc_chain->getVertex(i)[1] <= dec_chain->getVertex(j)[1])
814f220fa62Smrg       {
815f220fa62Smrg	 //find the k so that dec_chain[k][1] < inc_chain[i][1]
816f220fa62Smrg	 for(k=j; k<=dec_end; k++)
817f220fa62Smrg	   {
818f220fa62Smrg	     if(dec_chain->getVertex(k)[1] < inc_chain->getVertex(i)[1])
819f220fa62Smrg	       break;
820f220fa62Smrg	   }
821f220fa62Smrg         //we know that dec_chain[j][1] >= inc_chian[i][1]
822f220fa62Smrg	 //we know that dec_chain[k-1][1]>=inc_chain[i][1]
823f220fa62Smrg         //we know that dec_chian[k][1] < inc_chain[i][1]
824f220fa62Smrg         //find l in [j, k-1] so that dec_chain[l][0] 0 is closest to
825f220fa62Smrg         // inc_chain[i]
826f220fa62Smrg         int l;
827f220fa62Smrg         Real tempI = Real(j);
828f220fa62Smrg         Real tempMin = (Real)fabs(inc_chain->getVertex(i)[0] - dec_chain->getVertex(j)[0]);
829f220fa62Smrg         for(l=j+1; l<= k-1; l++)
830f220fa62Smrg	   {
831f220fa62Smrg	     if(fabs(inc_chain->getVertex(i)[0] - dec_chain->getVertex(l)[0])
832f220fa62Smrg		<= tempMin)
833f220fa62Smrg	       {
834f220fa62Smrg		 tempMin = (Real)fabs(inc_chain->getVertex(i)[0] - dec_chain->getVertex(l)[0]);
835f220fa62Smrg		 tempI = (Real)l;
836f220fa62Smrg	       }
837f220fa62Smrg	   }
838f220fa62Smrg	 //inc_chain[i] and dec_chain[tempI] are connected.
839f220fa62Smrg	 monoTriangulationRecGenOpt(dec_chain->getVertex((int)tempI),
840f220fa62Smrg				    botVertex,
841f220fa62Smrg				    inc_chain, i, inc_end,
842f220fa62Smrg				    dec_chain, (int)(tempI+1), dec_end,
843f220fa62Smrg				    pStream);
844f220fa62Smrg	 //recursively do the rest
845f220fa62Smrg	 sampleCompTopSimpleOpt(grid,
846f220fa62Smrg				gridV+1,
847f220fa62Smrg				topVertex, inc_chain->getVertex(i),
848f220fa62Smrg				inc_chain, inc_current, i-1,
849f220fa62Smrg				dec_chain, dec_current, (int)tempI,
850f220fa62Smrg				pStream);
851f220fa62Smrg       }
852f220fa62Smrg      else
853f220fa62Smrg	{
854f220fa62Smrg	  //find the k so that inc_chain[k][1] <= dec_chain[j][1]
855f220fa62Smrg	  for(k=i; k<=inc_end; k++)
856f220fa62Smrg	    {
857f220fa62Smrg	      if(inc_chain->getVertex(k)[1] <= dec_chain->getVertex(j)[1])
858f220fa62Smrg		break;
859f220fa62Smrg	    }
860f220fa62Smrg	  //we know that inc_chain[i] > dec_chain[j]
861f220fa62Smrg	  //we know that inc_chain[k-1][1] > dec_chain[j][1]
862f220fa62Smrg	  //we know that inc_chain[k][1] <= dec_chain[j][1]
863f220fa62Smrg	  //so we find l between [i,k-1] so that
864f220fa62Smrg	  //inc_chain[l][0] is the closet to dec_chain[j][0]
865f220fa62Smrg	  int tempI = i;
866f220fa62Smrg	  int l;
867f220fa62Smrg	  Real tempMin = (Real)fabs(inc_chain->getVertex(i)[0] - dec_chain->getVertex(j)[0]);
868f220fa62Smrg	  for(l=i+1; l<=k-1; l++)
869f220fa62Smrg	    {
870f220fa62Smrg	      if(fabs(inc_chain->getVertex(l)[0] - dec_chain->getVertex(j)[0]) <= tempMin)
871f220fa62Smrg		{
872f220fa62Smrg		  tempMin = (Real)fabs(inc_chain->getVertex(l)[0] - dec_chain->getVertex(j)[0]);
873f220fa62Smrg		  tempI = l;
874f220fa62Smrg		}
875f220fa62Smrg	    }
876f220fa62Smrg
877f220fa62Smrg	  //inc_chain[tempI] and dec_chain[j] are connected
878f220fa62Smrg
879f220fa62Smrg	  monoTriangulationRecGenOpt(inc_chain->getVertex(tempI),
880f220fa62Smrg				     botVertex,
881f220fa62Smrg				     inc_chain, tempI+1, inc_end,
882f220fa62Smrg				     dec_chain, j, dec_end,
883f220fa62Smrg				     pStream);
884f220fa62Smrg
885f220fa62Smrg	  //recurvesily do the rest
886f220fa62Smrg	  sampleCompTopSimpleOpt(grid, gridV+1,
887f220fa62Smrg				 topVertex, dec_chain->getVertex(j),
888f220fa62Smrg				 inc_chain, inc_current, tempI,
889f220fa62Smrg				 dec_chain, dec_current, j-1,
890f220fa62Smrg				 pStream);
891f220fa62Smrg	}
892f220fa62Smrg    }
893f220fa62Smrg  else //go to the next higher gridV
894f220fa62Smrg    {
895f220fa62Smrg      sampleCompTopSimpleOpt(grid,
896f220fa62Smrg			     gridV+1,
897f220fa62Smrg			     topVertex, botVertex,
898f220fa62Smrg			     inc_chain, inc_current, inc_end,
899f220fa62Smrg			     dec_chain, dec_current, dec_end,
900f220fa62Smrg			     pStream);
901f220fa62Smrg    }
902f220fa62Smrg}
903f220fa62Smrg
904f220fa62Smrgvoid sampleCompTopSimple(Real* topVertex,
905f220fa62Smrg                   vertexArray* leftChain,
906f220fa62Smrg                   Int leftStartIndex,
907f220fa62Smrg                   vertexArray* rightChain,
908f220fa62Smrg                   Int rightStartIndex,
909f220fa62Smrg                   gridBoundaryChain* leftGridChain,
910f220fa62Smrg                   gridBoundaryChain* rightGridChain,
911f220fa62Smrg                   Int gridIndex1,
912f220fa62Smrg                   Int up_leftCornerWhere,
913f220fa62Smrg                   Int up_leftCornerIndex,
914f220fa62Smrg                   Int up_rightCornerWhere,
915f220fa62Smrg                   Int up_rightCornerIndex,
916f220fa62Smrg                   primStream* pStream)
917f220fa62Smrg{
918f220fa62Smrg  //the plan is to use monotriangulation algortihm.
919f220fa62Smrg  Int i,k;
920f220fa62Smrg  Real* ActualTop;
921f220fa62Smrg  Real* ActualBot;
922f220fa62Smrg  Int ActualLeftStart, ActualLeftEnd;
923f220fa62Smrg  Int ActualRightStart, ActualRightEnd;
924f220fa62Smrg
925f220fa62Smrg  //creat an array to store the points on the grid line
926f220fa62Smrg  gridWrap* grid = leftGridChain->getGrid();
927f220fa62Smrg  Int gridV = leftGridChain->getVlineIndex(gridIndex1);
928f220fa62Smrg  Int gridLeftU = leftGridChain->getUlineIndex(gridIndex1);
929f220fa62Smrg  Int gridRightU = rightGridChain->getUlineIndex(gridIndex1);
930f220fa62Smrg
931f220fa62Smrg  Real2* gridPoints = (Real2*) malloc(sizeof(Real2) * (gridRightU - gridLeftU +1));
932f220fa62Smrg  assert(gridPoints);
933f220fa62Smrg
934f220fa62Smrg  for(k=0, i=gridRightU; i>= gridLeftU; i--, k++)
935f220fa62Smrg    {
936f220fa62Smrg      gridPoints[k][0] = grid->get_u_value(i);
937f220fa62Smrg      gridPoints[k][1] = grid->get_v_value(gridV);
938f220fa62Smrg    }
939f220fa62Smrg
940f220fa62Smrg  if(up_leftCornerWhere != 2)
941f220fa62Smrg    ActualRightStart = rightStartIndex;
942f220fa62Smrg  else
943f220fa62Smrg    ActualRightStart = up_leftCornerIndex+1; //up_leftCornerIndex will be the ActualTop
944f220fa62Smrg
945f220fa62Smrg  if(up_rightCornerWhere != 2) //right corner is not on right chain
946f220fa62Smrg    ActualRightEnd = rightStartIndex-1; //meaning that there is no actual rigth section
947f220fa62Smrg  else
948f220fa62Smrg    ActualRightEnd = up_rightCornerIndex;
949f220fa62Smrg
950f220fa62Smrg  vertexArray ActualRightChain(max(0, ActualRightEnd-ActualRightStart+1) + gridRightU-gridLeftU+1);
951f220fa62Smrg
952f220fa62Smrg  for(i=ActualRightStart; i<= ActualRightEnd; i++)
953f220fa62Smrg    ActualRightChain.appendVertex(rightChain->getVertex(i));
954f220fa62Smrg  for(i=0; i<gridRightU-gridLeftU+1; i++)
955f220fa62Smrg    ActualRightChain.appendVertex(gridPoints[i]);
956f220fa62Smrg
957f220fa62Smrg  //determine ActualLeftEnd
958f220fa62Smrg  if(up_leftCornerWhere != 0)
959f220fa62Smrg    ActualLeftEnd = leftStartIndex-1;
960f220fa62Smrg  else
961f220fa62Smrg    ActualLeftEnd = up_leftCornerIndex;
962f220fa62Smrg
963f220fa62Smrg  if(up_rightCornerWhere != 0)
964f220fa62Smrg    ActualLeftStart = leftStartIndex;
965f220fa62Smrg  else
966f220fa62Smrg    ActualLeftStart = up_rightCornerIndex+1; //up_rightCornerIndex will be the actual top
967f220fa62Smrg
968f220fa62Smrg  if(up_leftCornerWhere == 0)
969f220fa62Smrg    {
970f220fa62Smrg      if(up_rightCornerWhere == 0)
971f220fa62Smrg	ActualTop = leftChain->getVertex(up_rightCornerIndex);
972f220fa62Smrg      else
973f220fa62Smrg	ActualTop = topVertex;
974f220fa62Smrg    }
975f220fa62Smrg  else if(up_leftCornerWhere == 1)
976f220fa62Smrg    ActualTop = topVertex;
977f220fa62Smrg  else  //up_leftCornerWhere == 2
978f220fa62Smrg    ActualTop = rightChain->getVertex(up_leftCornerIndex);
979f220fa62Smrg
980f220fa62Smrg  ActualBot = gridPoints[gridRightU - gridLeftU];
981f220fa62Smrg
982f220fa62Smrg
983f220fa62Smrg
984f220fa62Smrg
985f220fa62Smrg  if(leftChain->getVertex(ActualLeftEnd)[1] == ActualBot[1])
986f220fa62Smrg    {
987f220fa62Smrg/*
988f220fa62Smrg    monoTriangulationRecGenOpt(ActualTop, leftChain->getVertex(ActualLeftEnd),
989f220fa62Smrg			    leftChain,
990f220fa62Smrg			    ActualLeftStart, ActualLeftEnd-1,
991f220fa62Smrg			    &ActualRightChain,
992f220fa62Smrg			    0,
993f220fa62Smrg			    ActualRightChain.getNumElements()-1,
994f220fa62Smrg			    pStream);
995f220fa62Smrg*/
996f220fa62Smrg
997f220fa62Smrg    sampleCompTopSimpleOpt(grid, gridV,
998f220fa62Smrg			   ActualTop, leftChain->getVertex(ActualLeftEnd),
999f220fa62Smrg			    leftChain,
1000f220fa62Smrg			    ActualLeftStart, ActualLeftEnd-1,
1001f220fa62Smrg			    &ActualRightChain,
1002f220fa62Smrg			    0,
1003f220fa62Smrg			    ActualRightChain.getNumElements()-1,
1004f220fa62Smrg			    pStream);
1005f220fa62Smrg
1006f220fa62Smrg  }
1007f220fa62Smrg  else
1008f220fa62Smrg    {
1009f220fa62Smrg/*
1010f220fa62Smrg    monoTriangulationRecGenOpt(ActualTop, ActualBot, leftChain,
1011f220fa62Smrg			  ActualLeftStart, ActualLeftEnd,
1012f220fa62Smrg			  &ActualRightChain,
1013f220fa62Smrg			  0, ActualRightChain.getNumElements()-2, //the last is the bot.
1014f220fa62Smrg			  pStream);
1015f220fa62Smrg*/
1016f220fa62Smrg
1017f220fa62Smrg    sampleCompTopSimpleOpt(grid, gridV,
1018f220fa62Smrg			   ActualTop, ActualBot, leftChain,
1019f220fa62Smrg			  ActualLeftStart, ActualLeftEnd,
1020f220fa62Smrg			  &ActualRightChain,
1021f220fa62Smrg			  0, ActualRightChain.getNumElements()-2, //the last is the bot.
1022f220fa62Smrg			  pStream);
1023f220fa62Smrg
1024f220fa62Smrg
1025f220fa62Smrg  }
1026f220fa62Smrg
1027f220fa62Smrg  free(gridPoints);
1028f220fa62Smrg
1029f220fa62Smrg}
1030f220fa62Smrg
1031