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