Mandelbrot 集合。

复数集合,详情见各种百科全书。
下面做了个示例,附件内有 vc6 工程。

Mandelbrot 集合。


#include <windows.h>
#include <tchar.h>

#define MANDELBROT_ITER 2000

#define MANDELBROT_COLORS 128

#define MANDELBROT_VW 400
#define MANDELBROT_VH 300 // MANDELBROT_VW * .75

#define MANDELBROT_CW MANDELBROT_VW / 2
#define MANDELBROT_CH MANDELBROT_VH / 2

#define MANDELBROT_L -2.50
#define MANDELBROT_T +1.35

#define MANDELBROT_W +3.60
#define MANDELBROT_H -2.70

typedef struct {
	double r;
	double i;
} complex;

typedef struct {
	void *hwnd;
	int l;
	int t;
	int r;
	int b;
	RECT rect;
} region;

struct {
	struct {
		void *himg;
		void *pixs;
		int w;
		int h;
	} simg;
	int iter;
	double setx;
	double sety;
	double setw;
	double seth;
	int cunt;
} sdata;

struct {
	int x;
	int y;
	double w;
	double h;
	int move;
} scoor;

unsigned int palet[] = {
	0xff000086, 0xff01018c, 0xff040491, 0xff070797, 0xff0c0c9c, 0xff1212a1, 0xff1919a7, 0xff2020ac,
	0xff2929b1, 0xff3333b6, 0xff3d3dbb, 0xff4747bf, 0xff5252c4, 0xff5e5ec8, 0xff6a6acc, 0xff7676d1,
	0xff8181d4, 0xff8d8dd8, 0xff9999dc, 0xffa5a5df, 0xffb0b0e2, 0xffbbbbe5, 0xffc5c5e8, 0xffcfcfea,
	0xffd8d8ec, 0xffe1e1ee, 0xffe8e8f0, 0xffefeff2, 0xfff5f5f3, 0xfffafaf4, 0xfffdfdf5, 0xfffffff5,
	0xfffffff5, 0xfffffff4, 0xfffffff2, 0xfffffeee, 0xfffffee9, 0xfffffde4, 0xfffffcdd, 0xfffffcd6,
	0xffffface, 0xfffff9c4, 0xfffff8bb, 0xfffff6b0, 0xfffff5a6, 0xfffff39b, 0xfffff190, 0xffffef84,
	0xffffed79, 0xffffeb6d, 0xffffe862, 0xffffe557, 0xffffe34c, 0xffffe041, 0xffffdc37, 0xffffd92e,
	0xffffd625, 0xffffd21d, 0xffffce16, 0xffffca0f, 0xffffc60a, 0xffffc205, 0xffffbd02, 0xffffb900,
	0xffffb400, 0xffffaf00, 0xfffea900, 0xfffea400, 0xfffd9d00, 0xfffc9700, 0xfffb9000, 0xfff98900,
	0xfff88200, 0xfff67a00, 0xfff47300, 0xfff16b00, 0xffef6400, 0xffec5c00, 0xffe95500, 0xffe64d00,
	0xffe34600, 0xffe03f00, 0xffdc3800, 0xffd93100, 0xffd52b00, 0xffd12400, 0xffcd1f00, 0xffc81900,
	0xffc41400, 0xffbf0f00, 0xffba0b00, 0xffb60800, 0xffb00500, 0xffab0300, 0xffa60100, 0xffa10000,
	0xff9b0000, 0xff950000, 0xff8f0001, 0xff890002, 0xff830004, 0xff7d0006, 0xff760008, 0xff70000a,
	0xff69000d, 0xff630010, 0xff5c0014, 0xff560017, 0xff4f001b, 0xff49001f, 0xff430024, 0xff3d0028,
	0xff37002d, 0xff310032, 0xff2b0037, 0xff26003c, 0xff210042, 0xff1c0047, 0xff17004d, 0xff130052,
	0xff0f0058, 0xff0c005e, 0xff090063, 0xff060069, 0xff04006f, 0xff020075, 0xff01007b, 0xff000080,
};

unsigned int templ[] = { WS_MINIMIZEBOX | WS_SYSMENU, WS_EX_DLGMODALFRAME, 0, 0, 0, 0, };

__declspec(naked) double __cdecl sqrt(double x) {
	__asm fld	qword ptr [esp+4]
	__asm fsqrt
	__asm ret
}

double complex_abs(complex *a) {
	return sqrt(a->r * a->r + a->i * a->i);
}

void complex_sub(complex *a, complex *b, complex *o) {
	o->i = a->i - b->i;
	o->r = a->r - b->r;
}

void complex_mul(complex *a, complex *b, complex *o) {
	double r = a->r * b->r - a->i * b->i;

	o->i = a->i * b->r + a->r * b->i;
	o->r = r;
}

unsigned int __stdcall mandelbrot_thread_proc(region *rptr) {
	int x, y, i;
	complex c, z, t, n;
	unsigned char *pixs;
	void *hwnd = rptr->hwnd;

	n.r = -.9;
	n.i = +.0;

	for (y = rptr->t; y < rptr->b; ++y) {
		pixs = (unsigned char*)sdata.simg.pixs + y * sdata.simg.w + rptr->l;

		for (x = rptr->l; x < rptr->r; ++x) {
			i = 0;

			t.r = sdata.setx + x * (sdata.setw / sdata.simg.w);
			t.i = sdata.sety + y * (sdata.seth / sdata.simg.h);

			complex_mul(&n, &t, &c);

			z.r = .0;
			z.i = .0;

			while (i++ < sdata.iter - 1 && complex_abs(&z) < 2.0) {
				complex_mul(&z, &z, &z);
				complex_sub(&z, &c, &z);
			}

			*pixs++ = (i == sdata.iter) ? MANDELBROT_COLORS : (i % MANDELBROT_COLORS);
		}

		if (!(y % 20)) InvalidateRect(hwnd, &rptr->rect, 1);
	}

	InvalidateRect(hwnd, 0, 1);

	free(rptr);

	--sdata.cunt;

	return 0;
}

void mandelbrot_create_image(int w, int h) {
	void *hmdc;
	BITMAPINFO *bmif = calloc(sizeof(char), sizeof(BITMAPINFOHEADER) + sizeof(int) * 256);

	sdata.simg.w = w;
	sdata.simg.h = h;

	bmif->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	bmif->bmiHeader.biWidth = w;
	bmif->bmiHeader.biHeight = -h;
	bmif->bmiHeader.biPlanes = 1;
	bmif->bmiHeader.biBitCount = 8;

	for (w = 0; w < MANDELBROT_COLORS; ++w) *(int*)(bmif->bmiColors + w) = palet[w];

	hmdc = CreateCompatibleDC(0);

	sdata.simg.himg = CreateDIBSection(hmdc, bmif, DIB_RGB_COLORS, &sdata.simg.pixs, 0, 0);

	DeleteDC(hmdc);

	free(bmif);
}

void mandelbrot_update(void *hwnd) {
	int x, y;
	double n;
	void *hthr;
	region *rptr;

	n = (double)MANDELBROT_VW / sdata.simg.w;

	for (y = 0; y < sdata.simg.h; y = y + MANDELBROT_CH)
		for (x = 0; x < sdata.simg.w; x = x + MANDELBROT_CW) {
			rptr = calloc(1, sizeof(region));

			rptr->hwnd = hwnd;
			rptr->l = x;
			rptr->t = y;
			rptr->r = MANDELBROT_CW <= sdata.simg.w - x ? x + MANDELBROT_CW : sdata.simg.w;
			rptr->b = MANDELBROT_CH <= sdata.simg.h - y ? y + MANDELBROT_CH : sdata.simg.h;

			SetRect(&rptr->rect, (int)(rptr->l * n), (int)(rptr->t * n), (int)(rptr->r * n), (int)(rptr->b * n));

			hthr = CreateThread(0, 0, mandelbrot_thread_proc, rptr, 0, 0);

			CloseHandle(hthr);

			if (hthr) ++sdata.cunt;
		}
}

void mandelbrot_draw_image(void *htdc) {
	void *himg, *hmdc;

	hmdc = CreateCompatibleDC(0);
	himg = SelectObject(hmdc, sdata.simg.himg);

	SetStretchBltMode(htdc, HALFTONE);

	StretchBlt(htdc, 0, 0, MANDELBROT_VW, MANDELBROT_VH, hmdc, 0, 0, sdata.simg.w, sdata.simg.h, SRCCOPY);

	SelectObject(hmdc, himg);

	DeleteDC(hmdc);
}

void mandelbrot_rbuttonup(void *hwnd) {
	if (sdata.cunt) return;

	if (scoor.move) return;

	sdata.setx = MANDELBROT_L;
	sdata.sety = MANDELBROT_T;

	sdata.setw = MANDELBROT_W;
	sdata.seth = MANDELBROT_H;

	mandelbrot_update(hwnd);
}

void mandelbrot_activate(void *hwnd, int code) {
	if (WA_INACTIVE != code) return;

	SetCapture(0);

	scoor.move = 0;

	InvalidateRect(hwnd, 0, 1);
}

void mandelbrot_initdialog(void *hwnd) {
	RECT rect = { 0, 0, MANDELBROT_VW, MANDELBROT_VH, };

	AdjustWindowRect(&rect, WS_CAPTION, 0);
	OffsetRect(&rect, -rect.left, -rect.top);

	MoveWindow(hwnd,
		(GetSystemMetrics(SM_CXSCREEN) - rect.right) / 2,
		(GetSystemMetrics(SM_CYSCREEN) - rect.bottom) / 2, rect.right, rect.bottom, 1);

	sdata.iter = MANDELBROT_ITER;

	mandelbrot_create_image(800, 600);
	mandelbrot_rbuttonup(hwnd);
}

void mandelbrot_lbuttondown(void *hwnd, int x, int y) {
	if (sdata.cunt) return;

	scoor.x = x;
	scoor.y = y;
	scoor.w = .0;
	scoor.h = .0;

	SetCapture(hwnd);

	scoor.move = 1;
}

void mandelbrot_lbuttonup(void *hwnd, int x, int y) {
	if (sdata.cunt) return;

	if (!scoor.move) return;

	SetCapture(0);

	scoor.move = 0;

	if (.0 >= scoor.w || .0 >= scoor.h) return;

	sdata.setx = sdata.setx + (scoor.x - scoor.w) / MANDELBROT_VW * sdata.setw;
	sdata.sety = sdata.sety + (scoor.y - scoor.h) / MANDELBROT_VH * sdata.seth;

	sdata.setw = sdata.setw / MANDELBROT_VW * (scoor.w * 2.0);
	sdata.seth = sdata.seth / MANDELBROT_VH * (scoor.h * 2.0);

	mandelbrot_update(hwnd);
}

void mandelbrot_mousemove(void *hwnd, int code, int x, int y) {
	if (!scoor.move) return;

	x = abs(x - scoor.x);
	y = abs(y - scoor.y);

	if (x < y) {
		scoor.w = y / .75;
		scoor.h = y;
	} else {
		scoor.w = x;
		scoor.h = x * .75;
	}

	InvalidateRect(hwnd, 0, 1);
}

void mandelbrot_paint(void *hwnd) {
	PAINTSTRUCT ps;
	int l, t, r, b;
	RECT rect = { 0, 0, MANDELBROT_VW, MANDELBROT_VH, };
	void *himg, *hmdc, *hwdc = BeginPaint(hwnd, &ps);

	hmdc = CreateCompatibleDC(0);
	himg = SelectObject(hmdc, CreateCompatibleBitmap(hwdc, MANDELBROT_VW, MANDELBROT_VH));

	FillRect(hmdc, &rect, GetSysColorBrush(COLOR_3DFACE));

	mandelbrot_draw_image(hmdc);

	if (scoor.move) {
		l = (int)(scoor.x - scoor.w);
		t = (int)(scoor.y - scoor.h);
		r = (int)(scoor.x + scoor.w);
		b = (int)(scoor.y + scoor.h);

		SetROP2(hmdc, R2_NOT);

		MoveToEx(hmdc, l, t, 0);

		LineTo(hmdc, r, t);
		LineTo(hmdc, r, b);
		LineTo(hmdc, l, b);
		LineTo(hmdc, l, t);
	}

	BitBlt(hwdc, 0, 0, rect.right, rect.bottom, hmdc, 0, 0, SRCCOPY);

	DeleteObject(SelectObject(hmdc, himg));

	DeleteDC(hmdc);

	EndPaint(hwnd, &ps);
}

int __stdcall mandelbrot_proc(void *hwnd, unsigned int umsg, unsigned int wprm, long lprm) {
	switch (umsg) {
		case WM_ACTIVATE: mandelbrot_activate(hwnd, wprm); break;

		case WM_ERASEBKGND: break;

		case WM_INITDIALOG: mandelbrot_initdialog(hwnd); break;

		case WM_LBUTTONDOWN: mandelbrot_lbuttondown(hwnd, (short)lprm, lprm >> 16); break;

		case WM_LBUTTONUP: mandelbrot_lbuttonup(hwnd, (short)lprm, lprm >> 16); break;

		case WM_MOUSEMOVE: mandelbrot_mousemove(hwnd, wprm, (short)lprm, lprm >> 16); break;

		case WM_PAINT: mandelbrot_paint(hwnd); break;

		case WM_RBUTTONUP: mandelbrot_rbuttonup(hwnd); break;

		case WM_SYSCOMMAND: if (SC_CLOSE == wprm) EndDialog(hwnd, 0); // break;

		default: return 0;
	}

	return 1;
}

void mandelbrot() {
	ExitProcess(DialogBoxIndirectParam(GetModuleHandle(0), (void*)templ, 0, mandelbrot_proc, 0));
}



你可能感兴趣的:(c,Mandelbrot)