|
ocssw
1.0
|
00001 /*********************************************************** 00002 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts, 00003 and the Massachusetts Institute of Technology, Cambridge, Massachusetts. 00004 00005 All Rights Reserved 00006 00007 Permission to use, copy, modify, and distribute this software and its 00008 documentation for any purpose and without fee is hereby granted, 00009 provided that the above copyright notice appear in all copies and that 00010 both that copyright notice and this permission notice appear in 00011 supporting documentation, and that the names of Digital or MIT not be 00012 used in advertising or publicity pertaining to distribution of the 00013 software without specific, written prior permission. 00014 00015 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 00016 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 00017 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 00018 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 00019 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 00020 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 00021 SOFTWARE. 00022 00023 ******************************************************************/ 00024 /* $XConsortium: mipolyutil.c,v 1.14 89/03/22 10:50:55 rws Exp $ */ 00025 #include <stdlib.h> 00026 #include "miscstruct.h" 00027 #include "gc.h" 00028 #include "miscanfill.h" 00029 #include "mipoly.h" 00030 00031 extern void miFreeStorage(); 00032 00033 #define MAXINT 0x7fffffff 00034 #define MININT -MAXINT 00035 00036 /* 00037 * fillUtils.c 00038 * 00039 * Written by Brian Kelleher; Oct. 1985 00040 * 00041 * This module contains all of the utility functions 00042 * needed to scan convert a polygon. 00043 * 00044 */ 00045 00046 /* 00047 * InsertEdgeInET 00048 * 00049 * Insert the given edge into the edge table. 00050 * First we must find the correct bucket in the 00051 * Edge table, then find the right slot in the 00052 * bucket. Finally, we can insert it. 00053 * 00054 */ 00055 Bool 00056 miInsertEdgeInET(ET, ETE, scanline, SLLBlock, iSLLBlock) 00057 EdgeTable *ET; 00058 EdgeTableEntry *ETE; 00059 int scanline; 00060 ScanLineListBlock **SLLBlock; 00061 int *iSLLBlock; 00062 { 00063 register EdgeTableEntry *start, *prev; 00064 register ScanLineList *pSLL, *pPrevSLL; 00065 ScanLineListBlock *tmpSLLBlock; 00066 00067 /* 00068 * find the right bucket to put the edge into 00069 */ 00070 pPrevSLL = &ET->scanlines; 00071 pSLL = pPrevSLL->next; 00072 while (pSLL && (pSLL->scanline < scanline)) 00073 { 00074 pPrevSLL = pSLL; 00075 pSLL = pSLL->next; 00076 } 00077 00078 /* 00079 * reassign pSLL (pointer to ScanLineList) if necessary 00080 */ 00081 if ((!pSLL) || (pSLL->scanline > scanline)) 00082 { 00083 if (*iSLLBlock > SLLSPERBLOCK-1) 00084 { 00085 tmpSLLBlock = 00086 (ScanLineListBlock *)malloc(sizeof(ScanLineListBlock)); 00087 if (!tmpSLLBlock) 00088 return FALSE; 00089 (*SLLBlock)->next = tmpSLLBlock; 00090 tmpSLLBlock->next = (ScanLineListBlock *)NULL; 00091 *SLLBlock = tmpSLLBlock; 00092 *iSLLBlock = 0; 00093 } 00094 pSLL = &((*SLLBlock)->SLLs[(*iSLLBlock)++]); 00095 00096 pSLL->next = pPrevSLL->next; 00097 pSLL->edgelist = (EdgeTableEntry *)NULL; 00098 pPrevSLL->next = pSLL; 00099 } 00100 pSLL->scanline = scanline; 00101 00102 /* 00103 * now insert the edge in the right bucket 00104 */ 00105 prev = (EdgeTableEntry *)NULL; 00106 start = pSLL->edgelist; 00107 while (start && (start->bres.minor < ETE->bres.minor)) 00108 { 00109 prev = start; 00110 start = start->next; 00111 } 00112 ETE->next = start; 00113 00114 if (prev) 00115 prev->next = ETE; 00116 else 00117 pSLL->edgelist = ETE; 00118 return TRUE; 00119 } 00120 00121 /* 00122 * CreateEdgeTable 00123 * 00124 * This routine creates the edge table for 00125 * scan converting polygons. 00126 * The Edge Table (ET) looks like: 00127 * 00128 * EdgeTable 00129 * -------- 00130 * | ymax | ScanLineLists 00131 * |scanline|-->------------>-------------->... 00132 * -------- |scanline| |scanline| 00133 * |edgelist| |edgelist| 00134 * --------- --------- 00135 * | | 00136 * | | 00137 * V V 00138 * list of ETEs list of ETEs 00139 * 00140 * where ETE is an EdgeTableEntry data structure, 00141 * and there is one ScanLineList per scanline at 00142 * which an edge is initially entered. 00143 * 00144 */ 00145 00146 Bool 00147 miCreateETandAET(count, pts, ET, AET, pETEs, pSLLBlock) 00148 register int count; 00149 register DDXPointPtr pts; 00150 EdgeTable *ET; 00151 EdgeTableEntry *AET; 00152 register EdgeTableEntry *pETEs; 00153 ScanLineListBlock *pSLLBlock; 00154 { 00155 register DDXPointPtr top, bottom; 00156 register DDXPointPtr PrevPt, CurrPt; 00157 int iSLLBlock = 0; 00158 00159 int dy; 00160 00161 if (count < 2) return TRUE; 00162 00163 /* 00164 * initialize the Active Edge Table 00165 */ 00166 AET->next = (EdgeTableEntry *)NULL; 00167 AET->back = (EdgeTableEntry *)NULL; 00168 AET->nextWETE = (EdgeTableEntry *)NULL; 00169 AET->bres.minor = MININT; 00170 00171 /* 00172 * initialize the Edge Table. 00173 */ 00174 ET->scanlines.next = (ScanLineList *)NULL; 00175 ET->ymax = MININT; 00176 ET->ymin = MAXINT; 00177 pSLLBlock->next = (ScanLineListBlock *)NULL; 00178 00179 PrevPt = &pts[count-1]; 00180 00181 /* 00182 * for each vertex in the array of points. 00183 * In this loop we are dealing with two vertices at 00184 * a time -- these make up one edge of the polygon. 00185 */ 00186 while (count--) 00187 { 00188 CurrPt = pts++; 00189 00190 /* 00191 * find out which point is above and which is below. 00192 */ 00193 if (PrevPt->y > CurrPt->y) 00194 { 00195 bottom = PrevPt, top = CurrPt; 00196 pETEs->ClockWise = 0; 00197 } 00198 else 00199 { 00200 bottom = CurrPt, top = PrevPt; 00201 pETEs->ClockWise = 1; 00202 } 00203 00204 /* 00205 * don't add horizontal edges to the Edge table. 00206 */ 00207 if (bottom->y != top->y) 00208 { 00209 pETEs->ymax = bottom->y-1; /* -1 so we don't get last scanline */ 00210 00211 /* 00212 * initialize integer edge algorithm 00213 */ 00214 dy = bottom->y - top->y; 00215 BRESINITPGONSTRUCT(dy, top->x, bottom->x, pETEs->bres); 00216 00217 if (!miInsertEdgeInET(ET, pETEs, top->y, &pSLLBlock, &iSLLBlock)) 00218 { 00219 miFreeStorage(pSLLBlock->next); 00220 return FALSE; 00221 } 00222 00223 ET->ymax = max(ET->ymax, PrevPt->y); 00224 ET->ymin = min(ET->ymin, PrevPt->y); 00225 pETEs++; 00226 } 00227 00228 PrevPt = CurrPt; 00229 } 00230 return TRUE; 00231 } 00232 00233 /* 00234 * loadAET 00235 * 00236 * This routine moves EdgeTableEntries from the 00237 * EdgeTable into the Active Edge Table, 00238 * leaving them sorted by smaller x coordinate. 00239 * 00240 */ 00241 00242 void 00243 miloadAET(AET, ETEs) 00244 register EdgeTableEntry *AET, *ETEs; 00245 { 00246 register EdgeTableEntry *pPrevAET; 00247 register EdgeTableEntry *tmp; 00248 00249 pPrevAET = AET; 00250 AET = AET->next; 00251 while (ETEs) 00252 { 00253 while (AET && (AET->bres.minor < ETEs->bres.minor)) 00254 { 00255 pPrevAET = AET; 00256 AET = AET->next; 00257 } 00258 tmp = ETEs->next; 00259 ETEs->next = AET; 00260 if (AET) 00261 AET->back = ETEs; 00262 ETEs->back = pPrevAET; 00263 pPrevAET->next = ETEs; 00264 pPrevAET = ETEs; 00265 00266 ETEs = tmp; 00267 } 00268 } 00269 00270 /* 00271 * computeWAET 00272 * 00273 * This routine links the AET by the 00274 * nextWETE (winding EdgeTableEntry) link for 00275 * use by the winding number rule. The final 00276 * Active Edge Table (AET) might look something 00277 * like: 00278 * 00279 * AET 00280 * ---------- --------- --------- 00281 * |ymax | |ymax | |ymax | 00282 * | ... | |... | |... | 00283 * |next |->|next |->|next |->... 00284 * |nextWETE| |nextWETE| |nextWETE| 00285 * --------- --------- ^-------- 00286 * | | | 00287 * V-------------------> V---> ... 00288 * 00289 */ 00290 void 00291 micomputeWAET(AET) 00292 register EdgeTableEntry *AET; 00293 { 00294 register EdgeTableEntry *pWETE; 00295 register int inside = 1; 00296 register int isInside = 0; 00297 00298 AET->nextWETE = (EdgeTableEntry *)NULL; 00299 pWETE = AET; 00300 AET = AET->next; 00301 while (AET) 00302 { 00303 if (AET->ClockWise) 00304 isInside++; 00305 else 00306 isInside--; 00307 00308 if ((!inside && !isInside) || 00309 ( inside && isInside)) 00310 { 00311 pWETE->nextWETE = AET; 00312 pWETE = AET; 00313 inside = !inside; 00314 } 00315 AET = AET->next; 00316 } 00317 pWETE->nextWETE = (EdgeTableEntry *)NULL; 00318 } 00319 00320 /* 00321 * InsertionSort 00322 * 00323 * Just a simple insertion sort using 00324 * pointers and back pointers to sort the Active 00325 * Edge Table. 00326 * 00327 */ 00328 00329 int 00330 miInsertionSort(AET) 00331 register EdgeTableEntry *AET; 00332 { 00333 register EdgeTableEntry *pETEchase; 00334 register EdgeTableEntry *pETEinsert; 00335 register EdgeTableEntry *pETEchaseBackTMP; 00336 register int changed = 0; 00337 00338 AET = AET->next; 00339 while (AET) 00340 { 00341 pETEinsert = AET; 00342 pETEchase = AET; 00343 while (pETEchase->back->bres.minor > AET->bres.minor) 00344 pETEchase = pETEchase->back; 00345 00346 AET = AET->next; 00347 if (pETEchase != pETEinsert) 00348 { 00349 pETEchaseBackTMP = pETEchase->back; 00350 pETEinsert->back->next = AET; 00351 if (AET) 00352 AET->back = pETEinsert->back; 00353 pETEinsert->next = pETEchase; 00354 pETEchase->back->next = pETEinsert; 00355 pETEchase->back = pETEinsert; 00356 pETEinsert->back = pETEchaseBackTMP; 00357 changed = 1; 00358 } 00359 } 00360 return(changed); 00361 } 00362 00363 /* 00364 * Clean up our act. 00365 */ 00366 void 00367 miFreeStorage(pSLLBlock) 00368 register ScanLineListBlock *pSLLBlock; 00369 { 00370 register ScanLineListBlock *tmpSLLBlock; 00371 00372 while (pSLLBlock) 00373 { 00374 tmpSLLBlock = pSLLBlock->next; 00375 free(pSLLBlock); 00376 pSLLBlock = tmpSLLBlock; 00377 } 00378 }
1.7.6.1