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

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

unix.superglobalmegacorp.com

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