1/*
2** License Applicability. Except to the extent portions of this file are
3** made subject to an alternative license as permitted in the SGI Free
4** Software License B, Version 1.1 (the "License"), the contents of this
5** file are subject only to the provisions of the License. You may not use
6** this file except in compliance with the License. You may obtain a copy
7** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
8** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
9**
10** http://oss.sgi.com/projects/FreeB
11**
12** Note that, as provided in the License, the Software is distributed on an
13** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
14** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
15** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
16** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
17**
18** Original Code. The Original Code is: OpenGL Sample Implementation,
19** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
20** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
21** Copyright in any portions created by third parties is as indicated
22** elsewhere herein. All Rights Reserved.
23**
24** Additional Notice Provisions: The application programming interfaces
25** established by SGI in conjunction with the Original Code are The
26** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
27** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
28** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
29** Window System(R) (Version 1.3), released October 19, 1998. This software
30** was created using the OpenGL(R) version 1.2.1 Sample Implementation
31** published by SGI, but has not been independently verified as being
32** compliant with the OpenGL(R) version 1.2.1 Specification.
33**
34*/
35/*
36*/
37
38#include <stdlib.h>
39#include <stdio.h>
40#include "gluos.h"
41#include "glimports.h"
42#include "zlassert.h"
43#include "sampleCompRight.h"
44
45#define max(a,b) ((a>b)? a:b)
46#define min(a,b) ((a>b)? b:a)
47
48
49
50#ifdef NOT_TAKEOUT
51
52/*notice that we need leftChain because the
53 *corners could be on the leftChain.
54 */
55void sampleCompRight(Real* topVertex, Real* botVertex,
56		    vertexArray* leftChain,
57		    Int leftStartIndex, Int leftEndIndex,
58		    vertexArray* rightChain,
59		    Int rightStartIndex, Int rightEndIndex,
60		    gridBoundaryChain* rightGridChain,
61		    Int gridIndex1, Int gridIndex2,
62		    Int up_rightCornerWhere,
63		    Int up_rightCornerIndex,
64		    Int down_rightCornerWhere,
65		    Int down_rightCornerIndex,
66		    primStream* pStream)
67{
68  /*find out whether there is a trim vertex  which is
69   *inbetween the top and bot grid lines or not.
70   */
71  Int midIndex1;
72  Int midIndex2;
73  Int gridMidIndex1 = 0, gridMidIndex2 = 0;
74  //midIndex1: array[i] <= v, array[i+1] > v
75  //midIndex2: array[i] >= v,  array[i+1] < v
76  midIndex1 = rightChain->findIndexBelowGen(rightGridChain->get_v_value(gridIndex1),
77					    rightStartIndex,
78					    rightEndIndex);
79  midIndex2 = -1; //initilization
80  if(midIndex1 <= rightEndIndex && gridIndex1 < gridIndex2)
81    if(rightChain->getVertex(midIndex1)[1] >= rightGridChain->get_v_value(gridIndex2))
82      {
83	//midIndex2 must exist:
84	midIndex2 = rightChain->findIndexAboveGen(rightGridChain->get_v_value(gridIndex2),
85						  midIndex1, //midIndex1<=midIndex2
86						  rightEndIndex);
87	//find gridMidIndex1 so that either it=gridIndex1 when the gridline is
88	// at the same height as trim vertex midIndex1, or it is the last one
89	//which is strictly above midIndex1.
90	{
91	  Real temp = rightChain->getVertex(midIndex1)[1];
92	  if(rightGridChain->get_v_value(gridIndex1) == temp)
93	    gridMidIndex1 = gridIndex1;
94	  else
95	    {
96	    gridMidIndex1 = gridIndex1;
97	    while(rightGridChain->get_v_value(gridMidIndex1) > temp)
98	      gridMidIndex1++;
99	    gridMidIndex1--;
100	    }
101	}//end of find gridMindIndex1
102	//find gridMidIndex2 so that it is the (first one below or equal
103	//midIndex) last one above or equal midIndex2
104	{
105	  Real temp = rightChain->getVertex(midIndex2)[1];
106	  for(gridMidIndex2 = gridMidIndex1+1; gridMidIndex2 <= gridIndex2; gridMidIndex2++)
107	    if(rightGridChain->get_v_value(gridMidIndex2) <= temp)
108	      break;
109
110	  assert(gridMidIndex2 <= gridIndex2);
111	}//end of find gridMidIndex2
112      }
113
114
115
116  //to interprete the corner information
117  Real* cornerTop;
118  Real* cornerBot;
119  Int cornerRightStart;
120  Int cornerRightEnd;
121  Int cornerLeftUpEnd;
122  Int cornerLeftDownStart;
123  if(up_rightCornerWhere == 2) //right corner is on right chain
124    {
125      cornerTop = rightChain->getVertex(up_rightCornerIndex);
126      cornerRightStart = up_rightCornerIndex+1;
127      cornerLeftUpEnd = -1; //no left
128    }
129  else if(up_rightCornerWhere == 1) //right corner is on top
130    {
131      cornerTop = topVertex;
132      cornerRightStart = rightStartIndex;
133      cornerLeftUpEnd = -1; //no left
134    }
135  else //right corner is on left chain
136    {
137      cornerTop = topVertex;
138      cornerRightStart = rightStartIndex;
139      cornerLeftUpEnd = up_rightCornerIndex;
140    }
141
142  if(down_rightCornerWhere == 2) //right corner is on right chan
143    {
144      cornerBot = rightChain->getVertex(down_rightCornerIndex);
145      cornerRightEnd = down_rightCornerIndex-1;
146      cornerLeftDownStart = leftEndIndex+1; //no left
147    }
148  else if (down_rightCornerWhere == 1) //right corner is at bot
149    {
150      cornerBot = botVertex;
151      cornerRightEnd = rightEndIndex;
152      cornerLeftDownStart = leftEndIndex+1; //no left
153    }
154  else //right corner is on the left chain
155    {
156      cornerBot = botVertex;
157      cornerRightEnd = rightEndIndex;
158      cornerLeftDownStart = down_rightCornerIndex;
159    }
160
161  //sample
162  if(midIndex2 >= 0) //there is a trm point between grid lines
163    {
164
165      sampleRightSingleTrimEdgeRegionGen(cornerTop, rightChain->getVertex(midIndex1),
166					 rightChain,
167					 cornerRightStart,
168					 midIndex1-1,
169					 rightGridChain,
170					 gridIndex1,
171					 gridMidIndex1,
172					 leftChain,
173					 leftStartIndex,
174					 cornerLeftUpEnd,
175					 0, //no left down section,
176					 -1,
177					 pStream);
178
179      sampleRightSingleTrimEdgeRegionGen(rightChain->getVertex(midIndex2),
180					 cornerBot,
181					 rightChain,
182					 midIndex2+1,
183					 cornerRightEnd,
184					 rightGridChain,
185					 gridMidIndex2,
186					 gridIndex2,
187					 leftChain,
188					 0, //no left up section
189					 -1,
190					 cornerLeftDownStart,
191					 leftEndIndex,
192					 pStream);
193
194      sampleRightStripRecF(rightChain,
195			   midIndex1,
196			   midIndex2,
197			   rightGridChain,
198			   gridMidIndex1,
199			   gridMidIndex2,
200			   pStream);
201
202    }
203  else
204    {
205      sampleRightSingleTrimEdgeRegionGen(cornerTop, cornerBot,
206					 rightChain,
207					 cornerRightStart,
208					 cornerRightEnd,
209					 rightGridChain,
210					 gridIndex1,
211					 gridIndex2,
212					 leftChain,
213					 leftStartIndex,
214					 cornerLeftUpEnd,
215					 cornerLeftDownStart,
216					 leftEndIndex,
217					 pStream);
218    }
219}
220
221void sampleRightSingleTrimEdgeRegionGen(Real topVertex[2], Real botVertex[2],
222					 vertexArray* rightChain,
223					 Int rightStart,
224					 Int rightEnd,
225					 gridBoundaryChain* gridChain,
226					 Int gridBeginIndex,
227					 Int gridEndIndex,
228					 vertexArray* leftChain,
229					 Int leftUpBegin,
230					 Int leftUpEnd,
231					 Int leftDownBegin,
232					 Int leftDownEnd,
233					 primStream* pStream)
234{
235  Int i,k;
236   /*creat an array to store all the up and down secments of the left chain,
237   *and the right end grid points
238   *
239   *although vertex array is a dynamic array, but to gain efficiency,
240   *it is better to initiliza the exact array size
241   */
242  vertexArray vArray(gridEndIndex-gridBeginIndex+1 +
243		     max(0,leftUpEnd - leftUpBegin+1)+
244		     max(0,leftDownEnd - leftDownBegin+1));
245  //append the vertices on the up section of the left chain
246  for(i=leftUpBegin; i<= leftUpEnd; i++)
247    vArray.appendVertex(leftChain->getVertex(i));
248
249  //append the vertices of the right extremal grid points,
250  //and at the same time, perform triangulation for the stair cases
251  vArray.appendVertex(gridChain->get_vertex(gridBeginIndex));
252
253  for(k=1, i=gridBeginIndex+1; i<= gridEndIndex; i++, k++)
254    {
255      vArray.appendVertex(gridChain->get_vertex(i));
256
257      //output the fan of the grid points of the (i)th and (i-1)th grid line.
258      gridChain->rightEndFan(i, pStream);
259    }
260
261  //append all the vertices on the down section of the left chain
262  for(i=leftDownBegin; i<= leftDownEnd; i++)
263    vArray.appendVertex(leftChain->getVertex(i));
264  monoTriangulationRecGen(topVertex, botVertex,
265			  &vArray, 0, vArray.getNumElements()-1,
266			  rightChain, rightStart, rightEnd,
267			  pStream);
268}
269
270void sampleRightSingleTrimEdgeRegion(Real upperVert[2], Real lowerVert[2],
271				     gridBoundaryChain* gridChain,
272				     Int beginIndex,
273				     Int endIndex,
274				     primStream* pStream)
275{
276  Int i,k;
277  vertexArray vArray(endIndex-beginIndex+1);
278  vArray.appendVertex(gridChain->get_vertex(beginIndex));
279  for(k=1, i=beginIndex+1; i<= endIndex; i++, k++)
280    {
281      vArray.appendVertex(gridChain->get_vertex(i));
282      //output the fan of the grid points of the (i)_th and i-1th gridLine
283      gridChain->rightEndFan(i, pStream);
284    }
285  monoTriangulation2(upperVert, lowerVert, &vArray, 0, endIndex-beginIndex,
286		     1, //increase chain (to the left)
287		     pStream);
288}
289
290
291/*the gridlines from rightGridChainStartIndex to
292 *rightGridChainEndIndex are assumed to form a
293 *connected componenet
294 *the trm vertex of topRightIndex is assumed to be below
295 *or equal the first gridLine, and the trm vertex of
296 *botRightIndex is assumed to be above or equal the last gridline
297 **there could be multipe trm vertices equal to the last gridline, but
298 **only one could be equal to top gridline. shape: ____| (recall that
299 **for left chain recF, we allow shape: |----
300 *if botRightIndex<topRightIndex, then no connected componenet exists, and
301 *no triangles are generated.
302 *Othewise, botRightIndex>= topRightIndex, there is at least one triangles to
303 *output
304 */
305void sampleRightStripRecF(vertexArray* rightChain,
306		     Int topRightIndex,
307		     Int botRightIndex,
308		     gridBoundaryChain* rightGridChain,
309		     Int rightGridChainStartIndex,
310		     Int rightGridChainEndIndex,
311		     primStream* pStream
312		     )
313{
314
315  //sstop conditionL: if topRightIndex > botRightIndex, then stop
316  if(topRightIndex > botRightIndex)
317    return;
318
319  //if there is only one grid line, return
320  if(rightGridChainStartIndex >= rightGridChainEndIndex)
321    return;
322
323
324  assert(rightChain->getVertex(topRightIndex)[1] <= rightGridChain->get_v_value(rightGridChainStartIndex) &&
325	 rightChain->getVertex(botRightIndex)[1] >= rightGridChain->get_v_value(rightGridChainEndIndex));
326
327  //firstfind the first trim vertex which is strictly below the second top
328  //grid line: index1.
329  Real secondGridChainV = rightGridChain->get_v_value(rightGridChainStartIndex+1);
330  Int index1 = topRightIndex;
331  while(rightChain->getVertex(index1)[1] >= secondGridChainV){
332    index1++;
333    if(index1 >  botRightIndex)
334      break;
335  }
336  //now rightChain->getVertex(index1-1)[1] >= secondGridChainV and
337  //rightChain->getVertex(index1)[1] < secondGridChainV and
338  //we should include index1-1 to perform a gridStep
339    index1--;
340
341  //now we have rightChain->getVertex(index1)[1] >= secondGridChainV, and
342  //rightChain->getVertex(index1+1)[1] < secondGridChainV
343  sampleRightOneGridStep(rightChain, topRightIndex, index1, rightGridChain, rightGridChainStartIndex, pStream);
344
345  //if rightChain->getVertex(index1)[1] ==secondGridChainV then we can
346  //recurvesively to the rest
347  if(rightChain->getVertex(index1)[1] == secondGridChainV)
348    {
349
350
351      sampleRightStripRecF(rightChain, index1, botRightIndex, rightGridChain, rightGridChainStartIndex+1, rightGridChainEndIndex, pStream);
352    }
353  else if(index1 < botRightIndex)
354    {
355      //otherwise, we have rightChain->getVertex(index1)[1] > secondV
356      //let the next trim vertex be nextTrimVertex, (which should be strictly
357      //below the second grid line). Find the last grid line index2 which is STRICTLY ABOVE
358      //nextTrimVertex.
359      //sample one trm edge region.
360      Real *uppervert, *lowervert;
361      uppervert = rightChain->getVertex(index1);
362      lowervert = rightChain->getVertex(index1+1); //okay since index1<botRightindex
363      Int index2 = rightGridChainStartIndex+1;
364      while(rightGridChain->get_v_value(index2) > lowervert[1])
365	{
366	  index2++;
367	  if(index2 > rightGridChainEndIndex)
368	    break;
369	}
370      index2--;
371
372      sampleRightSingleTrimEdgeRegion(uppervert, lowervert, rightGridChain, rightGridChainStartIndex+1, index2, pStream);
373
374      //recursion
375      sampleRightStripRecF(rightChain, index1+1, botRightIndex, rightGridChain, index2, rightGridChainEndIndex, pStream);
376    }
377}
378
379//the degenerate case of sampleRightOneGridStep
380void sampleRightOneGridStepNoMiddle(vertexArray* rightChain,
381				    Int beginRightIndex,
382				    Int endRightIndex,
383				    gridBoundaryChain* rightGridChain,
384				    Int rightGridChainStartIndex,
385				    primStream* pStream)
386{
387  /*since there is no middle, there is at most one point which is on the
388   *second grid line, there could be multiple points on the first (top)
389   *grid line.
390   */
391  rightGridChain->rightEndFan(rightGridChainStartIndex+1, pStream);
392  monoTriangulation2(rightGridChain->get_vertex(rightGridChainStartIndex),
393		     rightGridChain->get_vertex(rightGridChainStartIndex+1),
394		     rightChain,
395		     beginRightIndex,
396		     endRightIndex,
397		     0, //decrease chain
398		     pStream);
399}
400
401//sampling the right area in between two grid lines
402//shape: _________|
403void sampleRightOneGridStep(vertexArray* rightChain,
404			    Int beginRightIndex,
405			    Int endRightIndex,
406			    gridBoundaryChain* rightGridChain,
407			    Int rightGridChainStartIndex,
408			    primStream* pStream)
409{
410  if(checkMiddle(rightChain, beginRightIndex, endRightIndex,
411		 rightGridChain->get_v_value(rightGridChainStartIndex),
412		 rightGridChain->get_v_value(rightGridChainStartIndex+1))<0)
413    {
414      sampleRightOneGridStepNoMiddle(rightChain, beginRightIndex, endRightIndex, rightGridChain, rightGridChainStartIndex, pStream);
415      return;
416    }
417
418  //copy into a polygn
419  {
420    directedLine* poly = NULL;
421    sampledLine* sline;
422    directedLine* dline;
423    gridWrap* grid = rightGridChain->getGrid();
424    float vert1[2];
425    float vert2[2];
426    Int i;
427
428    Int innerInd = rightGridChain->getInnerIndex(rightGridChainStartIndex+1);
429    Int upperInd = rightGridChain->getUlineIndex(rightGridChainStartIndex);
430    Int lowerInd = rightGridChain->getUlineIndex(rightGridChainStartIndex+1);
431    Real upperV = rightGridChain->get_v_value(rightGridChainStartIndex);
432    Real lowerV = rightGridChain->get_v_value(rightGridChainStartIndex+1);
433
434    //the upper gridline
435    vert1[1]=vert2[1]=upperV;
436    for(i=upperInd;
437	i>innerInd;
438	i--)
439      {
440	vert1[0]=grid->get_u_value(i);
441	vert2[0]=grid->get_u_value(i-1);
442	sline = new sampledLine(vert1, vert2);
443	dline = new directedLine(INCREASING, sline);
444	if(poly == NULL)
445	  poly = dline;
446	else
447	  poly->insert(dline);
448      }
449
450    //the vertical grid line segment
451    vert1[0]=vert2[0] = grid->get_u_value(innerInd);
452    vert1[1]=upperV;
453    vert2[1]=lowerV;
454    sline=new sampledLine(vert1, vert2);
455    dline=new directedLine(INCREASING, sline);
456    if(poly == NULL)
457      poly = dline;
458    else
459      poly->insert(dline);
460
461    //the lower grid line
462    vert1[1]=vert2[1]=lowerV;
463    for(i=innerInd; i<lowerInd; i++)
464      {
465	vert1[0] = grid->get_u_value(i);
466	vert2[0] = grid->get_u_value(i+1);
467	sline = new sampledLine(vert1, vert2);
468	dline = new directedLine(INCREASING, sline);
469	poly->insert(dline);
470      }
471
472    //the edge connecting lower grid to right chain
473    vert1[0]=grid->get_u_value(lowerInd);
474    sline = new sampledLine(vert1, rightChain->getVertex(endRightIndex));
475    dline = new directedLine(INCREASING, sline);
476    poly->insert(dline);
477
478
479    //the right Chain
480    for(i=endRightIndex; i>beginRightIndex; i--)
481      {
482	sline = new sampledLine(rightChain->getVertex(i), rightChain->getVertex(i-1));
483	dline = new directedLine(INCREASING, sline);
484	poly->insert(dline);
485      }
486
487    //the edge connecting right chain with upper grid
488    vert2[1]=upperV;
489    vert2[0]=grid->get_u_value(upperInd);
490    sline = new sampledLine(rightChain->getVertex(beginRightIndex), vert2);
491    dline = new directedLine(INCREASING, sline);
492    poly->insert(dline);
493    monoTriangulationOpt(poly, pStream);
494    //clean up
495    poly->deleteSinglePolygonWithSline();
496
497    return;
498  }
499
500  //this following code cannot be reached, but leave it for debuggig purpose.
501  Int i;
502  //find the maximal U-monotone chain of beginRightIndex, beginRightIndex+1,...
503  i=beginRightIndex;
504  Real prevU = rightChain->getVertex(i)[0];
505  for(i=beginRightIndex+1; i<= endRightIndex; i++){
506    Real thisU = rightChain->getVertex(i)[0];
507    if(thisU < prevU)
508      prevU = thisU;
509    else
510      break;
511  }
512  //from beginRightIndex to i-1 is strictly U-monotne
513  //if(i-1==beginRightIndex and the vertex of rightchain is on the first
514  //gridline, then we should use 2 vertices  on the right chain. Of we only
515  //use one (begin), we would output degenrate triangles.
516  if(i-1 == beginRightIndex && rightChain->getVertex(beginRightIndex)[1] == rightGridChain->get_v_value(rightGridChainStartIndex))
517    i++;
518
519  Int j = endRightIndex -1;
520  if(rightGridChain->getInnerIndex(rightGridChainStartIndex+1) < rightGridChain->getUlineIndex(rightGridChainStartIndex+1))
521    {
522      j = rightChain->findDecreaseChainFromEnd(i-1/*beginRightIndex*/, endRightIndex);
523      Int temp = endRightIndex;
524      //now from j+1 to end is strictly U-monotone.
525      //if j+1 is on the last grid line, then we wat to skip to the vertex
526      //whcih is strictly above the second grid line. This vertex must exist
527      //since there is a middle vertex
528      if(j+1 == endRightIndex)
529	{
530	  while(rightChain->getVertex(j+1)[1] == rightGridChain->get_v_value(rightGridChainStartIndex+1))
531	    j--;
532
533	  monoTriangulation2(rightChain->getVertex(j+1),
534			     rightGridChain->get_vertex(rightGridChainStartIndex+1),
535			     rightChain,
536			     j+2,
537			     endRightIndex,
538			     0, //a decrease chain
539			     pStream);
540
541	  temp = j+1;
542	}
543
544      stripOfFanRight(rightChain, temp, j+1, rightGridChain->getGrid(),
545		      rightGridChain->getVlineIndex(rightGridChainStartIndex+1),
546		      rightGridChain->getInnerIndex(rightGridChainStartIndex+1),
547		      rightGridChain->getUlineIndex(rightGridChainStartIndex+1),
548		      pStream,
549		      0 //the grid line is below the trim line
550		      );
551
552    }
553
554
555  stripOfFanRight(rightChain, i-1, beginRightIndex, rightGridChain->getGrid(),
556		  rightGridChain->getVlineIndex(rightGridChainStartIndex),
557		  rightGridChain->getInnerIndex(rightGridChainStartIndex+1),
558		  rightGridChain->getUlineIndex(rightGridChainStartIndex),
559		  pStream,
560		  1 //the grid line is above the trm lines
561		  );
562
563  //monotone triangulate the remaining rightchain together with the
564  //two vertices on the two grid v-lines
565  Real vert[2][2];
566  vert[0][0] = vert[1][0] = rightGridChain->getInner_u_value(rightGridChainStartIndex+1);
567  vert[0][1] = rightGridChain->get_v_value(rightGridChainStartIndex);
568  vert[1][1] = rightGridChain->get_v_value(rightGridChainStartIndex+1);
569
570  monoTriangulation2(&vert[0][0],
571		     &vert[1][0],
572		     rightChain,
573		     i-1,
574		     j+1,
575		     0, ///a decreae chain
576		     pStream);
577}
578
579#endif
580
581void stripOfFanRight(vertexArray* rightChain,
582		    Int largeIndex,
583		    Int smallIndex,
584		    gridWrap* grid,
585		    Int vlineIndex,
586		    Int ulineSmallIndex,
587		    Int ulineLargeIndex,
588		    primStream* pStream,
589		    Int gridLineUp /*1 if the grid line is above the trim lines*/
590		     )
591{
592  assert(largeIndex >= smallIndex);
593
594  Real grid_v_value;
595  grid_v_value = grid->get_v_value(vlineIndex);
596
597  Real2* trimVerts=(Real2*) malloc(sizeof(Real2)* (largeIndex-smallIndex+1));
598  assert(trimVerts);
599
600
601  Real2* gridVerts=(Real2*) malloc(sizeof(Real2)* (ulineLargeIndex-ulineSmallIndex+1));
602  assert(gridVerts);
603
604  Int k,i;
605  if(! gridLineUp) /*trim line is above grid line, so trim vertices are going right when index increases*/
606    for(k=0, i=smallIndex; i<=largeIndex; i++, k++)
607      {
608      trimVerts[k][0] = rightChain->getVertex(i)[0];
609      trimVerts[k][1] = rightChain->getVertex(i)[1];
610    }
611  else
612    for(k=0, i=largeIndex; i>=smallIndex; i--, k++)
613      {
614	trimVerts[k][0] = rightChain->getVertex(i)[0];
615	trimVerts[k][1] = rightChain->getVertex(i)[1];
616      }
617
618  for(k=0, i=ulineSmallIndex; i<= ulineLargeIndex; i++, k++)
619    {
620      gridVerts[k][0] = grid->get_u_value(i);
621      gridVerts[k][1] = grid_v_value;
622    }
623
624  if(gridLineUp)
625    triangulateXYMono(
626		      ulineLargeIndex-ulineSmallIndex+1, gridVerts,
627		      largeIndex-smallIndex+1, trimVerts,
628		      pStream);
629  else
630    triangulateXYMono(largeIndex-smallIndex+1, trimVerts,
631		      ulineLargeIndex-ulineSmallIndex+1, gridVerts,
632		      pStream);
633  free(trimVerts);
634  free(gridVerts);
635}
636
637
638
639
640
641
642
643
644
645