1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
|
#include <windows.h>
const int CLIENT_SIZE_X = 400;
const int CLIENT_SIZE_Y = 400;
const int SELECTION_TOO_SMALL = 4;
struct DRect { double left, top, right, bottom; };
struct WndSize { int horz, vert; };
const DRect INIT_LOCATION = { -2.0, 1.25, 0.5, -1.25 };
DRect g_location = INIT_LOCATION;
RECT g_selection;
void drawMandelbrot( HDC hdc, const DRect& loc, const WndSize& pixels ){
const double saturation = 0.5;
const double value = 0.7;
const double rotation = 20.0; // adjusts hue
const int MaxCount = 100;
COLORREF color;
double hue, f;
int p, q, t;
double xstep = (loc.right - loc.left) / pixels.horz;
double ystep = (loc.bottom - loc.top) / pixels.vert;
double cx, cy;
int x, y;
for( y = 0, cy = loc.top;
y < pixels.vert;
++y, cy += ystep )
for( x = 0, cx = loc.left;
x < pixels.horz;
++x, cx += xstep ){
double zx = 0, zy = 0;
double zx2 = 0, zy2 = 0; // zx and zy squared
int count;
for( count = 0; count < MaxCount; ++count ){
zy = 2 * zx * zy + cy; // must be before zx is changed
zx = zx2 - zy2 + cx;
zx2 = zx * zx;
zy2 = zy * zy;
if( zx2 + zy2 > 4.0 ) break;
}
color = RGB( 0, 0, 0 ); // Points in the set are black
if( count < MaxCount ){ // Points outside the set are colored
hue = count * 360.0 / MaxCount + rotation;
while( hue >= 360.0 ) hue -= 360.0;
// Convert HSV to RGB
f = hue / 60 - (int)(hue / 60);
p = (int) (value * (1 - saturation) * 255);
q = (int) (value * (1 - f * saturation) * 255);
t = (int) (value * (1 - (1 - f) * saturation) * 255);
switch( (int)(hue / 60) % 6 )
{
case 0: color = RGB( value, t, p ); break;
case 1: color = RGB( q, value, p ); break;
case 2: color = RGB( p, value, t ); break;
case 3: color = RGB( p, q, value ); break;
case 4: color = RGB( t, p, value ); break;
case 5: color = RGB( value, p, q ); break;
}
}
SetPixelV( hdc, x, y, color );
}
}
void normalizeRect( RECT *rect ){
LONG temp;
if( rect->top > rect->bottom ){
temp = rect->top;
rect->top = rect->bottom;
rect->bottom = temp;
}
if( rect->left > rect->right ){
temp = rect->left;
rect->left = rect->right;
rect->right = temp;
}
}
void setSelectRect( LONG l, LONG t, LONG r, LONG b ){
g_selection.left = l; g_selection.top = t;
g_selection.right = r; g_selection.bottom = b;
}
void drawSelectRect( HWND hwnd ){
HDC hdc = GetDC( hwnd );
RECT rect = g_selection;
normalizeRect( &rect );
DrawFocusRect( hdc, &rect );
ReleaseDC( hwnd, hdc );
}
void endSelection( HWND hwnd ){
HDC hdc = GetDC( hwnd );
normalizeRect( &g_selection );
DrawFocusRect( hdc, &g_selection );
ReleaseDC( hwnd, hdc );
ReleaseCapture();
}
BOOL isSelectionTooSmall( void ){
return( g_selection.right - g_selection.left < SELECTION_TOO_SMALL ||
g_selection.bottom - g_selection.top < SELECTION_TOO_SMALL );
}
void updateLocation( void ){
double size = g_location.right - g_location.left;
double temp = g_location.left + size * g_selection.left / CLIENT_SIZE_X;
g_location.right = g_location.left
+ size * g_selection.right / CLIENT_SIZE_X;
g_location.left = temp;
size = g_location.bottom - g_location.top;
temp = g_location.top + size * g_selection.top / CLIENT_SIZE_Y;
g_location.bottom = g_location.top +
size * g_selection.bottom / CLIENT_SIZE_Y;
g_location.top = temp;
}
void wmLButtonDown( HWND hwnd, WPARAM wp, LPARAM lp ){
SetCapture( hwnd );
setSelectRect( LOWORD( lp ), HIWORD( lp ),
LOWORD( lp ), HIWORD( lp ));
drawSelectRect( hwnd );
}
void wmMouseMove( HWND hwnd, WPARAM wp, LPARAM lp ){
if( GetCapture() != hwnd ) return;
drawSelectRect( hwnd );
g_selection.right = LOWORD( lp );
g_selection.bottom = HIWORD( lp );
drawSelectRect( hwnd );
}
void wmLButtonUp( HWND hwnd, WPARAM wp, LPARAM lp ){
if( GetCapture() != hwnd ) return;
endSelection( hwnd );
if( isSelectionTooSmall() ) return;
updateLocation();
InvalidateRect( hwnd, 0, 1 );
}
void wmRButtonDown( HWND hwnd, WPARAM wp, LPARAM lp ){
if( GetCapture() == hwnd ) // If in capture mode
endSelection( hwnd ); // cancel selection rect
}
void wmLButtonDblClk( HWND hwnd, WPARAM wp, LPARAM lp ){
g_location = INIT_LOCATION;
InvalidateRect( hwnd, 0, TRUE );
}
void wmPaint( HWND hwnd, WPARAM wp, LPARAM lp ){
PAINTSTRUCT ps;
HDC hdc = BeginPaint( hwnd, &ps );
WndSize wndSize = { CLIENT_SIZE_X, CLIENT_SIZE_Y };
drawMandelbrot( hdc, g_location, wndSize );
EndPaint( hwnd, &ps );
}
LRESULT CALLBACK mainWndProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp ){
switch( msg ){
case WM_PAINT: wmPaint (hwnd, wp, lp); break;
case WM_LBUTTONDOWN: wmLButtonDown (hwnd, wp, lp); break;
case WM_MOUSEMOVE: wmMouseMove (hwnd, wp, lp); break;
case WM_LBUTTONUP: wmLButtonUp (hwnd, wp, lp); break;
case WM_RBUTTONDOWN: wmRButtonDown (hwnd, wp, lp); break;
case WM_LBUTTONDBLCLK: wmLButtonDblClk(hwnd, wp, lp); break;
case WM_DESTROY: PostQuitMessage( 0 ); break;
default: return DefWindowProc (hwnd, msg, wp, lp);
}
return 0;
}
void registerWindow( HINSTANCE hinst, char *appname, WNDPROC wp ){
WNDCLASSEX wc = {sizeof(wc)}; // set first member, zero the rest
wc.style = CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS;
wc.lpfnWndProc = wp;
wc.hInstance = hinst;
wc.hIcon = LoadIcon( hinst, appname );
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.hbrBackground = (HBRUSH) GetStockObject( BLACK_BRUSH );
wc.lpszMenuName = appname;
wc.lpszClassName = appname;
wc.hIconSm = LoadIcon( hinst, appname );
RegisterClassEx( &wc );
}
int WINAPI WinMain( HINSTANCE hinst, HINSTANCE unused,
PSTR cmd, int show ){
char *appName = "Mandelbrot";
MSG msg;
DWORD style = WS_POPUPWINDOW|WS_CAPTION;
RECT rect = {0, 0, CLIENT_SIZE_X, CLIENT_SIZE_Y};
registerWindow( hinst, appName, mainWndProc );
AdjustWindowRect( &rect, style, FALSE );
CreateWindowEx( 0, appName, appName, style | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT,
rect.right - rect.left, rect.bottom - rect.top,
NULL, NULL, hinst, NULL );
while( GetMessage( &msg, NULL, 0, 0 )){
TranslateMessage( &msg );
DispatchMessage( &msg );
}
return msg.wParam;
}
|