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 "gluos.h" 39 //#include <stdlib.h> 40 //#include <stdio.h> 41 #include <math.h> 42 43 #ifndef max 44 #define max(a,b) ((a>b)? a:b) 45 #endif 46 #ifndef min 47 #define min(a,b) ((a>b)? b:a) 48 #endif 49 50 #include <GL/gl.h> 51 52 #include "glimports.h" 53 #include "zlassert.h" 54 #include "sampleMonoPoly.h" 55 #include "sampleComp.h" 56 #include "polyDBG.h" 57 #include "partitionX.h" 58 59 60 #define ZERO 0.00001 61 62 //#define MYDEBUG 63 64 //#define SHORTEN_GRID_LINE 65 //see work/newtess/internal/test/problems 66 67 68 /*split a polygon so that each vertex correcpond to one edge 69 *the head of the first edge of the returned plygon must be the head of the first 70 *edge of the origianl polygon. This is crucial for the code in sampleMonoPoly function 71 */ 72 directedLine* polygonConvert(directedLine* polygon) 73 { 74 int i; 75 directedLine* ret; 76 sampledLine* sline; 77 sline = new sampledLine(2); 78 sline->setPoint(0, polygon->getVertex(0)); 79 sline->setPoint(1, polygon->getVertex(1)); 80 ret=new directedLine(INCREASING, sline); 81 for(i=1; i<= polygon->get_npoints()-2; i++) 82 { 83 sline = new sampledLine(2); 84 sline->setPoint(0, polygon->getVertex(i)); 85 sline->setPoint(1, polygon->getVertex(i+1)); 86 ret->insert(new directedLine(INCREASING, sline)); 87 } 88 89 for(directedLine *temp = polygon->getNext(); temp != polygon; temp = temp->getNext()) 90 { 91 for(i=0; i<= temp->get_npoints()-2; i++) 92 { 93 sline = new sampledLine(2); 94 sline->setPoint(0, temp->getVertex(i)); 95 sline->setPoint(1, temp->getVertex(i+1)); 96 ret->insert(new directedLine(INCREASING, sline)); 97 } 98 } 99 return ret; 100 } 101 102 void triangulateConvexPolyVertical(directedLine* topV, directedLine* botV, primStream *pStream) 103 { 104 Int i,j; 105 Int n_leftVerts; 106 Int n_rightVerts; 107 Real** leftVerts; 108 Real** rightVerts; 109 directedLine* tempV; 110 n_leftVerts = 0; 111 for(tempV = topV; tempV != botV; tempV = tempV->getNext()) 112 { 113 n_leftVerts += tempV->get_npoints(); 114 } 115 n_rightVerts=0; 116 for(tempV = botV; tempV != topV; tempV = tempV->getNext()) 117 { 118 n_rightVerts += tempV->get_npoints(); 119 } 120 121 Real2* temp_leftVerts = (Real2 *) malloc(sizeof(Real2) * n_leftVerts); 122 assert(temp_leftVerts); 123 Real2* temp_rightVerts = (Real2 *) malloc(sizeof(Real2) * n_rightVerts); 124 assert(temp_rightVerts); 125 126 leftVerts = (Real**) malloc(sizeof(Real2*) * n_leftVerts); 127 assert(leftVerts); 128 rightVerts = (Real**) malloc(sizeof(Real2*) * n_rightVerts); 129 assert(rightVerts); 130 for(i=0; i<n_leftVerts; i++) 131 leftVerts[i] = temp_leftVerts[i]; 132 for(i=0; i<n_rightVerts; i++) 133 rightVerts[i] = temp_rightVerts[i]; 134 135 i=0; 136 for(tempV = topV; tempV != botV; tempV = tempV->getNext()) 137 { 138 for(j=1; j<tempV->get_npoints(); j++) 139 { 140 leftVerts[i][0] = tempV->getVertex(j)[0]; 141 leftVerts[i][1] = tempV->getVertex(j)[1]; 142 i++; 143 } 144 } 145 n_leftVerts = i; 146 i=0; 147 for(tempV = topV->getPrev(); tempV != botV->getPrev(); tempV = tempV->getPrev()) 148 { 149 for(j=tempV->get_npoints()-1; j>=1; j--) 150 { 151 rightVerts[i][0] = tempV->getVertex(j)[0]; 152 rightVerts[i][1] = tempV->getVertex(j)[1]; 153 i++; 154 } 155 } 156 n_rightVerts = i; 157 triangulateXYMonoTB(n_leftVerts, leftVerts, n_rightVerts, rightVerts, pStream); 158 free(leftVerts); 159 free(rightVerts); 160 free(temp_leftVerts); 161 free(temp_rightVerts); 162 } 163 164 void triangulateConvexPolyHoriz(directedLine* leftV, directedLine* rightV, primStream *pStream) 165 { 166 Int i,j; 167 Int n_lowerVerts; 168 Int n_upperVerts; 169 Real2 *lowerVerts; 170 Real2 *upperVerts; 171 directedLine* tempV; 172 n_lowerVerts=0; 173 for(tempV = leftV; tempV != rightV; tempV = tempV->getNext()) 174 { 175 n_lowerVerts += tempV->get_npoints(); 176 } 177 n_upperVerts=0; 178 for(tempV = rightV; tempV != leftV; tempV = tempV->getNext()) 179 { 180 n_upperVerts += tempV->get_npoints(); 181 } 182 lowerVerts = (Real2 *) malloc(sizeof(Real2) * n_lowerVerts); 183 assert(n_lowerVerts); 184 upperVerts = (Real2 *) malloc(sizeof(Real2) * n_upperVerts); 185 assert(n_upperVerts); 186 i=0; 187 for(tempV = leftV; tempV != rightV; tempV = tempV->getNext()) 188 { 189 for(j=0; j<tempV->get_npoints(); j++) 190 { 191 lowerVerts[i][0] = tempV->getVertex(j)[0]; 192 lowerVerts[i][1] = tempV->getVertex(j)[1]; 193 i++; 194 } 195 } 196 i=0; 197 for(tempV = leftV->getPrev(); tempV != rightV->getPrev(); tempV = tempV->getPrev()) 198 { 199 for(j=tempV->get_npoints()-1; j>=0; j--) 200 { 201 upperVerts[i][0] = tempV->getVertex(j)[0]; 202 upperVerts[i][1] = tempV->getVertex(j)[1]; 203 i++; 204 } 205 } 206 triangulateXYMono(n_upperVerts, upperVerts, n_lowerVerts, lowerVerts, pStream); 207 free(lowerVerts); 208 free(upperVerts); 209 } 210 void triangulateConvexPoly(directedLine* polygon, Int ulinear, Int vlinear, primStream* pStream) 211 { 212 /*find left, right, top , bot 213 */ 214 directedLine* tempV; 215 directedLine* topV; 216 directedLine* botV; 217 directedLine* leftV; 218 directedLine* rightV; 219 topV = botV = polygon; 220 221 for(tempV = polygon->getNext(); tempV != polygon; tempV = tempV->getNext()) 222 { 223 if(compV2InY(topV->head(), tempV->head())<0) { 224 225 topV = tempV; 226 } 227 if(compV2InY(botV->head(), tempV->head())>0) { 228 229 botV = tempV; 230 } 231 } 232 //find leftV 233 for(tempV = topV; tempV != botV; tempV = tempV->getNext()) 234 { 235 if(tempV->tail()[0] >= tempV->head()[0]) 236 break; 237 } 238 leftV = tempV; 239 //find rightV 240 for(tempV = botV; tempV != topV; tempV = tempV->getNext()) 241 { 242 if(tempV->tail()[0] <= tempV->head()[0]) 243 break; 244 } 245 rightV = tempV; 246 if(vlinear) 247 { 248 triangulateConvexPolyHoriz( leftV, rightV, pStream); 249 } 250 else if(ulinear) 251 { 252 triangulateConvexPolyVertical(topV, botV, pStream); 253 } 254 else 255 { 256 if(DBG_is_U_direction(polygon)) 257 { 258 triangulateConvexPolyHoriz( leftV, rightV, pStream); 259 } 260 else 261 triangulateConvexPolyVertical(topV, botV, pStream); 262 } 263 } 264 265 /*for debug purpose*/ 266 void drawCorners( 267 Real* topV, Real* botV, 268 vertexArray* leftChain, 269 vertexArray* rightChain, 270 gridBoundaryChain* leftGridChain, 271 gridBoundaryChain* rightGridChain, 272 Int gridIndex1, 273 Int gridIndex2, 274 Int leftCornerWhere, 275 Int leftCornerIndex, 276 Int rightCornerWhere, 277 Int rightCornerIndex, 278 Int bot_leftCornerWhere, 279 Int bot_leftCornerIndex, 280 Int bot_rightCornerWhere, 281 Int bot_rightCornerIndex) 282 { 283 Real* leftCornerV; 284 Real* rightCornerV; 285 Real* bot_leftCornerV; 286 Real* bot_rightCornerV; 287 288 if(leftCornerWhere == 1) 289 leftCornerV = topV; 290 else if(leftCornerWhere == 0) 291 leftCornerV = leftChain->getVertex(leftCornerIndex); 292 else 293 leftCornerV = rightChain->getVertex(leftCornerIndex); 294 295 if(rightCornerWhere == 1) 296 rightCornerV = topV; 297 else if(rightCornerWhere == 0) 298 rightCornerV = leftChain->getVertex(rightCornerIndex); 299 else 300 rightCornerV = rightChain->getVertex(rightCornerIndex); 301 302 if(bot_leftCornerWhere == 1) 303 bot_leftCornerV = botV; 304 else if(bot_leftCornerWhere == 0) 305 bot_leftCornerV = leftChain->getVertex(bot_leftCornerIndex); 306 else 307 bot_leftCornerV = rightChain->getVertex(bot_leftCornerIndex); 308 309 if(bot_rightCornerWhere == 1) 310 bot_rightCornerV = botV; 311 else if(bot_rightCornerWhere == 0) 312 bot_rightCornerV = leftChain->getVertex(bot_rightCornerIndex); 313 else 314 bot_rightCornerV = rightChain->getVertex(bot_rightCornerIndex); 315 316 Real topGridV = leftGridChain->get_v_value(gridIndex1); 317 Real topGridU1 = leftGridChain->get_u_value(gridIndex1); 318 Real topGridU2 = rightGridChain->get_u_value(gridIndex1); 319 Real botGridV = leftGridChain->get_v_value(gridIndex2); 320 Real botGridU1 = leftGridChain->get_u_value(gridIndex2); 321 Real botGridU2 = rightGridChain->get_u_value(gridIndex2); 322 323 glBegin(GL_LINE_STRIP); 324 glVertex2fv(leftCornerV); 325 glVertex2f(topGridU1, topGridV); 326 glEnd(); 327 328 glBegin(GL_LINE_STRIP); 329 glVertex2fv(rightCornerV); 330 glVertex2f(topGridU2, topGridV); 331 glEnd(); 332 333 glBegin(GL_LINE_STRIP); 334 glVertex2fv(bot_leftCornerV); 335 glVertex2f(botGridU1, botGridV); 336 glEnd(); 337 338 glBegin(GL_LINE_STRIP); 339 glVertex2fv(bot_rightCornerV); 340 glVertex2f(botGridU2, botGridV); 341 glEnd(); 342 343 344 } 345 346 void toVertexArrays(directedLine* topV, directedLine* botV, vertexArray& leftChain, vertexArray& rightChain) 347 { 348 Int i; 349 directedLine* tempV; 350 for(i=1; i<=topV->get_npoints()-2; i++) { /*the first vertex is the top vertex which doesn't belong to inc_chain*/ 351 leftChain.appendVertex(topV->getVertex(i)); 352 } 353 for(tempV = topV->getNext(); tempV != botV; tempV = tempV->getNext()) 354 { 355 for(i=0; i<=tempV->get_npoints()-2; i++){ 356 leftChain.appendVertex(tempV->getVertex(i)); 357 } 358 } 359 360 for(tempV = topV->getPrev(); tempV != botV; tempV = tempV->getPrev()) 361 { 362 for(i=tempV->get_npoints()-2; i>=0; i--){ 363 rightChain.appendVertex(tempV->getVertex(i)); 364 } 365 } 366 for(i=botV->get_npoints()-2; i>=1; i--){ 367 rightChain.appendVertex(tempV->getVertex(i)); 368 } 369 } 370 371 372 void findTopAndBot(directedLine* polygon, directedLine*& topV, directedLine*& botV) 373 { 374 assert(polygon); 375 directedLine* tempV; 376 topV = botV = polygon; 377 for(tempV = polygon->getNext(); tempV != polygon; tempV = tempV->getNext()) 378 { 379 if(compV2InY(topV->head(), tempV->head())<0) { 380 topV = tempV; 381 } 382 if(compV2InY(botV->head(), tempV->head())>0) { 383 botV = tempV; 384 } 385 } 386 } 387 388 void findGridChains(directedLine* topV, directedLine* botV, 389 gridWrap* grid, 390 gridBoundaryChain*& leftGridChain, 391 gridBoundaryChain*& rightGridChain) 392 { 393 /*find the first(top) and the last (bottom) grid line which intersect the 394 *this polygon 395 */ 396 Int firstGridIndex; /*the index in the grid*/ 397 Int lastGridIndex; 398 399 firstGridIndex = (Int) ((topV->head()[1] - grid->get_v_min()) / (grid->get_v_max() - grid->get_v_min()) * (grid->get_n_vlines()-1)); 400 401 if(botV->head()[1] < grid->get_v_min()) 402 lastGridIndex = 0; 403 else 404 lastGridIndex = (Int) ((botV->head()[1] - grid->get_v_min()) / (grid->get_v_max() - grid->get_v_min()) * (grid->get_n_vlines()-1)) + 1; 405 406 /*find the interval inside the polygon for each gridline*/ 407 Int *leftGridIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1)); 408 assert(leftGridIndices); 409 Int *rightGridIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1)); 410 assert(rightGridIndices); 411 Int *leftGridInnerIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1)); 412 assert(leftGridInnerIndices); 413 Int *rightGridInnerIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1)); 414 assert(rightGridInnerIndices); 415 416 findLeftGridIndices(topV, firstGridIndex, lastGridIndex, grid, leftGridIndices, leftGridInnerIndices); 417 418 findRightGridIndices(topV, firstGridIndex, lastGridIndex, grid, rightGridIndices, rightGridInnerIndices); 419 420 leftGridChain = new gridBoundaryChain(grid, firstGridIndex, firstGridIndex-lastGridIndex+1, leftGridIndices, leftGridInnerIndices); 421 422 rightGridChain = new gridBoundaryChain(grid, firstGridIndex, firstGridIndex-lastGridIndex+1, rightGridIndices, rightGridInnerIndices); 423 424 free(leftGridIndices); 425 free(rightGridIndices); 426 free(leftGridInnerIndices); 427 free(rightGridInnerIndices); 428 } 429 430 void findDownCorners(Real *botVertex, 431 vertexArray *leftChain, Int leftChainStartIndex, Int leftChainEndIndex, 432 vertexArray *rightChain, Int rightChainStartIndex, Int rightChainEndIndex, 433 Real v, 434 Real uleft, 435 Real uright, 436 Int& ret_leftCornerWhere, /*0: left chain, 1: topvertex, 2: rightchain*/ 437 Int& ret_leftCornerIndex, /*useful when ret_leftCornerWhere == 0 or 2*/ 438 Int& ret_rightCornerWhere, /*0: left chain, 1: topvertex, 2: rightchain*/ 439 Int& ret_rightCornerIndex /*useful when ret_leftCornerWhere == 0 or 2*/ 440 ) 441 { 442 #ifdef MYDEBUG 443 printf("*************enter find donw corner\n"); 444 printf("finddownCorner: v=%f, uleft=%f, uright=%f\n", v, uleft, uright); 445 printf("(%i,%i,%i,%i)\n", leftChainStartIndex, leftChainEndIndex,rightChainStartIndex, rightChainEndIndex); 446 printf("left chain is\n"); 447 leftChain->print(); 448 printf("right chain is\n"); 449 rightChain->print(); 450 #endif 451 452 assert(v > botVertex[1]); 453 Real leftGridPoint[2]; 454 leftGridPoint[0] = uleft; 455 leftGridPoint[1] = v; 456 Real rightGridPoint[2]; 457 rightGridPoint[0] = uright; 458 rightGridPoint[1] = v; 459 460 Int i; 461 Int index1, index2; 462 463 index1 = leftChain->findIndexBelowGen(v, leftChainStartIndex, leftChainEndIndex); 464 index2 = rightChain->findIndexBelowGen(v, rightChainStartIndex, rightChainEndIndex); 465 466 if(index2 <= rightChainEndIndex) //index2 was found above 467 index2 = rightChain->skipEqualityFromStart(v, index2, rightChainEndIndex); 468 469 if(index1>leftChainEndIndex && index2 > rightChainEndIndex) /*no point below v on left chain or right chain*/ 470 { 471 472 /*the botVertex is the only vertex below v*/ 473 ret_leftCornerWhere = 1; 474 ret_rightCornerWhere = 1; 475 } 476 else if(index1>leftChainEndIndex ) /*index2 <= rightChainEndIndex*/ 477 { 478 479 ret_rightCornerWhere = 2; /*on right chain*/ 480 ret_rightCornerIndex = index2; 481 482 483 Real tempMin = rightChain->getVertex(index2)[0]; 484 Int tempI = index2; 485 for(i=index2+1; i<= rightChainEndIndex; i++) 486 if(rightChain->getVertex(i)[0] < tempMin) 487 { 488 tempI = i; 489 tempMin = rightChain->getVertex(i)[0]; 490 } 491 492 493 //we consider whether we can use botVertex as left corner. First check 494 //if (leftGirdPoint, botVertex) interesects right chian or not. 495 if(DBG_intersectChain(rightChain, rightChainStartIndex,rightChainEndIndex, 496 leftGridPoint, botVertex)) 497 { 498 ret_leftCornerWhere = 2;//right 499 ret_leftCornerIndex = index2; //should use tempI??? 500 } 501 else if(botVertex[0] < tempMin) 502 ret_leftCornerWhere = 1; //bot 503 else 504 { 505 ret_leftCornerWhere = 2; //right 506 ret_leftCornerIndex = tempI; 507 } 508 } 509 else if(index2> rightChainEndIndex) /*index1<=leftChainEndIndex*/ 510 { 511 ret_leftCornerWhere = 0; /*left chain*/ 512 ret_leftCornerIndex = index1; 513 514 /*find the vertex on the left chain with the maximum u, 515 *either this vertex or the botvertex can be used as the right corner 516 */ 517 518 Int tempI; 519 //skip those points which are equal to v. (avoid degeneratcy) 520 for(tempI = index1; tempI <= leftChainEndIndex; tempI++) 521 if(leftChain->getVertex(tempI)[1] < v) 522 break; 523 if(tempI > leftChainEndIndex) 524 ret_rightCornerWhere = 1; 525 else 526 { 527 Real tempMax = leftChain->getVertex(tempI)[0]; 528 for(i=tempI; i<= leftChainEndIndex; i++) 529 if(leftChain->getVertex(i)[0] > tempMax) 530 { 531 tempI = i; 532 tempMax = leftChain->getVertex(i)[0]; 533 } 534 535 536 537 //we consider whether we can use botVertex as a corner. So first we check 538 //whether (rightGridPoint, botVertex) interescts the left chain or not. 539 if(DBG_intersectChain(leftChain, leftChainStartIndex,leftChainEndIndex, 540 rightGridPoint, botVertex)) 541 { 542 ret_rightCornerWhere = 0; 543 ret_rightCornerIndex = index1; //should use tempI??? 544 } 545 else if(botVertex[0] > tempMax) 546 { 547 548 ret_rightCornerWhere = 1; 549 } 550 else 551 { 552 ret_rightCornerWhere = 0; 553 ret_rightCornerIndex = tempI; 554 } 555 } 556 557 } 558 else /*index1<=leftChainEndIndex and index2 <=rightChainEndIndex*/ 559 { 560 if(leftChain->getVertex(index1)[1] >= rightChain->getVertex(index2)[1]) /*left point above right point*/ 561 { 562 ret_leftCornerWhere = 0; /*on left chain*/ 563 ret_leftCornerIndex = index1; 564 565 Real tempMax; 566 Int tempI; 567 568 tempI = index1; 569 tempMax = leftChain->getVertex(index1)[0]; 570 571 /*find the maximum u for all the points on the left above the right point index2*/ 572 for(i=index1+1; i<= leftChainEndIndex; i++) 573 { 574 if(leftChain->getVertex(i)[1] < rightChain->getVertex(index2)[1]) 575 break; 576 577 if(leftChain->getVertex(i)[0]>tempMax) 578 { 579 tempI = i; 580 tempMax = leftChain->getVertex(i)[0]; 581 } 582 } 583 //we consider if we can use rightChain(index2) as right corner 584 //we check if (rightChain(index2), rightGidPoint) intersecs left chain or not. 585 if(DBG_intersectChain(leftChain, leftChainStartIndex,leftChainEndIndex, rightGridPoint, rightChain->getVertex(index2))) 586 { 587 ret_rightCornerWhere = 0; 588 ret_rightCornerIndex = index1; //should use tempI??? 589 } 590 else if(tempMax >= rightChain->getVertex(index2)[0] || 591 tempMax >= uright 592 ) 593 { 594 595 ret_rightCornerWhere = 0; /*on left Chain*/ 596 ret_rightCornerIndex = tempI; 597 } 598 else 599 { 600 ret_rightCornerWhere = 2; /*on right chain*/ 601 ret_rightCornerIndex = index2; 602 } 603 } 604 else /*left below right*/ 605 { 606 ret_rightCornerWhere = 2; /*on the right*/ 607 ret_rightCornerIndex = index2; 608 609 Real tempMin; 610 Int tempI; 611 612 tempI = index2; 613 tempMin = rightChain->getVertex(index2)[0]; 614 615 /*find the minimum u for all the points on the right above the left poitn index1*/ 616 for(i=index2+1; i<= rightChainEndIndex; i++) 617 { 618 if( rightChain->getVertex(i)[1] < leftChain->getVertex(index1)[1]) 619 break; 620 if(rightChain->getVertex(i)[0] < tempMin) 621 { 622 tempI = i; 623 tempMin = rightChain->getVertex(i)[0]; 624 } 625 } 626 627 //we consider if we can use leftchain(index1) as left corner. 628 //we check if (leftChain(index1) intersects right chian or not 629 if(DBG_intersectChain(rightChain, rightChainStartIndex, rightChainEndIndex, leftGridPoint, leftChain->getVertex(index1))) 630 { 631 ret_leftCornerWhere = 2; 632 ret_leftCornerIndex = index2; //should use tempI??? 633 } 634 else if(tempMin <= leftChain->getVertex(index1)[0] || 635 tempMin <= uleft) 636 { 637 ret_leftCornerWhere = 2; /* on right chain*/ 638 ret_leftCornerIndex = tempI; 639 } 640 else 641 { 642 ret_leftCornerWhere = 0; /*on left chain*/ 643 ret_leftCornerIndex = index1; 644 } 645 } 646 } 647 648 } 649 650 651 void findUpCorners(Real *topVertex, 652 vertexArray *leftChain, Int leftChainStartIndex, Int leftChainEndIndex, 653 vertexArray *rightChain, Int rightChainStartIndex, Int rightChainEndIndex, 654 Real v, 655 Real uleft, 656 Real uright, 657 Int& ret_leftCornerWhere, /*0: left chain, 1: topvertex, 2: rightchain*/ 658 Int& ret_leftCornerIndex, /*useful when ret_leftCornerWhere == 0 or 2*/ 659 Int& ret_rightCornerWhere, /*0: left chain, 1: topvertex, 2: rightchain*/ 660 Int& ret_rightCornerIndex /*useful when ret_leftCornerWhere == 0 or 2*/ 661 ) 662 { 663 #ifdef MYDEBUG 664 printf("***********enter findUpCorners\n"); 665 #endif 666 667 assert(v < topVertex[1]); 668 Real leftGridPoint[2]; 669 leftGridPoint[0] = uleft; 670 leftGridPoint[1] = v; 671 Real rightGridPoint[2]; 672 rightGridPoint[0] = uright; 673 rightGridPoint[1] = v; 674 675 Int i; 676 Int index1, index2; 677 678 index1 = leftChain->findIndexFirstAboveEqualGen(v, leftChainStartIndex, leftChainEndIndex); 679 680 681 index2 = rightChain->findIndexFirstAboveEqualGen(v, rightChainStartIndex, rightChainEndIndex); 682 683 if(index2>= leftChainStartIndex) //index2 was found above 684 index2 = rightChain->skipEqualityFromStart(v, index2, rightChainEndIndex); 685 686 if(index1<leftChainStartIndex && index2 <rightChainStartIndex) /*no point above v on left chain or right chain*/ 687 { 688 /*the topVertex is the only vertex above v*/ 689 ret_leftCornerWhere = 1; 690 ret_rightCornerWhere = 1; 691 } 692 else if(index1<leftChainStartIndex ) /*index2 >= rightChainStartIndex*/ 693 { 694 ret_rightCornerWhere = 2; /*on right chain*/ 695 ret_rightCornerIndex = index2; 696 697 //find the minimum u on right top, either that, or top, or right[index2] is the left corner 698 Real tempMin = rightChain->getVertex(index2)[0]; 699 Int tempI = index2; 700 for(i=index2-1; i>=rightChainStartIndex; i--) 701 if(rightChain->getVertex(i)[0] < tempMin) 702 { 703 tempMin = rightChain->getVertex(i)[0]; 704 tempI = i; 705 } 706 //chech whether (leftGridPoint, top) intersects rightchai, 707 //if yes, use right corner as left corner 708 //if not, use top or right[tempI] as left corner 709 if(DBG_intersectChain(rightChain, rightChainStartIndex, rightChainEndIndex, 710 leftGridPoint, topVertex)) 711 { 712 ret_leftCornerWhere = 2; //rightChain 713 ret_leftCornerIndex = index2; 714 } 715 else if(topVertex[0] < tempMin) 716 ret_leftCornerWhere = 1; /*topvertex*/ 717 else 718 { 719 ret_leftCornerWhere = 2; //right chain 720 ret_leftCornerIndex = tempI; 721 } 722 723 } 724 else if(index2< rightChainStartIndex) /*index1>=leftChainStartIndex*/ 725 { 726 ret_leftCornerWhere = 0; /*left chain*/ 727 ret_leftCornerIndex = index1; 728 729 //find the maximum u on the left top section. either that or topvertex, or left[index1] is the right corner 730 Real tempMax = leftChain->getVertex(index1)[0]; 731 Int tempI = index1; 732 733 for(i=index1-1; i>=leftChainStartIndex; i--){ 734 735 if(leftChain->getVertex(i)[0] > tempMax) 736 { 737 738 tempMax = leftChain->getVertex(i)[0]; 739 tempI = i; 740 } 741 } 742 //check whether (rightGridPoint, top) intersects leftChain or not 743 //if yes, we use leftCorner as the right corner 744 //if not, we use either top or left[tempI] as the right corner 745 if(DBG_intersectChain(leftChain, leftChainStartIndex,leftChainEndIndex, 746 rightGridPoint, topVertex)) 747 { 748 ret_rightCornerWhere = 0; //left chan 749 ret_rightCornerIndex = index1; 750 } 751 else if(topVertex[0] > tempMax) 752 ret_rightCornerWhere = 1;//topVertex 753 else 754 { 755 ret_rightCornerWhere = 0;//left chain 756 ret_rightCornerIndex = tempI; 757 } 758 } 759 else /*index1>=leftChainStartIndex and index2 >=rightChainStartIndex*/ 760 { 761 if(leftChain->getVertex(index1)[1] <= rightChain->getVertex(index2)[1]) /*left point below right point*/ 762 { 763 ret_leftCornerWhere = 0; /*on left chain*/ 764 ret_leftCornerIndex = index1; 765 766 Real tempMax; 767 Int tempI; 768 769 tempI = index1; 770 tempMax = leftChain->getVertex(index1)[0]; 771 772 /*find the maximum u for all the points on the left below the right point index2*/ 773 for(i=index1-1; i>= leftChainStartIndex; i--) 774 { 775 if(leftChain->getVertex(i)[1] > rightChain->getVertex(index2)[1]) 776 break; 777 778 if(leftChain->getVertex(i)[0]>tempMax) 779 { 780 tempI = i; 781 tempMax = leftChain->getVertex(i)[0]; 782 } 783 } 784 //chek whether (rightChain(index2), rightGridPoint) intersects leftchian or not 785 if(DBG_intersectChain(leftChain, leftChainStartIndex, leftChainEndIndex, rightGridPoint, rightChain->getVertex(index2))) 786 { 787 ret_rightCornerWhere = 0; 788 ret_rightCornerIndex = index1; 789 } 790 else if(tempMax >= rightChain->getVertex(index2)[0] || 791 tempMax >= uright) 792 { 793 ret_rightCornerWhere = 0; /*on left Chain*/ 794 ret_rightCornerIndex = tempI; 795 } 796 else 797 { 798 ret_rightCornerWhere = 2; /*on right chain*/ 799 ret_rightCornerIndex = index2; 800 } 801 } 802 else /*left above right*/ 803 { 804 ret_rightCornerWhere = 2; /*on the right*/ 805 ret_rightCornerIndex = index2; 806 807 Real tempMin; 808 Int tempI; 809 810 tempI = index2; 811 tempMin = rightChain->getVertex(index2)[0]; 812 813 /*find the minimum u for all the points on the right below the left poitn index1*/ 814 for(i=index2-1; i>= rightChainStartIndex; i--) 815 { 816 if( rightChain->getVertex(i)[1] > leftChain->getVertex(index1)[1]) 817 break; 818 if(rightChain->getVertex(i)[0] < tempMin) 819 { 820 tempI = i; 821 tempMin = rightChain->getVertex(i)[0]; 822 } 823 } 824 //check whether (leftGRidPoint,left(index1)) interesect right chain 825 if(DBG_intersectChain(rightChain, rightChainStartIndex, rightChainEndIndex, 826 leftGridPoint, leftChain->getVertex(index1))) 827 { 828 ret_leftCornerWhere = 2; //right 829 ret_leftCornerIndex = index2; 830 } 831 else if(tempMin <= leftChain->getVertex(index1)[0] || 832 tempMin <= uleft) 833 { 834 ret_leftCornerWhere = 2; /* on right chain*/ 835 ret_leftCornerIndex = tempI; 836 } 837 else 838 { 839 ret_leftCornerWhere = 0; /*on left chain*/ 840 ret_leftCornerIndex = index1; 841 } 842 } 843 } 844 #ifdef MYDEBUG 845 printf("***********leave findUpCorners\n"); 846 #endif 847 } 848 849 //return 1 if neck exists, 0 othewise 850 Int findNeckF(vertexArray *leftChain, Int botLeftIndex, 851 vertexArray *rightChain, Int botRightIndex, 852 gridBoundaryChain* leftGridChain, 853 gridBoundaryChain* rightGridChain, 854 Int gridStartIndex, 855 Int& neckLeft, 856 Int& neckRight) 857 { 858 /* 859 printf("enter findNeckF, botleft, botright=%i,%i,gstartindex=%i\n",botLeftIndex,botRightIndex,gridStartIndex); 860 printf("leftChain is\n"); 861 leftChain->print(); 862 printf("rightChain is\n"); 863 rightChain->print(); 864 */ 865 866 Int lowerGridIndex; //the grid below leftChain and rightChian vertices 867 Int i; 868 Int n_vlines = leftGridChain->get_nVlines(); 869 Real v; 870 if(botLeftIndex >= leftChain->getNumElements() || 871 botRightIndex >= rightChain->getNumElements()) 872 return 0; //no neck exists 873 874 v=min(leftChain->getVertex(botLeftIndex)[1], rightChain->getVertex(botRightIndex)[1]); 875 876 877 878 879 for(i=gridStartIndex; i<n_vlines; i++) 880 if(leftGridChain->get_v_value(i) <= v && 881 leftGridChain->getUlineIndex(i)<= rightGridChain->getUlineIndex(i)) 882 break; 883 884 lowerGridIndex = i; 885 886 if(lowerGridIndex == n_vlines) //the two trm vertex are higher than all gridlines 887 return 0; 888 else 889 { 890 Int botLeft2, botRight2; 891 /* 892 printf("leftGridChain->get_v_)value=%f\n",leftGridChain->get_v_value(lowerGridIndex), botLeftIndex); 893 printf("leftChain->get_vertex(0)=(%f,%f)\n", leftChain->getVertex(0)[0],leftChain->getVertex(0)[1]); 894 printf("leftChain->get_vertex(1)=(%f,%f)\n", leftChain->getVertex(1)[0],leftChain->getVertex(1)[1]); 895 printf("leftChain->get_vertex(2)=(%f,%f)\n", leftChain->getVertex(2)[0],leftChain->getVertex(2)[1]); 896 */ 897 botLeft2 = leftChain->findIndexFirstAboveEqualGen(leftGridChain->get_v_value(lowerGridIndex), botLeftIndex, leftChain->getNumElements()-1) -1 ; 898 899 /* 900 printf("botLeft2=%i\n", botLeft2); 901 printf("leftChain->getNumElements=%i\n", leftChain->getNumElements()); 902 */ 903 904 botRight2 = rightChain->findIndexFirstAboveEqualGen(leftGridChain->get_v_value(lowerGridIndex), botRightIndex, rightChain->getNumElements()-1) -1; 905 if(botRight2 < botRightIndex) botRight2=botRightIndex; 906 907 if(botLeft2 < botLeftIndex) botLeft2 = botLeftIndex; 908 909 assert(botLeft2 >= botLeftIndex); 910 assert(botRight2 >= botRightIndex); 911 //find nectLeft so that it is th erightmost vertex on letChain 912 913 Int tempI = botLeftIndex; 914 Real temp = leftChain->getVertex(tempI)[0]; 915 for(i=botLeftIndex+1; i<= botLeft2; i++) 916 if(leftChain->getVertex(i)[0] > temp) 917 { 918 temp = leftChain->getVertex(i)[0]; 919 tempI = i; 920 } 921 neckLeft = tempI; 922 923 tempI = botRightIndex; 924 temp = rightChain->getVertex(tempI)[0]; 925 for(i=botRightIndex+1; i<= botRight2; i++) 926 if(rightChain->getVertex(i)[0] < temp) 927 { 928 temp = rightChain->getVertex(i)[0]; 929 tempI = i; 930 } 931 neckRight = tempI; 932 return 1; 933 } 934 } 935 936 937 938 /*find i>=botLeftIndex,j>=botRightIndex so that 939 *(leftChain[i], rightChain[j]) is a neck. 940 */ 941 void findNeck(vertexArray *leftChain, Int botLeftIndex, 942 vertexArray *rightChain, Int botRightIndex, 943 Int& leftLastIndex, /*left point of the neck*/ 944 Int& rightLastIndex /*right point of the neck*/ 945 ) 946 { 947 assert(botLeftIndex < leftChain->getNumElements() && 948 botRightIndex < rightChain->getNumElements()); 949 950 /*now the neck exists for sure*/ 951 952 if(leftChain->getVertex(botLeftIndex)[1] <= rightChain->getVertex(botRightIndex)[1]) //left below right 953 { 954 955 leftLastIndex = botLeftIndex; 956 957 /*find i so that rightChain[i][1] >= leftchainbotverte[1], and i+1< 958 */ 959 rightLastIndex=rightChain->findIndexAboveGen(leftChain->getVertex(botLeftIndex)[1], botRightIndex+1, rightChain->getNumElements()-1); 960 } 961 else //left above right 962 { 963 964 rightLastIndex = botRightIndex; 965 966 leftLastIndex = leftChain->findIndexAboveGen(rightChain->getVertex(botRightIndex)[1], 967 botLeftIndex+1, 968 leftChain->getNumElements()-1); 969 } 970 } 971 972 973 974 void findLeftGridIndices(directedLine* topEdge, Int firstGridIndex, Int lastGridIndex, gridWrap* grid, Int* ret_indices, Int* ret_innerIndices) 975 { 976 977 Int i,k,isHoriz = 0; 978 Int n_ulines = grid->get_n_ulines(); 979 Real uMin = grid->get_u_min(); 980 Real uMax = grid->get_u_max(); 981 /* 982 Real vMin = grid->get_v_min(); 983 Real vMax = grid->get_v_max(); 984 */ 985 Real slop = 0.0, uinterc; 986 987 #ifdef SHORTEN_GRID_LINE 988 //uintercBuf stores all the interction u value for each grid line 989 //notice that lastGridIndex<= firstGridIndex 990 Real *uintercBuf = (Real *) malloc (sizeof(Real) * (firstGridIndex-lastGridIndex+1)); 991 assert(uintercBuf); 992 #endif 993 994 /*initialization to make vtail bigger than grid->...*/ 995 directedLine* dLine = topEdge; 996 Real vtail = grid->get_v_value(firstGridIndex) + 1.0; 997 Real tempMaxU = grid->get_u_min(); 998 999 1000 /*for each grid line*/ 1001 for(k=0, i=firstGridIndex; i>=lastGridIndex; i--, k++) 1002 { 1003 1004 Real grid_v_value = grid->get_v_value(i); 1005 1006 /*check whether this grid line is below the current trim edge.*/ 1007 if(vtail > grid_v_value) 1008 { 1009 /*since the grid line is below the trim edge, we 1010 *find the trim edge which will contain the trim line 1011 */ 1012 while( (vtail=dLine->tail()[1]) > grid_v_value){ 1013 1014 tempMaxU = max(tempMaxU, dLine->tail()[0]); 1015 dLine = dLine -> getNext(); 1016 } 1017 1018 if( fabs(dLine->head()[1] - vtail) < ZERO) 1019 isHoriz = 1; 1020 else 1021 { 1022 isHoriz = 0; 1023 slop = (dLine->head()[0] - dLine->tail()[0]) / (dLine->head()[1]-vtail); 1024 } 1025 } 1026 1027 if(isHoriz) 1028 { 1029 uinterc = max(dLine->head()[0], dLine->tail()[0]); 1030 } 1031 else 1032 { 1033 uinterc = slop * (grid_v_value - vtail) + dLine->tail()[0]; 1034 } 1035 1036 tempMaxU = max(tempMaxU, uinterc); 1037 1038 if(uinterc < uMin && uinterc >= uMin - ZERO) 1039 uinterc = uMin; 1040 if(uinterc > uMax && uinterc <= uMax + ZERO) 1041 uinterc = uMax; 1042 1043 #ifdef SHORTEN_GRID_LINE 1044 uintercBuf[k] = uinterc; 1045 #endif 1046 1047 assert(uinterc >= uMin && uinterc <= uMax); 1048 if(uinterc == uMax) 1049 ret_indices[k] = n_ulines-1; 1050 else 1051 ret_indices[k] = (Int)(((uinterc-uMin)/(uMax - uMin)) * (n_ulines-1)) + 1; 1052 if(ret_indices[k] >= n_ulines) 1053 ret_indices[k] = n_ulines-1; 1054 1055 1056 ret_innerIndices[k] = (Int)(((tempMaxU-uMin)/(uMax - uMin)) * (n_ulines-1)) + 1; 1057 1058 /*reinitialize tempMaxU for next grdiLine*/ 1059 tempMaxU = uinterc; 1060 } 1061 #ifdef SHORTEN_GRID_LINE 1062 //for each grid line, compare the left grid point with the 1063 //intersection point. If the two points are too close, then 1064 //we should move the grid point one grid to the right 1065 //and accordingly we should update the inner index. 1066 for(k=0, i=firstGridIndex; i>=lastGridIndex; i--, k++) 1067 { 1068 //check gridLine i 1069 //check ret_indices[k] 1070 Real a = grid->get_u_value(ret_indices[k]-1); 1071 Real b = grid->get_u_value(ret_indices[k]); 1072 assert(uintercBuf[k] >= a && uintercBuf < b); 1073 if( (b-uintercBuf[k]) <= 0.2 * (b-a)) //interc is very close to b 1074 { 1075 ret_indices[k]++; 1076 } 1077 1078 //check ret_innerIndices[k] 1079 if(k>0) 1080 { 1081 if(ret_innerIndices[k] < ret_indices[k-1]) 1082 ret_innerIndices[k] = ret_indices[k-1]; 1083 if(ret_innerIndices[k] < ret_indices[k]) 1084 ret_innerIndices[k] = ret_indices[k]; 1085 } 1086 } 1087 //clean up 1088 free(uintercBuf); 1089 #endif 1090 } 1091 1092 void findRightGridIndices(directedLine* topEdge, Int firstGridIndex, Int lastGridIndex, gridWrap* grid, Int* ret_indices, Int* ret_innerIndices) 1093 { 1094 1095 Int i,k; 1096 Int n_ulines = grid->get_n_ulines(); 1097 Real uMin = grid->get_u_min(); 1098 Real uMax = grid->get_u_max(); 1099 /* 1100 Real vMin = grid->get_v_min(); 1101 Real vMax = grid->get_v_max(); 1102 */ 1103 Real slop = 0.0, uinterc; 1104 1105 #ifdef SHORTEN_GRID_LINE 1106 //uintercBuf stores all the interction u value for each grid line 1107 //notice that firstGridIndex >= lastGridIndex 1108 Real *uintercBuf = (Real *) malloc (sizeof(Real) * (firstGridIndex-lastGridIndex+1)); 1109 assert(uintercBuf); 1110 #endif 1111 1112 /*initialization to make vhead bigger than grid->v_value...*/ 1113 directedLine* dLine = topEdge->getPrev(); 1114 Real vhead = dLine->tail()[1]; 1115 Real tempMinU = grid->get_u_max(); 1116 1117 /*for each grid line*/ 1118 for(k=0, i=firstGridIndex; i>=lastGridIndex; i--, k++) 1119 { 1120 1121 Real grid_v_value = grid->get_v_value(i); 1122 1123 1124 /*check whether this grid line is below the current trim edge.*/ 1125 if(vhead >= grid_v_value) 1126 { 1127 /*since the grid line is below the tail of the trim edge, we 1128 *find the trim edge which will contain the trim line 1129 */ 1130 while( (vhead=dLine->head()[1]) > grid_v_value){ 1131 tempMinU = min(tempMinU, dLine->head()[0]); 1132 dLine = dLine -> getPrev(); 1133 } 1134 1135 /*skip the equality in the case of degenerat case: horizontal */ 1136 while(dLine->head()[1] == grid_v_value) 1137 dLine = dLine->getPrev(); 1138 1139 assert( dLine->tail()[1] != dLine->head()[1]); 1140 slop = (dLine->tail()[0] - dLine->head()[0]) / (dLine->tail()[1]-dLine->head()[1]); 1141 /* 1142 if(dLine->tail()[1] == vhead) 1143 isHoriz = 1; 1144 else 1145 { 1146 isHoriz = 0; 1147 slop = (dLine->tail()[0] - dLine->head()[0]) / (dLine->tail()[1]-vhead); 1148 } 1149 */ 1150 } 1151 uinterc = slop * (grid_v_value - dLine->head()[1]) + dLine->head()[0]; 1152 1153 //in case unterc is outside of the grid due to floating point 1154 if(uinterc < uMin) 1155 uinterc = uMin; 1156 else if(uinterc > uMax) 1157 uinterc = uMax; 1158 1159 #ifdef SHORTEN_GRID_LINE 1160 uintercBuf[k] = uinterc; 1161 #endif 1162 1163 tempMinU = min(tempMinU, uinterc); 1164 1165 assert(uinterc >= uMin && uinterc <= uMax); 1166 1167 if(uinterc == uMin) 1168 ret_indices[k] = 0; 1169 else 1170 ret_indices[k] = (int)ceil((((uinterc-uMin)/(uMax - uMin)) * (n_ulines-1))) -1; 1171 /* 1172 if(ret_indices[k] >= grid->get_n_ulines()) 1173 { 1174 printf("ERROR3\n"); 1175 exit(0); 1176 } 1177 if(ret_indices[k] < 0) 1178 { 1179 printf("ERROR4\n"); 1180 exit(0); 1181 } 1182 */ 1183 ret_innerIndices[k] = (int)ceil ((((tempMinU-uMin)/(uMax - uMin)) * (n_ulines-1))) -1; 1184 1185 tempMinU = uinterc; 1186 } 1187 #ifdef SHORTEN_GRID_LINE 1188 //for each grid line, compare the left grid point with the 1189 //intersection point. If the two points are too close, then 1190 //we should move the grid point one grid to the right 1191 //and accordingly we should update the inner index. 1192 for(k=0, i=firstGridIndex; i>=lastGridIndex; i--, k++) 1193 { 1194 //check gridLine i 1195 //check ret_indices[k] 1196 Real a = grid->get_u_value(ret_indices[k]); 1197 Real b = grid->get_u_value(ret_indices[k]+1); 1198 assert(uintercBuf[k] > a && uintercBuf <= b); 1199 if( (uintercBuf[k]-a) <= 0.2 * (b-a)) //interc is very close to a 1200 { 1201 ret_indices[k]--; 1202 } 1203 1204 //check ret_innerIndices[k] 1205 if(k>0) 1206 { 1207 if(ret_innerIndices[k] > ret_indices[k-1]) 1208 ret_innerIndices[k] = ret_indices[k-1]; 1209 if(ret_innerIndices[k] > ret_indices[k]) 1210 ret_innerIndices[k] = ret_indices[k]; 1211 } 1212 } 1213 //clean up 1214 free(uintercBuf); 1215 #endif 1216 } 1217 1218 1219 void sampleMonoPoly(directedLine* polygon, gridWrap* grid, Int ulinear, Int vlinear, primStream* pStream, rectBlockArray* rbArray) 1220 { 1221 /* 1222 { 1223 grid->print(); 1224 polygon->writeAllPolygons("zloutputFile"); 1225 exit(0); 1226 } 1227 */ 1228 1229 if(grid->get_n_ulines() == 2 || 1230 grid->get_n_vlines() == 2) 1231 { 1232 if(ulinear && grid->get_n_ulines() == 2) 1233 { 1234 monoTriangulationFun(polygon, compV2InY, pStream); 1235 return; 1236 } 1237 else if(DBG_isConvex(polygon) && polygon->numEdges() >=4) 1238 { 1239 triangulateConvexPoly(polygon, ulinear, vlinear, pStream); 1240 return; 1241 } 1242 else if(vlinear || DBG_is_U_direction(polygon)) 1243 { 1244 Int n_cusps;//num interior cusps 1245 Int n_edges = polygon->numEdges(); 1246 directedLine** cusps = (directedLine**) malloc(sizeof(directedLine*) * n_edges); 1247 assert(cusps); 1248 findInteriorCuspsX(polygon, n_cusps, cusps); 1249 1250 if(n_cusps == 0) //u_monotone 1251 { 1252 1253 monoTriangulationFun(polygon, compV2InX, pStream); 1254 1255 free(cusps); 1256 return; 1257 } 1258 else if(n_cusps == 1) //one interior cusp 1259 { 1260 1261 directedLine* new_polygon = polygonConvert(cusps[0]); 1262 1263 directedLine* other = findDiagonal_singleCuspX( new_polygon); 1264 1265 1266 1267 //<other> should NOT be null unless there are self-intersecting 1268 //trim curves. In that case, we don't want to core dump, instead, 1269 //we triangulate anyway, and print out error message. 1270 if(other == NULL) 1271 { 1272 monoTriangulationFun(polygon, compV2InX, pStream); 1273 free(cusps); 1274 return; 1275 } 1276 1277 directedLine* ret_p1; 1278 directedLine* ret_p2; 1279 1280 new_polygon->connectDiagonal_2slines(new_polygon, other, 1281 &ret_p1, 1282 &ret_p2, 1283 new_polygon); 1284 1285 monoTriangulationFun(ret_p1, compV2InX, pStream); 1286 monoTriangulationFun(ret_p2, compV2InX, pStream); 1287 1288 ret_p1->deleteSinglePolygonWithSline(); 1289 ret_p2->deleteSinglePolygonWithSline(); 1290 1291 free(cusps); 1292 return; 1293 } 1294 free(cusps); 1295 } 1296 } 1297 1298 /*find the top and bottom of the polygon. It is supposed to be 1299 *a V-monotone polygon 1300 */ 1301 1302 directedLine* tempV; 1303 directedLine* topV; 1304 directedLine* botV; 1305 topV = botV = polygon; 1306 1307 for(tempV = polygon->getNext(); tempV != polygon; tempV = tempV->getNext()) 1308 { 1309 if(compV2InY(topV->head(), tempV->head())<0) { 1310 1311 topV = tempV; 1312 } 1313 if(compV2InY(botV->head(), tempV->head())>0) { 1314 1315 botV = tempV; 1316 } 1317 } 1318 1319 /*find the first(top) and the last (bottom) grid line which intersect the 1320 *this polygon 1321 */ 1322 Int firstGridIndex; /*the index in the grid*/ 1323 Int lastGridIndex; 1324 firstGridIndex = (Int) ((topV->head()[1] - grid->get_v_min()) / (grid->get_v_max() - grid->get_v_min()) * (grid->get_n_vlines()-1)); 1325 lastGridIndex = (Int) ((botV->head()[1] - grid->get_v_min()) / (grid->get_v_max() - grid->get_v_min()) * (grid->get_n_vlines()-1)) + 1; 1326 1327 1328 /*find the interval inside the polygon for each gridline*/ 1329 Int *leftGridIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1)); 1330 assert(leftGridIndices); 1331 Int *rightGridIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1)); 1332 assert(rightGridIndices); 1333 Int *leftGridInnerIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1)); 1334 assert(leftGridInnerIndices); 1335 Int *rightGridInnerIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1)); 1336 assert(rightGridInnerIndices); 1337 1338 findLeftGridIndices(topV, firstGridIndex, lastGridIndex, grid, leftGridIndices, leftGridInnerIndices); 1339 1340 findRightGridIndices(topV, firstGridIndex, lastGridIndex, grid, rightGridIndices, rightGridInnerIndices); 1341 1342 gridBoundaryChain leftGridChain(grid, firstGridIndex, firstGridIndex-lastGridIndex+1, leftGridIndices, leftGridInnerIndices); 1343 1344 gridBoundaryChain rightGridChain(grid, firstGridIndex, firstGridIndex-lastGridIndex+1, rightGridIndices, rightGridInnerIndices); 1345 1346 1347 1348 // leftGridChain.draw(); 1349 // leftGridChain.drawInner(); 1350 // rightGridChain.draw(); 1351 // rightGridChain.drawInner(); 1352 /*(1) determine the grid boundaries (left and right). 1353 *(2) process polygon into two monotone chaines: use vertexArray 1354 *(3) call sampleMonoPolyRec 1355 */ 1356 1357 /*copy the two chains into vertexArray datastructure*/ 1358 Int i; 1359 vertexArray leftChain(20); /*this is a dynamic array*/ 1360 for(i=1; i<=topV->get_npoints()-2; i++) { /*the first vertex is the top vertex which doesn't belong to inc_chain*/ 1361 leftChain.appendVertex(topV->getVertex(i)); 1362 } 1363 for(tempV = topV->getNext(); tempV != botV; tempV = tempV->getNext()) 1364 { 1365 for(i=0; i<=tempV->get_npoints()-2; i++){ 1366 leftChain.appendVertex(tempV->getVertex(i)); 1367 } 1368 } 1369 1370 vertexArray rightChain(20); 1371 for(tempV = topV->getPrev(); tempV != botV; tempV = tempV->getPrev()) 1372 { 1373 for(i=tempV->get_npoints()-2; i>=0; i--){ 1374 rightChain.appendVertex(tempV->getVertex(i)); 1375 } 1376 } 1377 for(i=botV->get_npoints()-2; i>=1; i--){ 1378 rightChain.appendVertex(tempV->getVertex(i)); 1379 } 1380 1381 sampleMonoPolyRec(topV->head(), 1382 botV->head(), 1383 &leftChain, 1384 0, 1385 &rightChain, 1386 0, 1387 &leftGridChain, 1388 &rightGridChain, 1389 0, 1390 pStream, 1391 rbArray); 1392 1393 1394 /*cleanup space*/ 1395 free(leftGridIndices); 1396 free(rightGridIndices); 1397 free(leftGridInnerIndices); 1398 free(rightGridInnerIndices); 1399 } 1400 1401 void sampleMonoPolyRec( 1402 Real* topVertex, 1403 Real* botVertex, 1404 vertexArray* leftChain, 1405 Int leftStartIndex, 1406 vertexArray* rightChain, 1407 Int rightStartIndex, 1408 gridBoundaryChain* leftGridChain, 1409 gridBoundaryChain* rightGridChain, 1410 Int gridStartIndex, 1411 primStream* pStream, 1412 rectBlockArray* rbArray) 1413 { 1414 1415 /*find the first connected component, and the four corners. 1416 */ 1417 Int index1, index2; /*the first and last grid line of the first connected component*/ 1418 1419 if(topVertex[1] <= botVertex[1]) 1420 return; 1421 1422 /*find i so that the grid line is below the top vertex*/ 1423 Int i=gridStartIndex; 1424 while (i < leftGridChain->get_nVlines()) 1425 { 1426 if(leftGridChain->get_v_value(i) < topVertex[1]) 1427 break; 1428 i++; 1429 } 1430 1431 /*find the first connected component starting with i*/ 1432 /*find index1 so that left_uline_index <= right_uline_index, that is, this 1433 *grid line contains at least one inner grid point 1434 */ 1435 index1=i; 1436 int num_skipped_grid_lines=0; 1437 while(index1 < leftGridChain->get_nVlines()) 1438 { 1439 if(leftGridChain->getUlineIndex(index1) <= rightGridChain->getUlineIndex(index1)) 1440 break; 1441 num_skipped_grid_lines++; 1442 index1++; 1443 } 1444 1445 1446 1447 if(index1 >= leftGridChain->get_nVlines()) /*no grid line exists which has inner point*/ 1448 { 1449 /*stop recursion, ...*/ 1450 /*monotone triangulate it...*/ 1451 // printf("no grid line exists\n"); 1452 /* 1453 monoTriangulationRecOpt(topVertex, botVertex, leftChain, leftStartIndex, 1454 rightChain, rightStartIndex, pStream); 1455 */ 1456 1457 if(num_skipped_grid_lines <2) 1458 { 1459 monoTriangulationRecGenOpt(topVertex, botVertex, leftChain, leftStartIndex, 1460 leftChain->getNumElements()-1, 1461 rightChain, rightStartIndex, 1462 rightChain->getNumElements()-1, 1463 pStream); 1464 } 1465 else 1466 { 1467 //the optimum way to triangulate is top-down since this polygon 1468 //is narrow-long. 1469 monoTriangulationRec(topVertex, botVertex, leftChain, leftStartIndex, 1470 rightChain, rightStartIndex, pStream); 1471 } 1472 1473 /* 1474 monoTriangulationRec(topVertex, botVertex, leftChain, leftStartIndex, 1475 rightChain, rightStartIndex, pStream); 1476 */ 1477 1478 /* monoTriangulationRecGenTBOpt(topVertex, botVertex, 1479 leftChain, leftStartIndex, leftChain->getNumElements()-1, 1480 rightChain, rightStartIndex, rightChain->getNumElements()-1, 1481 pStream);*/ 1482 1483 1484 1485 } 1486 else 1487 { 1488 1489 /*find index2 so that left_inner_index <= right_inner_index holds until index2*/ 1490 index2=index1+1; 1491 if(index2 < leftGridChain->get_nVlines()) 1492 while(leftGridChain->getInnerIndex(index2) <= rightGridChain->getInnerIndex(index2)) 1493 { 1494 index2++; 1495 if(index2 >= leftGridChain->get_nVlines()) 1496 break; 1497 } 1498 1499 index2--; 1500 1501 1502 1503 /*the neck*/ 1504 Int neckLeftIndex; 1505 Int neckRightIndex; 1506 1507 /*the four corners*/ 1508 Int up_leftCornerWhere; 1509 Int up_leftCornerIndex; 1510 Int up_rightCornerWhere; 1511 Int up_rightCornerIndex; 1512 Int down_leftCornerWhere; 1513 Int down_leftCornerIndex; 1514 Int down_rightCornerWhere; 1515 Int down_rightCornerIndex; 1516 1517 Real* tempBotVertex; /*the bottom vertex for this component*/ 1518 Real* nextTopVertex=NULL; /*for the recursion*/ 1519 Int nextLeftStartIndex=0; 1520 Int nextRightStartIndex=0; 1521 1522 /*find the points below the grid line index2 on both chains*/ 1523 Int botLeftIndex = leftChain->findIndexStrictBelowGen( 1524 leftGridChain->get_v_value(index2), 1525 leftStartIndex, 1526 leftChain->getNumElements()-1); 1527 Int botRightIndex = rightChain->findIndexStrictBelowGen( 1528 rightGridChain->get_v_value(index2), 1529 rightStartIndex, 1530 rightChain->getNumElements()-1); 1531 /*if either botLeftIndex>= numelements, 1532 * or botRightIndex >= numelemnet, 1533 *then there is no neck exists. the bottom vertex is botVertex, 1534 */ 1535 if(! findNeckF(leftChain, botLeftIndex, rightChain, botRightIndex, 1536 leftGridChain, rightGridChain, index2, neckLeftIndex, neckRightIndex)) 1537 /* 1538 if(botLeftIndex == leftChain->getNumElements() || 1539 botRightIndex == rightChain->getNumElements()) 1540 */ 1541 { 1542 #ifdef MYDEBUG 1543 printf("neck NOT exists, botRightIndex=%i\n", botRightIndex); 1544 #endif 1545 1546 tempBotVertex = botVertex; 1547 nextTopVertex = botVertex; 1548 botLeftIndex = leftChain->getNumElements()-1; 1549 botRightIndex = rightChain->getNumElements()-1; 1550 } 1551 else /*neck exists*/ 1552 { 1553 #ifdef MYDEBUG 1554 printf("neck exists\n"); 1555 #endif 1556 1557 /* 1558 findNeck(leftChain, botLeftIndex, 1559 rightChain, botRightIndex, 1560 neckLeftIndex, 1561 neckRightIndex); 1562 */ 1563 #ifdef MYDEBUG 1564 printf("neck is found, neckLeftIndex=%i, neckRightIndex=%i\n", neckLeftIndex, neckRightIndex); 1565 glBegin(GL_LINES); 1566 glVertex2fv(leftChain->getVertex(neckLeftIndex)); 1567 glVertex2fv(rightChain->getVertex(neckRightIndex)); 1568 glEnd(); 1569 #endif 1570 1571 if(leftChain->getVertex(neckLeftIndex)[1] <= rightChain->getVertex(neckRightIndex)[1]) 1572 { 1573 tempBotVertex = leftChain->getVertex(neckLeftIndex); 1574 botLeftIndex = neckLeftIndex-1; 1575 botRightIndex = neckRightIndex; 1576 nextTopVertex = rightChain->getVertex(neckRightIndex); 1577 nextLeftStartIndex = neckLeftIndex; 1578 nextRightStartIndex = neckRightIndex+1; 1579 } 1580 else 1581 { 1582 tempBotVertex = rightChain->getVertex(neckRightIndex); 1583 botLeftIndex = neckLeftIndex; 1584 botRightIndex = neckRightIndex-1; 1585 nextTopVertex = leftChain->getVertex(neckLeftIndex); 1586 nextLeftStartIndex = neckLeftIndex+1; 1587 nextRightStartIndex = neckRightIndex; 1588 } 1589 } 1590 1591 findUpCorners(topVertex, 1592 leftChain, 1593 leftStartIndex, botLeftIndex, 1594 rightChain, 1595 rightStartIndex, botRightIndex, 1596 leftGridChain->get_v_value(index1), 1597 leftGridChain->get_u_value(index1), 1598 rightGridChain->get_u_value(index1), 1599 up_leftCornerWhere, 1600 up_leftCornerIndex, 1601 up_rightCornerWhere, 1602 up_rightCornerIndex); 1603 1604 findDownCorners(tempBotVertex, 1605 leftChain, 1606 leftStartIndex, botLeftIndex, 1607 rightChain, 1608 rightStartIndex, botRightIndex, 1609 leftGridChain->get_v_value(index2), 1610 leftGridChain->get_u_value(index2), 1611 rightGridChain->get_u_value(index2), 1612 down_leftCornerWhere, 1613 down_leftCornerIndex, 1614 down_rightCornerWhere, 1615 down_rightCornerIndex); 1616 #ifdef MYDEBUG 1617 printf("find corners done, down_leftwhere=%i, down_righwhere=%i,\n",down_leftCornerWhere, down_rightCornerWhere ); 1618 printf("find corners done, up_leftwhere=%i, up_righwhere=%i,\n",up_leftCornerWhere, up_rightCornerWhere ); 1619 printf("find corners done, up_leftindex=%i, up_righindex=%i,\n",up_leftCornerIndex, up_rightCornerIndex ); 1620 printf("find corners done, down_leftindex=%i, down_righindex=%i,\n",down_leftCornerIndex, down_rightCornerIndex ); 1621 #endif 1622 1623 /* 1624 drawCorners(topVertex, 1625 tempBotVertex, 1626 leftChain, 1627 rightChain, 1628 leftGridChain, 1629 rightGridChain, 1630 index1, 1631 index2, 1632 up_leftCornerWhere, 1633 up_leftCornerIndex, 1634 up_rightCornerWhere, 1635 up_rightCornerIndex, 1636 down_leftCornerWhere, 1637 down_leftCornerIndex, 1638 down_rightCornerWhere, 1639 down_rightCornerIndex); 1640 */ 1641 1642 1643 sampleConnectedComp(topVertex, tempBotVertex, 1644 leftChain, 1645 leftStartIndex, botLeftIndex, 1646 rightChain, 1647 rightStartIndex, botRightIndex, 1648 leftGridChain, 1649 rightGridChain, 1650 index1, index2, 1651 up_leftCornerWhere, 1652 up_leftCornerIndex, 1653 up_rightCornerWhere, 1654 up_rightCornerIndex, 1655 down_leftCornerWhere, 1656 down_leftCornerIndex, 1657 down_rightCornerWhere, 1658 down_rightCornerIndex, 1659 pStream, 1660 rbArray 1661 ); 1662 1663 /*recursion*/ 1664 1665 sampleMonoPolyRec( 1666 nextTopVertex, 1667 botVertex, 1668 leftChain, 1669 nextLeftStartIndex, 1670 rightChain, 1671 nextRightStartIndex, 1672 leftGridChain, 1673 rightGridChain, 1674 index2+1, 1675 pStream, rbArray); 1676 1677 1678 } 1679 1680 } 1681 1682 void sampleLeftStrip(vertexArray* leftChain, 1683 Int topLeftIndex, 1684 Int botLeftIndex, 1685 gridBoundaryChain* leftGridChain, 1686 Int leftGridChainStartIndex, 1687 Int leftGridChainEndIndex, 1688 primStream* pStream 1689 ) 1690 { 1691 assert(leftChain->getVertex(topLeftIndex)[1] > leftGridChain->get_v_value(leftGridChainStartIndex)); 1692 assert(leftChain->getVertex(topLeftIndex+1)[1] <= leftGridChain->get_v_value(leftGridChainStartIndex)); 1693 assert(leftChain->getVertex(botLeftIndex)[1] <= leftGridChain->get_v_value(leftGridChainEndIndex)); 1694 assert(leftChain->getVertex(botLeftIndex-1)[1] > leftGridChain->get_v_value(leftGridChainEndIndex)); 1695 1696 /* 1697 *(1)find the last grid line which doesn'; pass below 1698 * this first edge, sample this region: one trim edge and 1699 * possily multiple grid lines. 1700 */ 1701 Real *upperVert, *lowerVert; /*the end points of the first trim edge*/ 1702 upperVert = leftChain->getVertex(topLeftIndex); 1703 lowerVert = leftChain->getVertex(topLeftIndex+1); 1704 1705 Int index = leftGridChainStartIndex; 1706 while(leftGridChain->get_v_value(index) >= lowerVert[1]){ 1707 index++; 1708 if(index > leftGridChainEndIndex) 1709 break; 1710 } 1711 index--; 1712 1713 sampleLeftSingleTrimEdgeRegion(upperVert, lowerVert, 1714 leftGridChain, 1715 leftGridChainStartIndex, 1716 index, 1717 pStream); 1718 sampleLeftStripRec(leftChain, topLeftIndex+1, botLeftIndex, 1719 leftGridChain, index, leftGridChainEndIndex, 1720 pStream); 1721 1722 } 1723 1724 void sampleLeftStripRec(vertexArray* leftChain, 1725 Int topLeftIndex, 1726 Int botLeftIndex, 1727 gridBoundaryChain* leftGridChain, 1728 Int leftGridChainStartIndex, 1729 Int leftGridChainEndIndex, 1730 primStream* pStream 1731 ) 1732 { 1733 /*now top left trim vertex is below the top grid line. 1734 */ 1735 /*stop condition: if topLeftIndex >= botLeftIndex, then stop. 1736 */ 1737 if(topLeftIndex >= botLeftIndex) 1738 return; 1739 1740 /*find the last trim vertex which is above the second top grid line: 1741 * index1. 1742 *and sampleLeftOneGridStep(leftchain, topLeftIndex, index1, leftGridChain, 1743 * leftGridChainStartIndex). 1744 * index1 could be equal to topLeftIndex. 1745 */ 1746 Real secondGridChainV = leftGridChain->get_v_value(leftGridChainStartIndex+1); 1747 assert(leftGridChainStartIndex < leftGridChainEndIndex); 1748 Int index1 = topLeftIndex; 1749 while(leftChain->getVertex(index1)[1] > secondGridChainV) 1750 index1++; 1751 index1--; 1752 1753 sampleLeftOneGridStep(leftChain, topLeftIndex, index1, leftGridChain, leftGridChainStartIndex, pStream); 1754 1755 1756 /* 1757 * Let the next trim vertex be nextTrimVertIndex (which should be 1758 * below the second grid line). 1759 * Find the last grid line index2 which is above nextTrimVert. 1760 * sampleLeftSingleTrimEdgeRegion(uppervert[2], lowervert[2], 1761 * leftGridChain, leftGridChainStartIndex+1, index2). 1762 */ 1763 Real *uppervert, *lowervert; 1764 uppervert = leftChain->getVertex(index1); 1765 lowervert = leftChain->getVertex(index1+1); 1766 Int index2 = leftGridChainStartIndex+1; 1767 1768 while(leftGridChain->get_v_value(index2) >= lowervert[1]) 1769 { 1770 index2++; 1771 if(index2 > leftGridChainEndIndex) 1772 break; 1773 } 1774 index2--; 1775 sampleLeftSingleTrimEdgeRegion(uppervert, lowervert, leftGridChain, leftGridChainStartIndex+1, index2, pStream); 1776 1777 /* sampleLeftStripRec(leftChain, 1778 nextTrimVertIndex, 1779 botLeftIndex, 1780 leftGridChain, 1781 index2, 1782 leftGridChainEndIndex 1783 ) 1784 * 1785 */ 1786 sampleLeftStripRec(leftChain, index1+1, botLeftIndex, leftGridChain, index2, leftGridChainEndIndex, pStream); 1787 1788 } 1789 1790 1791 /***************begin RecF***********************/ 1792 /* the gridlines from leftGridChainStartIndex to 1793 * leftGridChainEndIndex are assumed to form a 1794 * connected component. 1795 * the trim vertex of topLeftIndex is assumed to 1796 * be below the first gridline, and the tim vertex 1797 * of botLeftIndex is assumed to be above the last 1798 * grid line. 1799 * If botLeftIndex < topLeftIndex, then no connected componeent exists, and this funcion returns without 1800 * outputing any triangles. 1801 * Otherwise botLeftIndex >= topLeftIndex, there is at least one triangle to output. 1802 */ 1803 void sampleLeftStripRecF(vertexArray* leftChain, 1804 Int topLeftIndex, 1805 Int botLeftIndex, 1806 gridBoundaryChain* leftGridChain, 1807 Int leftGridChainStartIndex, 1808 Int leftGridChainEndIndex, 1809 primStream* pStream 1810 ) 1811 { 1812 /*now top left trim vertex is below the top grid line. 1813 */ 1814 /*stop condition: if topLeftIndex > botLeftIndex, then stop. 1815 */ 1816 if(topLeftIndex > botLeftIndex) 1817 return; 1818 1819 /*if there is only one grid Line, return.*/ 1820 1821 if(leftGridChainStartIndex>=leftGridChainEndIndex) 1822 return; 1823 1824 1825 assert(leftChain->getVertex(topLeftIndex)[1] <= leftGridChain->get_v_value(leftGridChainStartIndex) && 1826 leftChain->getVertex(botLeftIndex)[1] >= leftGridChain->get_v_value(leftGridChainEndIndex)); 1827 1828 /*firs find the first trim vertex which is below or equal to the second top grid line: 1829 * index1. 1830 */ 1831 Real secondGridChainV = leftGridChain->get_v_value(leftGridChainStartIndex+1); 1832 1833 1834 Int index1 = topLeftIndex; 1835 1836 while(leftChain->getVertex(index1)[1] > secondGridChainV){ 1837 index1++; 1838 if(index1>botLeftIndex) 1839 break; 1840 } 1841 1842 /*now leftChain->getVertex(index-1)[1] > secondGridChainV and 1843 * leftChain->getVertex(index)[1] <= secondGridChainV 1844 *If equality holds, then we should include the vertex index1, otherwise we include only index1-1, to 1845 *perform sampleOneGridStep. 1846 */ 1847 if(index1>botLeftIndex) 1848 index1--; 1849 else if(leftChain->getVertex(index1)[1] < secondGridChainV) 1850 index1--; 1851 1852 /*now we have leftChain->getVertex(index1)[1] >= secondGridChainV, and 1853 * leftChain->getVertex(index1+1)[1] <= secondGridChainV 1854 */ 1855 1856 1857 sampleLeftOneGridStep(leftChain, topLeftIndex, index1, leftGridChain, leftGridChainStartIndex, pStream); 1858 1859 1860 /*if leftChain->getVertex(index1)[1] == secondGridChainV, then we can recursively do the rest. 1861 */ 1862 if(leftChain->getVertex(index1)[1] == secondGridChainV) 1863 { 1864 1865 sampleLeftStripRecF(leftChain, index1, botLeftIndex,leftGridChain, leftGridChainStartIndex+1, leftGridChainEndIndex, pStream); 1866 } 1867 else if(index1 < botLeftIndex) 1868 { 1869 1870 /* Otherwise, we have leftChain->getVertex(index1)[1] > secondGridChainV, 1871 * let the next trim vertex be nextTrimVertIndex (which should be strictly 1872 * below the second grid line). 1873 * Find the last grid line index2 which is above nextTrimVert. 1874 * sampleLeftSingleTrimEdgeRegion(uppervert[2], lowervert[2], 1875 * leftGridChain, leftGridChainStartIndex+1, index2). 1876 */ 1877 Real *uppervert, *lowervert; 1878 uppervert = leftChain->getVertex(index1); 1879 lowervert = leftChain->getVertex(index1+1); //okay since index1<botLeftIndex 1880 Int index2 = leftGridChainStartIndex+1; 1881 1882 1883 while(leftGridChain->get_v_value(index2) >= lowervert[1]) 1884 { 1885 index2++; 1886 if(index2 > leftGridChainEndIndex) 1887 break; 1888 } 1889 index2--; 1890 1891 1892 sampleLeftSingleTrimEdgeRegion(uppervert, lowervert, leftGridChain, leftGridChainStartIndex+1, index2, pStream); 1893 1894 /*recursion*/ 1895 1896 sampleLeftStripRecF(leftChain, index1+1, botLeftIndex, leftGridChain, index2, leftGridChainEndIndex, pStream); 1897 } 1898 1899 } 1900 1901 /***************End RecF***********************/ 1902 1903 /*sample the left area in between one trim edge and multiple grid lines. 1904 * all the grid lines should be in between the two end poins of the 1905 *trim edge. 1906 */ 1907 void sampleLeftSingleTrimEdgeRegion(Real upperVert[2], Real lowerVert[2], 1908 gridBoundaryChain* gridChain, 1909 Int beginIndex, 1910 Int endIndex, 1911 primStream* pStream) 1912 { 1913 Int i,j,k; 1914 1915 vertexArray vArray(endIndex-beginIndex+1); 1916 vArray.appendVertex(gridChain->get_vertex(beginIndex)); 1917 1918 for(k=1, i=beginIndex+1; i<=endIndex; i++, k++) 1919 { 1920 vArray.appendVertex(gridChain->get_vertex(i)); 1921 1922 /*output the fan of the grid points of the (i)th and (i-1)th grid line. 1923 */ 1924 if(gridChain->getUlineIndex(i) < gridChain->getUlineIndex(i-1)) 1925 { 1926 pStream->begin(); 1927 pStream->insert(gridChain->get_vertex(i-1)); 1928 for(j=gridChain->getUlineIndex(i); j<= gridChain->getUlineIndex(i-1); j++) 1929 pStream->insert(gridChain->getGrid()->get_u_value(j), gridChain->get_v_value(i)); 1930 pStream->end(PRIMITIVE_STREAM_FAN); 1931 } 1932 else if(gridChain->getUlineIndex(i) > gridChain->getUlineIndex(i-1)) 1933 { 1934 pStream->begin(); 1935 pStream->insert(gridChain->get_vertex(i)); 1936 for(j=gridChain->getUlineIndex(i); j>= gridChain->getUlineIndex(i-1); j--) 1937 pStream->insert(gridChain->getGrid()->get_u_value(j), gridChain->get_v_value(i-1)); 1938 pStream->end(PRIMITIVE_STREAM_FAN); 1939 } 1940 /*otherwisem, the two are equal, so there is no fan to outout*/ 1941 } 1942 1943 monoTriangulation2(upperVert, lowerVert, &vArray, 0, endIndex-beginIndex, 1944 0, /*decreasing chain*/ 1945 pStream); 1946 } 1947 1948 /*return i, such that from begin to i-1 the chain is strictly u-monotone. 1949 */ 1950 Int findIncreaseChainFromBegin(vertexArray* chain, Int begin ,Int end) 1951 { 1952 Int i=begin; 1953 Real prevU = chain->getVertex(i)[0]; 1954 Real thisU; 1955 for(i=begin+1; i<=end; i++){ 1956 thisU = chain->getVertex(i)[0]; 1957 1958 if(prevU < thisU){ 1959 prevU = thisU; 1960 } 1961 else 1962 break; 1963 } 1964 return i; 1965 } 1966 1967 /*check whether there is a vertex whose v value is strictly 1968 *inbetween vup vbelow 1969 *if no middle exists return -1, else return the idnex. 1970 */ 1971 Int checkMiddle(vertexArray* chain, Int begin, Int end, 1972 Real vup, Real vbelow) 1973 { 1974 Int i; 1975 for(i=begin; i<=end; i++) 1976 { 1977 if(chain->getVertex(i)[1] < vup && chain->getVertex(i)[1]>vbelow) 1978 return i; 1979 } 1980 return -1; 1981 } 1982 1983 /*the degenerat case of sampleLeftOneGridStep*/ 1984 void sampleLeftOneGridStepNoMiddle(vertexArray* leftChain, 1985 Int beginLeftIndex, 1986 Int endLeftIndex, 1987 gridBoundaryChain* leftGridChain, 1988 Int leftGridChainStartIndex, 1989 primStream* pStream) 1990 { 1991 /*since there is no middle, there is at most one point which is on the 1992 *second grid line, there could be multiple points on the first (top) 1993 *grid line. 1994 */ 1995 1996 leftGridChain->leftEndFan(leftGridChainStartIndex+1, pStream); 1997 1998 monoTriangulation2(leftGridChain->get_vertex(leftGridChainStartIndex), 1999 leftGridChain->get_vertex(leftGridChainStartIndex+1), 2000 leftChain, 2001 beginLeftIndex, 2002 endLeftIndex, 2003 1, //is increase chain. 2004 pStream); 2005 } 2006 2007 2008 2009 /*sampling the left area in between two grid lines. 2010 */ 2011 void sampleLeftOneGridStep(vertexArray* leftChain, 2012 Int beginLeftIndex, 2013 Int endLeftIndex, 2014 gridBoundaryChain* leftGridChain, 2015 Int leftGridChainStartIndex, 2016 primStream* pStream 2017 ) 2018 { 2019 if(checkMiddle(leftChain, beginLeftIndex, endLeftIndex, 2020 leftGridChain->get_v_value(leftGridChainStartIndex), 2021 leftGridChain->get_v_value(leftGridChainStartIndex+1))<0) 2022 2023 { 2024 2025 sampleLeftOneGridStepNoMiddle(leftChain, beginLeftIndex, endLeftIndex, leftGridChain, leftGridChainStartIndex, pStream); 2026 return; 2027 } 2028 2029 //copy into a polygon 2030 { 2031 directedLine* poly = NULL; 2032 sampledLine* sline; 2033 directedLine* dline; 2034 gridWrap* grid = leftGridChain->getGrid(); 2035 Real vert1[2]; 2036 Real vert2[2]; 2037 Int i; 2038 2039 Int innerInd = leftGridChain->getInnerIndex(leftGridChainStartIndex+1); 2040 Int upperInd = leftGridChain->getUlineIndex(leftGridChainStartIndex); 2041 Int lowerInd = leftGridChain->getUlineIndex(leftGridChainStartIndex+1); 2042 Real upperV = leftGridChain->get_v_value(leftGridChainStartIndex); 2043 Real lowerV = leftGridChain->get_v_value(leftGridChainStartIndex+1); 2044 2045 //the upper gridline 2046 vert1[1] = vert2[1] = upperV; 2047 for(i=innerInd; i>upperInd; i--) 2048 { 2049 vert1[0]=grid->get_u_value(i); 2050 vert2[0]=grid->get_u_value(i-1); 2051 sline = new sampledLine(vert1, vert2); 2052 dline = new directedLine(INCREASING, sline); 2053 if(poly == NULL) 2054 poly = dline; 2055 else 2056 poly->insert(dline); 2057 } 2058 2059 //the edge connecting upper grid with left chain 2060 vert1[0] = grid->get_u_value(upperInd); 2061 vert1[1] = upperV; 2062 sline = new sampledLine(vert1, leftChain->getVertex(beginLeftIndex)); 2063 dline = new directedLine(INCREASING, sline); 2064 if(poly == NULL) 2065 poly = dline; 2066 else 2067 poly->insert(dline); 2068 2069 //the left chain 2070 for(i=beginLeftIndex; i<endLeftIndex; i++) 2071 { 2072 sline = new sampledLine(leftChain->getVertex(i), leftChain->getVertex(i+1)); 2073 dline = new directedLine(INCREASING, sline); 2074 poly->insert(dline); 2075 } 2076 2077 //the edge connecting left chain with lower gridline 2078 vert2[0] = grid->get_u_value(lowerInd); 2079 vert2[1] = lowerV; 2080 sline = new sampledLine(leftChain->getVertex(endLeftIndex), vert2); 2081 dline = new directedLine(INCREASING, sline); 2082 poly->insert(dline); 2083 2084 //the lower grid line 2085 vert1[1] = vert2[1] = lowerV; 2086 for(i=lowerInd; i<innerInd; i++) 2087 { 2088 vert1[0] = grid->get_u_value(i); 2089 vert2[0] = grid->get_u_value(i+1); 2090 sline = new sampledLine(vert1, vert2); 2091 dline = new directedLine(INCREASING, sline); 2092 poly->insert(dline); 2093 } 2094 2095 //the vertical grid line segement 2096 vert1[0]=vert2[0] = grid->get_u_value(innerInd); 2097 vert2[1]=upperV; 2098 vert1[1]=lowerV; 2099 sline=new sampledLine(vert1, vert2); 2100 dline=new directedLine(INCREASING, sline); 2101 poly->insert(dline); 2102 monoTriangulationOpt(poly, pStream); 2103 //cleanup 2104 poly->deleteSinglePolygonWithSline(); 2105 return; 2106 } 2107 2108 2109 2110 2111 2112 Int i; 2113 if(1/*leftGridChain->getUlineIndex(leftGridChainStartIndex) >= 2114 leftGridChain->getUlineIndex(leftGridChainStartIndex+1)*/ 2115 ) /*the second grid line is beyond the first one to the left*/ 2116 { 2117 /*find the maximal U-monotone chain 2118 * of endLeftIndex, endLeftIndex-1, ..., 2119 */ 2120 i=endLeftIndex; 2121 Real prevU = leftChain->getVertex(i)[0]; 2122 for(i=endLeftIndex-1; i>=beginLeftIndex; i--){ 2123 Real thisU = leftChain->getVertex(i)[0]; 2124 if( prevU < thisU){ 2125 prevU = thisU; 2126 } 2127 else 2128 break; 2129 } 2130 /*from endLeftIndex to i+1 is strictly U- monotone */ 2131 /*if i+1==endLeftIndex and the vertex and leftchain is on the second gridline, then 2132 *we should use 2 vertices on the leftchain. If we only use one (endLeftIndex), then we 2133 *we would output degenerate triangles 2134 */ 2135 if(i+1 == endLeftIndex && leftChain->getVertex(endLeftIndex)[1] == leftGridChain->get_v_value(1+leftGridChainStartIndex)) 2136 i--; 2137 2138 Int j = beginLeftIndex/*endLeftIndex*/+1; 2139 2140 2141 if(leftGridChain->getInnerIndex(leftGridChainStartIndex+1) > leftGridChain->getUlineIndex(leftGridChainStartIndex)) 2142 { 2143 j = findIncreaseChainFromBegin(leftChain, beginLeftIndex, i+1/*endLeftIndex*/); 2144 2145 Int temp = beginLeftIndex; 2146 /*now from begin to j-1 is strictly u-monotone*/ 2147 /*if j-1 is on the first grid line, then we want to skip to the vertex which is strictly 2148 *below the grid line. This vertexmust exist since there is a 'corner turn' inbetween the two grid lines 2149 */ 2150 if(j-1 == beginLeftIndex) 2151 { 2152 while(leftChain->getVertex(j-1)[1] == leftGridChain->get_v_value(leftGridChainStartIndex)) 2153 j++; 2154 2155 Real vert[2]; 2156 vert[0] = leftGridChain->get_u_value(leftGridChainStartIndex); 2157 vert[1] = leftGridChain->get_v_value(leftGridChainStartIndex); 2158 2159 monoTriangulation2( 2160 vert/*leftChain->getVertex(beginLeftIndex)*/, 2161 leftChain->getVertex(j-1), 2162 leftChain, 2163 beginLeftIndex, 2164 j-2, 2165 1, 2166 pStream //increase chain 2167 ); 2168 2169 temp = j-1; 2170 } 2171 2172 stripOfFanLeft(leftChain, j-1, temp/*beginLeftIndex*/, leftGridChain->getGrid(), 2173 leftGridChain->getVlineIndex(leftGridChainStartIndex), 2174 leftGridChain->getUlineIndex(leftGridChainStartIndex), 2175 leftGridChain->getInnerIndex(leftGridChainStartIndex+1), 2176 pStream, 2177 1 /*the grid line is above the trim line*/ 2178 ); 2179 } 2180 2181 stripOfFanLeft(leftChain, endLeftIndex, i+1, leftGridChain->getGrid(), 2182 leftGridChain->getVlineIndex(leftGridChainStartIndex+1), 2183 leftGridChain->getUlineIndex(leftGridChainStartIndex+1), 2184 leftGridChain->getInnerIndex(leftGridChainStartIndex+1), 2185 pStream, 2186 0 /*the grid line is below the trim lines*/ 2187 ); 2188 2189 /*monotone triangulate the remaining left chain togther with the 2190 *two vertices on the two grid v-lines. 2191 */ 2192 Real vert[2][2]; 2193 vert[0][0]=vert[1][0] = leftGridChain->getInner_u_value(leftGridChainStartIndex+1); 2194 vert[0][1] = leftGridChain->get_v_value(leftGridChainStartIndex); 2195 vert[1][1] = leftGridChain->get_v_value(leftGridChainStartIndex+1); 2196 2197 // vertexArray right(vert, 2); 2198 2199 monoTriangulation2( 2200 &vert[0][0], /*top vertex */ 2201 &vert[1][0], /*bottom vertex*/ 2202 leftChain, 2203 /*beginLeftIndex*/j-1, 2204 i+1, 2205 1, /*an increasing chain*/ 2206 pStream); 2207 } 2208 else /*the second one is shorter than the first one to the left*/ 2209 { 2210 /*find the maximal U-monotone chain of beginLeftIndex, beginLeftIndex+1,..., 2211 */ 2212 i=beginLeftIndex; 2213 Real prevU = leftChain->getVertex(i)[0]; 2214 for(i=beginLeftIndex+1; i<=endLeftIndex; i++){ 2215 Real thisU = leftChain->getVertex(i)[0]; 2216 2217 if(prevU < thisU){ 2218 prevU = thisU; 2219 } 2220 else 2221 break; 2222 } 2223 /*from beginLeftIndex to i-1 is strictly U-monotone*/ 2224 2225 2226 stripOfFanLeft(leftChain, i-1, beginLeftIndex, leftGridChain->getGrid(), 2227 leftGridChain->getVlineIndex(leftGridChainStartIndex), 2228 leftGridChain->getUlineIndex(leftGridChainStartIndex), 2229 leftGridChain->getUlineIndex(leftGridChainStartIndex+1), 2230 pStream, 2231 1 /*the grid line is above the trim lines*/ 2232 ); 2233 /*monotone triangulate the remaining left chain together with the 2234 *two vertices on the two grid v-lines. 2235 */ 2236 Real vert[2][2]; 2237 vert[0][0]=vert[1][0] = leftGridChain->get_u_value(leftGridChainStartIndex+1); 2238 vert[0][1] = leftGridChain->get_v_value(leftGridChainStartIndex); 2239 vert[1][1] = leftGridChain->get_v_value(leftGridChainStartIndex+1); 2240 2241 vertexArray right(vert, 2); 2242 2243 monoTriangulation2( 2244 &vert[0][0], //top vertex 2245 &vert[1][0], //bottom vertex 2246 leftChain, 2247 i-1, 2248 endLeftIndex, 2249 1, /*an increase chain*/ 2250 pStream); 2251 2252 } 2253 } 2254 2255 /*n_upper>=1 2256 *n_lower>=1 2257 */ 2258 void triangulateXYMono(Int n_upper, Real upperVerts[][2], 2259 Int n_lower, Real lowerVerts[][2], 2260 primStream* pStream) 2261 { 2262 Int i,j,k,l; 2263 Real* leftMostV; 2264 2265 assert(n_upper>=1 && n_lower>=1); 2266 if(upperVerts[0][0] <= lowerVerts[0][0]) 2267 { 2268 i=1; 2269 j=0; 2270 leftMostV = upperVerts[0]; 2271 } 2272 else 2273 { 2274 i=0; 2275 j=1; 2276 leftMostV = lowerVerts[0]; 2277 } 2278 2279 while(1) 2280 { 2281 if(i >= n_upper) /*case1: no more in upper*/ 2282 { 2283 2284 if(j<n_lower-1) /*at least two vertices in lower*/ 2285 { 2286 pStream->begin(); 2287 pStream->insert(leftMostV); 2288 while(j<n_lower){ 2289 pStream->insert(lowerVerts[j]); 2290 j++; 2291 } 2292 pStream->end(PRIMITIVE_STREAM_FAN); 2293 } 2294 2295 break; 2296 } 2297 else if(j>= n_lower) /*case2: no more in lower*/ 2298 { 2299 2300 if(i<n_upper-1) /*at least two vertices in upper*/ 2301 { 2302 pStream->begin(); 2303 pStream->insert(leftMostV); 2304 2305 for(k=n_upper-1; k>=i; k--) 2306 pStream->insert(upperVerts[k]); 2307 2308 pStream->end(PRIMITIVE_STREAM_FAN); 2309 } 2310 2311 break; 2312 } 2313 else /* case3: neither is empty, plus the leftMostV, there is at least one triangle to output*/ 2314 { 2315 2316 if(upperVerts[i][0] <= lowerVerts[j][0]) 2317 { 2318 pStream->begin(); 2319 pStream->insert(lowerVerts[j]); /*the origin of this fan*/ 2320 2321 /*find the last k>=i such that 2322 *upperverts[k][0] <= lowerverts[j][0] 2323 */ 2324 k=i; 2325 while(k<n_upper) 2326 { 2327 if(upperVerts[k][0] > lowerVerts[j][0]) 2328 break; 2329 k++; 2330 } 2331 k--; 2332 for(l=k; l>=i; l--)/*the reverse is for two-face lighting*/ 2333 { 2334 pStream->insert(upperVerts[l]); 2335 } 2336 pStream->insert(leftMostV); 2337 2338 pStream->end(PRIMITIVE_STREAM_FAN); 2339 //update i for next loop 2340 i = k+1; 2341 leftMostV = upperVerts[k]; 2342 2343 } 2344 else /*upperVerts[i][0] > lowerVerts[j][0]*/ 2345 { 2346 pStream->begin(); 2347 pStream->insert(upperVerts[i]);/*the origion of this fan*/ 2348 pStream->insert(leftMostV); 2349 /*find the last k>=j such that 2350 *lowerverts[k][0] < upperverts[i][0]*/ 2351 k=j; 2352 while(k< n_lower) 2353 { 2354 if(lowerVerts[k][0] >= upperVerts[i][0]) 2355 break; 2356 pStream->insert(lowerVerts[k]); 2357 k++; 2358 } 2359 pStream->end(PRIMITIVE_STREAM_FAN); 2360 j=k; 2361 leftMostV = lowerVerts[j-1]; 2362 } 2363 } 2364 } 2365 } 2366 2367 2368 void stripOfFanLeft(vertexArray* leftChain, 2369 Int largeIndex, 2370 Int smallIndex, 2371 gridWrap* grid, 2372 Int vlineIndex, 2373 Int ulineSmallIndex, 2374 Int ulineLargeIndex, 2375 primStream* pStream, 2376 Int gridLineUp /*1 if the grid line is above the trim lines*/ 2377 ) 2378 { 2379 assert(largeIndex >= smallIndex); 2380 2381 Real grid_v_value; 2382 grid_v_value = grid->get_v_value(vlineIndex); 2383 2384 Real2* trimVerts=(Real2*) malloc(sizeof(Real2)* (largeIndex-smallIndex+1)); 2385 assert(trimVerts); 2386 2387 2388 Real2* gridVerts=(Real2*) malloc(sizeof(Real2)* (ulineLargeIndex-ulineSmallIndex+1)); 2389 assert(gridVerts); 2390 2391 Int k,i; 2392 if(gridLineUp) /*trim line is below grid line, so trim vertices are going right when index increases*/ 2393 for(k=0, i=smallIndex; i<=largeIndex; i++, k++) 2394 { 2395 trimVerts[k][0] = leftChain->getVertex(i)[0]; 2396 trimVerts[k][1] = leftChain->getVertex(i)[1]; 2397 } 2398 else 2399 for(k=0, i=largeIndex; i>=smallIndex; i--, k++) 2400 { 2401 trimVerts[k][0] = leftChain->getVertex(i)[0]; 2402 trimVerts[k][1] = leftChain->getVertex(i)[1]; 2403 } 2404 2405 for(k=0, i=ulineSmallIndex; i<= ulineLargeIndex; i++, k++) 2406 { 2407 gridVerts[k][0] = grid->get_u_value(i); 2408 gridVerts[k][1] = grid_v_value; 2409 } 2410 2411 if(gridLineUp) 2412 triangulateXYMono( 2413 ulineLargeIndex-ulineSmallIndex+1, gridVerts, 2414 largeIndex-smallIndex+1, trimVerts, 2415 pStream); 2416 else 2417 triangulateXYMono(largeIndex-smallIndex+1, trimVerts, 2418 ulineLargeIndex-ulineSmallIndex+1, gridVerts, 2419 pStream); 2420 free(trimVerts); 2421 free(gridVerts); 2422 } 2423 2424 2425 2426 2427 2428