Part.9

曲線の描画

内容

  • y = sin(x) のグラフの描画

目標

  • コンピューターが曲線を描く原理を知る

y = sin(x) のグラフの描画

これから、gnuplot を使って y = sin(x) のグラフを描きます.もちろん,gnuplot では,

plot sin(x)

とすれば y = sin(x) のグラフが得られるのですが,gnuplot がどのようにしてそれを描いているかわかりません.そこで少々遠回りをします.

実際には y = sin(x) のグラフは滑らかな曲線ですが、コンピュータではそのような滑らかな曲線を直接は扱えませんので折れ線で近似して描画します.つまり、変数 x は、実際には連続的に変化するものですが、とびとびの値を使います.後の例で見るように、とびとびとはいえ、十分に細かく取れば、折れ線で曲線をうまく近似することができます.

図のように [0, L] 区間を N-1 等分して、その等分した小区間の幅を dx とします.N-1 等分すると図のように N 個の区切りが現れますが、それらに 0,1, ...., i, ...., N-1 と番号をつけることにします.また、 N を分割数、 dx を分割幅と呼びます.このとき、

Xi = i*dx

の部分についてそれぞれ y = sin(Xi) を計算し、それらを折れ線で結ぶことを考えます.C言語風に書けば

X[i] = dx*i;
Y[i] = sin(X[i]);

をそれぞれ求め、(X[0], Y[0]), (X[1],Y[1]), ...., (X[N-1], Y[N-1]) を結ぶ折れ線を描くことになります.これをプログラムにすると次のようになります.(上記の説明にあわせるためにかなり無駄なことをしています.)ファイル名を Part9-1.c として打ち込み、コンパイルして実行してみてください.

注意: 数学関数(sin, cos, tan 等)を使う場合には #include <math.h> が必要となります.また,コンパイルするときには

cc Part9-1.c -o Part9-1 -lm

というふうに,-lm を付け加える必要があります.

#include <stdio.h>
/* 次の文は数学関数を使う場合に必要 */
#include <math.h>

/* 定数の定義 */
#define N (5)
#define PI (3.1415926)
#define L (2*PI)

int main()
{
  int i;
  double X[N], Y[N], dx;

  /* dx を求める */
  dx = L/(N - 1);

  /* X[i] を求める */
  for(i = 0; i < N; i++)
  {
    X[i] = i*dx;
  }

  /* Y[i] を求める */
  for(i = 0; i < N; i++)
  {
    Y[i] = sin(X[i]);
  }

  /* 結果を数値として表示 */
  for(i = 0; i < N; i++)
  {
    printf("%lf %lf\n", X[i], Y[i]);
  }
}

上記プログラムを使って、N とグラフの関係を見てみましょう.まず,プログラムをコンパイルします.

cc Part9-1.c -o Part9-1 -lm

続いて実行してみましょう.

./Part9-1

数値が表示されます.これら数値をgnuplotでグラフ化しましょう.Nが5での結果ですから

./Part9-1 > N=5.data

としましょう.gnuplot を起動し,

plot [0:2*pi] "N=5.data" with linespoints, sin(x)

緑色で書かれたグラフが描きたいグラフ (y = sin(x) )です.赤色が描こうとしている折れ線です.N=5 の場合は上図のようになります(赤線).これでは、まったく y = sin(x) のグラフには見えません.

つづいて、プログラムを変更しNを10にして同様に N=10.data を作成しグラフを描いてみます.曲線っぽくみえてきました.

N=50 の場合.見た目はほぼ y=sin(x) のグラフに見えます.

先のプログラム例では、 説明の為,少々冗長なプログラムとなっていました.実際には以下のプログラムでも同様の結果が得られます.各人確認してください.

#include <stdio.h>
#include <math.h>

/* 定数の定義 */
#define N (5)
#define PI (3.1415926)
#define L (2*PI)

int main()
{
  int i;
  double Y[N], dx;

  /* dx を求める */
  dx = L/(N - 1);

  /* 結果を画面に表示 */
  for(i = 0; i < N; i++)
  {
    printf("%lf %lf\n", i*dx, sin(i*dx));
  }
}

さて,曲線を折れ線で近似することができました.gnuplot も内部で同じことをやっていることを確認しましょう.例えば,

plot [0:20*pi] sin(x)

としてみましょう.

折れ線近似をしている様子がよくわかりますね.gnuplotでも内部的には折れ線で近似しているのです(標準状態で100本の折れ線で描く).折れ線の本数を増やすことができます.

set samples 500

これで,500本の折れ線で描くことに変更できます.もう一度同じグラフを描きます.

plot [0:20*pi] sin(x)

なめらかな曲線になりました.ただし,ディスプレイの表示が点の集合によるものであるから,なめらかに見えるというのにも限界があります(折れ線数を増やすのに加えてぼかしの手法などを用いてなめらかに見せる方法が最近は使われています).

同様に,例えば次のような実験もしてみると良いでしょう.

set sample 5
plot [0:2*pi] sin(x)

Part9で学んだ事

  • 曲線は折れ線で近似して表示するということ