⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 devrgn2.c

📁 神龙卡开发原代码
💻 C
📖 第 1 页 / 共 2 页
字号:
    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 = &reg->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 + -