📄 devrgn2.c
字号:
EndPt = pts - 1; for(poly = 0; poly < nbpolygons; poly++) { count = Count[poly]; EndPt += count; if(count < 2) continue; PrevPt = EndPt; /* * for each vertex in the array of points. * In this loop we are dealing with two vertices at * a time -- these make up one edge of the polygon. */ while (count--) { CurrPt = pts++; /* * find out which point is above and which is below. */ if (PrevPt->y > CurrPt->y) { bottom = PrevPt, top = CurrPt; pETEs->ClockWise = 0; } else { bottom = CurrPt, top = PrevPt; pETEs->ClockWise = 1; } /* * don't add horizontal edges to the Edge table. */ if (bottom->y != top->y) { pETEs->ymax = bottom->y-1; /* -1 so we don't get last scanline */ /* * initialize integer edge algorithm */ dy = bottom->y - top->y; BRESINITPGONSTRUCT(dy, top->x, bottom->x, pETEs->bres); REGION_InsertEdgeInET(ET, pETEs, top->y, &pSLLBlock, &iSLLBlock); if (PrevPt->y > ET->ymax) ET->ymax = PrevPt->y; if (PrevPt->y < ET->ymin) ET->ymin = PrevPt->y; pETEs++; } PrevPt = CurrPt; } }}/* * REGION_loadAET * * This routine moves EdgeTableEntries from the * EdgeTable into the Active Edge Table, * leaving them sorted by smaller x coordinate. * */static void REGION_loadAET(EdgeTableEntry *AET, EdgeTableEntry *ETEs){ EdgeTableEntry *pPrevAET; EdgeTableEntry *tmp; pPrevAET = AET; AET = AET->next; while (ETEs) { while (AET && (AET->bres.minor_axis < ETEs->bres.minor_axis)) { pPrevAET = AET; AET = AET->next; } tmp = ETEs->next; ETEs->next = AET; if (AET) AET->back = ETEs; ETEs->back = pPrevAET; pPrevAET->next = ETEs; pPrevAET = ETEs; ETEs = tmp; }}/* * REGION_computeWAET * * This routine links the AET by the * nextWETE (winding EdgeTableEntry) link for * use by the winding number rule. The final * Active Edge Table (AET) might look something * like: * * AET * ---------- --------- --------- * |ymax | |ymax | |ymax | * | ... | |... | |... | * |next |->|next |->|next |->... * |nextWETE| |nextWETE| |nextWETE| * --------- --------- ^-------- * | | | * V-------------------> V---> ... * */static void REGION_computeWAET(EdgeTableEntry *AET){ EdgeTableEntry *pWETE; int inside = 1; int isInside = 0; AET->nextWETE = (EdgeTableEntry *)NULL; pWETE = AET; AET = AET->next; while (AET) { if (AET->ClockWise) isInside++; else isInside--; if ((!inside && !isInside) || ( inside && isInside)) { pWETE->nextWETE = AET; pWETE = AET; inside = !inside; } AET = AET->next; } pWETE->nextWETE = (EdgeTableEntry *)NULL;}/* * REGION_InsertionSort * * Just a simple insertion sort using * pointers and back pointers to sort the Active * Edge Table. * */static MWBOOL REGION_InsertionSort(EdgeTableEntry *AET){ EdgeTableEntry *pETEchase; EdgeTableEntry *pETEinsert; EdgeTableEntry *pETEchaseBackTMP; MWBOOL changed = FALSE; AET = AET->next; while (AET) { pETEinsert = AET; pETEchase = AET; while (pETEchase->back->bres.minor_axis > AET->bres.minor_axis) pETEchase = pETEchase->back; AET = AET->next; if (pETEchase != pETEinsert) { pETEchaseBackTMP = pETEchase->back; pETEinsert->back->next = AET; if (AET) AET->back = pETEinsert->back; pETEinsert->next = pETEchase; pETEchase->back->next = pETEinsert; pETEchase->back = pETEinsert; pETEinsert->back = pETEchaseBackTMP; changed = TRUE; } } return changed;}/* * REGION_FreeStorage * * Clean up our act. */static void REGION_FreeStorage(ScanLineListBlock *pSLLBlock){ ScanLineListBlock *tmpSLLBlock; while (pSLLBlock) { tmpSLLBlock = pSLLBlock->next; free( pSLLBlock ); pSLLBlock = tmpSLLBlock; }}/* * REGION_PtsToRegion * * Create an array of rectangles from a list of points. */static int REGION_PtsToRegion(int numFullPtBlocks, int iCurPtBlock, POINTBLOCK *FirstPtBlock, MWCLIPREGION *reg){ MWRECT *rects; MWPOINT *pts; POINTBLOCK *CurPtBlock; int i; MWRECT *extents; int numRects; extents = ®->extents; numRects = ((numFullPtBlocks * NUMPTSTOBUFFER) + iCurPtBlock) >> 1; if (!(reg->rects = realloc( reg->rects, sizeof(MWRECT) * numRects ))) return(0); reg->size = numRects; CurPtBlock = FirstPtBlock; rects = reg->rects - 1; numRects = 0; extents->left = LARGE_COORDINATE, extents->right = SMALL_COORDINATE; for ( ; numFullPtBlocks >= 0; numFullPtBlocks--) { /* the loop uses 2 points per iteration */ i = NUMPTSTOBUFFER >> 1; if (!numFullPtBlocks) i = iCurPtBlock >> 1; for (pts = CurPtBlock->pts; i--; pts += 2) { if (pts->x == pts[1].x) continue; if (numRects && pts->x == rects->left && pts->y == rects->bottom && pts[1].x == rects->right && (numRects == 1 || rects[-1].top != rects->top) && (i && pts[2].y > pts[1].y)) { rects->bottom = pts[1].y + 1; continue; } numRects++; rects++; rects->left = pts->x; rects->top = pts->y; rects->right = pts[1].x; rects->bottom = pts[1].y + 1; if (rects->left < extents->left) extents->left = rects->left; if (rects->right > extents->right) extents->right = rects->right; } CurPtBlock = CurPtBlock->next; } if (numRects) { extents->top = reg->rects->top; extents->bottom = rects->bottom; } else { extents->left = 0; extents->top = 0; extents->right = 0; extents->bottom = 0; } reg->numRects = numRects; return(TRUE);}/* * GdAllocPolygonRegion */MWCLIPREGION *GdAllocPolygonRegion(MWPOINT *points, int count, int mode){ return GdAllocPolyPolygonRegion(points, &count, 1, mode );}/* * GdAllocPolyPolygonRegion */MWCLIPREGION *GdAllocPolyPolygonRegion(MWPOINT *points, int *count, int nbpolygons, int mode){ MWCLIPREGION *rgn; EdgeTableEntry *pAET; /* Active Edge Table */ int y; /* current scanline */ int iPts = 0; /* number of pts in buffer */ EdgeTableEntry *pWETE; /* Winding Edge Table Entry*/ ScanLineList *pSLL; /* current scanLineList */ MWPOINT *pts; /* output buffer */ EdgeTableEntry *pPrevAET; /* ptr to previous AET */ EdgeTable ET; /* header node for ET */ EdgeTableEntry AET; /* header node for AET */ EdgeTableEntry *pETEs; /* EdgeTableEntries pool */ ScanLineListBlock SLLBlock; /* header for scanlinelist */ int fixWAET = FALSE; POINTBLOCK FirstPtBlock, *curPtBlock; /* PtBlock buffers */ POINTBLOCK *tmpPtBlock; int numFullPtBlocks = 0; int poly, total; if(!(rgn = GdAllocRegion())) return NULL; /* special case a rectangle */ if (((nbpolygons == 1) && ((*count == 4) || ((*count == 5) && (points[4].x == points[0].x) && (points[4].y == points[0].y)))) && (((points[0].y == points[1].y) && (points[1].x == points[2].x) && (points[2].y == points[3].y) && (points[3].x == points[0].x)) || ((points[0].x == points[1].x) && (points[1].y == points[2].y) && (points[2].x == points[3].x) && (points[3].y == points[0].y)))) { GdSetRectRegion( rgn, MWMIN(points[0].x, points[2].x), MWMIN(points[0].y, points[2].y), MWMAX(points[0].x, points[2].x), MWMAX(points[0].y, points[2].y) ); return rgn; } for(poly = total = 0; poly < nbpolygons; poly++) total += count[poly]; if (! (pETEs = malloc( sizeof(EdgeTableEntry) * total ))) { GdDestroyRegion( rgn ); return 0; } pts = FirstPtBlock.pts; REGION_CreateETandAET(count, nbpolygons, points, &ET, &AET, pETEs, &SLLBlock); pSLL = ET.scanlines.next; curPtBlock = &FirstPtBlock; if (mode != MWPOLY_WINDING) { /* * for each scanline */ for (y = ET.ymin; y < ET.ymax; y++) { /* * Add a new edge to the active edge table when we * get to the next edge. */ if (pSLL != NULL && y == pSLL->scanline) { REGION_loadAET(&AET, pSLL->edgelist); pSLL = pSLL->next; } pPrevAET = &AET; pAET = AET.next; /* * for each active edge */ while (pAET) { pts->x = pAET->bres.minor_axis, pts->y = y; pts++, iPts++; /* * send out the buffer */ if (iPts == NUMPTSTOBUFFER) { tmpPtBlock = malloc( sizeof(POINTBLOCK)); if(!tmpPtBlock) { return 0; } curPtBlock->next = tmpPtBlock; curPtBlock = tmpPtBlock; pts = curPtBlock->pts; numFullPtBlocks++; iPts = 0; } EVALUATEEDGEEVENODD(pAET, pPrevAET, y); } REGION_InsertionSort(&AET); } } else { /* * for each scanline */ for (y = ET.ymin; y < ET.ymax; y++) { /* * Add a new edge to the active edge table when we * get to the next edge. */ if (pSLL != NULL && y == pSLL->scanline) { REGION_loadAET(&AET, pSLL->edgelist); REGION_computeWAET(&AET); pSLL = pSLL->next; } pPrevAET = &AET; pAET = AET.next; pWETE = pAET; /* * for each active edge */ while (pAET) { /* * add to the buffer only those edges that * are in the Winding active edge table. */ if (pWETE == pAET) { pts->x = pAET->bres.minor_axis, pts->y = y; pts++, iPts++; /* * send out the buffer */ if (iPts == NUMPTSTOBUFFER) { tmpPtBlock = malloc( sizeof(POINTBLOCK) ); if(!tmpPtBlock) { return 0; } curPtBlock->next = tmpPtBlock; curPtBlock = tmpPtBlock; pts = curPtBlock->pts; numFullPtBlocks++; iPts = 0; } pWETE = pWETE->nextWETE; } EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET); } /* * recompute the winding active edge table if * we just resorted or have exited an edge. */ if (REGION_InsertionSort(&AET) || fixWAET) { REGION_computeWAET(&AET); fixWAET = FALSE; } } } REGION_FreeStorage(SLLBlock.next); REGION_PtsToRegion(numFullPtBlocks, iPts, &FirstPtBlock, rgn); for (curPtBlock = FirstPtBlock.next; --numFullPtBlocks >= 0;) { tmpPtBlock = curPtBlock->next; free( curPtBlock ); curPtBlock = tmpPtBlock; } free( pETEs ); return rgn;}#endif /* POLYREGIONS*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -