Annotation of mstools/samples/mandel/bndscan.c, revision 1.1

1.1     ! root        1: /******************************Module*Header*******************************\
        !             2: * Module Name: bndscan.c
        !             3: *
        !             4: * Contains the boundary scaning functions
        !             5: *
        !             6: * Created: 14-Apr-1992 10:59:52
        !             7: * Author: Petrus Wong
        !             8: *
        !             9: * Copyright (c) 1990 Microsoft Corporation
        !            10: *
        !            11: * Dependencies:
        !            12: *
        !            13: *   none
        !            14: *
        !            15: \**************************************************************************/
        !            16: #include <windows.h>
        !            17: #include <stdio.h>
        !            18: #include "jtypes.h"
        !            19: #include "bndscan.h"
        !            20: 
        !            21: extern LONG lMul(LONG, LONG);
        !            22: extern LONG lDiv(LONG, LONG);
        !            23: 
        !            24: BOOL   bBoundaryScanFix(PINFO);
        !            25: LPPOINT pptTrace(LONG, LONG, PINFO, INT *, HDC);
        !            26: DWORD  dwGetNextBoundaryPoint(DWORD, POINT, LPPOINT, PINFO);
        !            27: BOOL   bEscape(POINT, LONG, LONG, LONG, LONG, int, RECT);
        !            28: BOOL   bDirToPt(DWORD, POINT, LPPOINT);
        !            29: DWORD   dwShift(DWORD, int, int);
        !            30: 
        !            31: /******************************Public*Routine******************************\
        !            32: *
        !            33: * bBoundaryScanFix
        !            34: *
        !            35: * Effects:  Traces the outline of the mandelbrot set.  Currently,
        !            36: *           1. Uses the old method to set the color of each pixel
        !            37: *           2. Remember the first pixel from top that doesn't escape
        !            38: *              st we can do boundary trace later.
        !            39: *           3. When the whole set is done, do boundary trace.
        !            40: *           4. Store the boundary points in an array. Then build a path.
        !            41: *           5. Converts the path to region and then select the region as
        !            42: *              current clip region.
        !            43: *
        !            44: * Warnings: Only traces the first non-singular pixel island from top.
        !            45: *
        !            46: * History:
        !            47: *  20-Feb-1992 -by- Petrus Wong
        !            48: * Wrote it.
        !            49: \**************************************************************************/
        !            50: 
        !            51: BOOL bBoundaryScanFix(PINFO pInfo)
        !            52: {
        !            53:     DWORD       dwTick1;
        !            54:     int         m, n, o, p;
        !            55:     HDC         hDC;
        !            56:     RECT        rc;
        !            57:     LONG        c1, c2;
        !            58:     LONG        x0, y0;
        !            59:     int         iIteration;
        !            60:     LPPOINT     lpPt;
        !            61:     int        iCount;
        !            62:     POINT      Pt;
        !            63:     BOOL        bFirstPtSet;
        !            64: 
        !            65:     pInfo->bMandel = TRUE;
        !            66:     pInfo->bDrawing = TRUE;
        !            67:     bFirstPtSet = FALSE;
        !            68:     iIteration = pInfo->iIteration;
        !            69:     hDC = GetDC(pInfo->hwnd);
        !            70:     GetClientRect(pInfo->hwnd, &rc);
        !            71: 
        !            72:     dwTick1 = GetTickCount();
        !            73:     for (n=rc.bottom/2; n<=rc.bottom; n++) {
        !            74:        c2 = y0 = XformFix(n, rc.top, rc.bottom, pInfo->lyFrom, pInfo->lyTo);
        !            75: 
        !            76:         for (m=rc.left; m<=rc.right; m++) {
        !            77:            c1 = x0 = XformFix(m, rc.left, rc.right, pInfo->lxFrom, pInfo->lxTo);
        !            78:            Pt.x = m;
        !            79:            Pt.y = n;
        !            80:            if (bEscape(Pt, x0, y0, c1, c2, iIteration, rc)) {
        !            81:                 //SetPixel(hDC, m, n, 0x000000ff);
        !            82:             } else {
        !            83: 
        !            84:                 if (!bFirstPtSet)
        !            85:                 {
        !            86:                     o = m;
        !            87:                     p = n;
        !            88:                     bFirstPtSet = TRUE;
        !            89:                 }
        !            90:                 goto BOUNDTRACE;
        !            91:             }
        !            92:         }
        !            93:     }
        !            94: 
        !            95: BOUNDTRACE:
        !            96: 
        !            97:     SelectObject(hDC, hpnGreen);
        !            98:     if ((lpPt = pptTrace(o, p, pInfo, &iCount, hDC)) == NULL)
        !            99:     {
        !           100:         m = o+1;
        !           101: 
        !           102:         for (n=p; n<=rc.bottom; n++) {
        !           103:            c2 = y0 = XformFix(n, rc.top, rc.bottom, pInfo->lyFrom, pInfo->lyTo);
        !           104: 
        !           105:             while (m <= rc.right)
        !           106:             {
        !           107:                c1 = x0 = XformFix(m, rc.left, rc.right, pInfo->lxFrom, pInfo->lxTo);
        !           108:                Pt.x = m;
        !           109:                Pt.y = n;
        !           110: 
        !           111:                if (!bEscape(Pt, x0, y0, c1, c2, iIteration, rc))
        !           112:                 {
        !           113:                     o = m;
        !           114:                     p = n;
        !           115:                     goto BOUNDTRACE;
        !           116:                 }
        !           117: 
        !           118:                 m++;
        !           119:             }
        !           120:             m = rc.left;
        !           121:         }
        !           122:     }
        !           123: 
        !           124:     if (!BeginPath(hDC)) {
        !           125:         sprintf( gtext,"Failing in BeginPath!\n");
        !           126:         OutputDebugString( gtext );
        !           127:     }
        !           128: 
        !           129:     MoveToEx(hDC, m, n, NULL);
        !           130:     Polyline(hDC, lpPt, iCount);
        !           131: 
        !           132:     if (EndPath(hDC)) {
        !           133:         StrokePath(hDC);
        !           134:     }
        !           135: 
        !           136:     //
        !           137:     // Stroking discards the path
        !           138:     //
        !           139:     if (!BeginPath(hDC)) {
        !           140:         sprintf( gtext,"Failing in BeginPath!\n");
        !           141:         OutputDebugString( gtext );
        !           142:     }
        !           143: 
        !           144:     MoveToEx(hDC, m, n, NULL);
        !           145:     Polyline(hDC, lpPt, iCount);
        !           146: 
        !           147:     if (EndPath(hDC)) {
        !           148:         //
        !           149:         // Convert the path to region
        !           150:         //
        !           151:         pInfo->hRgnPath = PathToRegion(hDC);
        !           152: 
        !           153: #if 0
        !           154:         //
        !           155:         // SelectClipPath doesn't seem to work at this time
        !           156:         //
        !           157:         if (SelectClipPath(hDC, RGN_COPY)) {
        !           158:             //
        !           159:             // Testing if the clip region is effective or not
        !           160:             //
        !           161:             //MoveToEx(hDC, 0, 0, NULL);
        !           162:             //GetClientRect(pInfo->hwnd, &rc);
        !           163:             //LineTo(hDC, rc.right, rc.bottom);
        !           164:         }
        !           165: #endif
        !           166:     }
        !           167: 
        !           168:     if (pInfo->hRgnPath != (HRGN) NULL) {
        !           169:         if (SelectClipRgn(hDC, pInfo->hRgnPath) == ERROR) {
        !           170:             sprintf( gtext,"Error in Selecting clip region\n");
        !           171:             OutputDebugString( gtext );
        !           172:             goto EXIT;
        !           173:         }
        !           174:         //
        !           175:         // Testing if the clip region is effective or not
        !           176:         //
        !           177:         //MoveToEx(hDC, 0, 0, NULL);
        !           178:         //GetClientRect(pInfo->hwnd, &rc);
        !           179:         //LineTo(hDC, rc.right, rc.bottom);
        !           180:     }
        !           181: 
        !           182: 
        !           183: EXIT:
        !           184: 
        !           185:     pInfo->dwElapsed = GetTickCount() - dwTick1;
        !           186:     pInfo->hBmpSaved = SaveBitmap(pInfo->hwnd);
        !           187:     pInfo->bDrawing = FALSE;
        !           188: 
        !           189:     ReleaseDC(pInfo->hwnd, hDC);
        !           190:     //
        !           191:     // GlobalAlloc was called in pptTrace for storing the boundary points
        !           192:     //
        !           193:     GlobalFree((HANDLE) lpPt);
        !           194:     ExitThread(0);
        !           195:     if (!CloseHandle(pInfo->hThrd))
        !           196:          MessageBox(ghwndMain, "Failed in CloseHandle!", "Error", MB_OK);
        !           197: 
        !           198:     return TRUE;
        !           199: }
        !           200: 
        !           201: /******************************Public*Routine******************************\
        !           202: *
        !           203: * pptTrace
        !           204: *
        !           205: * Effects:  Given a boundary point, traces the whole boundary of the
        !           206: *           set by calling dwGetNextBoundaryPoint() repeatedly.  Returns
        !           207: *           a pointer to an array of boundary points and also the count
        !           208: *           of boundary points in the array, if successful.  Otherwise,
        !           209: *           returns null.
        !           210: *           m, n is the x, y coordinates of the pixel of the initial
        !           211: *           boundary point.
        !           212: *
        !           213: * Warnings:
        !           214: *
        !           215: * History:
        !           216: *  20-Feb-1992 -by- Petrus Wong
        !           217: * Wrote it.
        !           218: \**************************************************************************/
        !           219: 
        !           220: LPPOINT pptTrace(LONG m, LONG n, PINFO pInfo, INT * piCount, HDC hDC)
        !           221: {
        !           222:     DWORD        dwFace;
        !           223:     LPPOINT      lpPt, lpTmpPt;
        !           224:     POINT        Init;
        !           225:     int          iNumPt;
        !           226: 
        !           227:     //
        !           228:     // MAXPOINT points should be enough for storing the boundary for now.  If
        !           229:     // it's not enough, it is more likely that it is an error.
        !           230:     //
        !           231:     if ((lpPt = (PPOINT) GlobalAlloc(GMEM_FIXED, MAXPOINT * sizeof(POINT))) == NULL) {
        !           232:         MessageBox(ghwndMain, "Failed in Memory Allocation for lpPt!", "Error", MB_OK);
        !           233:         return (LPPOINT) NULL;
        !           234:     }
        !           235:     lpTmpPt = lpPt;
        !           236:     lpPt->x = Init.x = m;
        !           237:     lpPt->y = Init.y = n;
        !           238:     lpPt++;
        !           239:     iNumPt = 1;
        !           240:     dwFace = dwGetNextBoundaryPoint(EAST, Init, lpPt, pInfo);
        !           241:     //
        !           242:     // If can't find next boundary point, return null
        !           243:     //
        !           244:     if (dwFace == 0)
        !           245:         return((LPPOINT)NULL);
        !           246: //#if 0
        !           247:     //
        !           248:     // remove the ifdef if we wanted to see the boundary as we trace
        !           249:     //
        !           250:     MoveToEx(hDC, Init.x, Init.y, NULL);
        !           251:     LineTo(hDC, lpPt->x, lpPt->y);
        !           252: //#endif
        !           253:     //
        !           254:     // Keep looking for next boundary point until I get back to where I
        !           255:     // started or exceeding MAXPOINT points
        !           256:     //
        !           257:     while ((iNumPt < MAXPOINT) &&
        !           258:            ((lpPt->x != lpTmpPt->x) || (lpPt->y != lpTmpPt->y))) {
        !           259:         Init.x = lpPt->x;
        !           260:         Init.y = lpPt->y;
        !           261:         lpPt++;
        !           262:         iNumPt++;
        !           263:        dwFace = dwGetNextBoundaryPoint(dwFace, Init, lpPt, pInfo);
        !           264:         //
        !           265:         // If can't find next boundary point, return null
        !           266:         //
        !           267:         if (dwFace == 0)
        !           268:             return((LPPOINT)NULL);
        !           269: //#if 0
        !           270:         //
        !           271:         // remove the ifdef if we wanted to see the boundary as we trace
        !           272:         //
        !           273:         MoveToEx(hDC, Init.x, Init.y, NULL);
        !           274:         LineTo(hDC, lpPt->x, lpPt->y);
        !           275: //#endif
        !           276: 
        !           277:     }
        !           278:     //
        !           279:     // It is more likely that it is an error of the algorithm, if ever happens.
        !           280:     //
        !           281:     if (iNumPt >= MAXPOINT) {
        !           282:         MessageBox(ghwndMain, "Not enough memory!!", "Error", MB_OK);
        !           283:     }
        !           284:     *piCount = iNumPt;
        !           285:     return (LPPOINT) lpTmpPt;
        !           286: }
        !           287: 
        !           288: 
        !           289: /******************************Public*Routine******************************\
        !           290: *
        !           291: * dwGetNextBoundaryPoint
        !           292: *
        !           293: * Effects:  Start checking the 8 neighbors in clockwise direction.  Returns
        !           294: *           the first neighbor that does not escape.
        !           295: *           dwFace      where we face
        !           296: *           InitPt      where we are right now in pixel coordinates
        !           297: *
        !           298: * Warnings: assumes that we start at a boundary point.  Does not trace into
        !           299: *           a bay if the entrance closed. Ie, it cuts cycle.
        !           300: *
        !           301: * History:
        !           302: *  12-Feb-1992 -by- Petrus Wong
        !           303: * Wrote it.
        !           304: \**************************************************************************/
        !           305: 
        !           306: DWORD dwGetNextBoundaryPoint(DWORD dwFace, POINT InitPt, LPPOINT lpPt, PINFO pInfo)
        !           307: {
        !           308:     BOOL    bEsc;
        !           309:     DWORD   dwExplore;
        !           310:     DWORD   dwEnd;
        !           311:     int     i;
        !           312:     NODE    arg[8];
        !           313:     POINT   BndPt;
        !           314:     LONG    lx, c1, ly, c2;
        !           315:     RECT    rc;
        !           316: 
        !           317:     GetClientRect(pInfo->hwnd, &rc);
        !           318:     //
        !           319:     // Start exploring clockwise, ending at where we came from
        !           320:     //
        !           321:     dwExplore = dwShift(dwFace, RIGHT, 3);
        !           322:     dwEnd = dwShift(dwFace, LEFT, 4);
        !           323:     i = 0;
        !           324:     bDirToPt(dwExplore, InitPt, &BndPt);
        !           325:     c1 = lx = XformFix(BndPt.x, rc.left, rc.right, pInfo->lxFrom, pInfo->lxTo);
        !           326:     c2 = ly = XformFix(BndPt.y, rc.top, rc.bottom, pInfo->lyFrom, pInfo->lyTo);
        !           327: 
        !           328:     while (bEsc = bEscape(BndPt, lx, ly, c1, c2, pInfo->iIteration, rc)) {
        !           329:         arg[i].dwDirection = dwExplore;
        !           330:         arg[i].bEscape     = TRUE;
        !           331: 
        !           332:         i++;
        !           333: 
        !           334:         if (dwExplore == dwEnd)
        !           335:             break;
        !           336: 
        !           337:         dwExplore = dwShift(dwExplore, LEFT, 1);
        !           338:        bDirToPt(dwExplore, InitPt, &BndPt);
        !           339:        c1 = lx = XformFix(BndPt.x, rc.left, rc.right, pInfo->lxFrom, pInfo->lxTo);
        !           340:        c2 = ly = XformFix(BndPt.y, rc.top, rc.bottom, pInfo->lyFrom, pInfo->lyTo);
        !           341: 
        !           342:     }
        !           343: 
        !           344:     if (bEsc) {
        !           345:         return 0L;
        !           346:     }
        !           347: 
        !           348:     arg[i].dwDirection = dwExplore;
        !           349:     arg[i].bEscape     = FALSE;
        !           350: 
        !           351:     bDirToPt(arg[i].dwDirection, InitPt, lpPt);
        !           352: 
        !           353:     return arg[i].dwDirection;
        !           354: }
        !           355: 
        !           356: 
        !           357: 
        !           358: /******************************Public*Routine******************************\
        !           359: *
        !           360: * bEscape
        !           361: *
        !           362: * Effects: Test if the point excapes based on the number of iterations
        !           363: *
        !           364: * Warnings:
        !           365: *
        !           366: * History:
        !           367: *  20-Feb-1992 -by- Petrus Wong
        !           368: * Wrote it.
        !           369: \**************************************************************************/
        !           370: 
        !           371: BOOL bEscape(POINT Pt, LONG x, LONG y, LONG c1, LONG c2, int iIteration, RECT rc)
        !           372: {
        !           373:     LONG x1, y1, z;
        !           374:     BOOL bEscape;
        !           375:     int i;
        !           376: 
        !           377:     bEscape = FALSE;
        !           378: 
        !           379:     //
        !           380:     // Treat points outside of client rect as escaping
        !           381:     //
        !           382:     if ((Pt.x < rc.left)   || (Pt.x > rc.right-1) ||
        !           383:         (Pt.y > rc.bottom-1) || (Pt.y < rc.top))     {
        !           384:         return TRUE;
        !           385:     }
        !           386:     for (i=1; i<=iIteration; i++) {
        !           387:         x1 = lMul(x - y, x + y) + c1;
        !           388:         y1 = (lMul(x, y) * 2) + c2;
        !           389:         x = x1;
        !           390:         y = y1;                             //    2       2     2 1/2     2
        !           391:         z = lMul(x, x) + lMul(y, y);        // |Z|  = ((x1  + x2 )   ) > 2
        !           392: 
        !           393:         if (z > 8192) {
        !           394:             bEscape = TRUE;
        !           395:             break;
        !           396:         }
        !           397:     }
        !           398:     return bEscape;
        !           399: }
        !           400: 
        !           401: /******************************Public*Routine******************************\
        !           402: *
        !           403: * bDirToPt
        !           404: *
        !           405: * Effects: Returns the pixel coordinates based the direction we are facing
        !           406: *          and our current position
        !           407: *
        !           408: * Warnings:
        !           409: *
        !           410: * History:
        !           411: *  20-Feb-1992
        !           412: * Wrote it.
        !           413: \**************************************************************************/
        !           414: 
        !           415: BOOL bDirToPt(DWORD dwDirection, POINT InitPt, LPPOINT lpPt)
        !           416: {
        !           417:     BOOL bSuccess;
        !           418: 
        !           419:     bSuccess = TRUE;
        !           420:     switch ((LONG)dwDirection) {
        !           421:         case EAST:
        !           422:             lpPt->x = InitPt.x+1;
        !           423:             lpPt->y = InitPt.y;
        !           424:             break;
        !           425:         case SOUTHEAST:
        !           426:             lpPt->x = InitPt.x+1;
        !           427:             lpPt->y = InitPt.y+1;
        !           428:             break;
        !           429:         case SOUTH:
        !           430:             lpPt->x = InitPt.x;
        !           431:             lpPt->y = InitPt.y+1;
        !           432:             break;
        !           433:         case SOUTHWEST:
        !           434:             lpPt->x = InitPt.x-1;
        !           435:             lpPt->y = InitPt.y+1;
        !           436:             break;
        !           437:         case WEST:
        !           438:             lpPt->x = InitPt.x-1;
        !           439:             lpPt->y = InitPt.y;
        !           440:             break;
        !           441:         case NORTHWEST:
        !           442:             lpPt->x = InitPt.x-1;
        !           443:             lpPt->y = InitPt.y-1;
        !           444:             break;
        !           445:         case NORTH:
        !           446:             lpPt->x = InitPt.x;
        !           447:             lpPt->y = InitPt.y-1;
        !           448:             break;
        !           449:         case NORTHEAST:
        !           450:             lpPt->x = InitPt.x+1;
        !           451:             lpPt->y = InitPt.y-1;
        !           452:             break;
        !           453:         default:
        !           454:             bSuccess = FALSE;
        !           455:             break;
        !           456:     }
        !           457:     return bSuccess;
        !           458: }
        !           459: 
        !           460: /******************************Public*Routine******************************\
        !           461: *
        !           462: * dwShift
        !           463: *                                     NORTH
        !           464: *                           NW        0x0040        NE
        !           465: *                               0x0020      0x0080
        !           466: * Effects:      WEST    0x0010          *           0x0001  EAST
        !           467: *                               0x0008      0x0002
        !           468: *                           SW        0x0004        SE
        !           469: *                                     SOUTH
        !           470: *
        !           471: *               Shift dwOpnd left or right by iNum.
        !           472: *               dwOpnd contains the above values. The shift operation is
        !           473: *               closed.
        !           474: *
        !           475: * Warnings:
        !           476: *
        !           477: * History:
        !           478: *  20-Feb-1992 -by- Petrus Wong
        !           479: * Wrote it.
        !           480: \**************************************************************************/
        !           481: 
        !           482: DWORD dwShift(DWORD dwOpnd, int iDir, int iNum)
        !           483: {
        !           484:     DWORD dwTmp;
        !           485: 
        !           486:     dwTmp = ((dwOpnd << 8) | dwOpnd);
        !           487:     switch ((LONG)iDir) {
        !           488:        case LEFT:
        !           489:             dwTmp = dwTmp << iNum;
        !           490:            dwTmp = dwTmp & 0x0ff00;
        !           491:             dwTmp = dwTmp >> 8;
        !           492:             break;
        !           493:        case RIGHT:
        !           494:             dwTmp = dwTmp >> iNum;
        !           495:             dwTmp = dwTmp & 0x0ff;
        !           496:             break;
        !           497:        default:
        !           498:             dwTmp = 0L;
        !           499:            break;
        !           500:     }
        !           501:     return dwTmp;
        !           502: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.