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 } 1483