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

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

unix.superglobalmegacorp.com

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