// ■充填ジュリア集合(Filled Julia set)の描画 // // CST: 計算開始実数部, CED: 計算終了実数部 // DST: 計算開始虚数部, DED: 計算終了虚数部 // SC: スケール, DT: 計算ステップ数 // XST, YST: 表示画面中央位置の画面XY座標 // (修練も発散も検出できなかった場所は黒で表示する) // // @右ボタンダブルクリックで配色タイプを変更します。 // A左ボタンダブルクリックで拡大します。 // B左ボタンドラッギングで上下または左右に動きます。 // (斜めには動きませんので、上下/左右の組み合わせで移動して下さい) // C右ボタンドラッギングで縮小します。 // #include "myWin.h" #include "stdio.h" #define swap(type, x,y) do{type t;t=x;x=y;y=t;}while(0) // LOOPを大きくすると絵が緻密になるが、速度が遅くなる。 #define LOOP 1024 #define LB_1 1 #define LB_2 2 #define ED_1 11 #define ED_2 12 #define BT_1 21 #define BT_2 22 static HWND edit1, edit2, btn1; // 初期値 double CST = -2, CED = 2, DST = -2; //A0, B0の範囲 double DED, DT, SC, XST, YST; //計算で求める int curX,curY; int exID[]={0x000077, 0x0000AA, 0x0000FF, 0x0077FF, 0x00FFFF, 0x77FFFF};//発散したときの色 int cnID[]={0x770000, 0xAA0000, 0xFF0000, 0xFF7700, 0xFFFF00, 0xFFFF77};//収斂したときの色 int cType=0; static HDC hbuf; static HBITMAP hBM; int Iter(double A0, double B0,double C, double D){// 複素数の繰り返し演算による発散回数の設定 double A=A0, B=B0, AA, BB, DA, DB; for(int i=1; i= 4) return (i%256); // 発散判定(発散したとき正の数) DA = A - AA; DB = B - BB; // 収斂判定(収斂したとき負の数) if((DA * DA + DB * DB) < 0.00001) return -(i %256); } return 0;// 収斂も発散もしないとき振動状態 } void initBitMap(HWND hw){// ビットマップ作成とメモリデバイスコンテキスト作成 HDC hdc=GetDC(hw); hBM=CreateCompatibleBitmap(hdc,1000,1000); hbuf=CreateCompatibleDC(hdc);SelectObject(hbuf,hBM); SelectObject(hbuf,GetStockObject(NULL_PEN)); PatBlt(hbuf,0,0,1000,1000,WHITENESS); ReleaseDC(hw, hdc); } int setColor(int ID){ if(ID==0)return 0; else if(ID<0){ ID=-ID; if(ID<64)return RGB(0,ID*4, 0); if(ID<128)return RGB(ID*4-256, 255, 0); if(ID<192)return RGB(255,767-ID*4, 0); return RGB(255,ID*4-768,0); } if(ID<64)return RGB(0,ID*4, 255); if(ID<128)return RGB(ID*4-256, 255,255); if(ID<192)return RGB(255,767-ID*4, 255); return RGB(255,ID*4-768,255); } int setColor2(int ID){ if(LOOP>=4096)return abs(ID) % 4096 - 1; return abs(ID)*(4096/LOOP)-1; } double strToDbl(TCHAR str[]){ char strA[129];int i; for(i=0;i<128 && str[i]!=0;i++) strA[i]=(char)(str[i] & 0x00FF); strA[i] = 0; double X; sscanf(strA,"%lf",&X); return X; } void Julia(){ if(CST>CED) swap(double, CST,CED); double DR=CED-CST; SC = 400/DR;DED = DST + DR; DT = 1.0 / SC; XST=240-SC*(CST+CED)/2; YST=230+SC*(DST+DED)/2; TCHAR str[128];double C, D; GetWindowText(edit1,str,128); C=strToDbl(str); GetWindowText(edit2,str,128); D=strToDbl(str); for(double A0=CST ; A0<=CED; A0+=DT) for(double B0=DST;B0<=DED; B0+=DT){ int ID=Iter(A0,B0, C,D),CL; if(cType==0) CL=(ID==0)? 0:(ID>0 ? exID[ID % 6]: cnID[(-ID) % 6]); else if(cType==1) CL=setColor(ID%256); else CL=setColor2(ID); int XP = (int)(XST + A0 * SC+0.5), YP=(int)(YST - B0 * SC+0.5); SetPixel(hbuf,XP,YP,CL); } } HWND lbCreate(HWND hw, LPCTSTR str, int X, int Y, int W, int H, HMENU hm){ return CreateWindow(TEXT("STATIC"), str, WS_CHILD |WS_VISIBLE |SS_CENTER, X, Y, W, H, hw, hm, hInstance, NULL); } HWND edCreate(HWND hw, LPCTSTR str, int X, int Y, int W, int H, HMENU hm){ return CreateWindow(TEXT("EDIT"), str, WS_CHILD |WS_VISIBLE |WS_BORDER |ES_RIGHT, X, Y, W, H, hw, hm, hInstance, NULL); } HWND btCreate(HWND hw, LPCTSTR str, int X, int Y, int W, int H, HMENU hm){ return CreateWindow(TEXT("BUTTON"), str, WS_CHILD |WS_VISIBLE |WS_BORDER |BS_PUSHBUTTON|BS_CENTER, X, Y, W, H, hw, hm, hInstance, NULL); } void procCreate(HWND hw, WPARAM wp, LPARAM lp){ SetWindowText(hw,TEXT("充填ジュリア集合(Filled Julia set)")); MoveWindow(hw,0,0,500,500,true); lbCreate(hw,TEXT("C"), 0, 2, 20, 30, (HMENU)LB_1); lbCreate(hw,TEXT("D"), 120, 2, 10, 30, (HMENU)LB_1); edit1=edCreate(hw,TEXT("0.266"), 25, 2, 80, 20, (HMENU)ED_1); edit2=edCreate(hw,TEXT("0.0056"), 145, 2, 80,20, (HMENU)ED_2); btn1=btCreate(hw,TEXT("再実行"), 250, 2, 75,23, (HMENU)BT_1); btn1=btCreate(hw,TEXT("初期位置"), 330, 2, 75,23, (HMENU)BT_2); initBitMap(hw);Julia(); InvalidateRect(hw,NULL,FALSE); } void procLButtonDown(HWND hw, WPARAM wp, LPARAM lp){ curX=LOWORD(lp); curY=HIWORD(lp); } void procLButtonUp(HWND hw, WPARAM wp, LPARAM lp){ int x=LOWORD(lp), y=HIWORD(lp), XX=x-curX, YY=y-curY; if(abs(XX)<5 && abs(YY)<5) return; if(abs(XX)> abs(YY)) { double DC = (CED-CST); if(XX<0) CST+=DC*0.1; else CST-=DC*0.1; CED=CST+DC; } else{ double DD = (DED-DST); if(YY<0) DST-=DD*0.1; else DST+=DD*0.1; } Julia(); InvalidateRect(hw,NULL,FALSE); } void procLButtonDblClk(HWND hw, WPARAM wp, LPARAM lp){ int x=LOWORD(lp), y=HIWORD(lp); double c=(double)(x-XST)/SC, d=(double)(YST-y)/SC; CST=(c+CST*4)/5; CED=(c+CED*4)/5; DST=(d+DST*4)/5; Julia(); InvalidateRect(hw,NULL,FALSE); } void procRButtonDblClk(HWND hw, WPARAM wp, LPARAM lp){ cType=cType++;if(cType>2)cType=0; Julia(); InvalidateRect(hw,NULL,FALSE); } void procRButtonDown(HWND hw, WPARAM wp, LPARAM lp){ curX=LOWORD(lp); curY=HIWORD(lp); } void procRButtonUp(HWND hw, WPARAM wp, LPARAM lp){ int x=LOWORD(lp), y=HIWORD(lp), XX=x-curX, YY=y-curY; if(abs(XX)<5 && abs(YY)<5) return; double DC = (CED-CST); CST -= DC*0.1; CED += DC*0.1; DST -= DC*0.1; Julia(); InvalidateRect(hw,NULL,FALSE); } void procPaint(HWND hw, WPARAM wp, LPARAM lp){// ビットマップを画面に表示 PAINTSTRUCT ps; HDC hdc=BeginPaint(hw, &ps); BitBlt(hdc,0,0,1000,1000,hbuf,0,0,SRCCOPY); EndPaint(hw,&ps); } void procCommand(HWND hw, WPARAM wp, LPARAM lp){ switch(LOWORD(wp)){ case BT_1: Julia(); InvalidateRect(hw,NULL,FALSE); break; case BT_2: CST=-2;CED = 2;DST = -2;Julia(); InvalidateRect(hw,NULL,FALSE); break; } } LRESULT CALLBACK WndProc(HWND hw, UINT msg, WPARAM wp, LPARAM lp){ switch(msg){ case WM_DESTROY : PostQuitMessage(0) ; return 0; case WM_CREATE : procCreate(hw,wp,lp) ; return 0; case WM_PAINT : procPaint (hw, wp, lp) ; return 0; case WM_LBUTTONDOWN : procLButtonDown (hw, wp, lp) ; return 0; case WM_LBUTTONUP : procLButtonUp (hw, wp, lp) ; return 0; case WM_RBUTTONDOWN : procRButtonDown (hw, wp, lp) ; return 0; case WM_RBUTTONUP : procRButtonUp (hw, wp, lp) ; return 0; case WM_LBUTTONDBLCLK : procLButtonDblClk (hw, wp, lp); return 0; case WM_RBUTTONDBLCLK : procRButtonDblClk (hw, wp, lp); return 0; case WM_COMMAND : procCommand(hw,wp,lp); } return DefWindowProc(hw, msg, wp, lp); }