|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.