グラフィックを用いた関数のグラフ表示 1.目的 関数のグラフを画面上に描くプログラムを通して、グラフィック処理の基礎を学ぶ。また、座標 系の変換や2次元空間における方程式の扱いについて実習する。 2.概要 パソコン等で普及している言語BASIC(Beginner’s All purpose Symbolic Instruction Code) 等では簡単にグラフィックを扱うことができる。しかし、大規模なプログラムを作るための機能 に乏しいという欠点がある。一方で、標準的なC言語ではグラフィックを扱う機能が定められて いないという問題がある。 この実験では、VC++のGDI(Graphics Device Interface)を使用し、比較的簡単な方法で 描画をする実習を行う。 3.プログラミング環境 ここでは以下の手順でVC++を立ち上げ、ユーザーは描画に関する記述を追加しプログラムを 完成させるものとする。 ⅰ.VC++を起動する。 ⅱ.「ファイル」−「新規作成」を選択。 ⅲ.「プロジェクト」−「MFC AppWizard(exe)」を選択。 ⅳ.プロジェクト名、位置を入力後「OK」を選択。 ⅴ.ステップ1にて、アプリケーションの種類で「SDI」を選択。 ⅵ.「終了」を選択。プロジェクト情報も「OK」を選択。 ここまでの手順によりプログラムを実行すると描画を行うキャンバスが用意される。 (実際に実行 してみてよい。) ここまでの手順はプログラムを実行すると所定の位置に、所定のサイズでウィンドウを表示する という動作を自動でコンピュータがプログラミングした事に相当する。今回は最も簡単な方法を 示したが、ⅵにて「終了」でなく「次へ」を選択する事により、各自の細かい設定を行える。 後は自動で作成されたプログラムの中の OnDraw 関数内にどのようなグラフィックを行いたい かをプログラムすればよい。OnDraw 関数はウィンドウが表示される際に実行される関数である。 OnDraw 関数はワークスペースウィンドウ(画面左側)から ClassView タグ内の xxx クラス、 Cmy xxx View、OnDraw と辿ることができる。 (xxx はプロジェクト名) 1 4.グラフィック関数 リスト1に、簡単なグラフィックプログラムの例を示す。 CPen myPEN( PS_SOLID, 1, RGB( 255, 255, 0 ) ); CPen* oldPEN = pDC -> SelectObject( &myPEN ); pDC -> SetTextColor( RGB( 0, 0, 255 ) ); pDC -> TextOut( 10, 10, "graphic star" ); pDC -> MoveTo( 320, 50 ); pDC -> LineTo( 160, 350 ); pDC -> LineTo( 540, 130 ); pDC -> LineTo( 100, 130 ); pDC -> LineTo( 480, 350 ); pDC -> LineTo( 320, 50 ); pDC -> SelectObject( oldPEN ); リスト1 リスト1で使用した基本的な命令の意味を以下にまとめる。 ☆ CPen myPEN( style, width, RGB( Red, Green, Blue ) ) ペンを定義し名前を myPEN とする。 Style:ペンの種類 ★ PS_SOLID:実線 ★ PS_DASH:破線 ★ PS_DOT:点線 など。 Width:ペンの幅(1∼3) RGB:ペンの色 ★ 色の指定には RGB マクロを使う。Red, Green,Blue をそれぞれ0∼255の強さで 指定する。 例)RGB( 0, 0, 0 ):黒 RGB( 255, 0, 0 ) :赤 RGB( 0, 255, 0 ) :緑 RGB( 255, 0, 255 ):紫 RGB( 255, 255, 255 ):白 ☆ pDC -> SelectObject( &myPEN ) 定義したどのペンを使用するかを設定する。 ☆ pDC -> SetTextColor( RGB( Red, Green, Blue ) ) 表示する文字の色を設定する。 ☆ pDC -> TextOut( x, y, "string" ) 座標(x,y)に string を表示する。 2 pDC -> MoveTo( x, y ) ☆ カーソルの位置を(x,y)に移す。 pDC -> LineTo( x, y ) ☆ (x,y)まで直線を描く。 5.関数のグラフ表示 グラフィック座標では、画面の左上の座標を( 0, 0 )として、x 軸を水平右方向、y 軸を垂直下方向 をそれぞれ正の方向とした座標系となっている。 この点に注意し、例としてxの値域が[‐1≦x≦1]、yの値域が [‐1≦x≦1]のグラフを表示する考え方を示す。 YF O XG O XF YG 図1 グラフィック座標の値域 グラフィック描画のイメージ 関数の値域 XG : [0≦XG≦640] XF : [‐1≦XF≦1] YG : [0≦YG≦450] YF : [‐1≦YF≦1] 注:グラフィック座標の描画範囲は特に固定されていないが、以下のプログラム例では上の範囲 内での描画で考えていく事とする。 グラフの表示は描きたい関数をグラフィック座標の上に投影するイメージとなる。しかし、この ように 2 つの座標系を比較すると、両座標系での軸の取り方および取りうる値域の幅に相違が生 じている。 このため、関数の座標( XF, YF )をグラフィック座標( XG, YG )に変換するには、 XG = XH + XF × XM YG = YH + YF × YM ( XM, YM ) の計算が必要となる。ここで( XH, YH )はグラフィック座標系における原点設定座標、 は x 方向、y方向それぞれの描画倍率とする。倍率については両関数の値域の倍率を指定すれば ほぼグラフィック領域いっぱいに表示される。 3 6.直交座標形の関数表示 平面上の点の位置を座標軸によって位置付けする座標形を直交座標と呼ぶ。2次元平面において はx軸、y軸を基本軸とする。 例題1 リスト2のプログラムを入力し、その動作を確認する。 例題2 プログラムのxの値域を[‐1≦x≦1]に変更し結果を画面いっぱいに表示するように変更する。 例題 3 関数y=sinxのグラフをxの値域を[‐π≦x≦π]の範囲で表示するように変更する。 注1:数学関数を使用する際はファイル math.h をインクルードする必要がある。プログラムの 先頭にて宣言すること。 注2:sin 関数、cos 関数は引数としてラジアンの単位(弧度法)を使用するため度の単位(度数 法)で計算しても正しい結果は得られません。そのときは変換をすること。 int x, y; double xr, yr; int XHOME = 320, YHOME = 300; double XMAG = 50.0, YMAG = −50.0; CPen blackpen( PS_SOLID, 1, RGB( 0, 0, 0 ) ); CPen redpen( PS_SOLID, 1, RGB( 255, 0, 0 ) ); CPen* oldpen = pDC -> SelectObject( &blackpen ); pDC -> MoveTo( 0, YHOME ); pDC -> LineTo( 639, YHOME ); pDC -> MoveTo( XHOME, 0 ); pDC -> LineTo( XHOME, 449 ); pDC -> SelectObject( &redpen ); xr = -2.0; yr = xr * xr; x = XHOME + ( int )( XMAG * xr ); y = YHOME + ( int )( YMAG * yr ); pDC -> MoveTo( x, y ); while( xr <= 2.0 ) { yr = xr * xr; x = XHOME + ( int )( XMAG * xr ); 4 y = YHOME + ( int )( YMAG * yr ); pDC -> LineTo( x, y ); xr = xr + 0.02; } pDC -> SelectObject( oldpen ); リスト2 7.極座標形の関数表示 平面上の点の位置を直交座標でなく、原点( 0, 0 )からの距離rと、x軸との角度θで表現する座 標形を極座標と呼ぶ。 極座標と直交座標とは図のような関係にあるので極座標( r, θ )を直交座標 ( x, y )に変換するには x=rcosθ y=rsinθ の計算が必要となる。 (x,y) (r,θ) y r O θ x 図 2 直交座標と極座標 極座標形で関数が示された場合は上記の変換式を使用して、まず直交座標形に変換する。後は変 換された座標に対して直交座標形の表示方法にそって描けばよい。 例題4 リスト3の半径1の円を描くプログラムの空白を埋め、その動作を確認する。 int x, y; double xr, yr, r, theta; int XHOME = 320, YHOME = 300; 5 double XMAG = 50.0, YMAG = −50.0; CPen blackpen( PS_SOLID, 1, RGB( 0, 0, 0 ) ); CPen redpen( PS_SOLID, 1, RGB( 255, 0, 0 ) ); CPen* oldpen = pDC -> SelectObject( &blackpen ); pDC -> MoveTo( 0, YHOME ); pDC -> LineTo( 639, YHOME ); pDC -> MoveTo( XHOME, 0 ); pDC -> LineTo( XHOME, 449 ); pDC -> SelectObject( &redpen ); r = 1.0; theta = 0.0 * 3.14 / 180; xr = ; yr = ; x = XHOME + ( int )( XMAG * xr ); y = YHOME + ( int )( YMAG * yr ); pDC -> MoveTo( x, y ); while(theta <= ){ xr = ; yr = ; x = XHOME + ( int )( XMAG * xr ); y = YHOME + ( int )( YMAG * yr ); pDC -> LineTo( x, y ); theta = theta + 5.0 * 3.14 / 180; } pDC -> SelectObject( oldpen ); リスト3 6
© Copyright 2024 ExpyDoc