東京工芸大学 工学部  電子機械学科 2年 後期 

応用プログラミング 第5回
 2017.10.24
藤木 文彦


http://fujiki.tv/t-kougei/ouyouprog/

fujiki.kougei@gmail.com
 ■ 1   ■ 2   ■ 3   ■ 4  ■
  ■ 6   ■ 77   ■ 8   ■ 9   ■ 10   ■ 11  ■ 12    ■ 13   ■ 14   ■ 15   ■ 00   ■ 00   ■ 00

インデックスに戻る

 1.直線、曲線の描画。


 最初は、2次曲線を描くプログラムを作成します。

 少しずつ順を追って、形を整えていきます。

 まず、 Project501 を作成し、線を描く練習をします。

 2.出来上がりイメージ


 初めに今日の演習で作るプログラムの内容と、完成(間近の)イメージを掲げておきます。

  y=ax^2  のグラフを描きます。

 を y=x^2 と書きます。



 まず最初に下のような図面を書いてみましょう。
 まだそれらしく見えませんが、だんだん近づけていきます。




 3.画面の作成


 もう、1つ1つの配置を順を追って説明する必要はありませんね。
 とりあえず、次のような状態になるくらいまで自力で配置しましょう。

 ただし、後から、 x^2(xの2乗の意味)の前の部分に、あとから、数字入力BOXを入れますので、少し間をあけておいてください。(早まって、テキストボックスを入れないように。)

 「^」印は、キーボード右上の「BackSpace」の左の「¥」の左にあるはずです。

 日本語文字の 「あ」が出てしまいますが、「F9」で、「a」になるはずです。



 図を描く場所は、 PictureBox1 ですが、ここは、他の部分と区別しやすいように、背景色を変えましょう。
 BackgroundColor で、上の「Web」を選び、MistyRose を選びます(自分の気に入った色でも構いませんが、あまり濃い色にすると、これから描く線が見えにくくなります。)

 それから、あらかじめ、周りに枠を書いておいたほうがわかりやすいので、BorderStyle を FixedSingle にしておきます。

 4.決められた値の中から選択する
  NumericUpDown


次に、 y=ax^2
の、a の部分に数値を入力する枠を作ります。
 今までのように、textBox でもよいのですが、今回は、値の範囲を、0〜10までの整数に限る、ということにしたいので、次のような、あらかじめ入力する数値を決めておきます。

 ツールボックスから、
NumericUpDown を選んで下記の位置に挿入します。






挿入後、次のように、プロパティを設定します。

Minimun 0
Maximum 10
Value 1

としておきます。これは、数値の範囲を0〜10、までの整数に限定するもので、何もしなければ初期値に1を入れるようにします。

 下の例は、1,5,10を入力した例です。





 5.グラフを描画する



 上のような描画をするためのプログラムは、次のように記述します。

「描画」ボタンを押したときの処理に、次のように記述します。



private void button1_Click(object sender, EventArgs e)
{
Graphics g = this.pictureBox1.CreateGraphics();
int width = this.pictureBox1.Width - 1;
int height = this.pictureBox1.Height - 1;
int x0,y0,x1,y1;
int a = (int)numericUpDown1.Value;

Pen bluePen = new Pen(Color.Blue, 2);

for (int i = 0; i < 10; i++)
{

x0 = i * 50;
y0 = (i * i)*a;
x1 = (i + 1) * 50;
y1 = ((i + 1) * (i + 1))*a;

g.DrawLine(bluePen, x0, y0, x1, y1);
}
}


 6.y軸を逆転表示する方法
   height から y を引く


 ところで、上の図ですが、 xの2乗のグラフが下に向かっているのは見にくいでしょう。
 できれば、普通のグラフのように、上に向かっていたほうがわかりやすいですよね。
 下の図の赤線のように引けたほうがよいでしょう。



 そのためには、プログラムの一部を改造します。
 次のように、プログラムの一部に追加行を入れます。(どの行を入れたかは、自分で考えてください。)
 コンピュータ上では、y軸が下向きに+になっていますので、これを逆転させるために、枠の縦の大きさから、データを引いたものを、yの値としています。
 この方法は、グラフィックではよく使用される方法です。



 【演習問題1】 


 Project501 を作成し、完成した画面を印刷して提出しなさい。
 また、Project501.cs をメールに添付して送ってください。





 7.横の倍率を変えて、より2次曲線らしく描く


Project502
として、新規プロジェクトを始めます。

 上記の例を参考に、より2時曲線らしく描くために、横の倍率を選べるようにします。
 そのほか、いろいろな工夫をして、次のような表示が出るようにします。
 いくつも新しく付け加えるところや、プログラムの改変などもありますので、よく読んでから作成してください。




 プログラムは、次のような点が、追加、改変されています。

 ●xが1増えるたびに、右に何ドット進むかを設定する、x軸の倍率を、scale という変数とした。
 ●描画回数の上限を、10回ではなく、画面からはみ出すまでとするために、for文ではなく、 while 文を用い、x、yの両方が pictureBox 内にあるときに描画する。(どちらかがはみ出したら終了)
 このとき、回数のカウントを増やすための、 x++ を入れないと無限ループになり、終了しなくなるので注意。
 ●描画した線の端点がわかるように、赤の小さな丸を描くようにした。

 ●画面をクリアするボタンを追加し、その動作として、背景色でクリアするという処理をいれた。






プログラムミスがあると、終了できなくなります。
このような時は、次のように、
「デバッグの停止」を選ぶと止まるはずです。





Project502 は、まだ完成ではありません。次に続きます。

 8.上下を入れ替え、座標を表示する。


上の表示では、y軸の + の向きが下向きになっていますので、これを逆転させます。
さらに、座標がわかるように、座標を文字として、picturebox1 に表示させます。
表示は次のようになります。
 この画面ができたら、Project502 は、完成です。




プログラムは、上のプログラムを少し変えます。下記を参照してください。


 【演習問題2】 


 Project502 を作成し、完成した画面を印刷して提出しなさい。
 また、Project502.cs をメールに添付して送ってください。

 9.座標軸を真ん中に書く。

Project503 として、次の画面表示を出すプログラムを作成します。

このプログラムは、今までの知識を組み合わせて、少しだけ計算部分を作ることでできるはずですから、ヒントなしで自分で作ってみてください。

第3段階で一応完成ですが、座標の計算をどうするか、考え方がなかなか面倒なので、時間内でできるところまでやってみましょう。


【第1段階】




(参考:部分的に塗りつぶしてありますから、見えない部分は自分で考えてください。)



【第2段階】





【第3段階】




 【演習問題3】 


Project503 を自力で完成させなさい。


 10.sin cos 曲線の描画、位置の変更
    配列に与えられたデータを画面に表示する

Project504 として、Sin Cos のグラフの描画をします。

また、配列にあらかじめデータをいれ、それをプロットすることもしてみます。
以下の画面で、赤い点はこの配列データをかいたものです。

以下、順を追って授業中に説明し、最終的に次のような画面を作っていきます。



 以下のプログラムをそのまま入れると、問題なく動いてしまいますが、
実際には、途中で何段階か問題点を改良して行かなければなりません。









 【演習問題4】 


 sin、cosグラフを描く、新しいプロジェクト、 Project504 を作成しなさい。配列に与えた点を描画する部分は入れても入れなくても良い。

 【応用演習問題5】 


以下のように、 y=(1/4)x^2
を描画するプログラム、
Project505
を作りなさい。

xの刻み幅は、0.1 程度とする。





 【応用演習問題6】 



 問題4にあるような、 y=sin x
のグラフを、 −π≦x≦π
の範囲で書きなさい。その際、x軸、y軸と、目盛を入れなさい。

















 以下のプログラムはあくまで参考とし、うまく動かないときに見るにとどめてください。

 そのままコピペせず、
 授業でやる順に
自分で入力してください。



Project502 ソース

private void button1_Click(object sender, EventArgs e)
{
Graphics g = this.pictureBox1.CreateGraphics();
int width = this.pictureBox1.Width - 1;
int height = this.pictureBox1.Height - 1;
int x0=0, y0=0, x1=0, y1=0;
int a = (int)numericUpDown1.Value;
int scale = (int)numericUpDown2.Value;

Pen bluePen = new Pen(Color.Blue, 2);
Pen redPen = new Pen(Color.Red, 2);

int x = 0;
while( x1<width && y1<height )
{
x0 = x * scale;
y0 = (x * x) * a;
x1 = (x + 1) * scale;
y1 = ((x + 1) * (x + 1)) * a;

g.DrawEllipse(redPen, x1, y1, 2, 2);
g.DrawLine(bluePen, x0, y0, x1, y1);

x++;
}
}

private void button3_Click(object sender, EventArgs e)
{
Graphics g = this.pictureBox1.CreateGraphics();
Color bgcolor1 = pictureBox1.BackColor;
g.Clear(bgcolor1);
}

-------------------------------

Project502(改訂) ソース

private void button1_Click(object sender, EventArgs e)
{
Graphics g = this.pictureBox1.CreateGraphics();
int width = this.pictureBox1.Width - 1;
int height = this.pictureBox1.Height - 1;
int x0 = 0, y0 = 0, x1 = 0, y1 = 0, y2 = 0;
int a = (int)numericUpDown1.Value;
int scale = (int)numericUpDown2.Value;

Pen bluePen = new Pen(Color.Blue, 2);
Pen redPen = new Pen(Color.Red, 2);

int x = 0;
while( x1<width && y1<height )
{

x0 = x * scale;
y0 = (x * x) * a;
x1 = (x + 1) * scale;
y1 = y2 = ((x + 1) * (x + 1)) * a;

y0 = height - y0;
y1 = height - y1;


g.DrawEllipse(redPen, x1, y1, 2, 2);
g.DrawLine(bluePen, x0, y0, x1, y1);
Font font1 = new Font("MS UI Gothic",12);
Brush brush1 = new SolidBrush(Color.Black);
String str1 = "( "+(x+1).ToString()+" , "+y2.ToString()+" )"; //変数名に注意
g.DrawString(str1,font1,brush1,x1+20,y1);

x++;
}
}



Project503

  private void button1_Click(object sender, EventArgs e)
{
double pi=3.1416;
double x, y;
double xrad;
int hight2;
int x0,y0,x1,y1;
int xmin = 0, xmax = 360, xstep = 1;
double[] siny = new double[361];

Graphics g = this.pictureBox1.CreateGraphics();
int width = this.pictureBox1.Width - 1;
int height = this.pictureBox1.Height - 1;
g.DrawRectangle(Pens.Black, 0, 0, width, height);

Pen bluePen = new Pen(Color.Blue, 2);
Pen redPen = new Pen(Color.Red, 2);
Pen greenPen = new Pen(Color.Green, 2);

for (int i = 0; i < 20; i++) {

x0=i*10;
y0=(i*i);
x1=(i+1)*10;
y1=((i+1)*(i+1));

g.DrawLine(bluePen,x0,y0,x1,y1);

//
y0 = height - y0;
y1 = height - y1;

g.DrawLine(redPen, x0, y0, x1, y1);
}

//
hight2 = height / 2;
//y1 = 0;
y1 = hight2;
x1 = 0;
for (int i = xmin; i < xmax; i++)
{
y0 = y1;
x0 = x1;
x1 = i;
xrad = i * pi / 180;
y1 = (int)(Math.Sin(xrad) * 100);
y1 = hight2 - y1;
g.DrawLine(greenPen, x0, y0, x1, y1);
}
//
int[] data_a;
data_a = new int[11]{
0,11,20,29,41,53,58,72,80,91,99};
Pen deepPinkPen = new Pen(Color.DeepPink, 2);

for (int i = 0; i < 11; i++)
{
g.DrawEllipse(deepPinkPen, i * 10, data_a[i], 5, 5);
}
}