發表文章

Matlab:控制座標軸上顯示的數值標示

clc; % 控制要顯示的數值 xlblarr = [0:10:200]; ylblarr = [1:4:100]; % 產生新的繪圖視窗, 用handle設定繪圖視窗的一些屬性 handle = figure(); axes('Parent',handle,... 'XTick', xlblarr,... % 要標示 x 軸label的位置 'XTickLabel', int2str(xlblarr'),... % 位置所對應的 x 軸label文字 'YTick', ylblarr,... % 要標示 y 軸label的位置 'YTickLabel', int2str(ylblarr')); % 位置所對應的 y 軸label文字 box('on'); % 自動繪製圖形邊線 hold('all'); % 之後的plot指令都使用同一個視窗 % 資料點 x = [1:2:200]; y = [1:1:100]; plot(x, y); % 控制要顯示的位置 axis([-10 210 -5 100]);

C/C++:不可更動內容的常數字串

不可更動內容的常數字串,經使用Dev-C++實驗後得到結果, D才是內容不可更動,而且指標也不可更動的字串常數,在編譯時就會出現Compile Error。 A則是不能更動內容,在改變A指標時會出現Compile Error,但是使用[]編譯器並不會出現錯誤,而是執行是才產生錯誤。 B與C的宣告,在這實驗中只是具有相同效用,僅順序擺放不同。 #include using namespace std; int main() { char* x = "000"; char* const a = "121"; const char * b = "122"; char const* c = "123"; const char* const d = "123"; // pointer modify // a = x; // assignment of read-only variable b = x; c = x; // d = x; // assignment of read-only variable // a[2] = 'W'; // runtime-error, access violation // b[2] = 'X'; // assignment of read-only location // c[2] = 'Y'; // assignment of read-only location // d[2] = 'Z'; // assignment of read-only location cout<<a<<endl <<b<<endl <<c<<endl <<d<<endl <<x<<endl; system(...

BCB筆記:TStringGrid 移動捲軸時即時顯示內容

圖片
BCB預設使用TStringGrid移動捲軸時,並不會即時顯示資料表的內容,這樣在"view"資料的時候不太方便,不能直接找某個特定值。 將TStringGrid物件的Option展開(見圖),將getThumbTracking設定為true即可將即時顯示開啟。不過若你要顯示的資料十分龐大,還是不建議將設定開啟,可能在使用程式上會不太順。

BCB筆記:將檔案拖曳到程式中開啟

拖曳檔案到程式中開啟,需要系統配合,而BCB沒有提供一個簡單的方法達成,因此就需要寫用win32api的功能,使BCB的程式也能將拖曳的檔案開啟。 1. 將下面這一段程式碼加主程式的 .H 檔的public函數/成員的最後面(放在最後面是方便管理),還有就是這段程式碼沒有寫錯,END_MESSAGE_MAP (TForm)的TFrom也不需要更改! void __fastcall WmDropFiles(TWMDropFiles& Message); BEGIN_MESSAGE_MAP MESSAGE_HANDLER(WM_DROPFILES, TWMDropFiles, WmDropFiles) END_MESSAGE_MAP (TForm) 2. 接著切換到.CPP中,點擊點主視窗,並設定主視窗的Events的FormCreate,將下面的程式碼加入FromCreate中。 DragAcceptFiles(Handle, true); 3. 最後是寫開啟檔案的WmDropFiles函數內容。 void __fastcall TMainForm::WmDropFiles(TWMDropFiles& Message) { char buff[MAX_PATH]; HDROP hDrop = (HDROP)Message.Drop; int numFiles = DragQueryFile(hDrop, -1, NULL, NULL); if (numFiles >= 1) { for (int i=0 ; i<numFiles ; ++i) { DragQueryFile(hDrop, i, buff, sizeof(buff)); // 在這裡寫下開啟檔案的程式碼, buff就是檔案路徑的字串。 } } DragFinish(hDrop); }

BCB紀錄:Winapi 的 MessageBox

這程式碼我都已經弄成介面的基礎建設,放置在主程式的class中,這一切都是ShowMessage不夠Thread-Friendly的關係。 inline void TMainForm::ShowMessage(const AnsiString& msg, const AnsiString& cap) { ::MessageBox(this->Handle, msg.c_str(), cap.c_str(), MB_OK|MB_ICONINFORMATION); } inline void TMainForm::ErrorMessage(const AnsiString& msg, const AnsiString& cap) { ::MessageBox(this->Handle, msg.c_str(), cap.c_str(), MB_OK|MB_ICONERROR); } inline void TMainForm::WarnMessage(const AnsiString& msg, const AnsiString& cap) { ::MessageBox(this->Handle, msg.c_str(), cap.c_str(), MB_OK|MB_ICONWARNING); } inline bool TMainForm::ConfirmBox(const AnsiString& msg, const AnsiString& cap) { return (IDYES==::MessageBox(this->Handle, msg.c_str(), cap.c_str(), MB_YESNO|MB_ICONQUESTION)); } 2009-06-05 附註: 若是要給不同class與檔案間都只共用這一組Method,建議去除掉這些Method的inline修飾詞,因為有些時候inline會被compiler展開,所以造成Linker找不到我們宣告的這些Method,在編譯時造成困擾!

BCB同步捲軸

在影像處理的程式中,我時常會為了作兩種效果的比較,理所當然的將程式介面弄成左右兩個影像,雖然在處理小影像時,擺放足夠顯示的Image就足夠了,但是當要觀察的圖片太大時,便需要用ScrollBox來顯示大於規劃範圍的影像,然而轉動左邊或是右邊的ScrollBox,另一邊的影像卻不會動作,這對於觀察處理的效果實在是很不便利,因此我就需要加入同步捲軸。 一開始,我在程式介面中了擺置了兩個TScrollBox,分別為ScrollBox1與ScrollBox2。而我要這兩個ScrollBox能夠同步移動捲軸,就分別點這兩個物件的Events裡面的 CanResize ,並貼上下面的的程式碼。 TScrollBox* S = dynamic_cast<TScrollBox*>(Sender); // 轉型, 避免產生Exception if (S!=NULL) { int H = S->HorzScrollBar->Position; int V = S->VertScrollBar->Position; if (H != ScrollBox1->HorzScrollBar->Position) ScrollBox1->HorzScrollBar->Position = H; if (V != ScrollBox1->VertScrollBar->Position) ScrollBox1->VertScrollBar->Position = V; if (H != ScrollBox2->HorzScrollBar->Position) ScrollBox2->HorzScrollBar->Position = H; if (V != ScrollBox2->VertScrollBar->Position) ScrollBox2->VertScrollBar->Position = V; } 設定完後,只要任一個ScrollBox捲動時觸發CanResize,就會使上面的程式碼去取得使用者捲動後的ScrollBox水平與垂直軸位置,將這個位置資訊設定給還不是這個位置...

BCB筆記:開關按鈕(三態按鈕/狀態按鈕)

內建在Additional中的TSpeedButton(SpeedButton),可以很簡單改變設定成開關按鈕。 只要將布局好的SpeedButton的GroupIndex屬性設定成大於0的數值,就成為了一個開關按鈕, 不過若只這麼設定,你會發現按鈕只能按下去,無法再彈起來,這是因為它原先是設計成RadioButton的形式,屬性AllowAllUp被設定為false,因此無法彈起按鈕,只要改為true,就是真正的開關按鈕,而其Down方法,則可以取得目前按鈕的開關狀態。

迭代存取的謬誤

昨天寫的兩段愚蠢的Code,可以掉入兩個這樣的陷阱,刀也該拿去再磨磨了。 第一個 #include <vector> using namespace std; int main() { vector<int> v; // .... 寫了某些code 有可能有資料存到v裡頭 .... for (unsigned int i=v.size()-1 ; i>=0 ; --i) v.pop_back(); return 0; } 第二個 #include <list> using namespace std; int main() { list<int> l; for (int i=0 ; i<10 ; ++i) l.push_back(i); // 移除裡面的元素 for (int i=0 ; i<l.size() ; ++i) l.remove(i); return 0; } 第一個程式執行結果理應是無限迴圈,肇因於我在宣告i時使用了unsigned int作為資料型態,而我使用遞減進行for迴圈的迭代,使用unsigned僅僅是想減少warning的出現,沒想到這卻也是敗筆。由於unsinged int 沒有負數,因此當數值為0後,再進行減1的動作會變成最大值(反之,最大值再加1會成為0),因此這個迴圈的條件恆成立。若你認為只有for的條件判斷有問題需要修改,那你就錯了!在for的初始化部份也存在問題,當v.size()為0時,i的起始就因減1而成為最大值,也會造成程式的執行不正確,就算只改了判斷式,程式依然有可能進行錯誤的迭代。 第二個程式則是還沒移除所有的元素就會結束。因為l.size()是即時反應這個list中的元素個數,而我們使用l.remove()後會使l.size()減少,但是i依然會增加,導致我們只會移除list內一半數量。比較好的方法應該改為用while迴圈,並以l.empty()當作條件來判斷是否要結束;不過,若是常常使用vector.size()作為迴圈條件,就會覺得這個迴圈很直覺的是對的,難以察覺臭蟲的存在。

程式筆記: atan2 的角度值

圖片
我們可以寫一個簡單的程式,產生atan2的所取得的角度概略分佈。由於我目前所使用的是工具有Dev-C++4.9.9.0、BCB 6.0與Matlab 7.5,怕每個做的都不相同,所以我都得進行測試。 Matlab Matlab結果如圖上的第一個矩陣,得到的是有正角度與負角度的矩陣。由於概念上用0~360來表示較度會比較好懂,因此就將atan2所得到的負角度+360得到0~360尖的角度值,如圖方矩陣。 於Matlab用的程式碼 x=repmat([-2:2], [5,1]); y=repmat([2:-1:-2]',[1,5]); angle=atan2(y,x)/(2*pi)*360 neg=find(angle Borland C++ Builder與Dev C++ 基本上這兩個工具得到的結果都是相同的,但是BCB就是不一樣(汗) 用Dev C++獲得的結果就如同Matlab,只是有負的角度,需將小於零的角度+360。 但是,BCB就是不太一樣,中間數值為(0,0)的時候,BCB會跳出DOMAIN Error的例外,而最後產生出來的數值則是NaN,也就是不將atan2(0,0)視為0,這也就得讓我去作額外的判斷工作,實在麻煩。

Java小程式:貝茲曲線

這支程式是利用4點繪製一條貝茲曲線。 參考的程式碼在 這裡 ,我主要是將成是改寫成Java Application並加上一點點註解。 程式碼 import java.awt.BasicStroke; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Point; import java.awt.RenderingHints; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionListener; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; public class BzWindow extends JFrame implements ActionListener { /** * Eclipse 自動產生的數值,請無視。 */ private static final long serialVersionUID = -9060807186493274426L; // 資料結構 private Point[] coordlist; // 控制點 private int numpoints; // 控制點數目 // 貝茲曲線參數 double t; // the time interval double k = .025; // time step value for drawing curve int moveflag = 5; // flag to notify if user is moving a point boolean poly = true; // 是否要繪製控制點(沒畫還是可以移動控制點) JButton...