Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > DoxygensampleMonoPoly.cc
Go to the documentation of this file.
00001 /* 00002 ** License Applicability. Except to the extent portions of this file are 00003 ** made subject to an alternative license as permitted in the SGI Free 00004 ** Software License B, Version 1.1 (the "License"), the contents of this 00005 ** file are subject only to the provisions of the License. You may not use 00006 ** this file except in compliance with the License. You may obtain a copy 00007 ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 00008 ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: 00009 ** 00010 ** http://oss.sgi.com/projects/FreeB 00011 ** 00012 ** Note that, as provided in the License, the Software is distributed on an 00013 ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS 00014 ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND 00015 ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A 00016 ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. 00017 ** 00018 ** Original Code. The Original Code is: OpenGL Sample Implementation, 00019 ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, 00020 ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. 00021 ** Copyright in any portions created by third parties is as indicated 00022 ** elsewhere herein. All Rights Reserved. 00023 ** 00024 ** Additional Notice Provisions: The application programming interfaces 00025 ** established by SGI in conjunction with the Original Code are The 00026 ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released 00027 ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version 00028 ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X 00029 ** Window System(R) (Version 1.3), released October 19, 1998. This software 00030 ** was created using the OpenGL(R) version 1.2.1 Sample Implementation 00031 ** published by SGI, but has not been independently verified as being 00032 ** compliant with the OpenGL(R) version 1.2.1 Specification. 00033 ** 00034 ** $Date: 2006-03-12 00:07:02 +0000 (Sun, 12 Mar 2006) $ $Revision: 1.1 $ 00035 */ 00036 /* 00037 ** $Header: /cygdrive/c/RCVS/CVS/ReactOS/reactos/lib/glu32/libnurbs/nurbtess/sampleMonoPoly.cc,v 1.1 2004/02/02 16:39:15 navaraf Exp $ 00038 */ 00039 00040 #include "gluos.h" 00041 #include <stdlib.h> 00042 #include <stdio.h> 00043 #include <math.h> 00044 00045 #ifndef max 00046 #define max(a,b) ((a>b)? a:b) 00047 #endif 00048 #ifndef min 00049 #define min(a,b) ((a>b)? b:a) 00050 #endif 00051 00052 #include <GL/gl.h> 00053 00054 #include "glimports.h" 00055 #include "zlassert.h" 00056 #include "sampleMonoPoly.h" 00057 #include "sampleComp.h" 00058 #include "polyDBG.h" 00059 #include "partitionX.h" 00060 00061 00062 #define ZERO 0.00001 00063 00064 //#define MYDEBUG 00065 00066 //#define SHORTEN_GRID_LINE 00067 //see work/newtess/internal/test/problems 00068 00069 00070 /*split a polygon so that each vertex correcpond to one edge 00071 *the head of the first edge of the returned plygon must be the head of the first 00072 *edge of the origianl polygon. This is crucial for the code in sampleMonoPoly function 00073 */ 00074 directedLine* polygonConvert(directedLine* polygon) 00075 { 00076 int i; 00077 directedLine* ret; 00078 sampledLine* sline; 00079 sline = new sampledLine(2); 00080 sline->setPoint(0, polygon->getVertex(0)); 00081 sline->setPoint(1, polygon->getVertex(1)); 00082 ret=new directedLine(INCREASING, sline); 00083 for(i=1; i<= polygon->get_npoints()-2; i++) 00084 { 00085 sline = new sampledLine(2); 00086 sline->setPoint(0, polygon->getVertex(i)); 00087 sline->setPoint(1, polygon->getVertex(i+1)); 00088 ret->insert(new directedLine(INCREASING, sline)); 00089 } 00090 00091 for(directedLine *temp = polygon->getNext(); temp != polygon; temp = temp->getNext()) 00092 { 00093 for(i=0; i<= temp->get_npoints()-2; i++) 00094 { 00095 sline = new sampledLine(2); 00096 sline->setPoint(0, temp->getVertex(i)); 00097 sline->setPoint(1, temp->getVertex(i+1)); 00098 ret->insert(new directedLine(INCREASING, sline)); 00099 } 00100 } 00101 return ret; 00102 } 00103 00104 void triangulateConvexPolyVertical(directedLine* topV, directedLine* botV, primStream *pStream) 00105 { 00106 Int i,j; 00107 Int n_leftVerts; 00108 Int n_rightVerts; 00109 Real** leftVerts; 00110 Real** rightVerts; 00111 directedLine* tempV; 00112 n_leftVerts = 0; 00113 for(tempV = topV; tempV != botV; tempV = tempV->getNext()) 00114 { 00115 n_leftVerts += tempV->get_npoints(); 00116 } 00117 n_rightVerts=0; 00118 for(tempV = botV; tempV != topV; tempV = tempV->getNext()) 00119 { 00120 n_rightVerts += tempV->get_npoints(); 00121 } 00122 00123 Real2* temp_leftVerts = (Real2 *) malloc(sizeof(Real2) * n_leftVerts); 00124 assert(temp_leftVerts); 00125 Real2* temp_rightVerts = (Real2 *) malloc(sizeof(Real2) * n_rightVerts); 00126 assert(temp_rightVerts); 00127 00128 leftVerts = (Real**) malloc(sizeof(Real2*) * n_leftVerts); 00129 assert(leftVerts); 00130 rightVerts = (Real**) malloc(sizeof(Real2*) * n_rightVerts); 00131 assert(rightVerts); 00132 for(i=0; i<n_leftVerts; i++) 00133 leftVerts[i] = temp_leftVerts[i]; 00134 for(i=0; i<n_rightVerts; i++) 00135 rightVerts[i] = temp_rightVerts[i]; 00136 00137 i=0; 00138 for(tempV = topV; tempV != botV; tempV = tempV->getNext()) 00139 { 00140 for(j=1; j<tempV->get_npoints(); j++) 00141 { 00142 leftVerts[i][0] = tempV->getVertex(j)[0]; 00143 leftVerts[i][1] = tempV->getVertex(j)[1]; 00144 i++; 00145 } 00146 } 00147 n_leftVerts = i; 00148 i=0; 00149 for(tempV = topV->getPrev(); tempV != botV->getPrev(); tempV = tempV->getPrev()) 00150 { 00151 for(j=tempV->get_npoints()-1; j>=1; j--) 00152 { 00153 rightVerts[i][0] = tempV->getVertex(j)[0]; 00154 rightVerts[i][1] = tempV->getVertex(j)[1]; 00155 i++; 00156 } 00157 } 00158 n_rightVerts = i; 00159 triangulateXYMonoTB(n_leftVerts, leftVerts, n_rightVerts, rightVerts, pStream); 00160 free(leftVerts); 00161 free(rightVerts); 00162 free(temp_leftVerts); 00163 free(temp_rightVerts); 00164 } 00165 00166 void triangulateConvexPolyHoriz(directedLine* leftV, directedLine* rightV, primStream *pStream) 00167 { 00168 Int i,j; 00169 Int n_lowerVerts; 00170 Int n_upperVerts; 00171 Real2 *lowerVerts; 00172 Real2 *upperVerts; 00173 directedLine* tempV; 00174 n_lowerVerts=0; 00175 for(tempV = leftV; tempV != rightV; tempV = tempV->getNext()) 00176 { 00177 n_lowerVerts += tempV->get_npoints(); 00178 } 00179 n_upperVerts=0; 00180 for(tempV = rightV; tempV != leftV; tempV = tempV->getNext()) 00181 { 00182 n_upperVerts += tempV->get_npoints(); 00183 } 00184 lowerVerts = (Real2 *) malloc(sizeof(Real2) * n_lowerVerts); 00185 assert(n_lowerVerts); 00186 upperVerts = (Real2 *) malloc(sizeof(Real2) * n_upperVerts); 00187 assert(n_upperVerts); 00188 i=0; 00189 for(tempV = leftV; tempV != rightV; tempV = tempV->getNext()) 00190 { 00191 for(j=0; j<tempV->get_npoints(); j++) 00192 { 00193 lowerVerts[i][0] = tempV->getVertex(j)[0]; 00194 lowerVerts[i][1] = tempV->getVertex(j)[1]; 00195 i++; 00196 } 00197 } 00198 i=0; 00199 for(tempV = leftV->getPrev(); tempV != rightV->getPrev(); tempV = tempV->getPrev()) 00200 { 00201 for(j=tempV->get_npoints()-1; j>=0; j--) 00202 { 00203 upperVerts[i][0] = tempV->getVertex(j)[0]; 00204 upperVerts[i][1] = tempV->getVertex(j)[1]; 00205 i++; 00206 } 00207 } 00208 triangulateXYMono(n_upperVerts, upperVerts, n_lowerVerts, lowerVerts, pStream); 00209 free(lowerVerts); 00210 free(upperVerts); 00211 } 00212 void triangulateConvexPoly(directedLine* polygon, Int ulinear, Int vlinear, primStream* pStream) 00213 { 00214 /*find left, right, top , bot 00215 */ 00216 directedLine* tempV; 00217 directedLine* topV; 00218 directedLine* botV; 00219 directedLine* leftV; 00220 directedLine* rightV; 00221 topV = botV = polygon; 00222 00223 for(tempV = polygon->getNext(); tempV != polygon; tempV = tempV->getNext()) 00224 { 00225 if(compV2InY(topV->head(), tempV->head())<0) { 00226 00227 topV = tempV; 00228 } 00229 if(compV2InY(botV->head(), tempV->head())>0) { 00230 00231 botV = tempV; 00232 } 00233 } 00234 //find leftV 00235 for(tempV = topV; tempV != botV; tempV = tempV->getNext()) 00236 { 00237 if(tempV->tail()[0] >= tempV->head()[0]) 00238 break; 00239 } 00240 leftV = tempV; 00241 //find rightV 00242 for(tempV = botV; tempV != topV; tempV = tempV->getNext()) 00243 { 00244 if(tempV->tail()[0] <= tempV->head()[0]) 00245 break; 00246 } 00247 rightV = tempV; 00248 if(vlinear) 00249 { 00250 triangulateConvexPolyHoriz( leftV, rightV, pStream); 00251 } 00252 else if(ulinear) 00253 { 00254 triangulateConvexPolyVertical(topV, botV, pStream); 00255 } 00256 else 00257 { 00258 if(DBG_is_U_direction(polygon)) 00259 { 00260 triangulateConvexPolyHoriz( leftV, rightV, pStream); 00261 } 00262 else 00263 triangulateConvexPolyVertical(topV, botV, pStream); 00264 } 00265 } 00266 00267 /*for debug purpose*/ 00268 void drawCorners( 00269 Real* topV, Real* botV, 00270 vertexArray* leftChain, 00271 vertexArray* rightChain, 00272 gridBoundaryChain* leftGridChain, 00273 gridBoundaryChain* rightGridChain, 00274 Int gridIndex1, 00275 Int gridIndex2, 00276 Int leftCornerWhere, 00277 Int leftCornerIndex, 00278 Int rightCornerWhere, 00279 Int rightCornerIndex, 00280 Int bot_leftCornerWhere, 00281 Int bot_leftCornerIndex, 00282 Int bot_rightCornerWhere, 00283 Int bot_rightCornerIndex) 00284 { 00285 Real* leftCornerV; 00286 Real* rightCornerV; 00287 Real* bot_leftCornerV; 00288 Real* bot_rightCornerV; 00289 00290 if(leftCornerWhere == 1) 00291 leftCornerV = topV; 00292 else if(leftCornerWhere == 0) 00293 leftCornerV = leftChain->getVertex(leftCornerIndex); 00294 else 00295 leftCornerV = rightChain->getVertex(leftCornerIndex); 00296 00297 if(rightCornerWhere == 1) 00298 rightCornerV = topV; 00299 else if(rightCornerWhere == 0) 00300 rightCornerV = leftChain->getVertex(rightCornerIndex); 00301 else 00302 rightCornerV = rightChain->getVertex(rightCornerIndex); 00303 00304 if(bot_leftCornerWhere == 1) 00305 bot_leftCornerV = botV; 00306 else if(bot_leftCornerWhere == 0) 00307 bot_leftCornerV = leftChain->getVertex(bot_leftCornerIndex); 00308 else 00309 bot_leftCornerV = rightChain->getVertex(bot_leftCornerIndex); 00310 00311 if(bot_rightCornerWhere == 1) 00312 bot_rightCornerV = botV; 00313 else if(bot_rightCornerWhere == 0) 00314 bot_rightCornerV = leftChain->getVertex(bot_rightCornerIndex); 00315 else 00316 bot_rightCornerV = rightChain->getVertex(bot_rightCornerIndex); 00317 00318 Real topGridV = leftGridChain->get_v_value(gridIndex1); 00319 Real topGridU1 = leftGridChain->get_u_value(gridIndex1); 00320 Real topGridU2 = rightGridChain->get_u_value(gridIndex1); 00321 Real botGridV = leftGridChain->get_v_value(gridIndex2); 00322 Real botGridU1 = leftGridChain->get_u_value(gridIndex2); 00323 Real botGridU2 = rightGridChain->get_u_value(gridIndex2); 00324 00325 glBegin(GL_LINE_STRIP); 00326 glVertex2fv(leftCornerV); 00327 glVertex2f(topGridU1, topGridV); 00328 glEnd(); 00329 00330 glBegin(GL_LINE_STRIP); 00331 glVertex2fv(rightCornerV); 00332 glVertex2f(topGridU2, topGridV); 00333 glEnd(); 00334 00335 glBegin(GL_LINE_STRIP); 00336 glVertex2fv(bot_leftCornerV); 00337 glVertex2f(botGridU1, botGridV); 00338 glEnd(); 00339 00340 glBegin(GL_LINE_STRIP); 00341 glVertex2fv(bot_rightCornerV); 00342 glVertex2f(botGridU2, botGridV); 00343 glEnd(); 00344 00345 00346 } 00347 00348 void toVertexArrays(directedLine* topV, directedLine* botV, vertexArray& leftChain, vertexArray& rightChain) 00349 { 00350 Int i; 00351 directedLine* tempV; 00352 for(i=1; i<=topV->get_npoints()-2; i++) { /*the first vertex is the top vertex which doesn't belong to inc_chain*/ 00353 leftChain.appendVertex(topV->getVertex(i)); 00354 } 00355 for(tempV = topV->getNext(); tempV != botV; tempV = tempV->getNext()) 00356 { 00357 for(i=0; i<=tempV->get_npoints()-2; i++){ 00358 leftChain.appendVertex(tempV->getVertex(i)); 00359 } 00360 } 00361 00362 for(tempV = topV->getPrev(); tempV != botV; tempV = tempV->getPrev()) 00363 { 00364 for(i=tempV->get_npoints()-2; i>=0; i--){ 00365 rightChain.appendVertex(tempV->getVertex(i)); 00366 } 00367 } 00368 for(i=botV->get_npoints()-2; i>=1; i--){ 00369 rightChain.appendVertex(tempV->getVertex(i)); 00370 } 00371 } 00372 00373 00374 void findTopAndBot(directedLine* polygon, directedLine*& topV, directedLine*& botV) 00375 { 00376 assert(polygon); 00377 directedLine* tempV; 00378 topV = botV = polygon; 00379 for(tempV = polygon->getNext(); tempV != polygon; tempV = tempV->getNext()) 00380 { 00381 if(compV2InY(topV->head(), tempV->head())<0) { 00382 topV = tempV; 00383 } 00384 if(compV2InY(botV->head(), tempV->head())>0) { 00385 botV = tempV; 00386 } 00387 } 00388 } 00389 00390 void findGridChains(directedLine* topV, directedLine* botV, 00391 gridWrap* grid, 00392 gridBoundaryChain*& leftGridChain, 00393 gridBoundaryChain*& rightGridChain) 00394 { 00395 /*find the first(top) and the last (bottom) grid line which intersect the 00396 *this polygon 00397 */ 00398 Int firstGridIndex; /*the index in the grid*/ 00399 Int lastGridIndex; 00400 00401 firstGridIndex = (Int) ((topV->head()[1] - grid->get_v_min()) / (grid->get_v_max() - grid->get_v_min()) * (grid->get_n_vlines()-1)); 00402 00403 if(botV->head()[1] < grid->get_v_min()) 00404 lastGridIndex = 0; 00405 else 00406 lastGridIndex = (Int) ((botV->head()[1] - grid->get_v_min()) / (grid->get_v_max() - grid->get_v_min()) * (grid->get_n_vlines()-1)) + 1; 00407 00408 /*find the interval inside the polygon for each gridline*/ 00409 Int *leftGridIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1)); 00410 assert(leftGridIndices); 00411 Int *rightGridIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1)); 00412 assert(rightGridIndices); 00413 Int *leftGridInnerIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1)); 00414 assert(leftGridInnerIndices); 00415 Int *rightGridInnerIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1)); 00416 assert(rightGridInnerIndices); 00417 00418 findLeftGridIndices(topV, firstGridIndex, lastGridIndex, grid, leftGridIndices, leftGridInnerIndices); 00419 00420 findRightGridIndices(topV, firstGridIndex, lastGridIndex, grid, rightGridIndices, rightGridInnerIndices); 00421 00422 leftGridChain = new gridBoundaryChain(grid, firstGridIndex, firstGridIndex-lastGridIndex+1, leftGridIndices, leftGridInnerIndices); 00423 00424 rightGridChain = new gridBoundaryChain(grid, firstGridIndex, firstGridIndex-lastGridIndex+1, rightGridIndices, rightGridInnerIndices); 00425 00426 free(leftGridIndices); 00427 free(rightGridIndices); 00428 free(leftGridInnerIndices); 00429 free(rightGridInnerIndices); 00430 } 00431 00432 void findDownCorners(Real *botVertex, 00433 vertexArray *leftChain, Int leftChainStartIndex, Int leftChainEndIndex, 00434 vertexArray *rightChain, Int rightChainStartIndex, Int rightChainEndIndex, 00435 Real v, 00436 Real uleft, 00437 Real uright, 00438 Int& ret_leftCornerWhere, /*0: left chain, 1: topvertex, 2: rightchain*/ 00439 Int& ret_leftCornerIndex, /*useful when ret_leftCornerWhere == 0 or 2*/ 00440 Int& ret_rightCornerWhere, /*0: left chain, 1: topvertex, 2: rightchain*/ 00441 Int& ret_rightCornerIndex /*useful when ret_leftCornerWhere == 0 or 2*/ 00442 ) 00443 { 00444 #ifdef MYDEBUG 00445 printf("*************enter find donw corner\n"); 00446 printf("finddownCorner: v=%f, uleft=%f, uright=%f\n", v, uleft, uright); 00447 printf("(%i,%i,%i,%i)\n", leftChainStartIndex, leftChainEndIndex,rightChainStartIndex, rightChainEndIndex); 00448 printf("left chain is\n"); 00449 leftChain->print(); 00450 printf("right chain is\n"); 00451 rightChain->print(); 00452 #endif 00453 00454 assert(v > botVertex[1]); 00455 Real leftGridPoint[2]; 00456 leftGridPoint[0] = uleft; 00457 leftGridPoint[1] = v; 00458 Real rightGridPoint[2]; 00459 rightGridPoint[0] = uright; 00460 rightGridPoint[1] = v; 00461 00462 Int i; 00463 Int index1, index2; 00464 00465 index1 = leftChain->findIndexBelowGen(v, leftChainStartIndex, leftChainEndIndex); 00466 index2 = rightChain->findIndexBelowGen(v, rightChainStartIndex, rightChainEndIndex); 00467 00468 if(index2 <= rightChainEndIndex) //index2 was found above 00469 index2 = rightChain->skipEqualityFromStart(v, index2, rightChainEndIndex); 00470 00471 if(index1>leftChainEndIndex && index2 > rightChainEndIndex) /*no point below v on left chain or right chain*/ 00472 { 00473 00474 /*the botVertex is the only vertex below v*/ 00475 ret_leftCornerWhere = 1; 00476 ret_rightCornerWhere = 1; 00477 } 00478 else if(index1>leftChainEndIndex ) /*index2 <= rightChainEndIndex*/ 00479 { 00480 00481 ret_rightCornerWhere = 2; /*on right chain*/ 00482 ret_rightCornerIndex = index2; 00483 00484 00485 Real tempMin = rightChain->getVertex(index2)[0]; 00486 Int tempI = index2; 00487 for(i=index2+1; i<= rightChainEndIndex; i++) 00488 if(rightChain->getVertex(i)[0] < tempMin) 00489 { 00490 tempI = i; 00491 tempMin = rightChain->getVertex(i)[0]; 00492 } 00493 00494 00495 //we consider whether we can use botVertex as left corner. First check 00496 //if (leftGirdPoint, botVertex) interesects right chian or not. 00497 if(DBG_intersectChain(rightChain, rightChainStartIndex,rightChainEndIndex, 00498 leftGridPoint, botVertex)) 00499 { 00500 ret_leftCornerWhere = 2;//right 00501 ret_leftCornerIndex = index2; //should use tempI??? 00502 } 00503 else if(botVertex[0] < tempMin) 00504 ret_leftCornerWhere = 1; //bot 00505 else 00506 { 00507 ret_leftCornerWhere = 2; //right 00508 ret_leftCornerIndex = tempI; 00509 } 00510 } 00511 else if(index2> rightChainEndIndex) /*index1<=leftChainEndIndex*/ 00512 { 00513 ret_leftCornerWhere = 0; /*left chain*/ 00514 ret_leftCornerIndex = index1; 00515 00516 /*find the vertex on the left chain with the maximum u, 00517 *either this vertex or the botvertex can be used as the right corner 00518 */ 00519 00520 Int tempI; 00521 //skip those points which are equal to v. (avoid degeneratcy) 00522 for(tempI = index1; tempI <= leftChainEndIndex; tempI++) 00523 if(leftChain->getVertex(tempI)[1] < v) 00524 break; 00525 if(tempI > leftChainEndIndex) 00526 ret_rightCornerWhere = 1; 00527 else 00528 { 00529 Real tempMax = leftChain->getVertex(tempI)[0]; 00530 for(i=tempI; i<= leftChainEndIndex; i++) 00531 if(leftChain->getVertex(i)[0] > tempMax) 00532 { 00533 tempI = i; 00534 tempMax = leftChain->getVertex(i)[0]; 00535 } 00536 00537 00538 00539 //we consider whether we can use botVertex as a corner. So first we check 00540 //whether (rightGridPoint, botVertex) interescts the left chain or not. 00541 if(DBG_intersectChain(leftChain, leftChainStartIndex,leftChainEndIndex, 00542 rightGridPoint, botVertex)) 00543 { 00544 ret_rightCornerWhere = 0; 00545 ret_rightCornerIndex = index1; //should use tempI??? 00546 } 00547 else if(botVertex[0] > tempMax) 00548 { 00549 00550 ret_rightCornerWhere = 1; 00551 } 00552 else 00553 { 00554 ret_rightCornerWhere = 0; 00555 ret_rightCornerIndex = tempI; 00556 } 00557 } 00558 00559 } 00560 else /*index1<=leftChainEndIndex and index2 <=rightChainEndIndex*/ 00561 { 00562 if(leftChain->getVertex(index1)[1] >= rightChain->getVertex(index2)[1]) /*left point above right point*/ 00563 { 00564 ret_leftCornerWhere = 0; /*on left chain*/ 00565 ret_leftCornerIndex = index1; 00566 00567 Real tempMax; 00568 Int tempI; 00569 00570 tempI = index1; 00571 tempMax = leftChain->getVertex(index1)[0]; 00572 00573 /*find the maximum u for all the points on the left above the right point index2*/ 00574 for(i=index1+1; i<= leftChainEndIndex; i++) 00575 { 00576 if(leftChain->getVertex(i)[1] < rightChain->getVertex(index2)[1]) 00577 break; 00578 00579 if(leftChain->getVertex(i)[0]>tempMax) 00580 { 00581 tempI = i; 00582 tempMax = leftChain->getVertex(i)[0]; 00583 } 00584 } 00585 //we consider if we can use rightChain(index2) as right corner 00586 //we check if (rightChain(index2), rightGidPoint) intersecs left chain or not. 00587 if(DBG_intersectChain(leftChain, leftChainStartIndex,leftChainEndIndex, rightGridPoint, rightChain->getVertex(index2))) 00588 { 00589 ret_rightCornerWhere = 0; 00590 ret_rightCornerIndex = index1; //should use tempI??? 00591 } 00592 else if(tempMax >= rightChain->getVertex(index2)[0] || 00593 tempMax >= uright 00594 ) 00595 { 00596 00597 ret_rightCornerWhere = 0; /*on left Chain*/ 00598 ret_rightCornerIndex = tempI; 00599 } 00600 else 00601 { 00602 ret_rightCornerWhere = 2; /*on right chain*/ 00603 ret_rightCornerIndex = index2; 00604 } 00605 } 00606 else /*left below right*/ 00607 { 00608 ret_rightCornerWhere = 2; /*on the right*/ 00609 ret_rightCornerIndex = index2; 00610 00611 Real tempMin; 00612 Int tempI; 00613 00614 tempI = index2; 00615 tempMin = rightChain->getVertex(index2)[0]; 00616 00617 /*find the minimum u for all the points on the right above the left poitn index1*/ 00618 for(i=index2+1; i<= rightChainEndIndex; i++) 00619 { 00620 if( rightChain->getVertex(i)[1] < leftChain->getVertex(index1)[1]) 00621 break; 00622 if(rightChain->getVertex(i)[0] < tempMin) 00623 { 00624 tempI = i; 00625 tempMin = rightChain->getVertex(i)[0]; 00626 } 00627 } 00628 00629 //we consider if we can use leftchain(index1) as left corner. 00630 //we check if (leftChain(index1) intersects right chian or not 00631 if(DBG_intersectChain(rightChain, rightChainStartIndex, rightChainEndIndex, leftGridPoint, leftChain->getVertex(index1))) 00632 { 00633 ret_leftCornerWhere = 2; 00634 ret_leftCornerIndex = index2; //should use tempI??? 00635 } 00636 else if(tempMin <= leftChain->getVertex(index1)[0] || 00637 tempMin <= uleft) 00638 { 00639 ret_leftCornerWhere = 2; /* on right chain*/ 00640 ret_leftCornerIndex = tempI; 00641 } 00642 else 00643 { 00644 ret_leftCornerWhere = 0; /*on left chain*/ 00645 ret_leftCornerIndex = index1; 00646 } 00647 } 00648 } 00649 00650 } 00651 00652 00653 void findUpCorners(Real *topVertex, 00654 vertexArray *leftChain, Int leftChainStartIndex, Int leftChainEndIndex, 00655 vertexArray *rightChain, Int rightChainStartIndex, Int rightChainEndIndex, 00656 Real v, 00657 Real uleft, 00658 Real uright, 00659 Int& ret_leftCornerWhere, /*0: left chain, 1: topvertex, 2: rightchain*/ 00660 Int& ret_leftCornerIndex, /*useful when ret_leftCornerWhere == 0 or 2*/ 00661 Int& ret_rightCornerWhere, /*0: left chain, 1: topvertex, 2: rightchain*/ 00662 Int& ret_rightCornerIndex /*useful when ret_leftCornerWhere == 0 or 2*/ 00663 ) 00664 { 00665 #ifdef MYDEBUG 00666 printf("***********enter findUpCorners\n"); 00667 #endif 00668 00669 assert(v < topVertex[1]); 00670 Real leftGridPoint[2]; 00671 leftGridPoint[0] = uleft; 00672 leftGridPoint[1] = v; 00673 Real rightGridPoint[2]; 00674 rightGridPoint[0] = uright; 00675 rightGridPoint[1] = v; 00676 00677 Int i; 00678 Int index1, index2; 00679 00680 index1 = leftChain->findIndexFirstAboveEqualGen(v, leftChainStartIndex, leftChainEndIndex); 00681 00682 00683 index2 = rightChain->findIndexFirstAboveEqualGen(v, rightChainStartIndex, rightChainEndIndex); 00684 00685 if(index2>= leftChainStartIndex) //index2 was found above 00686 index2 = rightChain->skipEqualityFromStart(v, index2, rightChainEndIndex); 00687 00688 if(index1<leftChainStartIndex && index2 <rightChainStartIndex) /*no point above v on left chain or right chain*/ 00689 { 00690 /*the topVertex is the only vertex above v*/ 00691 ret_leftCornerWhere = 1; 00692 ret_rightCornerWhere = 1; 00693 } 00694 else if(index1<leftChainStartIndex ) /*index2 >= rightChainStartIndex*/ 00695 { 00696 ret_rightCornerWhere = 2; /*on right chain*/ 00697 ret_rightCornerIndex = index2; 00698 00699 //find the minimum u on right top, either that, or top, or right[index2] is the left corner 00700 Real tempMin = rightChain->getVertex(index2)[0]; 00701 Int tempI = index2; 00702 for(i=index2-1; i>=rightChainStartIndex; i--) 00703 if(rightChain->getVertex(i)[0] < tempMin) 00704 { 00705 tempMin = rightChain->getVertex(i)[0]; 00706 tempI = i; 00707 } 00708 //chech whether (leftGridPoint, top) intersects rightchai, 00709 //if yes, use right corner as left corner 00710 //if not, use top or right[tempI] as left corner 00711 if(DBG_intersectChain(rightChain, rightChainStartIndex, rightChainEndIndex, 00712 leftGridPoint, topVertex)) 00713 { 00714 ret_leftCornerWhere = 2; //rightChain 00715 ret_leftCornerIndex = index2; 00716 } 00717 else if(topVertex[0] < tempMin) 00718 ret_leftCornerWhere = 1; /*topvertex*/ 00719 else 00720 { 00721 ret_leftCornerWhere = 2; //right chain 00722 ret_leftCornerIndex = tempI; 00723 } 00724 00725 } 00726 else if(index2< rightChainStartIndex) /*index1>=leftChainStartIndex*/ 00727 { 00728 ret_leftCornerWhere = 0; /*left chain*/ 00729 ret_leftCornerIndex = index1; 00730 00731 //find the maximum u on the left top section. either that or topvertex, or left[index1] is the right corner 00732 Real tempMax = leftChain->getVertex(index1)[0]; 00733 Int tempI = index1; 00734 00735 for(i=index1-1; i>=leftChainStartIndex; i--){ 00736 00737 if(leftChain->getVertex(i)[0] > tempMax) 00738 { 00739 00740 tempMax = leftChain->getVertex(i)[0]; 00741 tempI = i; 00742 } 00743 } 00744 //check whether (rightGridPoint, top) intersects leftChain or not 00745 //if yes, we use leftCorner as the right corner 00746 //if not, we use either top or left[tempI] as the right corner 00747 if(DBG_intersectChain(leftChain, leftChainStartIndex,leftChainEndIndex, 00748 rightGridPoint, topVertex)) 00749 { 00750 ret_rightCornerWhere = 0; //left chan 00751 ret_rightCornerIndex = index1; 00752 } 00753 else if(topVertex[0] > tempMax) 00754 ret_rightCornerWhere = 1;//topVertex 00755 else 00756 { 00757 ret_rightCornerWhere = 0;//left chain 00758 ret_rightCornerIndex = tempI; 00759 } 00760 } 00761 else /*index1>=leftChainStartIndex and index2 >=rightChainStartIndex*/ 00762 { 00763 if(leftChain->getVertex(index1)[1] <= rightChain->getVertex(index2)[1]) /*left point below right point*/ 00764 { 00765 ret_leftCornerWhere = 0; /*on left chain*/ 00766 ret_leftCornerIndex = index1; 00767 00768 Real tempMax; 00769 Int tempI; 00770 00771 tempI = index1; 00772 tempMax = leftChain->getVertex(index1)[0]; 00773 00774 /*find the maximum u for all the points on the left below the right point index2*/ 00775 for(i=index1-1; i>= leftChainStartIndex; i--) 00776 { 00777 if(leftChain->getVertex(i)[1] > rightChain->getVertex(index2)[1]) 00778 break; 00779 00780 if(leftChain->getVertex(i)[0]>tempMax) 00781 { 00782 tempI = i; 00783 tempMax = leftChain->getVertex(i)[0]; 00784 } 00785 } 00786 //chek whether (rightChain(index2), rightGridPoint) intersects leftchian or not 00787 if(DBG_intersectChain(leftChain, leftChainStartIndex, leftChainEndIndex, rightGridPoint, rightChain->getVertex(index2))) 00788 { 00789 ret_rightCornerWhere = 0; 00790 ret_rightCornerIndex = index1; 00791 } 00792 else if(tempMax >= rightChain->getVertex(index2)[0] || 00793 tempMax >= uright) 00794 { 00795 ret_rightCornerWhere = 0; /*on left Chain*/ 00796 ret_rightCornerIndex = tempI; 00797 } 00798 else 00799 { 00800 ret_rightCornerWhere = 2; /*on right chain*/ 00801 ret_rightCornerIndex = index2; 00802 } 00803 } 00804 else /*left above right*/ 00805 { 00806 ret_rightCornerWhere = 2; /*on the right*/ 00807 ret_rightCornerIndex = index2; 00808 00809 Real tempMin; 00810 Int tempI; 00811 00812 tempI = index2; 00813 tempMin = rightChain->getVertex(index2)[0]; 00814 00815 /*find the minimum u for all the points on the right below the left poitn index1*/ 00816 for(i=index2-1; i>= rightChainStartIndex; i--) 00817 { 00818 if( rightChain->getVertex(i)[1] > leftChain->getVertex(index1)[1]) 00819 break; 00820 if(rightChain->getVertex(i)[0] < tempMin) 00821 { 00822 tempI = i; 00823 tempMin = rightChain->getVertex(i)[0]; 00824 } 00825 } 00826 //check whether (leftGRidPoint,left(index1)) interesect right chain 00827 if(DBG_intersectChain(rightChain, rightChainStartIndex, rightChainEndIndex, 00828 leftGridPoint, leftChain->getVertex(index1))) 00829 { 00830 ret_leftCornerWhere = 2; //right 00831 ret_leftCornerIndex = index2; 00832 } 00833 else if(tempMin <= leftChain->getVertex(index1)[0] || 00834 tempMin <= uleft) 00835 { 00836 ret_leftCornerWhere = 2; /* on right chain*/ 00837 ret_leftCornerIndex = tempI; 00838 } 00839 else 00840 { 00841 ret_leftCornerWhere = 0; /*on left chain*/ 00842 ret_leftCornerIndex = index1; 00843 } 00844 } 00845 } 00846 #ifdef MYDEBUG 00847 printf("***********leave findUpCorners\n"); 00848 #endif 00849 } 00850 00851 //return 1 if neck exists, 0 othewise 00852 Int findNeckF(vertexArray *leftChain, Int botLeftIndex, 00853 vertexArray *rightChain, Int botRightIndex, 00854 gridBoundaryChain* leftGridChain, 00855 gridBoundaryChain* rightGridChain, 00856 Int gridStartIndex, 00857 Int& neckLeft, 00858 Int& neckRight) 00859 { 00860 /* 00861 printf("enter findNeckF, botleft, botright=%i,%i,gstartindex=%i\n",botLeftIndex,botRightIndex,gridStartIndex); 00862 printf("leftChain is\n"); 00863 leftChain->print(); 00864 printf("rightChain is\n"); 00865 rightChain->print(); 00866 */ 00867 00868 Int lowerGridIndex; //the grid below leftChain and rightChian vertices 00869 Int i; 00870 Int n_vlines = leftGridChain->get_nVlines(); 00871 Real v; 00872 if(botLeftIndex >= leftChain->getNumElements() || 00873 botRightIndex >= rightChain->getNumElements()) 00874 return 0; //no neck exists 00875 00876 v=min(leftChain->getVertex(botLeftIndex)[1], rightChain->getVertex(botRightIndex)[1]); 00877 00878 00879 00880 00881 for(i=gridStartIndex; i<n_vlines; i++) 00882 if(leftGridChain->get_v_value(i) <= v && 00883 leftGridChain->getUlineIndex(i)<= rightGridChain->getUlineIndex(i)) 00884 break; 00885 00886 lowerGridIndex = i; 00887 00888 if(lowerGridIndex == n_vlines) //the two trm vertex are higher than all gridlines 00889 return 0; 00890 else 00891 { 00892 Int botLeft2, botRight2; 00893 /* 00894 printf("leftGridChain->get_v_)value=%f\n",leftGridChain->get_v_value(lowerGridIndex), botLeftIndex); 00895 printf("leftChain->get_vertex(0)=(%f,%f)\n", leftChain->getVertex(0)[0],leftChain->getVertex(0)[1]); 00896 printf("leftChain->get_vertex(1)=(%f,%f)\n", leftChain->getVertex(1)[0],leftChain->getVertex(1)[1]); 00897 printf("leftChain->get_vertex(2)=(%f,%f)\n", leftChain->getVertex(2)[0],leftChain->getVertex(2)[1]); 00898 */ 00899 botLeft2 = leftChain->findIndexFirstAboveEqualGen(leftGridChain->get_v_value(lowerGridIndex), botLeftIndex, leftChain->getNumElements()-1) -1 ; 00900 00901 /* 00902 printf("botLeft2=%i\n", botLeft2); 00903 printf("leftChain->getNumElements=%i\n", leftChain->getNumElements()); 00904 */ 00905 00906 botRight2 = rightChain->findIndexFirstAboveEqualGen(leftGridChain->get_v_value(lowerGridIndex), botRightIndex, rightChain->getNumElements()-1) -1; 00907 if(botRight2 < botRightIndex) botRight2=botRightIndex; 00908 00909 if(botLeft2 < botLeftIndex) botLeft2 = botLeftIndex; 00910 00911 assert(botLeft2 >= botLeftIndex); 00912 assert(botRight2 >= botRightIndex); 00913 //find nectLeft so that it is th erightmost vertex on letChain 00914 00915 Int tempI = botLeftIndex; 00916 Real temp = leftChain->getVertex(tempI)[0]; 00917 for(i=botLeftIndex+1; i<= botLeft2; i++) 00918 if(leftChain->getVertex(i)[0] > temp) 00919 { 00920 temp = leftChain->getVertex(i)[0]; 00921 tempI = i; 00922 } 00923 neckLeft = tempI; 00924 00925 tempI = botRightIndex; 00926 temp = rightChain->getVertex(tempI)[0]; 00927 for(i=botRightIndex+1; i<= botRight2; i++) 00928 if(rightChain->getVertex(i)[0] < temp) 00929 { 00930 temp = rightChain->getVertex(i)[0]; 00931 tempI = i; 00932 } 00933 neckRight = tempI; 00934 return 1; 00935 } 00936 } 00937 00938 00939 00940 /*find i>=botLeftIndex,j>=botRightIndex so that 00941 *(leftChain[i], rightChain[j]) is a neck. 00942 */ 00943 void findNeck(vertexArray *leftChain, Int botLeftIndex, 00944 vertexArray *rightChain, Int botRightIndex, 00945 Int& leftLastIndex, /*left point of the neck*/ 00946 Int& rightLastIndex /*right point of the neck*/ 00947 ) 00948 { 00949 assert(botLeftIndex < leftChain->getNumElements() && 00950 botRightIndex < rightChain->getNumElements()); 00951 00952 /*now the neck exists for sure*/ 00953 00954 if(leftChain->getVertex(botLeftIndex)[1] <= rightChain->getVertex(botRightIndex)[1]) //left below right 00955 { 00956 00957 leftLastIndex = botLeftIndex; 00958 00959 /*find i so that rightChain[i][1] >= leftchainbotverte[1], and i+1< 00960 */ 00961 rightLastIndex=rightChain->findIndexAboveGen(leftChain->getVertex(botLeftIndex)[1], botRightIndex+1, rightChain->getNumElements()-1); 00962 } 00963 else //left above right 00964 { 00965 00966 rightLastIndex = botRightIndex; 00967 00968 leftLastIndex = leftChain->findIndexAboveGen(rightChain->getVertex(botRightIndex)[1], 00969 botLeftIndex+1, 00970 leftChain->getNumElements()-1); 00971 } 00972 } 00973 00974 00975 00976 void findLeftGridIndices(directedLine* topEdge, Int firstGridIndex, Int lastGridIndex, gridWrap* grid, Int* ret_indices, Int* ret_innerIndices) 00977 { 00978 00979 Int i,k,isHoriz = 0; 00980 Int n_ulines = grid->get_n_ulines(); 00981 Real uMin = grid->get_u_min(); 00982 Real uMax = grid->get_u_max(); 00983 Real slop = 0.0f, uinterc; 00984 00985 #ifdef SHORTEN_GRID_LINE 00986 //uintercBuf stores all the interction u value for each grid line 00987 //notice that lastGridIndex<= firstGridIndex 00988 Real *uintercBuf = (Real *) malloc (sizeof(Real) * (firstGridIndex-lastGridIndex+1)); 00989 assert(uintercBuf); 00990 #endif 00991 00992 /*initialization to make vtail bigger than grid->...*/ 00993 directedLine* dLine = topEdge; 00994 Real vtail = grid->get_v_value(firstGridIndex) + 1.0; 00995 Real tempMaxU = grid->get_u_min(); 00996 00997 00998 /*for each grid line*/ 00999 for(k=0, i=firstGridIndex; i>=lastGridIndex; i--, k++) 01000 { 01001 01002 Real grid_v_value = grid->get_v_value(i); 01003 01004 /*check whether this grid line is below the current trim edge.*/ 01005 if(vtail > grid_v_value) 01006 { 01007 /*since the grid line is below the trim edge, we 01008 *find the trim edge which will contain the trim line 01009 */ 01010 while( (vtail=dLine->tail()[1]) > grid_v_value){ 01011 01012 tempMaxU = max(tempMaxU, dLine->tail()[0]); 01013 dLine = dLine -> getNext(); 01014 } 01015 01016 if( fabs(dLine->head()[1] - vtail) < ZERO) 01017 isHoriz = 1; 01018 else 01019 { 01020 isHoriz = 0; 01021 slop = (dLine->head()[0] - dLine->tail()[0]) / (dLine->head()[1]-vtail); 01022 } 01023 } 01024 01025 if(isHoriz) 01026 { 01027 uinterc = max(dLine->head()[0], dLine->tail()[0]); 01028 } 01029 else 01030 { 01031 uinterc = slop * (grid_v_value - vtail) + dLine->tail()[0]; 01032 } 01033 01034 tempMaxU = max(tempMaxU, uinterc); 01035 01036 if(uinterc < uMin && uinterc >= uMin - ZERO) 01037 uinterc = uMin; 01038 if(uinterc > uMax && uinterc <= uMax + ZERO) 01039 uinterc = uMax; 01040 01041 #ifdef SHORTEN_GRID_LINE 01042 uintercBuf[k] = uinterc; 01043 #endif 01044 01045 assert(uinterc >= uMin && uinterc <= uMax); 01046 if(uinterc == uMax) 01047 ret_indices[k] = n_ulines-1; 01048 else 01049 ret_indices[k] = (Int)(((uinterc-uMin)/(uMax - uMin)) * (n_ulines-1)) + 1; 01050 if(ret_indices[k] >= n_ulines) 01051 ret_indices[k] = n_ulines-1; 01052 01053 01054 ret_innerIndices[k] = (Int)(((tempMaxU-uMin)/(uMax - uMin)) * (n_ulines-1)) + 1; 01055 01056 /*reinitialize tempMaxU for next grdiLine*/ 01057 tempMaxU = uinterc; 01058 } 01059 #ifdef SHORTEN_GRID_LINE 01060 //for each grid line, compare the left grid point with the 01061 //intersection point. If the two points are too close, then 01062 //we should move the grid point one grid to the right 01063 //and accordingly we should update the inner index. 01064 for(k=0, i=firstGridIndex; i>=lastGridIndex; i--, k++) 01065 { 01066 //check gridLine i 01067 //check ret_indices[k] 01068 Real a = grid->get_u_value(ret_indices[k]-1); 01069 Real b = grid->get_u_value(ret_indices[k]); 01070 assert(uintercBuf[k] >= a && uintercBuf < b); 01071 if( (b-uintercBuf[k]) <= 0.2 * (b-a)) //interc is very close to b 01072 { 01073 ret_indices[k]++; 01074 } 01075 01076 //check ret_innerIndices[k] 01077 if(k>0) 01078 { 01079 if(ret_innerIndices[k] < ret_indices[k-1]) 01080 ret_innerIndices[k] = ret_indices[k-1]; 01081 if(ret_innerIndices[k] < ret_indices[k]) 01082 ret_innerIndices[k] = ret_indices[k]; 01083 } 01084 } 01085 //clean up 01086 free(uintercBuf); 01087 #endif 01088 } 01089 01090 void findRightGridIndices(directedLine* topEdge, Int firstGridIndex, Int lastGridIndex, gridWrap* grid, Int* ret_indices, Int* ret_innerIndices) 01091 { 01092 01093 Int i,k; 01094 Int n_ulines = grid->get_n_ulines(); 01095 Real uMin = grid->get_u_min(); 01096 Real uMax = grid->get_u_max(); 01097 Real slop = 0.0f, uinterc; 01098 01099 #ifdef SHORTEN_GRID_LINE 01100 //uintercBuf stores all the interction u value for each grid line 01101 //notice that firstGridIndex >= lastGridIndex 01102 Real *uintercBuf = (Real *) malloc (sizeof(Real) * (firstGridIndex-lastGridIndex+1)); 01103 assert(uintercBuf); 01104 #endif 01105 01106 /*initialization to make vhead bigger than grid->v_value...*/ 01107 directedLine* dLine = topEdge->getPrev(); 01108 Real vhead = dLine->tail()[1]; 01109 Real tempMinU = grid->get_u_max(); 01110 01111 /*for each grid line*/ 01112 for(k=0, i=firstGridIndex; i>=lastGridIndex; i--, k++) 01113 { 01114 01115 Real grid_v_value = grid->get_v_value(i); 01116 01117 01118 /*check whether this grid line is below the current trim edge.*/ 01119 if(vhead >= grid_v_value) 01120 { 01121 /*since the grid line is below the tail of the trim edge, we 01122 *find the trim edge which will contain the trim line 01123 */ 01124 while( (vhead=dLine->head()[1]) > grid_v_value){ 01125 tempMinU = min(tempMinU, dLine->head()[0]); 01126 dLine = dLine -> getPrev(); 01127 } 01128 01129 /*skip the equality in the case of degenerat case: horizontal */ 01130 while(dLine->head()[1] == grid_v_value) 01131 dLine = dLine->getPrev(); 01132 01133 assert( dLine->tail()[1] != dLine->head()[1]); 01134 slop = (dLine->tail()[0] - dLine->head()[0]) / (dLine->tail()[1]-dLine->head()[1]); 01135 /* 01136 if(dLine->tail()[1] == vhead) 01137 isHoriz = 1; 01138 else 01139 { 01140 isHoriz = 0; 01141 slop = (dLine->tail()[0] - dLine->head()[0]) / (dLine->tail()[1]-vhead); 01142 } 01143 */ 01144 } 01145 uinterc = slop * (grid_v_value - dLine->head()[1]) + dLine->head()[0]; 01146 01147 //in case unterc is outside of the grid due to floating point 01148 if(uinterc < uMin) 01149 uinterc = uMin; 01150 else if(uinterc > uMax) 01151 uinterc = uMax; 01152 01153 #ifdef SHORTEN_GRID_LINE 01154 uintercBuf[k] = uinterc; 01155 #endif 01156 01157 tempMinU = min(tempMinU, uinterc); 01158 01159 assert(uinterc >= uMin && uinterc <= uMax); 01160 01161 if(uinterc == uMin) 01162 ret_indices[k] = 0; 01163 else 01164 ret_indices[k] = (int)ceil((((uinterc-uMin)/(uMax - uMin)) * (n_ulines-1))) -1; 01165 /* 01166 if(ret_indices[k] >= grid->get_n_ulines()) 01167 { 01168 printf("ERROR3\n"); 01169 exit(0); 01170 } 01171 if(ret_indices[k] < 0) 01172 { 01173 printf("ERROR4\n"); 01174 exit(0); 01175 } 01176 */ 01177 ret_innerIndices[k] = (int)ceil ((((tempMinU-uMin)/(uMax - uMin)) * (n_ulines-1))) -1; 01178 01179 tempMinU = uinterc; 01180 } 01181 #ifdef SHORTEN_GRID_LINE 01182 //for each grid line, compare the left grid point with the 01183 //intersection point. If the two points are too close, then 01184 //we should move the grid point one grid to the right 01185 //and accordingly we should update the inner index. 01186 for(k=0, i=firstGridIndex; i>=lastGridIndex; i--, k++) 01187 { 01188 //check gridLine i 01189 //check ret_indices[k] 01190 Real a = grid->get_u_value(ret_indices[k]); 01191 Real b = grid->get_u_value(ret_indices[k]+1); 01192 assert(uintercBuf[k] > a && uintercBuf <= b); 01193 if( (uintercBuf[k]-a) <= 0.2 * (b-a)) //interc is very close to a 01194 { 01195 ret_indices[k]--; 01196 } 01197 01198 //check ret_innerIndices[k] 01199 if(k>0) 01200 { 01201 if(ret_innerIndices[k] > ret_indices[k-1]) 01202 ret_innerIndices[k] = ret_indices[k-1]; 01203 if(ret_innerIndices[k] > ret_indices[k]) 01204 ret_innerIndices[k] = ret_indices[k]; 01205 } 01206 } 01207 //clean up 01208 free(uintercBuf); 01209 #endif 01210 } 01211 01212 01213 void sampleMonoPoly(directedLine* polygon, gridWrap* grid, Int ulinear, Int vlinear, primStream* pStream, rectBlockArray* rbArray) 01214 { 01215 /* 01216 { 01217 grid->print(); 01218 polygon->writeAllPolygons("zloutputFile"); 01219 exit(0); 01220 } 01221 */ 01222 01223 if(grid->get_n_ulines() == 2 || 01224 grid->get_n_vlines() == 2) 01225 { 01226 if(ulinear && grid->get_n_ulines() == 2) 01227 { 01228 monoTriangulationFun(polygon, compV2InY, pStream); 01229 return; 01230 } 01231 else if(DBG_isConvex(polygon) && polygon->numEdges() >=4) 01232 { 01233 triangulateConvexPoly(polygon, ulinear, vlinear, pStream); 01234 return; 01235 } 01236 else if(vlinear || DBG_is_U_direction(polygon)) 01237 { 01238 Int n_cusps;//num interior cusps 01239 Int n_edges = polygon->numEdges(); 01240 directedLine** cusps = (directedLine**) malloc(sizeof(directedLine*) * n_edges); 01241 assert(cusps); 01242 findInteriorCuspsX(polygon, n_cusps, cusps); 01243 01244 if(n_cusps == 0) //u_monotone 01245 { 01246 01247 monoTriangulationFun(polygon, compV2InX, pStream); 01248 01249 free(cusps); 01250 return; 01251 } 01252 else if(n_cusps == 1) //one interior cusp 01253 { 01254 01255 directedLine* new_polygon = polygonConvert(cusps[0]); 01256 01257 directedLine* other = findDiagonal_singleCuspX( new_polygon); 01258 01259 01260 01261 //<other> should NOT be null unless there are self-intersecting 01262 //trim curves. In that case, we don't want to core dump, instead, 01263 //we triangulate anyway, and print out error message. 01264 if(other == NULL) 01265 { 01266 monoTriangulationFun(polygon, compV2InX, pStream); 01267 free(cusps); 01268 return; 01269 } 01270 01271 directedLine* ret_p1; 01272 directedLine* ret_p2; 01273 01274 new_polygon->connectDiagonal_2slines(new_polygon, other, 01275 &ret_p1, 01276 &ret_p2, 01277 new_polygon); 01278 01279 monoTriangulationFun(ret_p1, compV2InX, pStream); 01280 monoTriangulationFun(ret_p2, compV2InX, pStream); 01281 01282 ret_p1->deleteSinglePolygonWithSline(); 01283 ret_p2->deleteSinglePolygonWithSline(); 01284 01285 free(cusps); 01286 return; 01287 } 01288 free(cusps); 01289 } 01290 } 01291 01292 /*find the top and bottom of the polygon. It is supposed to be 01293 *a V-monotone polygon 01294 */ 01295 01296 directedLine* tempV; 01297 directedLine* topV; 01298 directedLine* botV; 01299 topV = botV = polygon; 01300 01301 for(tempV = polygon->getNext(); tempV != polygon; tempV = tempV->getNext()) 01302 { 01303 if(compV2InY(topV->head(), tempV->head())<0) { 01304 01305 topV = tempV; 01306 } 01307 if(compV2InY(botV->head(), tempV->head())>0) { 01308 01309 botV = tempV; 01310 } 01311 } 01312 01313 /*find the first(top) and the last (bottom) grid line which intersect the 01314 *this polygon 01315 */ 01316 Int firstGridIndex; /*the index in the grid*/ 01317 Int lastGridIndex; 01318 firstGridIndex = (Int) ((topV->head()[1] - grid->get_v_min()) / (grid->get_v_max() - grid->get_v_min()) * (grid->get_n_vlines()-1)); 01319 lastGridIndex = (Int) ((botV->head()[1] - grid->get_v_min()) / (grid->get_v_max() - grid->get_v_min()) * (grid->get_n_vlines()-1)) + 1; 01320 01321 01322 /*find the interval inside the polygon for each gridline*/ 01323 Int *leftGridIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1)); 01324 assert(leftGridIndices); 01325 Int *rightGridIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1)); 01326 assert(rightGridIndices); 01327 Int *leftGridInnerIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1)); 01328 assert(leftGridInnerIndices); 01329 Int *rightGridInnerIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1)); 01330 assert(rightGridInnerIndices); 01331 01332 findLeftGridIndices(topV, firstGridIndex, lastGridIndex, grid, leftGridIndices, leftGridInnerIndices); 01333 01334 findRightGridIndices(topV, firstGridIndex, lastGridIndex, grid, rightGridIndices, rightGridInnerIndices); 01335 01336 gridBoundaryChain leftGridChain(grid, firstGridIndex, firstGridIndex-lastGridIndex+1, leftGridIndices, leftGridInnerIndices); 01337 01338 gridBoundaryChain rightGridChain(grid, firstGridIndex, firstGridIndex-lastGridIndex+1, rightGridIndices, rightGridInnerIndices); 01339 01340 01341 01342 // leftGridChain.draw(); 01343 // leftGridChain.drawInner(); 01344 // rightGridChain.draw(); 01345 // rightGridChain.drawInner(); 01346 /*(1) determine the grid boundaries (left and right). 01347 *(2) process polygon into two monotone chaines: use vertexArray 01348 *(3) call sampleMonoPolyRec 01349 */ 01350 01351 /*copy the two chains into vertexArray datastructure*/ 01352 Int i; 01353 vertexArray leftChain(20); /*this is a dynamic array*/ 01354 for(i=1; i<=topV->get_npoints()-2; i++) { /*the first vertex is the top vertex which doesn't belong to inc_chain*/ 01355 leftChain.appendVertex(topV->getVertex(i)); 01356 } 01357 for(tempV = topV->getNext(); tempV != botV; tempV = tempV->getNext()) 01358 { 01359 for(i=0; i<=tempV->get_npoints()-2; i++){ 01360 leftChain.appendVertex(tempV->getVertex(i)); 01361 } 01362 } 01363 01364 vertexArray rightChain(20); 01365 for(tempV = topV->getPrev(); tempV != botV; tempV = tempV->getPrev()) 01366 { 01367 for(i=tempV->get_npoints()-2; i>=0; i--){ 01368 rightChain.appendVertex(tempV->getVertex(i)); 01369 } 01370 } 01371 for(i=botV->get_npoints()-2; i>=1; i--){ 01372 rightChain.appendVertex(tempV->getVertex(i)); 01373 } 01374 01375 sampleMonoPolyRec(topV->head(), 01376 botV->head(), 01377 &leftChain, 01378 0, 01379 &rightChain, 01380 0, 01381 &leftGridChain, 01382 &rightGridChain, 01383 0, 01384 pStream, 01385 rbArray); 01386 01387 01388 /*cleanup space*/ 01389 free(leftGridIndices); 01390 free(rightGridIndices); 01391 free(leftGridInnerIndices); 01392 free(rightGridInnerIndices); 01393 } 01394 01395 void sampleMonoPolyRec( 01396 Real* topVertex, 01397 Real* botVertex, 01398 vertexArray* leftChain, 01399 Int leftStartIndex, 01400 vertexArray* rightChain, 01401 Int rightStartIndex, 01402 gridBoundaryChain* leftGridChain, 01403 gridBoundaryChain* rightGridChain, 01404 Int gridStartIndex, 01405 primStream* pStream, 01406 rectBlockArray* rbArray) 01407 { 01408 01409 /*find the first connected component, and the four corners. 01410 */ 01411 Int index1, index2; /*the first and last grid line of the first connected component*/ 01412 01413 if(topVertex[1] <= botVertex[1]) 01414 return; 01415 01416 /*find i so that the grid line is below the top vertex*/ 01417 Int i=gridStartIndex; 01418 while (i < leftGridChain->get_nVlines()) 01419 { 01420 if(leftGridChain->get_v_value(i) < topVertex[1]) 01421 break; 01422 i++; 01423 } 01424 01425 /*find the first connected component starting with i*/ 01426 /*find index1 so that left_uline_index <= right_uline_index, that is, this 01427 *grid line contains at least one inner grid point 01428 */ 01429 index1=i; 01430 int num_skipped_grid_lines=0; 01431 while(index1 < leftGridChain->get_nVlines()) 01432 { 01433 if(leftGridChain->getUlineIndex(index1) <= rightGridChain->getUlineIndex(index1)) 01434 break; 01435 num_skipped_grid_lines++; 01436 index1++; 01437 } 01438 01439 01440 01441 if(index1 >= leftGridChain->get_nVlines()) /*no grid line exists which has inner point*/ 01442 { 01443 /*stop recursion, ...*/ 01444 /*monotone triangulate it...*/ 01445 // printf("no grid line exists\n"); 01446 /* 01447 monoTriangulationRecOpt(topVertex, botVertex, leftChain, leftStartIndex, 01448 rightChain, rightStartIndex, pStream); 01449 */ 01450 01451 if(num_skipped_grid_lines <2) 01452 { 01453 monoTriangulationRecGenOpt(topVertex, botVertex, leftChain, leftStartIndex, 01454 leftChain->getNumElements()-1, 01455 rightChain, rightStartIndex, 01456 rightChain->getNumElements()-1, 01457 pStream); 01458 } 01459 else 01460 { 01461 //the optimum way to triangulate is top-down since this polygon 01462 //is narrow-long. 01463 monoTriangulationRec(topVertex, botVertex, leftChain, leftStartIndex, 01464 rightChain, rightStartIndex, pStream); 01465 } 01466 01467 /* 01468 monoTriangulationRec(topVertex, botVertex, leftChain, leftStartIndex, 01469 rightChain, rightStartIndex, pStream); 01470 */ 01471 01472 /* monoTriangulationRecGenTBOpt(topVertex, botVertex, 01473 leftChain, leftStartIndex, leftChain->getNumElements()-1, 01474 rightChain, rightStartIndex, rightChain->getNumElements()-1, 01475 pStream);*/ 01476 01477 01478 01479 } 01480 else 01481 { 01482 01483 /*find index2 so that left_inner_index <= right_inner_index holds until index2*/ 01484 index2=index1+1; 01485 if(index2 < leftGridChain->get_nVlines()) 01486 while(leftGridChain->getInnerIndex(index2) <= rightGridChain->getInnerIndex(index2)) 01487 { 01488 index2++; 01489 if(index2 >= leftGridChain->get_nVlines()) 01490 break; 01491 } 01492 01493 index2--; 01494 01495 01496 01497 /*the neck*/ 01498 Int neckLeftIndex; 01499 Int neckRightIndex; 01500 01501 /*the four corners*/ 01502 Int up_leftCornerWhere; 01503 Int up_leftCornerIndex; 01504 Int up_rightCornerWhere; 01505 Int up_rightCornerIndex; 01506 Int down_leftCornerWhere; 01507 Int down_leftCornerIndex; 01508 Int down_rightCornerWhere; 01509 Int down_rightCornerIndex; 01510 01511 Real* tempBotVertex; /*the bottom vertex for this component*/ 01512 Real* nextTopVertex=NULL; /*for the recursion*/ 01513 Int nextLeftStartIndex=0; 01514 Int nextRightStartIndex=0; 01515 01516 /*find the points below the grid line index2 on both chains*/ 01517 Int botLeftIndex = leftChain->findIndexStrictBelowGen( 01518 leftGridChain->get_v_value(index2), 01519 leftStartIndex, 01520 leftChain->getNumElements()-1); 01521 Int botRightIndex = rightChain->findIndexStrictBelowGen( 01522 rightGridChain->get_v_value(index2), 01523 rightStartIndex, 01524 rightChain->getNumElements()-1); 01525 /*if either botLeftIndex>= numelements, 01526 * or botRightIndex >= numelemnet, 01527 *then there is no neck exists. the bottom vertex is botVertex, 01528 */ 01529 if(! findNeckF(leftChain, botLeftIndex, rightChain, botRightIndex, 01530 leftGridChain, rightGridChain, index2, neckLeftIndex, neckRightIndex)) 01531 /* 01532 if(botLeftIndex == leftChain->getNumElements() || 01533 botRightIndex == rightChain->getNumElements()) 01534 */ 01535 { 01536 #ifdef MYDEBUG 01537 printf("neck NOT exists, botRightIndex=%i\n", botRightIndex); 01538 #endif 01539 01540 tempBotVertex = botVertex; 01541 nextTopVertex = botVertex; 01542 botLeftIndex = leftChain->getNumElements()-1; 01543 botRightIndex = rightChain->getNumElements()-1; 01544 } 01545 else /*neck exists*/ 01546 { 01547 #ifdef MYDEBUG 01548 printf("neck exists\n"); 01549 #endif 01550 01551 /* 01552 findNeck(leftChain, botLeftIndex, 01553 rightChain, botRightIndex, 01554 neckLeftIndex, 01555 neckRightIndex); 01556 */ 01557 #ifdef MYDEBUG 01558 printf("neck is found, neckLeftIndex=%i, neckRightIndex=%i\n", neckLeftIndex, neckRightIndex); 01559 glBegin(GL_LINES); 01560 glVertex2fv(leftChain->getVertex(neckLeftIndex)); 01561 glVertex2fv(rightChain->getVertex(neckRightIndex)); 01562 glEnd(); 01563 #endif 01564 01565 if(leftChain->getVertex(neckLeftIndex)[1] <= rightChain->getVertex(neckRightIndex)[1]) 01566 { 01567 tempBotVertex = leftChain->getVertex(neckLeftIndex); 01568 botLeftIndex = neckLeftIndex-1; 01569 botRightIndex = neckRightIndex; 01570 nextTopVertex = rightChain->getVertex(neckRightIndex); 01571 nextLeftStartIndex = neckLeftIndex; 01572 nextRightStartIndex = neckRightIndex+1; 01573 } 01574 else 01575 { 01576 tempBotVertex = rightChain->getVertex(neckRightIndex); 01577 botLeftIndex = neckLeftIndex; 01578 botRightIndex = neckRightIndex-1; 01579 nextTopVertex = leftChain->getVertex(neckLeftIndex); 01580 nextLeftStartIndex = neckLeftIndex+1; 01581 nextRightStartIndex = neckRightIndex; 01582 } 01583 } 01584 01585 findUpCorners(topVertex, 01586 leftChain, 01587 leftStartIndex, botLeftIndex, 01588 rightChain, 01589 rightStartIndex, botRightIndex, 01590 leftGridChain->get_v_value(index1), 01591 leftGridChain->get_u_value(index1), 01592 rightGridChain->get_u_value(index1), 01593 up_leftCornerWhere, 01594 up_leftCornerIndex, 01595 up_rightCornerWhere, 01596 up_rightCornerIndex); 01597 01598 findDownCorners(tempBotVertex, 01599 leftChain, 01600 leftStartIndex, botLeftIndex, 01601 rightChain, 01602 rightStartIndex, botRightIndex, 01603 leftGridChain->get_v_value(index2), 01604 leftGridChain->get_u_value(index2), 01605 rightGridChain->get_u_value(index2), 01606 down_leftCornerWhere, 01607 down_leftCornerIndex, 01608 down_rightCornerWhere, 01609 down_rightCornerIndex); 01610 #ifdef MYDEBUG 01611 printf("find corners done, down_leftwhere=%i, down_righwhere=%i,\n",down_leftCornerWhere, down_rightCornerWhere ); 01612 printf("find corners done, up_leftwhere=%i, up_righwhere=%i,\n",up_leftCornerWhere, up_rightCornerWhere ); 01613 printf("find corners done, up_leftindex=%i, up_righindex=%i,\n",up_leftCornerIndex, up_rightCornerIndex ); 01614 printf("find corners done, down_leftindex=%i, down_righindex=%i,\n",down_leftCornerIndex, down_rightCornerIndex ); 01615 #endif 01616 01617 /* 01618 drawCorners(topVertex, 01619 tempBotVertex, 01620 leftChain, 01621 rightChain, 01622 leftGridChain, 01623 rightGridChain, 01624 index1, 01625 index2, 01626 up_leftCornerWhere, 01627 up_leftCornerIndex, 01628 up_rightCornerWhere, 01629 up_rightCornerIndex, 01630 down_leftCornerWhere, 01631 down_leftCornerIndex, 01632 down_rightCornerWhere, 01633 down_rightCornerIndex); 01634 */ 01635 01636 01637 sampleConnectedComp(topVertex, tempBotVertex, 01638 leftChain, 01639 leftStartIndex, botLeftIndex, 01640 rightChain, 01641 rightStartIndex, botRightIndex, 01642 leftGridChain, 01643 rightGridChain, 01644 index1, index2, 01645 up_leftCornerWhere, 01646 up_leftCornerIndex, 01647 up_rightCornerWhere, 01648 up_rightCornerIndex, 01649 down_leftCornerWhere, 01650 down_leftCornerIndex, 01651 down_rightCornerWhere, 01652 down_rightCornerIndex, 01653 pStream, 01654 rbArray 01655 ); 01656 01657 /*recursion*/ 01658 01659 sampleMonoPolyRec( 01660 nextTopVertex, 01661 botVertex, 01662 leftChain, 01663 nextLeftStartIndex, 01664 rightChain, 01665 nextRightStartIndex, 01666 leftGridChain, 01667 rightGridChain, 01668 index2+1, 01669 pStream, rbArray); 01670 01671 01672 } 01673 01674 } 01675 01676 void sampleLeftStrip(vertexArray* leftChain, 01677 Int topLeftIndex, 01678 Int botLeftIndex, 01679 gridBoundaryChain* leftGridChain, 01680 Int leftGridChainStartIndex, 01681 Int leftGridChainEndIndex, 01682 primStream* pStream 01683 ) 01684 { 01685 assert(leftChain->getVertex(topLeftIndex)[1] > leftGridChain->get_v_value(leftGridChainStartIndex)); 01686 assert(leftChain->getVertex(topLeftIndex+1)[1] <= leftGridChain->get_v_value(leftGridChainStartIndex)); 01687 assert(leftChain->getVertex(botLeftIndex)[1] <= leftGridChain->get_v_value(leftGridChainEndIndex)); 01688 assert(leftChain->getVertex(botLeftIndex-1)[1] > leftGridChain->get_v_value(leftGridChainEndIndex)); 01689 01690 /* 01691 *(1)find the last grid line which doesn'; pass below 01692 * this first edge, sample this region: one trim edge and 01693 * possily multiple grid lines. 01694 */ 01695 Real *upperVert, *lowerVert; /*the end points of the first trim edge*/ 01696 upperVert = leftChain->getVertex(topLeftIndex); 01697 lowerVert = leftChain->getVertex(topLeftIndex+1); 01698 01699 Int index = leftGridChainStartIndex; 01700 while(leftGridChain->get_v_value(index) >= lowerVert[1]){ 01701 index++; 01702 if(index > leftGridChainEndIndex) 01703 break; 01704 } 01705 index--; 01706 01707 sampleLeftSingleTrimEdgeRegion(upperVert, lowerVert, 01708 leftGridChain, 01709 leftGridChainStartIndex, 01710 index, 01711 pStream); 01712 sampleLeftStripRec(leftChain, topLeftIndex+1, botLeftIndex, 01713 leftGridChain, index, leftGridChainEndIndex, 01714 pStream); 01715 01716 } 01717 01718 void sampleLeftStripRec(vertexArray* leftChain, 01719 Int topLeftIndex, 01720 Int botLeftIndex, 01721 gridBoundaryChain* leftGridChain, 01722 Int leftGridChainStartIndex, 01723 Int leftGridChainEndIndex, 01724 primStream* pStream 01725 ) 01726 { 01727 /*now top left trim vertex is below the top grid line. 01728 */ 01729 /*stop condition: if topLeftIndex >= botLeftIndex, then stop. 01730 */ 01731 if(topLeftIndex >= botLeftIndex) 01732 return; 01733 01734 /*find the last trim vertex which is above the second top grid line: 01735 * index1. 01736 *and sampleLeftOneGridStep(leftchain, topLeftIndex, index1, leftGridChain, 01737 * leftGridChainStartIndex). 01738 * index1 could be equal to topLeftIndex. 01739 */ 01740 Real secondGridChainV = leftGridChain->get_v_value(leftGridChainStartIndex+1); 01741 assert(leftGridChainStartIndex < leftGridChainEndIndex); 01742 Int index1 = topLeftIndex; 01743 while(leftChain->getVertex(index1)[1] > secondGridChainV) 01744 index1++; 01745 index1--; 01746 01747 sampleLeftOneGridStep(leftChain, topLeftIndex, index1, leftGridChain, leftGridChainStartIndex, pStream); 01748 01749 01750 /* 01751 * Let the next trim vertex be nextTrimVertIndex (which should be 01752 * below the second grid line). 01753 * Find the last grid line index2 which is above nextTrimVert. 01754 * sampleLeftSingleTrimEdgeRegion(uppervert[2], lowervert[2], 01755 * leftGridChain, leftGridChainStartIndex+1, index2). 01756 */ 01757 Real *uppervert, *lowervert; 01758 uppervert = leftChain->getVertex(index1); 01759 lowervert = leftChain->getVertex(index1+1); 01760 Int index2 = leftGridChainStartIndex+1; 01761 01762 while(leftGridChain->get_v_value(index2) >= lowervert[1]) 01763 { 01764 index2++; 01765 if(index2 > leftGridChainEndIndex) 01766 break; 01767 } 01768 index2--; 01769 sampleLeftSingleTrimEdgeRegion(uppervert, lowervert, leftGridChain, leftGridChainStartIndex+1, index2, pStream); 01770 01771 /* sampleLeftStripRec(leftChain, 01772 nextTrimVertIndex, 01773 botLeftIndex, 01774 leftGridChain, 01775 index2, 01776 leftGridChainEndIndex 01777 ) 01778 * 01779 */ 01780 sampleLeftStripRec(leftChain, index1+1, botLeftIndex, leftGridChain, index2, leftGridChainEndIndex, pStream); 01781 01782 } 01783 01784 01785 /***************begin RecF***********************/ 01786 /* the gridlines from leftGridChainStartIndex to 01787 * leftGridChainEndIndex are assumed to form a 01788 * connected component. 01789 * the trim vertex of topLeftIndex is assumed to 01790 * be below the first gridline, and the tim vertex 01791 * of botLeftIndex is assumed to be above the last 01792 * grid line. 01793 * If botLeftIndex < topLeftIndex, then no connected componeent exists, and this funcion returns without 01794 * outputing any triangles. 01795 * Otherwise botLeftIndex >= topLeftIndex, there is at least one triangle to output. 01796 */ 01797 void sampleLeftStripRecF(vertexArray* leftChain, 01798 Int topLeftIndex, 01799 Int botLeftIndex, 01800 gridBoundaryChain* leftGridChain, 01801 Int leftGridChainStartIndex, 01802 Int leftGridChainEndIndex, 01803 primStream* pStream 01804 ) 01805 { 01806 /*now top left trim vertex is below the top grid line. 01807 */ 01808 /*stop condition: if topLeftIndex > botLeftIndex, then stop. 01809 */ 01810 if(topLeftIndex > botLeftIndex) 01811 return; 01812 01813 /*if there is only one grid Line, return.*/ 01814 01815 if(leftGridChainStartIndex>=leftGridChainEndIndex) 01816 return; 01817 01818 01819 assert(leftChain->getVertex(topLeftIndex)[1] <= leftGridChain->get_v_value(leftGridChainStartIndex) && 01820 leftChain->getVertex(botLeftIndex)[1] >= leftGridChain->get_v_value(leftGridChainEndIndex)); 01821 01822 /*firs find the first trim vertex which is below or equal to the second top grid line: 01823 * index1. 01824 */ 01825 Real secondGridChainV = leftGridChain->get_v_value(leftGridChainStartIndex+1); 01826 01827 01828 Int index1 = topLeftIndex; 01829 01830 while(leftChain->getVertex(index1)[1] > secondGridChainV){ 01831 index1++; 01832 if(index1>botLeftIndex) 01833 break; 01834 } 01835 01836 /*now leftChain->getVertex(index-1)[1] > secondGridChainV and 01837 * leftChain->getVertex(index)[1] <= secondGridChainV 01838 *If equality holds, then we should include the vertex index1, otherwise we include only index1-1, to 01839 *perform sampleOneGridStep. 01840 */ 01841 if(index1>botLeftIndex) 01842 index1--; 01843 else if(leftChain->getVertex(index1)[1] < secondGridChainV) 01844 index1--; 01845 01846 /*now we have leftChain->getVertex(index1)[1] >= secondGridChainV, and 01847 * leftChain->getVertex(index1+1)[1] <= secondGridChainV 01848 */ 01849 01850 01851 sampleLeftOneGridStep(leftChain, topLeftIndex, index1, leftGridChain, leftGridChainStartIndex, pStream); 01852 01853 01854 /*if leftChain->getVertex(index1)[1] == secondGridChainV, then we can recursively do the rest. 01855 */ 01856 if(leftChain->getVertex(index1)[1] == secondGridChainV) 01857 { 01858 01859 sampleLeftStripRecF(leftChain, index1, botLeftIndex,leftGridChain, leftGridChainStartIndex+1, leftGridChainEndIndex, pStream); 01860 } 01861 else if(index1 < botLeftIndex) 01862 { 01863 01864 /* Otherwise, we have leftChain->getVertex(index1)[1] > secondGridChainV, 01865 * let the next trim vertex be nextTrimVertIndex (which should be strictly 01866 * below the second grid line). 01867 * Find the last grid line index2 which is above nextTrimVert. 01868 * sampleLeftSingleTrimEdgeRegion(uppervert[2], lowervert[2], 01869 * leftGridChain, leftGridChainStartIndex+1, index2). 01870 */ 01871 Real *uppervert, *lowervert; 01872 uppervert = leftChain->getVertex(index1); 01873 lowervert = leftChain->getVertex(index1+1); //okay since index1<botLeftIndex 01874 Int index2 = leftGridChainStartIndex+1; 01875 01876 01877 while(leftGridChain->get_v_value(index2) >= lowervert[1]) 01878 { 01879 index2++; 01880 if(index2 > leftGridChainEndIndex) 01881 break; 01882 } 01883 index2--; 01884 01885 01886 sampleLeftSingleTrimEdgeRegion(uppervert, lowervert, leftGridChain, leftGridChainStartIndex+1, index2, pStream); 01887 01888 /*recursion*/ 01889 01890 sampleLeftStripRecF(leftChain, index1+1, botLeftIndex, leftGridChain, index2, leftGridChainEndIndex, pStream); 01891 } 01892 01893 } 01894 01895 /***************End RecF***********************/ 01896 01897 /*sample the left area in between one trim edge and multiple grid lines. 01898 * all the grid lines should be in between the two end poins of the 01899 *trim edge. 01900 */ 01901 void sampleLeftSingleTrimEdgeRegion(Real upperVert[2], Real lowerVert[2], 01902 gridBoundaryChain* gridChain, 01903 Int beginIndex, 01904 Int endIndex, 01905 primStream* pStream) 01906 { 01907 Int i,j,k; 01908 01909 vertexArray vArray(endIndex-beginIndex+1); 01910 vArray.appendVertex(gridChain->get_vertex(beginIndex)); 01911 01912 for(k=1, i=beginIndex+1; i<=endIndex; i++, k++) 01913 { 01914 vArray.appendVertex(gridChain->get_vertex(i)); 01915 01916 /*output the fan of the grid points of the (i)th and (i-1)th grid line. 01917 */ 01918 if(gridChain->getUlineIndex(i) < gridChain->getUlineIndex(i-1)) 01919 { 01920 pStream->begin(); 01921 pStream->insert(gridChain->get_vertex(i-1)); 01922 for(j=gridChain->getUlineIndex(i); j<= gridChain->getUlineIndex(i-1); j++) 01923 pStream->insert(gridChain->getGrid()->get_u_value(j), gridChain->get_v_value(i)); 01924 pStream->end(PRIMITIVE_STREAM_FAN); 01925 } 01926 else if(gridChain->getUlineIndex(i) > gridChain->getUlineIndex(i-1)) 01927 { 01928 pStream->begin(); 01929 pStream->insert(gridChain->get_vertex(i)); 01930 for(j=gridChain->getUlineIndex(i); j>= gridChain->getUlineIndex(i-1); j--) 01931 pStream->insert(gridChain->getGrid()->get_u_value(j), gridChain->get_v_value(i-1)); 01932 pStream->end(PRIMITIVE_STREAM_FAN); 01933 } 01934 /*otherwisem, the two are equal, so there is no fan to outout*/ 01935 } 01936 01937 monoTriangulation2(upperVert, lowerVert, &vArray, 0, endIndex-beginIndex, 01938 0, /*decreasing chain*/ 01939 pStream); 01940 } 01941 01942 /*return i, such that from begin to i-1 the chain is strictly u-monotone. 01943 */ 01944 Int findIncreaseChainFromBegin(vertexArray* chain, Int begin ,Int end) 01945 { 01946 Int i=begin; 01947 Real prevU = chain->getVertex(i)[0]; 01948 Real thisU; 01949 for(i=begin+1; i<=end; i++){ 01950 thisU = chain->getVertex(i)[0]; 01951 01952 if(prevU < thisU){ 01953 prevU = thisU; 01954 } 01955 else 01956 break; 01957 } 01958 return i; 01959 } 01960 01961 /*check whether there is a vertex whose v value is strictly 01962 *inbetween vup vbelow 01963 *if no middle exists return -1, else return the idnex. 01964 */ 01965 Int checkMiddle(vertexArray* chain, Int begin, Int end, 01966 Real vup, Real vbelow) 01967 { 01968 Int i; 01969 for(i=begin; i<=end; i++) 01970 { 01971 if(chain->getVertex(i)[1] < vup && chain->getVertex(i)[1]>vbelow) 01972 return i; 01973 } 01974 return -1; 01975 } 01976 01977 /*the degenerat case of sampleLeftOneGridStep*/ 01978 void sampleLeftOneGridStepNoMiddle(vertexArray* leftChain, 01979 Int beginLeftIndex, 01980 Int endLeftIndex, 01981 gridBoundaryChain* leftGridChain, 01982 Int leftGridChainStartIndex, 01983 primStream* pStream) 01984 { 01985 /*since there is no middle, there is at most one point which is on the 01986 *second grid line, there could be multiple points on the first (top) 01987 *grid line. 01988 */ 01989 01990 leftGridChain->leftEndFan(leftGridChainStartIndex+1, pStream); 01991 01992 monoTriangulation2(leftGridChain->get_vertex(leftGridChainStartIndex), 01993 leftGridChain->get_vertex(leftGridChainStartIndex+1), 01994 leftChain, 01995 beginLeftIndex, 01996 endLeftIndex, 01997 1, //is increase chain. 01998 pStream); 01999 } 02000 02001 02002 02003 /*sampling the left area in between two grid lines. 02004 */ 02005 void sampleLeftOneGridStep(vertexArray* leftChain, 02006 Int beginLeftIndex, 02007 Int endLeftIndex, 02008 gridBoundaryChain* leftGridChain, 02009 Int leftGridChainStartIndex, 02010 primStream* pStream 02011 ) 02012 { 02013 if(checkMiddle(leftChain, beginLeftIndex, endLeftIndex, 02014 leftGridChain->get_v_value(leftGridChainStartIndex), 02015 leftGridChain->get_v_value(leftGridChainStartIndex+1))<0) 02016 02017 { 02018 02019 sampleLeftOneGridStepNoMiddle(leftChain, beginLeftIndex, endLeftIndex, leftGridChain, leftGridChainStartIndex, pStream); 02020 return; 02021 } 02022 02023 //copy into a polygon 02024 { 02025 directedLine* poly = NULL; 02026 sampledLine* sline; 02027 directedLine* dline; 02028 gridWrap* grid = leftGridChain->getGrid(); 02029 Real vert1[2]; 02030 Real vert2[2]; 02031 Int i; 02032 02033 Int innerInd = leftGridChain->getInnerIndex(leftGridChainStartIndex+1); 02034 Int upperInd = leftGridChain->getUlineIndex(leftGridChainStartIndex); 02035 Int lowerInd = leftGridChain->getUlineIndex(leftGridChainStartIndex+1); 02036 Real upperV = leftGridChain->get_v_value(leftGridChainStartIndex); 02037 Real lowerV = leftGridChain->get_v_value(leftGridChainStartIndex+1); 02038 02039 //the upper gridline 02040 vert1[1] = vert2[1] = upperV; 02041 for(i=innerInd; i>upperInd; i--) 02042 { 02043 vert1[0]=grid->get_u_value(i); 02044 vert2[0]=grid->get_u_value(i-1); 02045 sline = new sampledLine(vert1, vert2); 02046 dline = new directedLine(INCREASING, sline); 02047 if(poly == NULL) 02048 poly = dline; 02049 else 02050 poly->insert(dline); 02051 } 02052 02053 //the edge connecting upper grid with left chain 02054 vert1[0] = grid->get_u_value(upperInd); 02055 vert1[1] = upperV; 02056 sline = new sampledLine(vert1, leftChain->getVertex(beginLeftIndex)); 02057 dline = new directedLine(INCREASING, sline); 02058 if(poly == NULL) 02059 poly = dline; 02060 else 02061 poly->insert(dline); 02062 02063 //the left chain 02064 for(i=beginLeftIndex; i<endLeftIndex; i++) 02065 { 02066 sline = new sampledLine(leftChain->getVertex(i), leftChain->getVertex(i+1)); 02067 dline = new directedLine(INCREASING, sline); 02068 poly->insert(dline); 02069 } 02070 02071 //the edge connecting left chain with lower gridline 02072 vert2[0] = grid->get_u_value(lowerInd); 02073 vert2[1] = lowerV; 02074 sline = new sampledLine(leftChain->getVertex(endLeftIndex), vert2); 02075 dline = new directedLine(INCREASING, sline); 02076 poly->insert(dline); 02077 02078 //the lower grid line 02079 vert1[1] = vert2[1] = lowerV; 02080 for(i=lowerInd; i<innerInd; i++) 02081 { 02082 vert1[0] = grid->get_u_value(i); 02083 vert2[0] = grid->get_u_value(i+1); 02084 sline = new sampledLine(vert1, vert2); 02085 dline = new directedLine(INCREASING, sline); 02086 poly->insert(dline); 02087 } 02088 02089 //the vertical grid line segement 02090 vert1[0]=vert2[0] = grid->get_u_value(innerInd); 02091 vert2[1]=upperV; 02092 vert1[1]=lowerV; 02093 sline=new sampledLine(vert1, vert2); 02094 dline=new directedLine(INCREASING, sline); 02095 poly->insert(dline); 02096 monoTriangulationOpt(poly, pStream); 02097 //cleanup 02098 poly->deleteSinglePolygonWithSline(); 02099 return; 02100 } 02101 02102 02103 02104 02105 02106 Int i; 02107 if(1/*leftGridChain->getUlineIndex(leftGridChainStartIndex) >= 02108 leftGridChain->getUlineIndex(leftGridChainStartIndex+1)*/ 02109 ) /*the second grid line is beyond the first one to the left*/ 02110 { 02111 /*find the maximal U-monotone chain 02112 * of endLeftIndex, endLeftIndex-1, ..., 02113 */ 02114 i=endLeftIndex; 02115 Real prevU = leftChain->getVertex(i)[0]; 02116 for(i=endLeftIndex-1; i>=beginLeftIndex; i--){ 02117 Real thisU = leftChain->getVertex(i)[0]; 02118 if( prevU < thisU){ 02119 prevU = thisU; 02120 } 02121 else 02122 break; 02123 } 02124 /*from endLeftIndex to i+1 is strictly U- monotone */ 02125 /*if i+1==endLeftIndex and the vertex and leftchain is on the second gridline, then 02126 *we should use 2 vertices on the leftchain. If we only use one (endLeftIndex), then we 02127 *we would output degenerate triangles 02128 */ 02129 if(i+1 == endLeftIndex && leftChain->getVertex(endLeftIndex)[1] == leftGridChain->get_v_value(1+leftGridChainStartIndex)) 02130 i--; 02131 02132 Int j = beginLeftIndex/*endLeftIndex*/+1; 02133 02134 02135 if(leftGridChain->getInnerIndex(leftGridChainStartIndex+1) > leftGridChain->getUlineIndex(leftGridChainStartIndex)) 02136 { 02137 j = findIncreaseChainFromBegin(leftChain, beginLeftIndex, i+1/*endLeftIndex*/); 02138 02139 Int temp = beginLeftIndex; 02140 /*now from begin to j-1 is strictly u-monotone*/ 02141 /*if j-1 is on the first grid line, then we want to skip to the vertex which is strictly 02142 *below the grid line. This vertexmust exist since there is a 'corner turn' inbetween the two grid lines 02143 */ 02144 if(j-1 == beginLeftIndex) 02145 { 02146 while(leftChain->getVertex(j-1)[1] == leftGridChain->get_v_value(leftGridChainStartIndex)) 02147 j++; 02148 02149 Real vert[2]; 02150 vert[0] = leftGridChain->get_u_value(leftGridChainStartIndex); 02151 vert[1] = leftGridChain->get_v_value(leftGridChainStartIndex); 02152 02153 monoTriangulation2( 02154 vert/*leftChain->getVertex(beginLeftIndex)*/, 02155 leftChain->getVertex(j-1), 02156 leftChain, 02157 beginLeftIndex, 02158 j-2, 02159 1, 02160 pStream //increase chain 02161 ); 02162 02163 temp = j-1; 02164 } 02165 02166 stripOfFanLeft(leftChain, j-1, temp/*beginLeftIndex*/, leftGridChain->getGrid(), 02167 leftGridChain->getVlineIndex(leftGridChainStartIndex), 02168 leftGridChain->getUlineIndex(leftGridChainStartIndex), 02169 leftGridChain->getInnerIndex(leftGridChainStartIndex+1), 02170 pStream, 02171 1 /*the grid line is above the trim line*/ 02172 ); 02173 } 02174 02175 stripOfFanLeft(leftChain, endLeftIndex, i+1, leftGridChain->getGrid(), 02176 leftGridChain->getVlineIndex(leftGridChainStartIndex+1), 02177 leftGridChain->getUlineIndex(leftGridChainStartIndex+1), 02178 leftGridChain->getInnerIndex(leftGridChainStartIndex+1), 02179 pStream, 02180 0 /*the grid line is below the trim lines*/ 02181 ); 02182 02183 /*monotone triangulate the remaining left chain togther with the 02184 *two vertices on the two grid v-lines. 02185 */ 02186 Real vert[2][2]; 02187 vert[0][0]=vert[1][0] = leftGridChain->getInner_u_value(leftGridChainStartIndex+1); 02188 vert[0][1] = leftGridChain->get_v_value(leftGridChainStartIndex); 02189 vert[1][1] = leftGridChain->get_v_value(leftGridChainStartIndex+1); 02190 02191 // vertexArray right(vert, 2); 02192 02193 monoTriangulation2( 02194 &vert[0][0], /*top vertex */ 02195 &vert[1][0], /*bottom vertex*/ 02196 leftChain, 02197 /*beginLeftIndex*/j-1, 02198 i+1, 02199 1, /*an increasing chain*/ 02200 pStream); 02201 } 02202 else /*the second one is shorter than the first one to the left*/ 02203 { 02204 /*find the maximal U-monotone chain of beginLeftIndex, beginLeftIndex+1,..., 02205 */ 02206 i=beginLeftIndex; 02207 Real prevU = leftChain->getVertex(i)[0]; 02208 for(i=beginLeftIndex+1; i<=endLeftIndex; i++){ 02209 Real thisU = leftChain->getVertex(i)[0]; 02210 02211 if(prevU < thisU){ 02212 prevU = thisU; 02213 } 02214 else 02215 break; 02216 } 02217 /*from beginLeftIndex to i-1 is strictly U-monotone*/ 02218 02219 02220 stripOfFanLeft(leftChain, i-1, beginLeftIndex, leftGridChain->getGrid(), 02221 leftGridChain->getVlineIndex(leftGridChainStartIndex), 02222 leftGridChain->getUlineIndex(leftGridChainStartIndex), 02223 leftGridChain->getUlineIndex(leftGridChainStartIndex+1), 02224 pStream, 02225 1 /*the grid line is above the trim lines*/ 02226 ); 02227 /*monotone triangulate the remaining left chain together with the 02228 *two vertices on the two grid v-lines. 02229 */ 02230 Real vert[2][2]; 02231 vert[0][0]=vert[1][0] = leftGridChain->get_u_value(leftGridChainStartIndex+1); 02232 vert[0][1] = leftGridChain->get_v_value(leftGridChainStartIndex); 02233 vert[1][1] = leftGridChain->get_v_value(leftGridChainStartIndex+1); 02234 02235 vertexArray right(vert, 2); 02236 02237 monoTriangulation2( 02238 &vert[0][0], //top vertex 02239 &vert[1][0], //bottom vertex 02240 leftChain, 02241 i-1, 02242 endLeftIndex, 02243 1, /*an increase chain*/ 02244 pStream); 02245 02246 } 02247 } 02248 02249 /*n_upper>=1 02250 *n_lower>=1 02251 */ 02252 void triangulateXYMono(Int n_upper, Real upperVerts[][2], 02253 Int n_lower, Real lowerVerts[][2], 02254 primStream* pStream) 02255 { 02256 Int i,j,k,l; 02257 Real* leftMostV; 02258 02259 assert(n_upper>=1 && n_lower>=1); 02260 if(upperVerts[0][0] <= lowerVerts[0][0]) 02261 { 02262 i=1; 02263 j=0; 02264 leftMostV = upperVerts[0]; 02265 } 02266 else 02267 { 02268 i=0; 02269 j=1; 02270 leftMostV = lowerVerts[0]; 02271 } 02272 02273 while(1) 02274 { 02275 if(i >= n_upper) /*case1: no more in upper*/ 02276 { 02277 02278 if(j<n_lower-1) /*at least two vertices in lower*/ 02279 { 02280 pStream->begin(); 02281 pStream->insert(leftMostV); 02282 while(j<n_lower){ 02283 pStream->insert(lowerVerts[j]); 02284 j++; 02285 } 02286 pStream->end(PRIMITIVE_STREAM_FAN); 02287 } 02288 02289 break; 02290 } 02291 else if(j>= n_lower) /*case2: no more in lower*/ 02292 { 02293 02294 if(i<n_upper-1) /*at least two vertices in upper*/ 02295 { 02296 pStream->begin(); 02297 pStream->insert(leftMostV); 02298 02299 for(k=n_upper-1; k>=i; k--) 02300 pStream->insert(upperVerts[k]); 02301 02302 pStream->end(PRIMITIVE_STREAM_FAN); 02303 } 02304 02305 break; 02306 } 02307 else /* case3: neither is empty, plus the leftMostV, there is at least one triangle to output*/ 02308 { 02309 02310 if(upperVerts[i][0] <= lowerVerts[j][0]) 02311 { 02312 pStream->begin(); 02313 pStream->insert(lowerVerts[j]); /*the origin of this fan*/ 02314 02315 /*find the last k>=i such that 02316 *upperverts[k][0] <= lowerverts[j][0] 02317 */ 02318 k=i; 02319 while(k<n_upper) 02320 { 02321 if(upperVerts[k][0] > lowerVerts[j][0]) 02322 break; 02323 k++; 02324 } 02325 k--; 02326 for(l=k; l>=i; l--)/*the reverse is for two-face lighting*/ 02327 { 02328 pStream->insert(upperVerts[l]); 02329 } 02330 pStream->insert(leftMostV); 02331 02332 pStream->end(PRIMITIVE_STREAM_FAN); 02333 //update i for next loop 02334 i = k+1; 02335 leftMostV = upperVerts[k]; 02336 02337 } 02338 else /*upperVerts[i][0] > lowerVerts[j][0]*/ 02339 { 02340 pStream->begin(); 02341 pStream->insert(upperVerts[i]);/*the origion of this fan*/ 02342 pStream->insert(leftMostV); 02343 /*find the last k>=j such that 02344 *lowerverts[k][0] < upperverts[i][0]*/ 02345 k=j; 02346 while(k< n_lower) 02347 { 02348 if(lowerVerts[k][0] >= upperVerts[i][0]) 02349 break; 02350 pStream->insert(lowerVerts[k]); 02351 k++; 02352 } 02353 pStream->end(PRIMITIVE_STREAM_FAN); 02354 j=k; 02355 leftMostV = lowerVerts[j-1]; 02356 } 02357 } 02358 } 02359 } 02360 02361 02362 void stripOfFanLeft(vertexArray* leftChain, 02363 Int largeIndex, 02364 Int smallIndex, 02365 gridWrap* grid, 02366 Int vlineIndex, 02367 Int ulineSmallIndex, 02368 Int ulineLargeIndex, 02369 primStream* pStream, 02370 Int gridLineUp /*1 if the grid line is above the trim lines*/ 02371 ) 02372 { 02373 assert(largeIndex >= smallIndex); 02374 02375 Real grid_v_value; 02376 grid_v_value = grid->get_v_value(vlineIndex); 02377 02378 Real2* trimVerts=(Real2*) malloc(sizeof(Real2)* (largeIndex-smallIndex+1)); 02379 assert(trimVerts); 02380 02381 02382 Real2* gridVerts=(Real2*) malloc(sizeof(Real2)* (ulineLargeIndex-ulineSmallIndex+1)); 02383 assert(gridVerts); 02384 02385 Int k,i; 02386 if(gridLineUp) /*trim line is below grid line, so trim vertices are going right when index increases*/ 02387 for(k=0, i=smallIndex; i<=largeIndex; i++, k++) 02388 { 02389 trimVerts[k][0] = leftChain->getVertex(i)[0]; 02390 trimVerts[k][1] = leftChain->getVertex(i)[1]; 02391 } 02392 else 02393 for(k=0, i=largeIndex; i>=smallIndex; i--, k++) 02394 { 02395 trimVerts[k][0] = leftChain->getVertex(i)[0]; 02396 trimVerts[k][1] = leftChain->getVertex(i)[1]; 02397 } 02398 02399 for(k=0, i=ulineSmallIndex; i<= ulineLargeIndex; i++, k++) 02400 { 02401 gridVerts[k][0] = grid->get_u_value(i); 02402 gridVerts[k][1] = grid_v_value; 02403 } 02404 02405 if(gridLineUp) 02406 triangulateXYMono( 02407 ulineLargeIndex-ulineSmallIndex+1, gridVerts, 02408 largeIndex-smallIndex+1, trimVerts, 02409 pStream); 02410 else 02411 triangulateXYMono(largeIndex-smallIndex+1, trimVerts, 02412 ulineLargeIndex-ulineSmallIndex+1, gridVerts, 02413 pStream); 02414 free(trimVerts); 02415 free(gridVerts); 02416 } 02417 02418 02419 02420 02421 Generated on Sat May 26 2012 04:22:20 for ReactOS by
1.7.6.1
|