monoPolyPart.cc revision f220fa62
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 *monoPolyPart.C 37 * 38 *To partition a v-monotone polygon into some uv-monotone polygons. 39 *The algorithm is different from the general monotone partition algorithm. 40 *while the general monotone partition algorithm works for this special case, 41 *but it is more expensive (O(nlogn)). The algorithm implemented here takes 42 *advantage of the fact that the input is a v-monotone polygon and it is 43 *conceptually simpler and computationally cheaper (a linear time algorithm). 44 *The algorithm is described in Zicheng Liu's paper 45 * "Quality-Oriented Linear Time Tessellation". 46 */ 47 48#include <stdlib.h> 49#include <stdio.h> 50#include "directedLine.h" 51#include "monoPolyPart.h" 52 53/*a vertex is u_maximal if both of its two neightbors are to the left of this 54 *vertex 55 */ 56static Int is_u_maximal(directedLine* v) 57{ 58 if (compV2InX(v->getPrev()->head(), v->head()) == -1 && 59 compV2InX(v->getNext()->head(), v->head()) == -1) 60 return 1; 61 else 62 return 0; 63} 64 65/*a vertex is u_minimal if both of its two neightbors are to the right of this 66 *vertex 67 */ 68static Int is_u_minimal(directedLine* v) 69{ 70 if (compV2InX(v->getPrev()->head(), v->head()) == 1 && 71 compV2InX(v->getNext()->head(), v->head()) == 1) 72 return 1; 73 else 74 return 0; 75} 76 77/*poly: a v-monotone polygon 78 *return: a linked list of uv-monotone polygons. 79 */ 80directedLine* monoPolyPart(directedLine* polygon) 81{ 82 //handle special cases: 83 if(polygon == NULL) 84 return NULL; 85 if(polygon->getPrev() == polygon) 86 return polygon; 87 if(polygon->getPrev() == polygon->getNext()) 88 return polygon; 89 if(polygon->getPrev()->getPrev() == polygon->getNext()) 90 return polygon; 91 92 //find the top and bottom vertexes 93 directedLine *tempV, *topV, *botV; 94 topV = botV = polygon; 95 for(tempV = polygon->getNext(); tempV != polygon; tempV = tempV->getNext()) 96 { 97 if(compV2InY(topV->head(), tempV->head())<0) { 98 topV = tempV; 99 } 100 if(compV2InY(botV->head(), tempV->head())>0) { 101 botV = tempV; 102 } 103 } 104 105 //initilization 106 directedLine *A, *B, *C, *D, *G, *H; 107 //find A:the first u_maximal vertex on the left chain 108 //and C: the left most vertex between top and A 109 A = NULL; 110 C = topV; 111 for(tempV=topV->getNext(); tempV != botV; tempV = tempV->getNext()) 112 { 113 if(tempV->head()[0] < C->head()[0]) 114 C = tempV; 115 116 if(is_u_maximal(tempV)) 117 { 118 A = tempV; 119 break; 120 } 121 } 122 if(A == NULL) 123 { 124 A = botV; 125 if(A->head()[0] < C->head()[0]) 126 C = A; 127 } 128 129 //find B: the first u_minimal vertex on the right chain 130 //and D: the right most vertex between top and B 131 B = NULL; 132 D = topV; 133 for(tempV=topV->getPrev(); tempV != botV; tempV = tempV->getPrev()) 134 { 135 if(tempV->head()[0] > D->head()[0]) 136 D = tempV; 137 if(is_u_minimal(tempV)) 138 { 139 B = tempV; 140 break; 141 } 142 } 143 if(B == NULL) 144 { 145 B = botV; 146 if(B->head()[0] > D->head()[0]) 147 D = B; 148 } 149 150 //error checking XXX 151 if(C->head()[0] >= D->head()[0]) 152 return polygon; 153 154 //find G on the left chain that is right above B 155 for(tempV=topV; compV2InY(tempV->head(), B->head()) == 1; tempV=tempV->getNext()); 156 G = tempV->getPrev(); 157 //find H on the right chain that is right above A 158 for(tempV=topV; compV2InY(tempV->head(), A->head()) == 1; tempV = tempV->getPrev()); 159 H = tempV->getNext(); 160 161 //Main Loop 162 directedLine* ret = NULL; 163 directedLine* currentPolygon = polygon; 164 while(1) 165 { 166 //if both B and D are equal to botV, then this polygon is already 167 //u-monotone 168 if(A == botV && B == botV) 169 { 170 ret = currentPolygon->insertPolygon(ret); 171 return ret; 172 } 173 else //not u-monotone 174 { 175 directedLine *ret_p1, *ret_p2; 176 if(compV2InY(A->head(),B->head()) == 1) //A is above B 177 { 178 directedLine* E = NULL; 179 for(tempV = C; tempV != D; tempV = tempV->getPrev()) 180 { 181 if(tempV->head()[0] >= A->head()[0]) 182 { 183 E = tempV; 184 break; 185 } 186 } 187 188 if(E == NULL) 189 E = D; 190 if(E->head()[0]> H->head()[0]) 191 E = H; 192 //connect AE and output polygon ECA 193 polygon->connectDiagonal_2slines(A, E, 194 &ret_p1, 195 &ret_p2, 196 NULL); 197 ret = ret_p2->insertPolygon(ret); 198 currentPolygon = ret_p1; 199 200 if(E == D) 201 D = ret_p1; 202 if(E == H) 203 H = ret_p1; 204 if(G->head()[1] >= A->head()[1]) 205 G = A; 206 //update A to be the next u-maxiaml vertex on left chain 207 //and C the leftmost vertex between the old A and the new A 208 C = A; 209 for(tempV = A->getNext(); tempV != botV; tempV = tempV->getNext()) 210 { 211 212 if(tempV->head()[0] < C->head()[0]) 213 C = tempV; 214 if(is_u_maximal(tempV)) 215 { 216 A = tempV; 217 break; 218 } 219 } 220 221 if(tempV == botV) 222 { 223 A = botV; 224 if(botV->head()[0] < C->head()[0]) 225 C = botV; 226 } 227 //update H 228 229 if(A == botV) 230 H = botV; 231 else 232 { 233 for(tempV = H; compV2InY(tempV->head(), A->head()) == 1; tempV = tempV->getPrev()); 234 H = tempV->getNext(); 235 } 236 237 } 238 else //A is below B 239 { 240 241 directedLine* F = NULL; 242 for(tempV = D; tempV != C; tempV = tempV->getNext()) 243 { 244 if(tempV->head()[0] <= B->head()[0]) 245 { 246 F = tempV; 247 break; 248 } 249 } 250 if(F == NULL) 251 F = C; 252 if(F->head()[0] < G->head()[0]) 253 F = G; 254 255 //connect FB 256 polygon->connectDiagonal_2slines(F, B, 257 &ret_p1, 258 &ret_p2, 259 NULL); 260 ret = ret_p2->insertPolygon(ret); 261 currentPolygon = ret_p1; 262 B = ret_p1; 263 if(H ->head()[1] >= B->head()[1]) 264 H = ret_p1; 265 266 //update B to be the next u-minimal vertex on right chain 267 //and D the rightmost vertex between the old B and the new B 268 D = B; 269 for(tempV = B->getPrev(); tempV != botV; tempV = tempV->getPrev()) 270 { 271 if(tempV->head()[0] > D->head()[0]) 272 D = tempV; 273 if(is_u_minimal(tempV)) 274 { 275 B = tempV; 276 break; 277 } 278 } 279 if(tempV == botV) 280 { 281 B = botV; 282 if(botV->head()[0] > D->head()[0]) 283 D = botV; 284 } 285 //update G 286 if(B == botV) 287 G = botV; 288 else 289 { 290 for(tempV = G; compV2InY(tempV->head(), B->head()) == 1; tempV = tempV->getNext()); 291 G = tempV->getPrev(); 292 } 293 } //end of A is below B 294 } //end not u-monotone 295 } //end of main loop 296} 297 298 299 300