2006.8.3.
石立 喬
Visual C++ 2005 Express Edition の易しい使い方(6)
――― Graphicsのペン(Pen^)を用いてフォーム上にグラフを描く
―――
ここでは、フォーム上にグラフを描く方法を紹介する。いままで、パソコンを用いて計算をし、計算結果をフォーム上に出力する方法を述べてきたが、やはり、結果をグラフで画面に表示しないと実感が湧かない。すでに紹介した「易しい使い方」で説明した部分は省略されている場合があるので注意して欲しい。
概要
電気技術者にとって興味のあるのは、各種の波形を画面上に表示することである。電気技術者が波形と言えば交流(正弦波)を思い浮かべるが、単なる交流波形では面白くないので、振幅変調波形、周波数変調波形を表示してみることにした。これにより変調の仕組みが理解でき、色々なパラメータを変化させて、どう変わるかを確認することができる。
変調に使用する波形の式
搬送波(被変調波) vC=AC sin(ωC t)
信号波(変調波) vS=AS sin(ωS t)
振幅変調波 vAM=(1+MAM vS) vC=AC(1+MAM AS sin(ωS t) )sin(ωC t)
周波数変調波 vFM=AC sin(ωC(1+MFM AS sin(ωS t)) t)
ただし、AC は搬送波の振幅、AS は信号波の振幅、ωC は搬送波の角周波数、ωS は信号波の角周波数、MAM は振幅変調の変調度、MFM は周波数変調の変調度である。
Graphicsの使い方
1)グラフィックスオブジェクトの取得
フォームに文字列を出力する方法は、「易しい使い方(2)」ですでに述べており、文字列は、Graphics機能を用い、g->DrawString()
で表示していた。
Form1_Paint() が自動的に呼び出されると、System::Windows::Forms::PaintEventArgs^
eが引き渡されるので、これを利用し、Javaスタイルに揃えるため、
Graphics^ g=e->Graphics;
としてグラフィックスオブジェクトgを生成しておく。
2)塗りつぶしで、グラフの背景を描く
矩形範囲の塗りつぶしには、
g->FillRectangle(Pens::Black,x,y,width,height);
を使用する。塗りつぶす色は、Pens::Black などで指定する。
3)線を引いてグラフを描く
線の開始点では、従来のpDC->SetPixelやpDC->MoveToの代わりに、
g->DrawLine(pen1,x,y,x,y);
を用い、
二回目からは、従来のpDC->LineToの代わりに、
g->DrawLine(pen1,old_x,old_y,x,y);
を用いる。
ここで、pen1は、
Pen^ pen1=gcnew Pen(Color::Red);
Pen^ pen1=gcnew Pen(Color::Blue,2);
などで生成する。上の例で、2は線の太さである。省略した場合には、太さが1になる。なお、これらのペンは、使用後に破棄手続きをする必要が無い。
フォームの設定
1)表示画面のタイトルバーにキャプションを入れる
「フォームデザイナー」上の「Form1」の中央部で右クリックし、「プロパティ」を選択して、「表示」欄の「Text」の右を、「Form1」から「振幅変調と周波数変調」に書き換えて、
「Enter」をクリックする。
2)プログラム実行時に開くウインドウのサイズを決める
同様に、「プロパティ」の「Size」欄の「300,300」を「528,445」に書き換える。これは、グラフのサイズや配置を決めて実際に実行させてみて、最終的に設定すると良い。
3)フォームの背景色を白にする
同様に、「プロパティ」の「BackColor」欄を「Window」に設定する。
プログラムの構成
プログラムは、Form1_Paint()メソッドに記述する。このメソッドは、Formが画面上に現れる度に呼び出される。
主な内容は以下の通りである。
1) 4種類のグラフを表示するために、4個の黒い背景(矩形)と、その中心に4本の明るいグレイの基準線を引く。
2) 時間を t=0 から t=499 まで変化させ、搬送波、変調信号などをグラフで描画する。
3) 各グラフの右下に、説明の文字列を表示する。
プログラムを実行するためには、ヘッダファイルstdafx.hに、
#define _USE_MATH_DEFINES
#include <math.h>
を記述しておく必要である。 前者は、π定数
M_PI を使用するために、後者は sin などの三角関数を使用するためである。
プログラムの実際(Form1.hのForm1_Paint()の内容)
private: System::Void Form1_Paint(System::Object^
sender,
System::Windows::Forms::PaintEventArgs^
e) {
Graphics^ g=e->Graphics;
int X0=10;
int Y0=55,Y1=155,Y2=255,Y3=355;
double AMP_C=20.0; //搬送波(被変調波)振幅
double FREQ_C=1/12.5; //搬送波周波数(時間500に40サイクル)
double OMEGA_C=2*M_PI*FREQ_C; //搬送波角周波数
double AMP_S=1.0; //信号波(変調波)振幅
double FREQ_S=1/250.0; //信号波周波数(時間500に2サイクル)
double OMEGA_S=2*M_PI*FREQ_S; //信号波角周波数
double MOD_A=0.5; //振幅変調変調度
double MOD_F=0.025; //周波数変調変調度
double out;
int y,old_y;
System::Drawing::Font^ font1=gcnew System::Drawing::Font("MSゴシック",10);
for(int i=0;i<4;i++){
//黒で背景を描く
g->FillRectangle(Brushes::Black,Rectangle(X0,Y0-45+100*i,500,90));
//明るいグレイで横線を描く
g->DrawLine(Pens::LightGray,X0,Y0+100*i,X0+500,Y0+100*i);
}
//搬送波
for(int t=0;t<500;t++){
out=AMP_C*sin(OMEGA_C*t);
y=Y0-(int)out;
if(t==0)
g->DrawLine(Pens::LightGreen,X0+t,y,X0+t,y);
else
g->DrawLine(Pens::LightGreen,X0+(t-1),old_y,X0+t,y);
old_y=y;
}
g->DrawString("搬送波(被変調波)",font1,Brushes::White,380,Y0+27);
//変調信号
for(int t=0;t<500;t++){
out=20.0*AMP_S*sin(OMEGA_S*t);
//表示のために20倍に拡大
y=Y1-(int)out;
if(t==0)
g->DrawLine(Pens::LightGreen,X0+t,y,X0+t,y);
else
g->DrawLine(Pens::LightGreen,X0+(t-1),old_y,X0+t,y);
old_y=y;
}
g->DrawString("信号波(変調波)",font1,Brushes::White,380,Y1+27);
//振幅変調
for(int t=0;t<500;t++){
out=AMP_C*(1+MOD_A*AMP_S*sin(OMEGA_S*t))*sin(OMEGA_C*t);
y=Y2-(int)out;
if(t==0)
g->DrawLine(Pens::Blue,X0+t,y,X0+t,y);
else
g->DrawLine(Pens::Blue,X0+(t-1),old_y,X0+t,y);
old_y=y;
}
g->DrawString("振幅変調波",font1,Brushes::White,380,Y2+27);
//周波数変調
for(int t=0;t<500;t++){
out=AMP_C*sin(OMEGA_C*(1+MOD_F*AMP_S*sin(OMEGA_S*t))*t);
y=Y3-(int)out;
if(t==0)
g->DrawLine(Pens::Red,X0+t,y,X0+t,y);
else
g->DrawLine(Pens::Red,X0+(t-1),old_y,X0+t,y);
old_y=y;
}
g->DrawString("周波数変調波",font1,Brushes::White,380,Y3+27);
}
得られた画面
