Annotation of mstools/samples/mandel/bndscan.c, revision 1.1.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.