SGI SI GLU library
[mesa.git] / src / glu / sgi / libnurbs / nurbtess / monoTriangulation.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 ** $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
35 */
36 /*
37 ** $Header: /home/krh/git/sync/mesa-cvs-repo/Mesa/src/glu/sgi/libnurbs/nurbtess/monoTriangulation.cc,v 1.1 2001/03/17 00:25:41 brianp Exp $
38 */
39
40 #include <stdlib.h>
41 #include <stdio.h>
42 #include "glimports.h"
43 #include "zlassert.h"
44
45 #include "monoTriangulation.h"
46 #include "polyUtil.h" /*for area*/
47 #include "partitionX.h"
48 #include "monoPolyPart.h"
49
50
51
52 extern directedLine* polygonConvert(directedLine* polygon);
53
54 /*poly is NOT deleted
55 */
56 void monoTriangulationOpt(directedLine* poly, primStream* pStream)
57 {
58 Int n_cusps;
59 Int n_edges = poly->numEdges();
60 directedLine** cusps = (directedLine**) malloc(sizeof(directedLine*)*n_edges);
61 assert(cusps);
62 findInteriorCuspsX(poly, n_cusps, cusps);
63 if(n_cusps ==0) //u monotine
64 {
65 monoTriangulationFun(poly, compV2InX, pStream);
66 }
67 else if(n_cusps == 1) // one interior cusp
68 {
69 directedLine* new_polygon = polygonConvert(cusps[0]);
70 directedLine* other = findDiagonal_singleCuspX(new_polygon);
71 //<other> should NOT be null unless there are self-intersecting
72 //trim curves. In that case, we don't want to core dump, instead,
73 //we triangulate anyway, and print out error message.
74 if(other == NULL)
75 {
76 monoTriangulationFun(poly, compV2InX, pStream);
77 }
78 else
79 {
80 directedLine* ret_p1;
81 directedLine* ret_p2;
82
83 new_polygon->connectDiagonal_2slines(new_polygon, other,
84 &ret_p1,
85 &ret_p2,
86 new_polygon);
87
88 monoTriangulationFun(ret_p1, compV2InX, pStream);
89 monoTriangulationFun(ret_p2, compV2InX, pStream);
90
91 ret_p1->deleteSinglePolygonWithSline();
92 ret_p2->deleteSinglePolygonWithSline();
93 }
94 }
95 else
96 {
97 //we need a general partitionX funtion (supposed to be in partitionX.C,
98 //not implemented yet. XXX
99 monoTriangulationFun(poly, compV2InY, pStream);
100 }
101
102 free(cusps);
103 }
104
105 void monoTriangulationRecOpt(Real* topVertex, Real* botVertex,
106 vertexArray* left_chain, Int left_current,
107 vertexArray* right_chain, Int right_current,
108 primStream* pStream)
109 {
110 Int i,j;
111 Int n_left = left_chain->getNumElements();
112 Int n_right = right_chain->getNumElements();
113 if(left_current>= n_left-1 ||
114 right_current>= n_right-1)
115 {
116 monoTriangulationRec(topVertex, botVertex, left_chain, left_current,
117 right_chain, right_current, pStream);
118 return;
119 }
120 //now both left and right have at least two vertices each.
121 Real left_v = left_chain->getVertex(left_current)[1];
122 Real right_v = right_chain->getVertex(right_current)[1];
123
124 if(left_v <= right_v) //first left vertex is below right
125 {
126 //find the last vertex of right which is above or equal to left
127 for(j=right_current; j<=n_right-1; j++)
128 {
129 if(right_chain->getVertex(j)[1] < left_v)
130 break;
131 }
132 monoTriangulationRecGen(topVertex, left_chain->getVertex(left_current),
133 left_chain, left_current, left_current,
134 right_chain, right_current, j-1,
135 pStream);
136 monoTriangulationRecOpt(right_chain->getVertex(j-1),
137 botVertex,
138 left_chain, left_current,
139 right_chain, j,
140 pStream);
141 }
142 else //first right vertex is strictly below left
143 {
144 //find the last vertex of left which is strictly above right
145 for(i=left_current; i<=n_left-1; i++)
146 {
147 if(left_chain->getVertex(i)[1] <= right_v)
148 break;
149 }
150 monoTriangulationRecGen(topVertex, right_chain->getVertex(right_current),
151 left_chain, left_current, i-1,
152 right_chain, right_current, right_current,
153 pStream);
154 monoTriangulationRecOpt(left_chain->getVertex(i-1),
155 botVertex,
156 left_chain, i,
157 right_chain, right_current,
158 pStream);
159 }
160 }
161
162
163 void monoTriangulationRecGenTBOpt(Real* topVertex, Real* botVertex,
164 vertexArray* inc_chain, Int inc_current, Int inc_end,
165 vertexArray* dec_chain, Int dec_current, Int dec_end,
166 primStream* pStream)
167 {
168 pStream->triangle(topVertex, inc_chain->getVertex(inc_current), dec_chain->getVertex(dec_current));
169
170 /*printf("**(%f,%f)\n", inc_chain->getArray()[0][0],inc_chain->getArray()[0][1]);*/
171 triangulateXYMonoTB(inc_end-inc_current+1, inc_chain->getArray()+inc_current, dec_end-dec_current+1, dec_chain->getArray()+dec_current, pStream);
172
173 pStream->triangle(botVertex, dec_chain->getVertex(dec_end), inc_chain->getVertex(inc_end));
174 }
175
176
177 /*n_left>=1
178 *n_right>=1
179 *the strip is going top to bottom. compared to the funtion
180 * triangulateXYmono()
181 */
182 void triangulateXYMonoTB(Int n_left, Real** leftVerts,
183 Int n_right, Real** rightVerts,
184 primStream* pStream)
185 {
186
187
188 Int i,j,k,l;
189 Real* topMostV;
190
191 assert(n_left>=1 && n_right>=1);
192 if(leftVerts[0][1] >= rightVerts[0][1])
193 {
194 i=1;
195 j=0;
196 topMostV = leftVerts[0];
197 }
198 else
199 {
200 i=0;
201 j=1;
202 topMostV = rightVerts[0];
203 }
204
205 while(1)
206 {
207 if(i >= n_left) /*case1: no more in left*/
208 {
209
210 if(j<n_right-1) /*at least two vertices in right*/
211 {
212 pStream->begin();
213 pStream->insert(topMostV);
214 for(k=n_right-1; k>=j; k--)
215 pStream->insert(rightVerts[j]);
216
217 pStream->end(PRIMITIVE_STREAM_FAN);
218
219 }
220
221 break;
222 }
223 else if(j>= n_right) /*case2: no more in right*/
224 {
225
226 if(i<n_left-1) /*at least two vertices in left*/
227 {
228 pStream->begin();
229 pStream->insert(topMostV);
230
231 for(k=i; k<n_left; k++)
232 pStream->insert(leftVerts[k]);
233
234 pStream->end(PRIMITIVE_STREAM_FAN);
235 }
236
237 break;
238 }
239 else /* case3: neither is empty, plus the topMostV, there is at least one triangle to output*/
240 {
241
242 if(leftVerts[i][1] >= rightVerts[j][1])
243 {
244 pStream->begin();
245 pStream->insert(rightVerts[j]); /*the origin of this fan*/
246
247 pStream->insert(topMostV);
248
249 /*find the last k>=i such that
250 *leftverts[k][1] >= rightverts[j][1]
251 */
252 k=i;
253 while(k<n_left)
254 {
255 if(leftVerts[k][1] < rightVerts[j][1])
256 break;
257 k++;
258 }
259 k--;
260 for(l=i; l<=k; l++)
261 {
262 pStream->insert(leftVerts[l]);
263 }
264
265 pStream->end(PRIMITIVE_STREAM_FAN);
266 //update i for next loop
267 i = k+1;
268 topMostV = leftVerts[k];
269
270 }
271 else /*leftVerts[i][1] < rightVerts[j][1]*/
272 {
273 pStream->begin();
274 pStream->insert(leftVerts[i]);/*the origion of this fan*/
275
276 /*find the last k>=j such that
277 *rightverts[k][1] > leftverts[i][1]*/
278 k=j;
279 while(k< n_right)
280 {
281 if(rightVerts[k][1] <= leftVerts[i][1])
282 break;
283 k++;
284 }
285 k--;
286
287 for(l=k; l>= j; l--)
288 pStream->insert(rightVerts[l]);
289
290 pStream->insert(topMostV);
291 pStream->end(PRIMITIVE_STREAM_FAN);
292 j=k+1;
293 topMostV = rightVerts[j-1];
294 }
295 }
296 }
297 }
298
299 static int chainConvex(vertexArray* inc_chain, Int inc_current, Int inc_end)
300 {
301 Int i;
302 //if there are no more than 2 vertices, return 1
303 if(inc_current >= inc_end-1) return 1;
304 for(i=inc_current; i<= inc_end-2; i++)
305 {
306 if(area(inc_chain->getVertex(i), inc_chain->getVertex(i+1), inc_chain->getVertex(i+2)) <0)
307 return 0;
308 }
309 return 1;
310 }
311
312 static int chainConcave(vertexArray* dec_chain, Int dec_current, Int dec_end)
313 {
314 Int i;
315 //if there are no more than 2 vertices, return 1
316 if(dec_current >= dec_end -1) return 1;
317 for(i=dec_current; i<=dec_end-2; i++)
318 {
319 if(area(dec_chain->getVertex(i), dec_chain->getVertex(i+1), dec_chain->getVertex(i+2)) >0)
320 return 0;
321 }
322 return 1;
323 }
324
325 void monoTriangulationRecGenInU(Real* topVertex, Real* botVertex,
326 vertexArray* inc_chain, Int inc_current, Int inc_end,
327 vertexArray* dec_chain, Int dec_current, Int dec_end,
328 primStream* pStream)
329 {
330
331 }
332
333 void monoTriangulationRecGenOpt(Real* topVertex, Real* botVertex,
334 vertexArray* inc_chain, Int inc_current, Int inc_end,
335 vertexArray* dec_chain, Int dec_current, Int dec_end,
336 primStream* pStream)
337 {
338 Int i;
339 //copy this to a polygon: directedLine Lioop
340 sampledLine* sline;
341 directedLine* dline;
342 directedLine* poly;
343
344 if(inc_current <= inc_end) //at least one vertex in inc_chain
345 {
346 sline = new sampledLine(topVertex, inc_chain->getVertex(inc_current));
347 poly = new directedLine(INCREASING, sline);
348 for(i=inc_current; i<=inc_end-1; i++)
349 {
350 sline = new sampledLine(inc_chain->getVertex(i), inc_chain->getVertex(i+1));
351 dline = new directedLine(INCREASING, sline);
352 poly->insert(dline);
353 }
354 sline = new sampledLine(inc_chain->getVertex(inc_end), botVertex);
355 dline = new directedLine(INCREASING, sline);
356 poly->insert(dline);
357 }
358 else //inc_chian is empty
359 {
360 sline = new sampledLine(topVertex, botVertex);
361 dline = new directedLine(INCREASING, sline);
362 poly = dline;
363 }
364
365 assert(poly != NULL);
366
367 if(dec_current <= dec_end) //at least on vertex in dec_Chain
368 {
369 sline = new sampledLine(botVertex, dec_chain->getVertex(dec_end));
370 dline = new directedLine(INCREASING, sline);
371 poly->insert(dline);
372 for(i=dec_end; i>dec_current; i--)
373 {
374 sline = new sampledLine(dec_chain->getVertex(i), dec_chain->getVertex(i-1));
375 dline = new directedLine(INCREASING, sline);
376 poly->insert(dline);
377 }
378 sline = new sampledLine(dec_chain->getVertex(dec_current), topVertex);
379 dline = new directedLine(INCREASING, sline);
380 poly->insert(dline);
381 }
382 else //dec_chain is empty
383 {
384 sline = new sampledLine(botVertex, topVertex);
385 dline = new directedLine(INCREASING, sline);
386 poly->insert(dline);
387 }
388
389 {
390 Int n_cusps;
391 Int n_edges = poly->numEdges();
392 directedLine** cusps = (directedLine**) malloc(sizeof(directedLine*)*n_edges);
393 assert(cusps);
394 findInteriorCuspsX(poly, n_cusps, cusps);
395
396 if(n_cusps ==0) //u monotine
397 {
398 monoTriangulationFun(poly, compV2InX, pStream);
399 }
400 else if(n_cusps == 1) // one interior cusp
401 {
402 directedLine* new_polygon = polygonConvert(cusps[0]);
403 directedLine* other = findDiagonal_singleCuspX(new_polygon);
404 //<other> should NOT be null unless there are self-intersecting
405 //trim curves. In that case, we don't want to core dump, instead,
406 //we triangulate anyway, and print out error message.
407 if(other == NULL)
408 {
409 monoTriangulationFun(poly, compV2InX, pStream);
410 }
411 else
412 {
413 directedLine* ret_p1;
414 directedLine* ret_p2;
415
416 new_polygon->connectDiagonal_2slines(new_polygon, other,
417 &ret_p1,
418 &ret_p2,
419 new_polygon);
420
421 monoTriangulationFun(ret_p1, compV2InX, pStream);
422 monoTriangulationFun(ret_p2, compV2InX, pStream);
423
424 ret_p1->deleteSinglePolygonWithSline();
425 ret_p2->deleteSinglePolygonWithSline();
426 }
427 }
428 else
429 {
430 //we need a general partitionX funtion (supposed to be in partitionX.C,
431 //not implemented yet. XXX
432 //monoTriangulationFun(poly, compV2InY, pStream);
433
434 directedLine* new_polygon = polygonConvert(poly);
435 directedLine* list = monoPolyPart(new_polygon);
436 for(directedLine* temp = list; temp != NULL; temp = temp->getNextPolygon())
437 {
438 monoTriangulationFun(temp, compV2InX, pStream);
439 }
440 //clean up
441 list->deletePolygonListWithSline();
442
443 }
444
445 free(cusps);
446 /*
447 if(numInteriorCuspsX(poly) == 0) //is u monotone
448 monoTriangulationFun(poly, compV2InX, pStream);
449 else //it is not u motone
450 monoTriangulationFun(poly, compV2InY, pStream);
451 */
452 //clean up space
453 poly->deleteSinglePolygonWithSline();
454 return;
455 }
456
457 //apparently the following code is not reachable,
458 //it is for test purpose
459 if(inc_current > inc_end || dec_current>dec_end)
460 {
461 monoTriangulationRecGen(topVertex, botVertex, inc_chain, inc_current, inc_end,
462 dec_chain, dec_current, dec_end,
463 pStream);
464 return;
465 }
466
467
468 if(
469 area(dec_chain->getVertex(dec_current),
470 topVertex,
471 inc_chain->getVertex(inc_current)) >=0
472 && chainConvex(inc_chain, inc_current, inc_end)
473 && chainConcave(dec_chain, dec_current, dec_end)
474 && area(inc_chain->getVertex(inc_end), botVertex, dec_chain->getVertex(dec_end)) >=0
475 )
476 {
477 monoTriangulationRecFunGen(topVertex, botVertex,
478 inc_chain, inc_current, inc_end,
479 dec_chain, dec_current, dec_end,
480 compV2InX, pStream);
481 }
482 else
483 {
484 monoTriangulationRecGen(topVertex, botVertex, inc_chain, inc_current, inc_end,
485 dec_chain, dec_current, dec_end,
486 pStream);
487 }
488 }
489
490 /*if inc_current>inc_end, then inc_chain has no points to be considered
491 *same for dec_chain
492 */
493 void monoTriangulationRecGen(Real* topVertex, Real* botVertex,
494 vertexArray* inc_chain, Int inc_current, Int inc_end,
495 vertexArray* dec_chain, Int dec_current, Int dec_end,
496 primStream* pStream)
497 {
498 Real** inc_array ;
499 Real** dec_array ;
500 Int i;
501
502 if(inc_current > inc_end && dec_current>dec_end)
503 return;
504 else if(inc_current>inc_end) /*no more vertices on inc_chain*/
505 {
506 dec_array = dec_chain->getArray();
507 reflexChain rChain(100,0);
508 /*put the top vertex into the reflex chain*/
509 rChain.processNewVertex(topVertex, pStream);
510 /*process all the vertices on the dec_chain*/
511 for(i=dec_current; i<=dec_end; i++){
512 rChain.processNewVertex(dec_array[i], pStream);
513 }
514 /*process the bottom vertex*/
515 rChain.processNewVertex(botVertex, pStream);
516 }
517 else if(dec_current> dec_end) /*no more vertices on dec_chain*/
518 {
519 inc_array = inc_chain->getArray();
520
521 reflexChain rChain(100,1);
522 /*put the top vertex into the reflex chain*/
523 rChain.processNewVertex(topVertex, pStream);
524 /*process all the vertices on the inc_chain*/
525 for(i=inc_current; i<=inc_end; i++){
526 rChain.processNewVertex(inc_array[i], pStream);
527 }
528 /*process the bottom vertex*/
529 rChain.processNewVertex(botVertex, pStream);
530 }
531 else /*neither chain is empty*/
532 {
533 inc_array = inc_chain -> getArray();
534 dec_array = dec_chain -> getArray();
535
536 /*if top of inc_chain is 'lower' than top of dec_chain, process all the
537 *vertices on the dec_chain which are higher than top of inc_chain
538 */
539 if(compV2InY(inc_array[inc_current], dec_array[dec_current]) <= 0)
540 {
541
542 reflexChain rChain(100, 0);
543 rChain.processNewVertex(topVertex, pStream);
544 for(i=dec_current; i<=dec_end; i++)
545 {
546 if(compV2InY(inc_array[inc_current], dec_array[i]) <= 0)
547 rChain.processNewVertex(dec_array[i], pStream);
548 else
549 break;
550 }
551 rChain.outputFan(inc_array[inc_current], pStream);
552 monoTriangulationRecGen(dec_array[i-1], botVertex,
553 inc_chain, inc_current, inc_end,
554 dec_chain, i, dec_end,
555 pStream);
556 }
557 else /*compV2InY(inc_array[inc_current], dec_array[dec_current]) > 0*/
558 {
559
560 reflexChain rChain(100, 1);
561 rChain.processNewVertex(topVertex, pStream);
562 for(i=inc_current; i<=inc_end; i++)
563 {
564 if(compV2InY(inc_array[i], dec_array[dec_current]) >0)
565 rChain.processNewVertex(inc_array[i], pStream);
566 else
567 break;
568 }
569 rChain.outputFan(dec_array[dec_current], pStream);
570 monoTriangulationRecGen(inc_array[i-1], botVertex,
571 inc_chain, i, inc_end,
572 dec_chain, dec_current,dec_end,
573 pStream);
574 }
575 }/*end case neither is empty*/
576 }
577
578 void monoTriangulationFun(directedLine* monoPolygon, Int (*compFun)(Real*, Real*), primStream* pStream)
579 {
580 Int i;
581 /*find the top vertex, bottom vertex, inccreasing chain, and decreasing chain,
582 *then call monoTriangulationRec
583 */
584 directedLine* tempV;
585 directedLine* topV;
586 directedLine* botV;
587 topV = botV = monoPolygon;
588 for(tempV = monoPolygon->getNext(); tempV != monoPolygon; tempV = tempV->getNext())
589 {
590 if(compFun(topV->head(), tempV->head())<0) {
591 topV = tempV;
592 }
593 if(compFun(botV->head(), tempV->head())>0) {
594 botV = tempV;
595 }
596 }
597
598 /*creat increase and decrease chains*/
599 vertexArray inc_chain(20); /*this is a dynamic array*/
600 for(i=1; i<=topV->get_npoints()-2; i++) { /*the first vertex is the top vertex which doesn't belong to inc_chain*/
601 inc_chain.appendVertex(topV->getVertex(i));
602 }
603 for(tempV = topV->getNext(); tempV != botV; tempV = tempV->getNext())
604 {
605 for(i=0; i<=tempV->get_npoints()-2; i++){
606 inc_chain.appendVertex(tempV->getVertex(i));
607 }
608 }
609
610 vertexArray dec_chain(20);
611 for(tempV = topV->getPrev(); tempV != botV; tempV = tempV->getPrev())
612 {
613 for(i=tempV->get_npoints()-2; i>=0; i--){
614 dec_chain.appendVertex(tempV->getVertex(i));
615 }
616 }
617 for(i=botV->get_npoints()-2; i>=1; i--){
618 dec_chain.appendVertex(tempV->getVertex(i));
619 }
620
621 monoTriangulationRecFun(topV->head(), botV->head(), &inc_chain, 0, &dec_chain, 0, compFun, pStream);
622
623 }
624
625 void monoTriangulation(directedLine* monoPolygon, primStream* pStream)
626 {
627 Int i;
628 /*find the top vertex, bottom vertex, inccreasing chain, and decreasing chain,
629 *then call monoTriangulationRec
630 */
631 directedLine* tempV;
632 directedLine* topV;
633 directedLine* botV;
634 topV = botV = monoPolygon;
635 for(tempV = monoPolygon->getNext(); tempV != monoPolygon; tempV = tempV->getNext())
636 {
637 if(compV2InY(topV->head(), tempV->head())<0) {
638 topV = tempV;
639 }
640 if(compV2InY(botV->head(), tempV->head())>0) {
641 botV = tempV;
642 }
643 }
644 /*creat increase and decrease chains*/
645 vertexArray inc_chain(20); /*this is a dynamic array*/
646 for(i=1; i<=topV->get_npoints()-2; i++) { /*the first vertex is the top vertex which doesn't belong to inc_chain*/
647 inc_chain.appendVertex(topV->getVertex(i));
648 }
649 for(tempV = topV->getNext(); tempV != botV; tempV = tempV->getNext())
650 {
651 for(i=0; i<=tempV->get_npoints()-2; i++){
652 inc_chain.appendVertex(tempV->getVertex(i));
653 }
654 }
655
656 vertexArray dec_chain(20);
657 for(tempV = topV->getPrev(); tempV != botV; tempV = tempV->getPrev())
658 {
659 for(i=tempV->get_npoints()-2; i>=0; i--){
660 dec_chain.appendVertex(tempV->getVertex(i));
661 }
662 }
663 for(i=botV->get_npoints()-2; i>=1; i--){
664 dec_chain.appendVertex(tempV->getVertex(i));
665 }
666
667 monoTriangulationRec(topV->head(), botV->head(), &inc_chain, 0, &dec_chain, 0, pStream);
668
669 }
670
671 /*the chain could be increasing or decreasing, although we use the
672 * name inc_chain.
673 *the argument is_increase_chain indicates whether this chain
674 *is increasing (left chain in V-monotone case) or decreaing (right chain
675 *in V-monotone case).
676 */
677 void monoTriangulation2(Real* topVertex, Real* botVertex,
678 vertexArray* inc_chain, Int inc_smallIndex,
679 Int inc_largeIndex,
680 Int is_increase_chain,
681 primStream* pStream)
682 {
683 assert( inc_chain != NULL);
684 Real** inc_array ;
685
686 if(inc_smallIndex > inc_largeIndex)
687 return; //no triangles
688 if(inc_smallIndex == inc_largeIndex)
689 {
690 if(is_increase_chain)
691 pStream->triangle(inc_chain->getVertex(inc_smallIndex), botVertex, topVertex);
692 else
693 pStream->triangle(inc_chain->getVertex(inc_smallIndex), topVertex, botVertex);
694 return;
695 }
696 Int i;
697
698 if(is_increase_chain && botVertex[1] == inc_chain->getVertex(inc_largeIndex)[1])
699 {
700 pStream->triangle(botVertex, inc_chain->getVertex(inc_largeIndex-1),
701 inc_chain->getVertex(inc_largeIndex));
702 monoTriangulation2(topVertex, botVertex, inc_chain, inc_smallIndex,
703 inc_largeIndex-1,
704 is_increase_chain,
705 pStream);
706 return;
707 }
708 else if( (!is_increase_chain) && topVertex[1] == inc_chain->getVertex(inc_smallIndex)[1])
709 {
710 pStream->triangle(topVertex, inc_chain->getVertex(inc_smallIndex+1),
711 inc_chain->getVertex(inc_smallIndex));
712 monoTriangulation2(topVertex, botVertex, inc_chain, inc_smallIndex+1,
713 inc_largeIndex, is_increase_chain, pStream);
714 return ;
715 }
716
717 inc_array = inc_chain->getArray();
718
719 reflexChain rChain(20,is_increase_chain); /*1 means the chain is increasing*/
720
721 rChain.processNewVertex(topVertex, pStream);
722
723 for(i=inc_smallIndex; i<=inc_largeIndex; i++){
724 rChain.processNewVertex(inc_array[i], pStream);
725 }
726 rChain.processNewVertex(botVertex, pStream);
727
728 }
729
730 /*if compFun == compV2InY, top to bottom: V-monotone
731 *if compFun == compV2InX, right to left: U-monotone
732 */
733 void monoTriangulationRecFunGen(Real* topVertex, Real* botVertex,
734 vertexArray* inc_chain, Int inc_current, Int inc_end,
735 vertexArray* dec_chain, Int dec_current, Int dec_end,
736 Int (*compFun)(Real*, Real*),
737 primStream* pStream)
738 {
739 assert( inc_chain != NULL && dec_chain != NULL);
740 assert( ! (inc_current> inc_end &&
741 dec_current> dec_end));
742 Int inc_nVertices;
743 Int dec_nVertices;
744 Real** inc_array ;
745 Real** dec_array ;
746 Int i;
747 assert( ! ( (inc_chain==NULL) && (dec_chain==NULL)));
748
749 if(inc_current> inc_end) /*no more vertices on inc_chain*/
750 {
751
752 dec_array = dec_chain->getArray();
753 reflexChain rChain(20,0);
754 /*put the top vertex into the reflex chain*/
755 rChain.processNewVertex(topVertex, pStream);
756 /*process all the vertices on the dec_chain*/
757 for(i=dec_current; i<=dec_end; i++){
758 rChain.processNewVertex(dec_array[i], pStream);
759 }
760 /*process the bottom vertex*/
761 rChain.processNewVertex(botVertex, pStream);
762
763 }
764 else if(dec_current> dec_end) /*no more vertices on dec_chain*/
765 {
766 inc_array = inc_chain->getArray();
767 reflexChain rChain(20,1);
768 /*put the top vertex into the reflex chain*/
769 rChain.processNewVertex(topVertex, pStream);
770 /*process all the vertices on the inc_chain*/
771 for(i=inc_current; i<=inc_end; i++){
772 rChain.processNewVertex(inc_array[i], pStream);
773 }
774 /*process the bottom vertex*/
775 rChain.processNewVertex(botVertex, pStream);
776 }
777 else /*neither chain is empty*/
778 {
779 inc_array = inc_chain -> getArray();
780 dec_array = dec_chain -> getArray();
781
782 /*if top of inc_chain is 'lower' than top of dec_chain, process all the
783 *vertices on the dec_chain which are higher than top of inc_chain
784 */
785 if(compFun(inc_array[inc_current], dec_array[dec_current]) <= 0)
786 {
787
788 reflexChain rChain(20, 0);
789 rChain.processNewVertex(topVertex, pStream);
790 for(i=dec_current; i<=dec_end; i++)
791 {
792 if(compFun(inc_array[inc_current], dec_array[i]) <= 0)
793 rChain.processNewVertex(dec_array[i], pStream);
794 else
795 break;
796 }
797 rChain.outputFan(inc_array[inc_current], pStream);
798 monoTriangulationRecFunGen(dec_array[i-1], botVertex,
799 inc_chain, inc_current, inc_end,
800 dec_chain, i, dec_end,
801 compFun,
802 pStream);
803 }
804 else /*compFun(inc_array[inc_current], dec_array[dec_current]) > 0*/
805 {
806
807 reflexChain rChain(20, 1);
808 rChain.processNewVertex(topVertex, pStream);
809 for(i=inc_current; i<=inc_end; i++)
810 {
811 if(compFun(inc_array[i], dec_array[dec_current]) >0)
812 rChain.processNewVertex(inc_array[i], pStream);
813 else
814 break;
815 }
816 rChain.outputFan(dec_array[dec_current], pStream);
817 monoTriangulationRecFunGen(inc_array[i-1], botVertex,
818 inc_chain, i,inc_end,
819 dec_chain, dec_current,dec_end,
820 compFun,
821 pStream);
822 }
823 }/*end case neither is empty*/
824 }
825
826 /*if compFun == compV2InY, top to bottom: V-monotone
827 *if compFun == compV2InX, right to left: U-monotone
828 */
829 void monoTriangulationRecFun(Real* topVertex, Real* botVertex,
830 vertexArray* inc_chain, Int inc_current,
831 vertexArray* dec_chain, Int dec_current,
832 Int (*compFun)(Real*, Real*),
833 primStream* pStream)
834 {
835 assert( inc_chain != NULL && dec_chain != NULL);
836 assert( ! (inc_current>=inc_chain->getNumElements() &&
837 dec_current>=dec_chain->getNumElements()));
838 Int inc_nVertices;
839 Int dec_nVertices;
840 Real** inc_array ;
841 Real** dec_array ;
842 Int i;
843 assert( ! ( (inc_chain==NULL) && (dec_chain==NULL)));
844
845 if(inc_current>=inc_chain->getNumElements()) /*no more vertices on inc_chain*/
846 {
847
848 dec_array = dec_chain->getArray();
849 dec_nVertices = dec_chain->getNumElements();
850 reflexChain rChain(20,0);
851 /*put the top vertex into the reflex chain*/
852 rChain.processNewVertex(topVertex, pStream);
853 /*process all the vertices on the dec_chain*/
854 for(i=dec_current; i<dec_nVertices; i++){
855 rChain.processNewVertex(dec_array[i], pStream);
856 }
857 /*process the bottom vertex*/
858 rChain.processNewVertex(botVertex, pStream);
859
860 }
861 else if(dec_current>= dec_chain->getNumElements()) /*no more vertices on dec_chain*/
862 {
863 inc_array = inc_chain->getArray();
864 inc_nVertices= inc_chain->getNumElements();
865 reflexChain rChain(20,1);
866 /*put the top vertex into the reflex chain*/
867 rChain.processNewVertex(topVertex, pStream);
868 /*process all the vertices on the inc_chain*/
869 for(i=inc_current; i<inc_nVertices; i++){
870 rChain.processNewVertex(inc_array[i], pStream);
871 }
872 /*process the bottom vertex*/
873 rChain.processNewVertex(botVertex, pStream);
874 }
875 else /*neither chain is empty*/
876 {
877 inc_array = inc_chain -> getArray();
878 dec_array = dec_chain -> getArray();
879 inc_nVertices= inc_chain->getNumElements();
880 dec_nVertices= dec_chain->getNumElements();
881 /*if top of inc_chain is 'lower' than top of dec_chain, process all the
882 *vertices on the dec_chain which are higher than top of inc_chain
883 */
884 if(compFun(inc_array[inc_current], dec_array[dec_current]) <= 0)
885 {
886
887 reflexChain rChain(20, 0);
888 rChain.processNewVertex(topVertex, pStream);
889 for(i=dec_current; i<dec_nVertices; i++)
890 {
891 if(compFun(inc_array[inc_current], dec_array[i]) <= 0)
892 rChain.processNewVertex(dec_array[i], pStream);
893 else
894 break;
895 }
896 rChain.outputFan(inc_array[inc_current], pStream);
897 monoTriangulationRecFun(dec_array[i-1], botVertex,
898 inc_chain, inc_current,
899 dec_chain, i,
900 compFun,
901 pStream);
902 }
903 else /*compFun(inc_array[inc_current], dec_array[dec_current]) > 0*/
904 {
905
906 reflexChain rChain(20, 1);
907 rChain.processNewVertex(topVertex, pStream);
908 for(i=inc_current; i<inc_nVertices; i++)
909 {
910 if(compFun(inc_array[i], dec_array[dec_current]) >0)
911 rChain.processNewVertex(inc_array[i], pStream);
912 else
913 break;
914 }
915 rChain.outputFan(dec_array[dec_current], pStream);
916 monoTriangulationRecFun(inc_array[i-1], botVertex,
917 inc_chain, i,
918 dec_chain, dec_current,
919 compFun,
920 pStream);
921 }
922 }/*end case neither is empty*/
923 }
924
925
926 void monoTriangulationRec(Real* topVertex, Real* botVertex,
927 vertexArray* inc_chain, Int inc_current,
928 vertexArray* dec_chain, Int dec_current,
929 primStream* pStream)
930 {
931 assert( inc_chain != NULL && dec_chain != NULL);
932 assert( ! (inc_current>=inc_chain->getNumElements() &&
933 dec_current>=dec_chain->getNumElements()));
934 Int inc_nVertices;
935 Int dec_nVertices;
936 Real** inc_array ;
937 Real** dec_array ;
938 Int i;
939 assert( ! ( (inc_chain==NULL) && (dec_chain==NULL)));
940
941 if(inc_current>=inc_chain->getNumElements()) /*no more vertices on inc_chain*/
942 {
943
944 dec_array = dec_chain->getArray();
945 dec_nVertices = dec_chain->getNumElements();
946 reflexChain rChain(20,0);
947 /*put the top vertex into the reflex chain*/
948 rChain.processNewVertex(topVertex, pStream);
949 /*process all the vertices on the dec_chain*/
950 for(i=dec_current; i<dec_nVertices; i++){
951 rChain.processNewVertex(dec_array[i], pStream);
952 }
953 /*process the bottom vertex*/
954 rChain.processNewVertex(botVertex, pStream);
955
956 }
957 else if(dec_current>= dec_chain->getNumElements()) /*no more vertices on dec_chain*/
958 {
959 inc_array = inc_chain->getArray();
960 inc_nVertices= inc_chain->getNumElements();
961 reflexChain rChain(20,1);
962 /*put the top vertex into the reflex chain*/
963 rChain.processNewVertex(topVertex, pStream);
964 /*process all the vertices on the inc_chain*/
965 for(i=inc_current; i<inc_nVertices; i++){
966 rChain.processNewVertex(inc_array[i], pStream);
967 }
968 /*process the bottom vertex*/
969 rChain.processNewVertex(botVertex, pStream);
970 }
971 else /*neither chain is empty*/
972 {
973 inc_array = inc_chain -> getArray();
974 dec_array = dec_chain -> getArray();
975 inc_nVertices= inc_chain->getNumElements();
976 dec_nVertices= dec_chain->getNumElements();
977 /*if top of inc_chain is 'lower' than top of dec_chain, process all the
978 *vertices on the dec_chain which are higher than top of inc_chain
979 */
980 if(compV2InY(inc_array[inc_current], dec_array[dec_current]) <= 0)
981 {
982
983 reflexChain rChain(20, 0);
984 rChain.processNewVertex(topVertex, pStream);
985 for(i=dec_current; i<dec_nVertices; i++)
986 {
987 if(compV2InY(inc_array[inc_current], dec_array[i]) <= 0)
988 rChain.processNewVertex(dec_array[i], pStream);
989 else
990 break;
991 }
992 rChain.outputFan(inc_array[inc_current], pStream);
993 monoTriangulationRec(dec_array[i-1], botVertex,
994 inc_chain, inc_current,
995 dec_chain, i,
996 pStream);
997 }
998 else /*compV2InY(inc_array[inc_current], dec_array[dec_current]) > 0*/
999 {
1000
1001 reflexChain rChain(20, 1);
1002 rChain.processNewVertex(topVertex, pStream);
1003 for(i=inc_current; i<inc_nVertices; i++)
1004 {
1005 if(compV2InY(inc_array[i], dec_array[dec_current]) >0)
1006 rChain.processNewVertex(inc_array[i], pStream);
1007 else
1008 break;
1009 }
1010 rChain.outputFan(dec_array[dec_current], pStream);
1011 monoTriangulationRec(inc_array[i-1], botVertex,
1012 inc_chain, i,
1013 dec_chain, dec_current,
1014 pStream);
1015 }
1016 }/*end case neither is empty*/
1017 }
1018
1019
1020
1021 /* the name here assumes that the polygon is Y-monotone, but
1022 *this function also works for X-monotone polygons.
1023 * a monotne polygon consists of two extrem verteices: topVertex and botVertex, and
1024 *two monotone chains: inc_chain, and dec_chain. The edges of the increasing chain (inc_chain)
1025 *is ordered by following pointer: next, while the edges of the decreasing chain (dec_chain)
1026 *is ordered by following pointer: prev
1027 * inc_index index the vertex which is the toppest of the inc_chain which we are handling currently.
1028 * dec_index index the vertex which is the toppest of the dec_chain which we are handling currently.
1029 */
1030 void monoTriangulationRec(directedLine* inc_chain, Int inc_index,
1031 directedLine* dec_chain, Int dec_index,
1032 directedLine* topVertex, Int top_index,
1033 directedLine* botVertex,
1034 primStream* pStream)
1035 {
1036 Int i;
1037 directedLine *temp, *oldtemp;
1038 Int tempIndex, oldtempIndex;
1039
1040 assert(inc_chain != NULL && dec_chain != NULL);
1041
1042 if(inc_chain == botVertex) {
1043 reflexChain rChain(20, 0);
1044 rChain.processNewVertex(topVertex->getVertex(top_index), pStream);
1045 for(i=dec_index; i< dec_chain->get_npoints(); i++){
1046 rChain.processNewVertex(dec_chain->getVertex(i), pStream);
1047 }
1048 for(temp = dec_chain->getPrev(); temp != botVertex; temp = temp->getPrev())
1049 {
1050 for(i=0; i<temp->get_npoints(); i++){
1051 rChain.processNewVertex(temp->getVertex(i), pStream);
1052 }
1053 }
1054 }
1055 else if(dec_chain==botVertex) {
1056 reflexChain rChain(20, 1);
1057 rChain.processNewVertex(topVertex->getVertex(top_index), pStream);
1058 for(i=inc_index; i< inc_chain->get_npoints(); i++){
1059 rChain.processNewVertex(inc_chain->getVertex(i), pStream);
1060 }
1061 for(temp = inc_chain->getPrev(); temp != botVertex; temp = temp->getNext())
1062 {
1063 for(i=0; i<temp->get_npoints(); i++){
1064 rChain.processNewVertex(temp->getVertex(i), pStream);
1065 }
1066 }
1067 }
1068 else /*neither reached the bottom*/{
1069 if(compV2InY(inc_chain->getVertex(inc_index), dec_chain->getVertex(dec_index)) <=0) {
1070 reflexChain rChain(20, 0);
1071 rChain.processNewVertex(topVertex -> getVertex(top_index), pStream);
1072 temp = dec_chain;
1073 tempIndex = dec_index;
1074 while( compV2InY(inc_chain->getVertex(inc_index), temp->getVertex(tempIndex))<=0) {
1075 oldtemp = temp;
1076 oldtempIndex = tempIndex;
1077 rChain.processNewVertex(temp->getVertex(tempIndex), pStream);
1078
1079 if(tempIndex == temp->get_npoints()-1){
1080 tempIndex = 0;
1081 temp = temp->getPrev();
1082 }
1083 else{
1084 tempIndex++;
1085 }
1086 }
1087 rChain.outputFan(inc_chain->getVertex(inc_index), pStream);
1088 monoTriangulationRec(inc_chain, inc_index, temp, tempIndex, oldtemp, oldtempIndex, botVertex, pStream);
1089 }
1090 else /* >0*/ {
1091 reflexChain rChain(20, 1);
1092 rChain.processNewVertex(topVertex -> getVertex(top_index), pStream);
1093 temp = inc_chain;
1094 tempIndex = inc_index;
1095 while( compV2InY(temp->getVertex(tempIndex), dec_chain->getVertex(dec_index))>0){
1096 oldtemp = temp;
1097 oldtempIndex = tempIndex;
1098 rChain.processNewVertex(temp->getVertex(tempIndex), pStream);
1099
1100 if(tempIndex == temp->get_npoints()-1){
1101 tempIndex = 0;
1102 temp = temp->getNext();
1103 }
1104 else{
1105 tempIndex++;
1106 }
1107 }
1108 rChain.outputFan(dec_chain->getVertex(dec_index), pStream);
1109 monoTriangulationRec(temp, tempIndex, dec_chain, dec_index, oldtemp, oldtempIndex, botVertex, pStream);
1110 }
1111 } /*end case neither reached the bottom*/
1112 }
1113
1114 /***************************vertexArray begin here**********************************/
1115 vertexArray::vertexArray(Real2* vertices, Int nVertices)
1116 {
1117 Int i;
1118 size = index = nVertices;
1119 array = (Real**) malloc(sizeof(Real*) * nVertices);
1120 assert(array);
1121 for(i=0; i<nVertices; i++)
1122 {
1123 array[i] = vertices[i];
1124 array[i] = vertices[i];
1125 }
1126 }
1127
1128 vertexArray::vertexArray(Int s)
1129 {
1130 size = s;
1131 array = (Real**) malloc(sizeof(Real*) * s);
1132 assert(array);
1133 index = 0;
1134 }
1135
1136 vertexArray::~vertexArray()
1137 {
1138 free(array);
1139 }
1140
1141 void vertexArray::appendVertex(Real* ptr)
1142 {
1143 Int i;
1144 if(index >= size){
1145 Real** temp = (Real**) malloc(sizeof(Real*) * (2*size +1));
1146 assert(temp);
1147 for(i=0; i<index; i++)
1148 temp[i] = array[i];
1149 free(array);
1150 array = temp;
1151 size = 2*size+1;
1152 }
1153 array[index++] = ptr;
1154 }
1155
1156 void vertexArray::print()
1157 {
1158 printf("vertex Array:index=%i, size=%i\n", index, size);
1159 for(Int i=0; i<index; i++)
1160 {
1161 printf("(%f,%f) ", array[i][0], array[i][1]);
1162 }
1163 printf("\n");
1164 }
1165
1166 /*find the first i such that array[i][1] >= v
1167 * and array[i+1][1] <v
1168 * if index == 0 (the array is empty, return -1.
1169 * if v is above all, return -1.
1170 * if v is below all, return index-1.
1171 */
1172 Int vertexArray::findIndexAbove(Real v)
1173 {
1174 Int i;
1175 if(index == 0)
1176 return -1;
1177 else if(array[0][1] < v)
1178 return -1;
1179 else
1180 {
1181 for(i=1; i<index; i++)
1182 {
1183 if(array[i][1] < v)
1184 break;
1185 }
1186 return i-1;
1187 }
1188 }
1189
1190 /*find the first i<=endIndex such that array[i][1] <= v
1191 * and array[i-1][1] > v
1192 *if sartIndex>endIndex, then return endIndex+1.
1193 *otherwise, startIndex<=endIndex, it is assumed that
1194 * 0<=startIndex<=endIndex<index.
1195 * if v is below all, return endIndex+1
1196 * if v is above all, return startIndex.
1197 */
1198 Int vertexArray::findIndexBelowGen(Real v, Int startIndex, Int endIndex)
1199 {
1200 Int i;
1201 if(startIndex > endIndex)
1202 return endIndex+1;
1203 else if(array[endIndex][1] > v)
1204 return endIndex+1;
1205 else //now array[endIndex][1] <= v
1206 {
1207 for(i=endIndex-1; i>=startIndex; i--)
1208 {
1209 if(array[i][1] > v)
1210 break;
1211 }
1212 return i+1;
1213 }
1214 }
1215
1216 /*find the first i<=endIndex such that array[i-1][1] >= v
1217 * and array[i][1] < v
1218 *if sartIndex>endIndex, then return endIndex+1.
1219 *otherwise, startIndex<=endIndex, it is assumed that
1220 * 0<=startIndex<=endIndex<index.
1221 * if v is below or equal to all, return endIndex+1
1222 * if v is strictly above all, return startIndex.
1223 */
1224 Int vertexArray::findIndexStrictBelowGen(Real v, Int startIndex, Int endIndex)
1225 {
1226 Int i;
1227 if(startIndex > endIndex)
1228 return endIndex+1;
1229 else if(array[endIndex][1] >= v)
1230 return endIndex+1;
1231 else //now array[endIndex][1] < v
1232 {
1233 for(i=endIndex-1; i>=startIndex; i--)
1234 {
1235 if(array[i][1] >= v)
1236 break;
1237 }
1238 return i+1;
1239 }
1240 }
1241
1242 /*find the first i>startIndex such that array[i-1][1] > v
1243 * and array[i][1] >=v
1244 *if sartIndex>endIndex, then return startIndex-1.
1245 *otherwise, startIndex<=endIndex, it is assumed that
1246 * 0<=startIndex<=endIndex<index.
1247 * if v is strictly above all, return startIndex-1
1248 * if v is strictly below all, return endIndex.
1249 */
1250 Int vertexArray::findIndexFirstAboveEqualGen(Real v, Int startIndex, Int endIndex)
1251 {
1252
1253 Int i;
1254 if(startIndex > endIndex)
1255 return startIndex-1;
1256 else if(array[startIndex][1] < v)
1257 return startIndex-1;
1258 else //now array[startIndex][1] >= v
1259 {
1260
1261 for(i=startIndex; i<=endIndex; i++)
1262 {
1263 if(array[i][1] <= v)
1264 break;
1265 }
1266 if(i>endIndex) // v is strictly below all
1267 return endIndex;
1268 else if(array[i][1] == v)
1269 return i;
1270 else
1271 return i-1;
1272 }
1273
1274 }
1275
1276
1277 /*find the first i>=startIndex such that array[i][1] >= v
1278 * and array[i+1][1] <v
1279 *if sartIndex>endIndex, then return startIndex-1.
1280 *otherwise, startIndex<=endIndex, it is assumed that
1281 * 0<=startIndex<=endIndex<index.
1282 * if v is above all, return startIndex-1
1283 * if v is below all, return endIndex.
1284 */
1285 Int vertexArray::findIndexAboveGen(Real v, Int startIndex, Int endIndex)
1286 {
1287 Int i;
1288 if(startIndex > endIndex)
1289 return startIndex-1;
1290 else if(array[startIndex][1] < v)
1291 return startIndex-1;
1292 else //now array[startIndex][1] >= v
1293 {
1294 for(i=startIndex+1; i<=endIndex; i++)
1295 {
1296 if(array[i][1] < v)
1297 break;
1298 }
1299 return i-1;
1300 }
1301 }
1302
1303 Int vertexArray::findDecreaseChainFromEnd(Int begin, Int end)
1304 {
1305 Int i = end;
1306 Real prevU = array[i][0];
1307 Real thisU;
1308 for(i=end-1; i>=begin; i--){
1309 thisU = array[i][0];
1310 if(thisU < prevU)
1311 prevU = thisU;
1312 else
1313 break;
1314 }
1315 return i;
1316 }
1317
1318 //if(V(start) == v, return start, other wise return the
1319 //last i so that V(i)==v
1320 Int vertexArray::skipEqualityFromStart(Real v, Int start, Int end)
1321 {
1322 Int i;
1323 if(array[start][1] != v)
1324 return start;
1325 //now array[start][1] == v
1326 for(i=start+1; i<= end; i++)
1327 if(array[i][1] != v)
1328 break;
1329 return i-1;
1330 }
1331
1332
1333 /***************************vertexArray end****************************************/
1334
1335
1336
1337 /***************************relfex chain stuff begin here*****************************/
1338
1339 reflexChain::reflexChain(Int size, Int is_increasing)
1340 {
1341 queue = (Real2*) malloc(sizeof(Real2) * size);
1342 assert(queue);
1343 index_queue = 0;
1344 size_queue = size;
1345 isIncreasing = is_increasing;
1346 }
1347
1348 reflexChain::~reflexChain()
1349 {
1350 free(queue);
1351 }
1352
1353 /*put (u,v) at the end of the queue
1354 *pay attention to space
1355 */
1356 void reflexChain::insert(Real u, Real v)
1357 {
1358 Int i;
1359 if(index_queue >= size_queue) {
1360 Real2 *temp = (Real2*) malloc(sizeof(Real2) * (2*size_queue+1));
1361 assert(temp);
1362
1363 /*copy*/
1364 for(i=0; i<index_queue; i++){
1365 temp[i][0] = queue[i][0];
1366 temp[i][1] = queue[i][1];
1367 }
1368
1369 free(queue);
1370 queue = temp;
1371 size_queue = 2*size_queue + 1;
1372 }
1373
1374 queue[index_queue][0] = u;
1375 queue[index_queue][1] = v;
1376 index_queue ++;
1377 }
1378
1379 void reflexChain::insert(Real v[2])
1380 {
1381 insert(v[0], v[1]);
1382 }
1383
1384 /*
1385 static Real area(Real A[2], Real B[2], Real C[2])
1386 {
1387 Real Bx, By, Cx, Cy;
1388 Bx = B[0] - A[0];
1389 By = B[1] - A[1];
1390 Cx = C[0] - A[0];
1391 Cy = C[1] - A[1];
1392 return Bx*Cy - Cx*By;
1393 }
1394 */
1395
1396 /*the chain is reflex, and the vertex v is
1397 *on the other side of the chain, so that
1398 *we can outout the fan with v as the
1399 *the center
1400 */
1401 void reflexChain::outputFan(Real v[2], primStream* pStream)
1402 {
1403 Int i;
1404 pStream->begin();
1405 pStream->insert(v);
1406 if(isIncreasing) {
1407 for(i=0; i<index_queue; i++)
1408 pStream->insert(queue[i]);
1409 }
1410 else {
1411 for(i=index_queue-1; i>=0; i--)
1412 pStream->insert(queue[i]);
1413 }
1414 pStream->end(PRIMITIVE_STREAM_FAN);
1415 }
1416
1417 void reflexChain::processNewVertex(Real v[2], primStream* pStream)
1418 {
1419 Int i,j,k;
1420 Int isReflex;
1421 /*if there are at most one vertex in the queue, then simply insert
1422 */
1423 if(index_queue <=1){
1424 insert(v);
1425 return;
1426 }
1427
1428 /*there are at least two vertices in the queue*/
1429 j=index_queue-1;
1430
1431 for(i=j; i>=1; i--) {
1432 if(isIncreasing) {
1433 isReflex = (area(queue[i-1], queue[i], v) <= 0.0);
1434 }
1435 else /*decreasing*/{
1436 isReflex = (area(v, queue[i], queue[i-1]) <= 0.0);
1437 }
1438 if(isReflex) {
1439 break;
1440 }
1441 }
1442
1443 /*
1444 *if i<j then vertices: i+1--j are convex
1445 * output triangle fan:
1446 * v, and queue[i], i+1, ..., j
1447 */
1448 if(i<j)
1449 {
1450 pStream->begin();
1451 pStream->insert(v);
1452 if(isIncreasing) {
1453 for(k=i; k<=j; k++)
1454 pStream->insert(queue[k]);
1455 }
1456 else {
1457 for(k=j; k>=i; k--)
1458 pStream->insert(queue[k]);
1459 }
1460
1461 pStream->end(PRIMITIVE_STREAM_FAN);
1462 }
1463
1464 /*delete vertices i+1--j from the queue*/
1465 index_queue = i+1;
1466 /*finally insert v at the end of the queue*/
1467 insert(v);
1468
1469 }
1470
1471 void reflexChain::print()
1472 {
1473 Int i;
1474 printf("reflex chain: isIncreasing=%i\n", isIncreasing);
1475 for(i=0; i<index_queue; i++) {
1476 printf("(%f,%f) ", queue[i][0], queue[i][1]);
1477 }
1478 printf("\n");
1479 }