以上影片說的是碎形幾何,若覺得手癢也想試試,以下的程式可幫上一點忙。
程式使用到 CxxlMan2 程式庫,可到 http://blog.cxxl3d.tk/2015/10/cxxlman2-class-lib.html 下載,不過只用到 cxxlcommon\include 內的引入檔,所以不用編譯這個程式庫,只要把 THREADMGR.HPP 所在的完整路徑加到 include path 就可以了。
程式在 Win10 用 vs2015 和 MinGW 6.3 編譯跑過沒有問題,程式只是一個架構,把程式碼整個複製貼上就能用了。
#include <windows.h>
#include <THREADMGR.HPP>
using namespace CxxlMan2;
HWND g_hwnd;
bool isQuit = false;
HDC g_memDC; // 輔助繪圖設備
RECT g_rcClient;//區域結構
const TCHAR *g_szClassName = TEXT("myWindowClass");
// 主要的功能宣告,邏輯運算放這裡,自由發揮
void Fractal(float X, float Y, ThreadLimit &Fractal_TL);
// Fractal() 算出來的結果交由這函數畫到畫布上
// 畫布左上是 (0.0, 0.0) 右下是 (1.0, 1.0)
void Show(float X, float Y)
{
SetPixel(g_memDC, g_rcClient.right * X, g_rcClient.bottom * Y,
RGB(255, 0, 0));
InvalidateRect(g_hwnd, nullptr, false);
}
void Draw()
{
HDC hDC = GetDC(g_hwnd); //獲得系統繪圖設備
g_memDC = CreateCompatibleDC(0); //創建輔助繪圖設備
GetClientRect(g_hwnd, &g_rcClient);//獲得 client 區域
//創建掩碼位圖(畫布)
HBITMAP bmpBack = CreateCompatibleBitmap(hDC,
g_rcClient.right - g_rcClient.left,
g_rcClient.bottom - g_rcClient.top);
SelectObject(g_memDC, bmpBack); //將畫布貼到繪圖設備上
//擦除背景
//獲得庫存物體,白色畫刷。
HBRUSH brushTemp = (HBRUSH)GetStockObject(WHITE_BRUSH);
FillRect(g_memDC, &g_rcClient, brushTemp);//填充客戶區域。
// 加上區塊可以等待 Fractal_TL 結束才繼續
{
ThreadLimit Fractal_TL(std::thread::hardware_concurrency());
Fractal_TL.Thread(Fractal, 0.5, 0.5, std::ref(Fractal_TL));
}
DeleteObject(bmpBack); //釋放位圖資源
DeleteDC(g_memDC); //釋放輔助繪圖設備
ReleaseDC(g_hwnd, hDC); //歸還繫統繪圖設備
PostMessage(g_hwnd, WM_DESTROY, 0, 0);
}
// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_KEYDOWN:
if (wParam == 0x51) // Q key
isQuit = true;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
if (g_memDC)
//複製到系統設備上顯示..
BitBlt(hdc, g_rcClient.left, g_rcClient.top,
g_rcClient.right, g_rcClient.bottom,
g_memDC, 0, 0, SRCCOPY);
EndPaint(hwnd, &ps);
}
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
MSG Msg;
//Step 1: Registering the Window Class
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = g_szClassName;
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if (!RegisterClassEx(&wc))
{
MessageBox(NULL, TEXT("Window Registration Failed!"), TEXT("Error!"),
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
// Step 2: Creating the Window
g_hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
g_szClassName,
TEXT("碎形測試"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 300, 300,
NULL, NULL, hInstance, NULL);
if (g_hwnd == NULL)
{
MessageBox(NULL, TEXT("Window Creation Failed!"), TEXT("Error!"),
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(g_hwnd, nCmdShow);
UpdateWindow(g_hwnd);
ThreadLimit TL(1);
TL.Thread(Draw);
// Step 3: The Message Loop
while (GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}
// 以下是實作的程式碼,可依自己的想法做修改
float Ax = 0.5, Ay = 0.1,
Bx = 0.1, By = 0.9,
Cx = 0.9, Cy = 0.9;
void Fractal(float X, float Y, ThreadLimit &Fractal_TL)
{
if (isQuit == false)
{
Show(X, Y);
Fractal_TL.Thread(Fractal, X + (Ax - X) / 2, Y + (Ay - Y) / 2,
std::ref(Fractal_TL));
Fractal_TL.Thread(Fractal, X + (Bx - X) / 2, Y + (By - Y) / 2,
std::ref(Fractal_TL));
Fractal_TL.Thread(Fractal, X + (Cx - X) / 2, Y + (Cy - Y) / 2,
std::ref(Fractal_TL));
}
else
Fractal_TL.Clear();
}
執行時可按 Q 鍵結束程式,因程式使用 ThreadLimit 作為任務的處理工具,加上程式的任務沒有止境,若不按 Q 鍵結束程式也會因記憶體資源用完而自行結束程式。其中 Fractal() 可以依自己的想法自己做修改,其他的部份沒必要就不用去動它,注意程式的畫布定義左上為 (0.0, 0.0) 右下為 (1.0, 1.0)。下圖是執行結果的截圖:
▲使用影片中講解的運算規則畫出的圖形
影片採用的是隨機的表現方法,而這程式採用量子演算法,意思是只要有可能就讓它發生,也就是走遍所有可能,也叫窮盡法或暴力法。影片採用隨機的表演方式是正確的,比較有衝擊性的戲劇效果,不然一板一眼的說明,可能沒人會繼續看下去。
沒有留言:
張貼留言