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