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