Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / glu / sgi / libnurbs / internals / slicer.cc
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  * slicer.c++
37  *
38  */
39
40 #include <stdlib.h>
41 #include <stdio.h>
42 #include <math.h>
43 #include "glimports.h"
44 #include "mystdio.h"
45 #include "myassert.h"
46 #include "bufpool.h"
47 #include "slicer.h"
48 #include "backend.h"
49 #include "arc.h"
50 #include "gridtrimvertex.h"
51 #include "simplemath.h"
52 #include "trimvertex.h"
53 #include "varray.h"
54
55 #include "polyUtil.h" //for area()
56
57 //static int count=0;
58
59 /*USE_OPTTT is initiated in trimvertex.h*/
60
61 #ifdef USE_OPTTT
62         #include <GL/gl.h>
63 #endif
64
65 //#define USE_READ_FLAG //whether to use new or old tesselator
66                           //if defined, it reads "flagFile", 
67                           // if the number is 1, then use new tess
68                           // otherwise, use the old tess.
69                          //if not defined, then use new tess.
70 #ifdef USE_READ_FLAG
71 static Int read_flag(char* name);
72 Int newtess_flag = read_flag("flagFile");
73 #endif
74
75 //#define COUNT_TRIANGLES
76 #ifdef COUNT_TRIANGLES
77 Int num_triangles = 0;
78 Int num_quads = 0;
79 #endif
80
81 #define max(a,b) ((a>b)? a:b)
82 #define ZERO 0.00001 /*determing whether a loop is a rectngle or not*/
83 #define equalRect(a,b) ((glu_abs(a-b) <= ZERO)? 1:0) //only used in tessellating a rectangle
84
85 #if 0 // UNUSED
86 static Int is_Convex(Arc_ptr loop)
87 {
88   if(area(loop->tail(), loop->head(), loop->next->head()) <0 )
89     return 0;
90   for(Arc_ptr jarc = loop->next; jarc != loop; jarc = jarc->next)
91     {
92       if(area(jarc->tail(), jarc->head(), jarc->next->head()) < 0)
93         return 0;
94     }
95   return 1;
96 }
97 #endif
98
99 /******triangulate a monotone polygon**************/
100 #include "monoTriangulation.h"
101 #if 0 // UNUSED
102 static int is_U_monotone(Arc_ptr loop)
103 {
104   int n_changes=0;
105   int prev_sign;
106   int cur_sign;
107   Arc_ptr temp;
108
109   cur_sign = compV2InX(loop->head(), loop->tail());
110
111   n_changes  = (compV2InX(loop->prev->head(), loop->prev->tail())
112                 != cur_sign);
113
114   for(temp=loop->next; temp != loop; temp = temp->next)
115     {
116       prev_sign = cur_sign;
117       cur_sign = compV2InX(temp->head(), temp->tail());
118       if(cur_sign != prev_sign)
119        {
120 #ifdef DEBUG
121          printf("***change signe\n");
122 #endif
123          n_changes++;
124        }
125     }
126   if(n_changes == 2) return 1;
127   else
128     return 0;
129 }
130 #endif
131
132 inline int compInY(REAL a[2], REAL b[2])
133 {
134   if(a[1] < b[1])
135     return -1;
136   else if (a[1] > b[1])
137     return 1;
138   else if(a[0] > b[0])
139     return 1;
140   else return -1;
141 }
142
143 void monoTriangulationLoop(Arc_ptr loop, Backend& backend, primStream* pStream)
144 {
145   int i;
146   //find the top, bottom, increasing and decreasing chain
147   //then call monoTrianulation
148   Arc_ptr jarc, temp;
149   Arc_ptr top;
150   Arc_ptr bot;
151   top = bot = loop;
152   if(compInY(loop->tail(), loop->prev->tail()) < 0)
153     {
154       //first find bot
155       for(temp = loop->next; temp != loop; temp = temp->next)
156         {
157           if(compInY(temp->tail(), temp->prev->tail()) > 0)
158             break;
159         }
160       bot = temp->prev;
161       //then find top
162       for(temp=loop->prev; temp != loop; temp = temp->prev)
163         {
164           if(compInY(temp->tail(), temp->prev->tail()) > 0)
165             break;
166         }
167       top = temp;
168     }
169   else //loop > loop->prev
170     {
171       for(temp=loop->next; temp != loop; temp = temp->next)
172         {
173           if(compInY(temp->tail(), temp->prev->tail()) < 0)
174             break;
175         }
176       top = temp->prev;
177       for(temp=loop->prev; temp != loop; temp = temp->prev)
178         {
179           if(compInY(temp->tail(), temp->prev->tail()) < 0)
180             break;
181         }
182       bot = temp;
183     }
184   //creat increase and decrease chains
185   vertexArray inc_chain(50); //this is a dynamci array
186   for(i=1; i<=top->pwlArc->npts-2; i++) 
187     {
188       //the first vertex is the top which doesn't below to inc_chain
189       inc_chain.appendVertex(top->pwlArc->pts[i].param);
190     }
191   for(jarc=top->next; jarc != bot; jarc = jarc->next)
192     {
193       for(i=0; i<=jarc->pwlArc->npts-2; i++)
194         {
195           inc_chain.appendVertex(jarc->pwlArc->pts[i].param);
196         }
197       
198     }
199   vertexArray dec_chain(50);
200   for(jarc = top->prev; jarc != bot; jarc = jarc->prev)
201     {
202       for(i=jarc->pwlArc->npts-2; i>=0; i--)
203         {
204           dec_chain.appendVertex(jarc->pwlArc->pts[i].param);
205         }
206     }
207   for(i=bot->pwlArc->npts-2; i>=1; i--)
208     {
209       dec_chain.appendVertex(jarc->pwlArc->pts[i].param);
210     }     
211
212   monoTriangulationRec(top->tail(), bot->tail(), &inc_chain, 0,
213                        &dec_chain, 0, &backend);
214
215 }
216
217 /********tesselate a rectanlge (OPTIMIZATION**************/
218 static void triangulateRectGen(Arc_ptr loop, int n_ulines, int n_vlines, Backend& backend);
219
220 static Int is_rect(Arc_ptr loop)
221 {
222   Int nlines =1;
223   for(Arc_ptr jarc = loop->next; jarc != loop; jarc = jarc->next)
224     {
225       nlines++;
226       if(nlines == 5)
227         break;
228     }
229   if(nlines != 4)
230     return 0;
231
232
233 /*
234 printf("here1\n");
235 printf("loop->tail=(%f,%f)\n", loop->tail()[0], loop->tail()[1]);
236 printf("loop->head=(%f,%f)\n", loop->head()[0], loop->head()[1]);
237 printf("loop->next->tail=(%f,%f)\n", loop->next->tail()[0], loop->next->tail()[1]);
238 printf("loop->next->head=(%f,%f)\n", loop->next->head()[0], loop->next->head()[1]);
239 if(fglu_abs(loop->tail()[0] - loop->head()[0])<0.000001)
240         printf("equal 1\n");
241 if(loop->next->tail()[1] == loop->next->head()[1])
242         printf("equal 2\n");
243 */
244
245   if( (glu_abs(loop->tail()[0] - loop->head()[0])<=ZERO) && 
246       (glu_abs(loop->next->tail()[1] - loop->next->head()[1])<=ZERO) &&
247       (glu_abs(loop->prev->tail()[1] - loop->prev->head()[1])<=ZERO) &&
248       (glu_abs(loop->prev->prev->tail()[0] - loop->prev->prev->head()[0])<=ZERO)
249      )
250     return 1;
251   else if
252     ( (glu_abs(loop->tail()[1] - loop->head()[1]) <= ZERO) && 
253       (glu_abs(loop->next->tail()[0] - loop->next->head()[0]) <= ZERO) &&
254       (glu_abs(loop->prev->tail()[0] - loop->prev->head()[0]) <= ZERO) &&
255       (glu_abs(loop->prev->prev->tail()[1] - loop->prev->prev->head()[1]) <= ZERO)
256      )
257       return 1;
258   else
259     return 0;
260 }
261
262
263 //a line with the same u for opt
264 #ifdef USE_OPTTT
265 static void evalLineNOGE_BU(TrimVertex *verts, int n, Backend& backend)
266 {
267   int i;
268   backend.preEvaluateBU(verts[0].param[0]);
269   for(i=0; i<n; i++)
270     backend.tmeshvertNOGE_BU(&verts[i]);
271 }
272 #endif
273
274 //a line with the same v for opt
275 #ifdef USE_OPTTT
276 static void evalLineNOGE_BV(TrimVertex *verts, int n, Backend& backend)
277 {
278   int i;
279   backend.preEvaluateBV(verts[0].param[1]);
280
281   for(i=0; i<n; i++)
282     backend.tmeshvertNOGE_BV(&verts[i]);
283 }
284 #endif
285
286 #ifdef USE_OPTTT
287 static void evalLineNOGE(TrimVertex *verts, int n, Backend& backend)
288 {
289
290   if(verts[0].param[0] == verts[n-1].param[0]) //all u;s are equal
291     evalLineNOGE_BU(verts, n, backend);
292   else if(verts[0].param[1] == verts[n-1].param[1]) //all v's are equal
293     evalLineNOGE_BV(verts, n, backend);
294   else
295     {
296       int i;
297       for(i=0; i<n; i++)
298         backend.tmeshvertNOGE(&verts[i]);
299     }
300 }
301 #endif
302
303 inline void  OPT_OUTVERT(TrimVertex& vv, Backend& backend) 
304 {
305
306 #ifdef USE_OPTTT
307   glNormal3fv(vv.cache_normal);                         
308   glVertex3fv(vv.cache_point);
309 #else
310
311   backend.tmeshvert(&vv);
312
313 #endif
314
315 }
316
317 static void triangulateRectAux(PwlArc* top, PwlArc* bot, PwlArc* left, PwlArc* right, Backend& backend);
318
319 static void triangulateRect(Arc_ptr loop, Backend& backend, int TB_or_LR, int ulinear, int vlinear)
320 {
321   //we know the loop is a rectangle, but not sure which is top
322   Arc_ptr top, bot, left, right;
323   if(loop->tail()[1] == loop->head()[1])
324     {
325       if(loop->tail()[1] > loop->prev->prev->tail()[1])
326         {
327
328         top = loop;
329         }
330       else{
331
332         top = loop->prev->prev;
333         }
334     }
335   else 
336     {
337       if(loop->tail()[0] > loop->prev->prev->tail()[0])
338         {
339           //loop is the right arc
340
341           top = loop->next;
342         }
343       else
344         {
345
346           top = loop->prev;
347         }
348     }
349   left = top->next;
350   bot  = left->next;
351   right= bot->next;
352
353   //if u, v are both nonlinear, then if the
354   //boundary is tessellated dense, we also
355   //sample the inside to get a better tesslletant.
356   if( (!ulinear) && (!vlinear))
357     {
358       int nu = top->pwlArc->npts;
359       if(nu < bot->pwlArc->npts)
360         nu = bot->pwlArc->npts;
361       int nv = left->pwlArc->npts;
362       if(nv < right->pwlArc->npts)
363         nv = right->pwlArc->npts;
364 /*
365       if(nu > 2 && nv > 2)
366         {
367           triangulateRectGen(top, nu-2,  nv-2, backend);
368           return;
369         }
370 */
371     }
372
373   if(TB_or_LR == 1)
374     triangulateRectAux(top->pwlArc, bot->pwlArc, left->pwlArc, right->pwlArc, backend);
375   else if(TB_or_LR == -1)
376     triangulateRectAux(left->pwlArc, right->pwlArc, bot->pwlArc, top->pwlArc, backend);    
377   else
378     {
379       Int maxPointsTB = top->pwlArc->npts + bot->pwlArc->npts;
380       Int maxPointsLR = left->pwlArc->npts + right->pwlArc->npts;
381       
382       if(maxPointsTB < maxPointsLR)
383         triangulateRectAux(left->pwlArc, right->pwlArc, bot->pwlArc, top->pwlArc, backend);    
384       else
385         triangulateRectAux(top->pwlArc, bot->pwlArc, left->pwlArc, right->pwlArc, backend);
386     }
387 }
388
389 static void triangulateRectAux(PwlArc* top, PwlArc* bot, PwlArc* left, PwlArc* right, Backend& backend)
390 { //if(maxPointsTB >= maxPointsLR)
391     {
392
393       Int d, topd_left, topd_right, botd_left, botd_right, i,j;
394       d = left->npts /2;
395
396 #ifdef USE_OPTTT
397       evalLineNOGE(top->pts, top->npts, backend);
398       evalLineNOGE(bot->pts, bot->npts, backend);
399       evalLineNOGE(left->pts, left->npts, backend);
400       evalLineNOGE(right->pts, right->npts, backend);
401 #endif
402
403       if(top->npts == 2) {
404         backend.bgntfan();
405         OPT_OUTVERT(top->pts[0], backend);//the root
406         for(i=0; i<left->npts; i++){
407           OPT_OUTVERT(left->pts[i], backend);
408         }
409         for(i=1; i<= bot->npts-2; i++){
410           OPT_OUTVERT(bot->pts[i], backend);
411         }
412         backend.endtfan();
413         
414         backend.bgntfan();
415         OPT_OUTVERT(bot->pts[bot->npts-2], backend);
416         for(i=0; i<right->npts; i++){
417           OPT_OUTVERT(right->pts[i], backend);
418         }
419         backend.endtfan();
420       }
421       else if(bot->npts == 2) {
422         backend.bgntfan();
423         OPT_OUTVERT(bot->pts[0], backend);//the root
424         for(i=0; i<right->npts; i++){
425           OPT_OUTVERT(right->pts[i], backend);
426         }
427         for(i=1; i<= top->npts-2; i++){
428           OPT_OUTVERT(top->pts[i], backend);
429         }
430         backend.endtfan();
431         
432         backend.bgntfan();
433         OPT_OUTVERT(top->pts[top->npts-2], backend);
434         for(i=0; i<left->npts; i++){
435           OPT_OUTVERT(left->pts[i], backend);
436         }
437         backend.endtfan();
438       }
439       else { //both top and bot have >=3 points
440         
441         backend.bgntfan();
442         
443         OPT_OUTVERT(top->pts[top->npts-2], backend);
444         
445         for(i=0; i<=d; i++)
446           {
447             OPT_OUTVERT(left->pts[i], backend);   
448           }
449         backend.endtfan();
450         
451         backend.bgntfan();
452         
453         OPT_OUTVERT(bot->pts[1], backend);
454         
455         OPT_OUTVERT(top->pts[top->npts-2], backend);
456         
457         for(i=d; i< left->npts; i++)
458           {      
459             OPT_OUTVERT(left->pts[i], backend);      
460           }
461         backend.endtfan();
462
463         d = right->npts/2;
464         //output only when d<right->npts-1 and
465         //
466         if(d<right->npts-1)
467           {     
468             backend.bgntfan();
469             //      backend.tmeshvert(& top->pts[1]);
470             OPT_OUTVERT(top->pts[1], backend);
471             for(i=d; i< right->npts; i++)
472               {
473                 //        backend.tmeshvert(& right->pts[i]);
474                 
475                 OPT_OUTVERT(right->pts[i], backend);
476                 
477               }
478             backend.endtfan();
479           }
480         
481         backend.bgntfan();
482         //      backend.tmeshvert(& bot->pts[bot->npts-2]);
483         OPT_OUTVERT( bot->pts[bot->npts-2], backend);
484         for(i=0; i<=d; i++)
485           {
486             //    backend.tmeshvert(& right->pts[i]);
487             OPT_OUTVERT(right->pts[i], backend);
488             
489           }
490         
491         //      backend.tmeshvert(& top->pts[1]);
492         OPT_OUTVERT(top->pts[1], backend);      
493         
494         backend.endtfan();
495
496
497         topd_left = top->npts-2;
498         topd_right = 1; //topd_left>= topd_right
499
500         botd_left = 1;
501         botd_right = bot->npts-2; //botd_left<= bot_dright
502
503         
504         if(top->npts < bot->npts)
505           {
506             int delta=bot->npts - top->npts;
507             int u = delta/2;
508             botd_left = 1+ u;
509             botd_right = bot->npts-2-( delta-u);            
510         
511             if(botd_left >1)
512               {
513                 backend.bgntfan();
514                 //        backend.tmeshvert(& top->pts[top->npts-2]);
515                 OPT_OUTVERT(top->pts[top->npts-2], backend);
516                 for(i=1; i<= botd_left; i++)
517                   {
518                     //        backend.tmeshvert(& bot->pts[i]);
519                     OPT_OUTVERT(bot->pts[i] , backend);
520                   }
521                 backend.endtfan();
522               }
523             if(botd_right < bot->npts-2)
524               {
525                 backend.bgntfan();
526                 OPT_OUTVERT(top->pts[1], backend);
527                 for(i=botd_right; i<= bot->npts-2; i++)
528                   OPT_OUTVERT(bot->pts[i], backend);
529                 backend.endtfan();
530               }
531           }
532         else if(top->npts> bot->npts)
533           {
534             int delta=top->npts-bot->npts;
535             int u = delta/2;
536             topd_left = top->npts-2 - u;
537             topd_right = 1+delta-u;
538             
539             if(topd_left < top->npts-2)
540               {
541                 backend.bgntfan();
542                 //        backend.tmeshvert(& bot->pts[1]);
543                 OPT_OUTVERT(bot->pts[1], backend);
544                 for(i=topd_left; i<= top->npts-2; i++)
545                   {
546                     //        backend.tmeshvert(& top->pts[i]);
547                     OPT_OUTVERT(top->pts[i], backend);
548                   }
549                 backend.endtfan();
550               }
551             if(topd_right > 1)
552               {
553                 backend.bgntfan();
554                 OPT_OUTVERT(bot->pts[bot->npts-2], backend);
555                 for(i=1; i<= topd_right; i++)
556                   OPT_OUTVERT(top->pts[i], backend);
557                 backend.endtfan();
558               }
559           }
560         
561         if(topd_left <= topd_right) 
562           return;
563
564         backend.bgnqstrip();
565         for(j=botd_left, i=topd_left; i>=topd_right; i--,j++)
566           {
567             //    backend.tmeshvert(& top->pts[i]);
568             //    backend.tmeshvert(& bot->pts[j]);
569             OPT_OUTVERT(top->pts[i], backend);
570             OPT_OUTVERT(bot->pts[j], backend);
571           }
572         backend.endqstrip();
573         
574       }
575     }
576 }
577
578   
579 static void triangulateRectCenter(int n_ulines, REAL* u_val, 
580                                   int n_vlines, REAL* v_val,
581                                   Backend& backend)
582 {
583
584   // XXX this code was patched by Diego Santa Cruz <Diego.SantaCruz@epfl.ch>
585   // to fix a problem in which glMapGrid2f() was called with bad parameters.
586   // This has beens submitted to SGI but not integrated as of May 1, 2001.
587   if(n_ulines>1 && n_vlines>1) {
588     backend.surfgrid(u_val[0], u_val[n_ulines-1], n_ulines-1, 
589                      v_val[n_vlines-1], v_val[0], n_vlines-1);
590     backend.surfmesh(0,0,n_ulines-1,n_vlines-1);
591   }
592
593   return;
594
595   /*
596   for(i=0; i<n_vlines-1; i++)
597     {
598
599       backend.bgnqstrip();
600       for(j=0; j<n_ulines; j++)
601         {
602           trimVert.param[0] = u_val[j];
603           trimVert.param[1] = v_val[i+1];
604           backend.tmeshvert(& trimVert);          
605
606           trimVert.param[1] = v_val[i];
607           backend.tmeshvert(& trimVert);          
608         }
609       backend.endqstrip();
610
611     }
612     */
613 }
614
615 //it works for top, bot, left ad right, you need ot select correct arguments
616 static void triangulateRectTopGen(Arc_ptr arc, int n_ulines, REAL* u_val, Real v, int dir, int is_u, Backend& backend)
617 {
618
619   if(is_u)
620     {
621       int i,k;
622       REAL* upper_val = (REAL*) malloc(sizeof(REAL) * arc->pwlArc->npts);
623       assert(upper_val);
624       if(dir)
625         {
626           for(k=0,i=arc->pwlArc->npts-1; i>=0; i--,k++)
627             {
628               upper_val[k] = arc->pwlArc->pts[i].param[0];
629             }   
630           backend.evalUStrip(arc->pwlArc->npts, arc->pwlArc->pts[0].param[1],
631                              upper_val,
632                              n_ulines, v, u_val);
633         }
634       else
635         {
636           for(k=0,i=0;  i<arc->pwlArc->npts; i++,k++)
637             {
638               upper_val[k] = arc->pwlArc->pts[i].param[0];
639
640             }             
641
642           backend.evalUStrip(
643                              n_ulines, v, u_val,
644                              arc->pwlArc->npts, arc->pwlArc->pts[0].param[1], upper_val
645                              );  
646         }
647
648       free(upper_val);
649       return;
650     }
651   else //is_v
652     {
653       int i,k;
654       REAL* left_val = (REAL*) malloc(sizeof(REAL) * arc->pwlArc->npts);
655       assert(left_val);   
656       if(dir)
657         {
658           for(k=0,i=arc->pwlArc->npts-1; i>=0; i--,k++)
659             {
660               left_val[k] = arc->pwlArc->pts[i].param[1];
661             }
662           backend.evalVStrip(arc->pwlArc->npts, arc->pwlArc->pts[0].param[0],
663                              left_val,
664                              n_ulines, v, u_val);
665         }
666       else 
667         {
668           for(k=0,i=0;  i<arc->pwlArc->npts; i++,k++)
669             {
670               left_val[k] = arc->pwlArc->pts[i].param[1];
671             }
672            backend.evalVStrip(
673                              n_ulines, v, u_val,
674                              arc->pwlArc->npts, arc->pwlArc->pts[0].param[0], left_val
675                              ); 
676         }
677       free(left_val);
678       return;
679     }
680         
681   //the following is a different version of the above code. If you comment
682   //the above code, the following code will still work. The reason to leave
683   //the folliwng code here is purely for testing purpose.
684   /*
685   int i,j;
686   PwlArc* parc = arc->pwlArc;
687   int d1 = parc->npts-1;
688   int d2 = 0;
689   TrimVertex trimVert;
690   trimVert.nuid = 0;//????
691   REAL* temp_u_val = u_val;
692   if(dir ==0) //have to reverse u_val
693     {
694       temp_u_val = (REAL*) malloc(sizeof(REAL) * n_ulines);
695       assert(temp_u_val);
696       for(i=0; i<n_ulines; i++)
697         temp_u_val[i] = u_val[n_ulines-1-i];
698     }
699   u_val = temp_u_val;
700
701   if(parc->npts > n_ulines)
702     {
703       d1 = n_ulines-1;
704
705       backend.bgntfan();
706       if(is_u){
707         trimVert.param[0] = u_val[0];
708         trimVert.param[1] = v;
709       }
710       else
711         {
712         trimVert.param[1] = u_val[0];
713         trimVert.param[0] = v;
714       }
715           
716       backend.tmeshvert(& trimVert);
717       for(i=d1; i< parc->npts; i++)
718         backend.tmeshvert(& parc->pts[i]);
719       backend.endtfan();
720
721
722     }
723   else if(parc->npts < n_ulines)
724     {
725       d2 = n_ulines-parc->npts;
726
727
728       backend.bgntfan();
729       backend.tmeshvert(& parc->pts[parc->npts-1]);
730       for(i=0; i<= d2; i++)
731         {
732           if(is_u){
733             trimVert.param[0] = u_val[i];
734             trimVert.param[1] = v;
735           }
736           else
737             {
738               trimVert.param[1] = u_val[i];
739               trimVert.param[0] = v;
740             }
741           backend.tmeshvert(&trimVert);
742         }
743       backend.endtfan();
744
745     }
746   if(d1>0){
747
748
749     backend.bgnqstrip();
750     for(i=d1, j=d2; i>=0; i--, j++)
751       {
752         backend.tmeshvert(& parc->pts[i]);
753
754         if(is_u){
755           trimVert.param[0] = u_val[j];
756           trimVert.param[1] = v;
757         }
758         else{
759           trimVert.param[1] = u_val[j];
760           trimVert.param[0] = v;
761         }
762         backend.tmeshvert(&trimVert);
763
764
765         
766       }
767     backend.endqstrip();
768
769
770   }
771   if(dir == 0)  //temp_u_val was mallocated
772     free(temp_u_val);
773  */
774 }
775
776 //n_ulines is the number of ulines inside, and n_vlines is the number of vlines
777 //inside, different from meanings elsewhere!!!
778 static void triangulateRectGen(Arc_ptr loop, int n_ulines, int n_vlines, Backend& backend)
779 {
780
781   int i;
782   //we know the loop is a rectangle, but not sure which is top
783   Arc_ptr top, bot, left, right;
784
785   if(equalRect(loop->tail()[1] ,  loop->head()[1]))
786     {
787
788       if(loop->tail()[1] > loop->prev->prev->tail()[1])
789         {
790
791         top = loop;
792         }
793       else{
794
795         top = loop->prev->prev;
796         }
797     }
798   else 
799     {
800       if(loop->tail()[0] > loop->prev->prev->tail()[0])
801         {
802           //loop is the right arc
803
804           top = loop->next;
805         }
806       else
807         {
808
809           top = loop->prev;
810         }
811     }
812
813   left = top->next;
814   bot  = left->next;
815   right= bot->next;
816
817 #ifdef COUNT_TRIANGLES
818   num_triangles += loop->pwlArc->npts + 
819                  left->pwlArc->npts + 
820                  bot->pwlArc->npts + 
821                   right->pwlArc->npts 
822                       + 2*n_ulines + 2*n_vlines 
823                         -8;
824   num_quads += (n_ulines-1)*(n_vlines-1);
825 #endif
826 /*
827   backend.surfgrid(left->tail()[0], right->tail()[0], n_ulines+1, 
828                    top->tail()[1], bot->tail()[1], n_vlines+1);
829 //  if(n_ulines>1 && n_vlines>1)
830     backend.surfmesh(0,0,n_ulines+1,n_vlines+1);
831 return;
832 */
833   REAL* u_val=(REAL*) malloc(sizeof(REAL)*n_ulines);
834   assert(u_val);
835   REAL* v_val=(REAL*)malloc(sizeof(REAL) * n_vlines);
836   assert(v_val);
837   REAL u_stepsize = (right->tail()[0] - left->tail()[0])/( (REAL) n_ulines+1);
838   REAL v_stepsize = (top->tail()[1] - bot->tail()[1])/( (REAL) n_vlines+1);
839   Real temp=left->tail()[0]+u_stepsize;
840   for(i=0; i<n_ulines; i++)
841     {
842       u_val[i] = temp;
843       temp += u_stepsize;
844     }
845   temp = bot->tail()[1] + v_stepsize;
846   for(i=0; i<n_vlines; i++)
847     {
848       v_val[i] = temp;
849       temp += v_stepsize;
850     }
851
852   triangulateRectTopGen(top, n_ulines, u_val, v_val[n_vlines-1], 1,1, backend);
853   triangulateRectTopGen(bot, n_ulines, u_val, v_val[0], 0, 1, backend);
854   triangulateRectTopGen(left, n_vlines, v_val, u_val[0], 1, 0, backend);
855   triangulateRectTopGen(right, n_vlines, v_val, u_val[n_ulines-1], 0,0, backend);
856
857
858
859
860   //triangulate the center
861   triangulateRectCenter(n_ulines, u_val, n_vlines, v_val, backend);
862
863   free(u_val);
864   free(v_val);
865   
866 }
867
868
869   
870
871 /**********for reading newtess_flag from a file**********/
872 #ifdef USE_READ_FLAG
873 static Int read_flag(char* name)
874 {
875   Int ret;
876   FILE* fp = fopen(name, "r");
877   if(fp == NULL)
878     {
879       fprintf(stderr, "can't open file %s\n", name);
880       exit(1);
881     }
882   fscanf(fp, "%i", &ret);
883   fclose(fp);
884   return ret;
885 }
886 #endif  
887
888 /***********nextgen tess****************/
889 #include "sampleMonoPoly.h"
890 directedLine* arcToDLine(Arc_ptr arc)
891 {
892   int i;
893   Real vert[2];
894   directedLine* ret;
895   sampledLine* sline = new sampledLine(arc->pwlArc->npts);
896   for(i=0; i<arc->pwlArc->npts; i++)
897     {
898       vert[0] = arc->pwlArc->pts[i].param[0];
899       vert[1] = arc->pwlArc->pts[i].param[1];
900       sline->setPoint(i, vert);
901     }
902   ret = new directedLine(INCREASING, sline);
903   return ret;
904 }
905  
906 /*an pwlArc may not be a straight line*/
907 directedLine* arcToMultDLines(directedLine* original, Arc_ptr arc)
908 {
909   directedLine* ret = original;
910   int is_linear = 0;
911   if(arc->pwlArc->npts == 2 )
912     is_linear = 1;
913   else if(area(arc->pwlArc->pts[0].param, arc->pwlArc->pts[1].param, arc->pwlArc->pts[arc->pwlArc->npts-1].param) == 0.0)
914     is_linear = 1;
915   
916   if(is_linear)
917     {
918       directedLine *dline = arcToDLine(arc);
919       if(ret == NULL)
920         ret = dline;
921       else
922         ret->insert(dline);
923       return ret;
924     }
925   else /*not linear*/
926     {
927       for(Int i=0; i<arc->pwlArc->npts-1; i++)
928         {
929           Real vert[2][2];
930           vert[0][0] = arc->pwlArc->pts[i].param[0];
931           vert[0][1] = arc->pwlArc->pts[i].param[1];
932           vert[1][0] = arc->pwlArc->pts[i+1].param[0];
933           vert[1][1] = arc->pwlArc->pts[i+1].param[1];
934           
935           sampledLine *sline = new sampledLine(2, vert);
936           directedLine *dline = new directedLine(INCREASING, sline);
937           if(ret == NULL)
938             ret = dline;
939           else
940             ret->insert(dline);
941         }
942       return ret;
943     }
944 }
945   
946      
947         
948 directedLine* arcLoopToDLineLoop(Arc_ptr loop)
949 {
950   directedLine* ret;
951
952   if(loop == NULL)
953     return NULL;
954   ret = arcToMultDLines(NULL, loop);
955 //ret->printSingle();
956   for(Arc_ptr temp = loop->next; temp != loop; temp = temp->next){
957     ret = arcToMultDLines(ret, temp);
958 //ret->printSingle();
959   }
960
961   return ret;
962 }
963
964 /*
965 void Slicer::evalRBArray(rectBlockArray* rbArray, gridWrap* grid)
966 {
967   TrimVertex *trimVert = (TrimVertex*)malloc(sizeof(TrimVertex));
968   trimVert -> nuid = 0;//????
969
970   Real* u_values = grid->get_u_values();
971   Real* v_values = grid->get_v_values();
972
973   Int i,j,k,l;
974
975   for(l=0; l<rbArray->get_n_elements(); l++)
976     {
977       rectBlock* block = rbArray->get_element(l);
978       for(k=0, i=block->get_upGridLineIndex(); i>block->get_lowGridLineIndex(); i--, k++)
979         {
980
981           backend.bgnqstrip();
982           for(j=block->get_leftIndices()[k+1]; j<= block->get_rightIndices()[k+1]; j++)
983             {
984               trimVert->param[0] = u_values[j];
985               trimVert->param[1] = v_values[i];
986               backend.tmeshvert(trimVert);
987
988               trimVert->param[1] = v_values[i-1];
989               backend.tmeshvert(trimVert);
990
991             }
992           backend.endqstrip();
993
994         }
995     }
996   
997   free(trimVert);
998 }
999 */
1000
1001 void Slicer::evalRBArray(rectBlockArray* rbArray, gridWrap* grid)
1002 {
1003   Int i,j,k;
1004   
1005   Int n_vlines=grid->get_n_vlines();
1006   //the reason to switch the position of v_max and v_min is because of the
1007   //the orientation problem. glEvalMesh generates quad_strip clockwise, but
1008   //we need counter-clockwise.
1009   backend.surfgrid(grid->get_u_min(), grid->get_u_max(), grid->get_n_ulines()-1,
1010                    grid->get_v_max(), grid->get_v_min(), n_vlines-1);
1011
1012
1013   for(j=0; j<rbArray->get_n_elements(); j++)
1014     {
1015       rectBlock* block = rbArray->get_element(j);
1016       Int low = block->get_lowGridLineIndex();
1017       Int high = block->get_upGridLineIndex();
1018
1019       for(k=0, i=high; i>low; i--, k++)
1020         {
1021           backend.surfmesh(block->get_leftIndices()[k+1], n_vlines-1-i, block->get_rightIndices()[k+1]-block->get_leftIndices()[k+1], 1);
1022         }
1023     }
1024 }
1025
1026
1027 void Slicer::evalStream(primStream* pStream)
1028 {
1029   Int i,j,k;
1030   k=0;
1031 /*  TrimVertex X;*/
1032   TrimVertex *trimVert =/*&X*/  (TrimVertex*)malloc(sizeof(TrimVertex));
1033   trimVert -> nuid = 0;//???
1034   Real* vertices = pStream->get_vertices(); //for efficiency
1035   for(i=0; i<pStream->get_n_prims(); i++)
1036     {
1037
1038      //ith primitive  has #vertices = lengths[i], type=types[i]
1039       switch(pStream->get_type(i)){
1040       case PRIMITIVE_STREAM_FAN:
1041
1042         backend.bgntfan();
1043
1044         for(j=0; j<pStream->get_length(i); j++)
1045           {         
1046             trimVert->param[0] = vertices[k];
1047             trimVert->param[1] = vertices[k+1];
1048             backend.tmeshvert(trimVert);           
1049             
1050 //          backend.tmeshvert(vertices[k], vertices[k+1]);
1051             k += 2;
1052           }
1053         backend.endtfan();
1054         break;
1055         
1056       default:
1057         fprintf(stderr, "evalStream: not implemented yet\n");
1058         exit(1);
1059
1060       }
1061     }
1062   free(trimVert);
1063 }
1064            
1065            
1066             
1067
1068 void Slicer::slice_new(Arc_ptr loop)
1069 {
1070 //count++;
1071 //if(count == 78) count=1;
1072 //printf("count=%i\n", count);
1073 //if( ! (4<= count && count <=4)) return;
1074
1075
1076   Int num_ulines;
1077   Int num_vlines;
1078   Real uMin, uMax, vMin, vMax;
1079   Real mydu, mydv;
1080   uMin = uMax = loop->tail()[0];
1081   vMin = vMax = loop->tail()[1];
1082   mydu = (du>0)? du: -du;
1083   mydv = (dv>0)? dv: -dv;
1084
1085   for(Arc_ptr jarc=loop->next; jarc != loop; jarc = jarc->next)
1086    {
1087
1088      if(jarc->tail()[0] < uMin)
1089        uMin = jarc->tail()[0];
1090      if(jarc->tail()[0] > uMax)
1091        uMax = jarc->tail()[0];
1092      if(jarc->tail()[1] < vMin)
1093        vMin = jarc->tail()[1];
1094      if(jarc->tail()[1] > vMax)
1095        vMax = jarc->tail()[1];
1096    }
1097
1098   if (uMax == uMin)
1099     return; // prevent divide-by-zero.  Jon Perry.  17 June 2002
1100
1101   if(mydu > uMax - uMin)
1102     num_ulines = 2;
1103   else
1104     {
1105       num_ulines = 3 + (Int) ((uMax-uMin)/mydu);
1106     }
1107   if(mydv>=vMax-vMin)
1108     num_vlines = 2;
1109   else
1110     {
1111       num_vlines = 2+(Int)((vMax-vMin)/mydv);
1112     }
1113
1114   Int isRect = is_rect(loop);
1115
1116   if(isRect && (num_ulines<=2 || num_vlines<=2))
1117     {
1118       if(vlinear)
1119         triangulateRect(loop, backend, 1, ulinear, vlinear);
1120       else if(ulinear)
1121         triangulateRect(loop, backend, -1, ulinear, vlinear);   
1122       else
1123         triangulateRect(loop, backend, 0, ulinear, vlinear);            
1124     }
1125
1126    else if(isRect)
1127     {
1128       triangulateRectGen(loop, num_ulines-2, num_vlines-2, backend); 
1129     }
1130   else if( (num_ulines<=2 || num_vlines <=2) && ulinear)
1131     {
1132       monoTriangulationFunBackend(loop, compV2InY, &backend);
1133     }
1134   else if( (!ulinear) && (!vlinear) && (num_ulines == 2) && (num_vlines > 2))
1135     {
1136       monoTriangulationFunBackend(loop, compV2InY, &backend);
1137     }
1138   else 
1139     {
1140       directedLine* poly = arcLoopToDLineLoop(loop);
1141
1142       gridWrap grid(num_ulines, num_vlines, uMin, uMax, vMin, vMax);
1143       primStream pStream(20, 20);
1144       rectBlockArray rbArray(20);
1145
1146       sampleMonoPoly(poly, &grid, ulinear, vlinear, &pStream, &rbArray);
1147
1148       evalStream(&pStream);
1149
1150       evalRBArray(&rbArray, &grid);
1151       
1152 #ifdef COUNT_TRIANGLES
1153       num_triangles += pStream.num_triangles();
1154       num_quads += rbArray.num_quads();
1155 #endif
1156       poly->deleteSinglePolygonWithSline();      
1157     }
1158   
1159 #ifdef COUNT_TRIANGLES
1160   printf("num_triangles=%i\n", num_triangles);
1161   printf("num_quads = %i\n", num_quads);
1162 #endif
1163 }
1164
1165 void Slicer::slice(Arc_ptr loop)
1166 {
1167 #ifdef USE_READ_FLAG
1168   if(read_flag("flagFile"))
1169     slice_new(loop);
1170   else
1171     slice_old(loop);
1172
1173 #else
1174     slice_new(loop);
1175 #endif
1176
1177 }
1178
1179   
1180
1181 Slicer::Slicer( Backend &b ) 
1182         : CoveAndTiler( b ), Mesher( b ), backend( b )
1183 {
1184     oneOverDu = 0;
1185     du = 0;
1186     dv = 0;
1187     isolines = 0;
1188     ulinear = 0;
1189     vlinear = 0;
1190 }
1191
1192 Slicer::~Slicer()
1193 {
1194 }
1195
1196 void
1197 Slicer::setisolines( int x )
1198 {
1199     isolines = x;
1200 }
1201
1202 void
1203 Slicer::setstriptessellation( REAL x, REAL y )
1204 {
1205     assert(x > 0 && y > 0);
1206     du = x;
1207     dv = y;
1208     setDu( du );
1209 }
1210
1211 void
1212 Slicer::slice_old( Arc_ptr loop )
1213 {
1214     loop->markverts();
1215
1216     Arc_ptr extrema[4];
1217     loop->getextrema( extrema );
1218
1219     unsigned int npts = loop->numpts();
1220     TrimRegion::init( npts, extrema[0] );
1221
1222     Mesher::init( npts );
1223
1224     long ulines = uarray.init( du, extrema[1], extrema[3] );
1225 //printf("ulines = %i\n", ulines);
1226     Varray varray;
1227     long vlines = varray.init( dv, extrema[0], extrema[2] );
1228 //printf("vlines = %i\n", vlines);
1229     long botv = 0;
1230     long topv;
1231     TrimRegion::init( varray.varray[botv] );
1232     getGridExtent( &extrema[0]->pwlArc->pts[0], &extrema[0]->pwlArc->pts[0] );
1233
1234     for( long quad=0; quad<varray.numquads; quad++ ) {
1235         backend.surfgrid( uarray.uarray[0], 
1236                        uarray.uarray[ulines-1], 
1237                        ulines-1, 
1238                        varray.vval[quad], 
1239                        varray.vval[quad+1], 
1240                        varray.voffset[quad+1] - varray.voffset[quad] );
1241
1242         for( long i=varray.voffset[quad]+1; i <= varray.voffset[quad+1]; i++ ) {
1243             topv = botv++;
1244             advance( topv - varray.voffset[quad], 
1245                      botv - varray.voffset[quad], 
1246                      varray.varray[botv] );
1247             if( i == vlines )
1248                 getPts( extrema[2] );
1249             else
1250                 getPts( backend );
1251             getGridExtent();
1252             if( isolines ) {
1253                 outline();
1254             } else {
1255                 if( canTile() ) 
1256                     coveAndTile();
1257                 else
1258                     mesh();
1259             }
1260         }
1261    }
1262 }
1263
1264
1265 void
1266 Slicer::outline( void )
1267 {
1268     GridTrimVertex upper, lower;
1269     Hull::init( );
1270
1271     backend.bgnoutline();
1272     while( (nextupper( &upper )) ) {
1273         if( upper.isGridVert() )
1274             backend.linevert( upper.g );
1275         else
1276             backend.linevert( upper.t );
1277     }
1278     backend.endoutline();
1279
1280     backend.bgnoutline();
1281     while( (nextlower( &lower )) ) {
1282         if( lower.isGridVert() )
1283             backend.linevert( lower.g );
1284         else
1285             backend.linevert( lower.t );
1286     }
1287     backend.endoutline();
1288 }
1289
1290
1291 void
1292 Slicer::outline( Arc_ptr jarc )
1293 {
1294     jarc->markverts();
1295
1296     if( jarc->pwlArc->npts >= 2 ) {
1297         backend.bgnoutline();
1298         for( int j = jarc->pwlArc->npts-1; j >= 0; j--  )
1299             backend.linevert( &(jarc->pwlArc->pts[j]) );
1300         backend.endoutline();
1301     }
1302 }
1303
1304