Previous ToC Next

3. C++言語入門 III

3.1. お絵書き

プログラムを書いて実行しても、でるものが数字ばかりではつまらない。せっかく再帰 をやったので、再帰を使ってわりあい簡単なプログラムで複雑な図形を書いてみよう。

     1:// tree.cpp
     2:#define _USE_MATH_DEFINES
     3:#include <iostream>
     4:#include <cmath>
     5:#include <gr.h>
     6:using namespace std;
     7:
     8:void draw(double x1, double y1, double x2, double y2)
     9:{
    10:    double xa[] = {x1,x2};
    11:    double ya[] = {y1,y2};
    12:    gr_polyline(2,xa,ya);
    13:}
    14:
    15:void tree(int n, double x, double y, double angle, double length)
    16:{
    17:    double x1, y1;
    18:    if (n >0){
    19:        x1 = x + length*cos(angle);
    20:        y1 = y - length*sin(angle);
    21:        draw(x,y,x1,y1);
    22:        tree(n-1,x1,y1,angle + 0.25, length*0.7);
    23:        tree(n-1,x1,y1,angle - 0.25, length*0.7);
    24:    }
    25:}
    26:  
    27:int main()
    28:{
    29:    int n;
    30:    cerr << "Level of the tree? :";
    31:    cin >> n;
    32:    gr_setwindow(0,1,0,1);
    33:    tree(n, 0.5, 0.0, -M_PI/2, 0.25);
    34:    cerr <<"Enter some char + retern to finish:";
    35:    char c; cin >>c;
    36:}
 
これは、樹形図を書くプログラムである。原理は、指定した長さと角度で一本 線を引き、その先から角度をつけて2本線を引き、それぞれの端からまた角度 をつけて、、、というのを繰り返すだけである。

再帰を使うことで、角度、長さを変えて自分自身を呼び出すという形で簡潔に アルゴリズムが表現できている。

3.2. コンパイル・実行の方法

まず、このプログラムのコンパイルには

がインストールされている必要がある。

インストールは C ラ イブラリのインストールページから、Ubuntu なら gr-latest-Ubuntu-x86_64.tar.gz を落としてきて、それを どこか適当なディレクトリで tar xzf とかで展開する。そうすると、grという てディレクトリと、その下に libとか include とかのサブディレクトリができる。そのディレクトリの名前 を GRDIR に設定して。bashなら

  export GRDIR=/foo/var/gr
csh 系なら

  setenv  GRDIR /foo/var/gr
でよい(/foo/bar は実際のディレクトリの名前に置き換えること)。あとは

  export GKS_WSTYPE=x11
を実行してから、 Getting Startedにあるような作業をすればよい。

  g++  tree.cpp -o tree   -std=c++11 -I $GRDIR/include -L  $GRDIR/lib -Wl,-rpath,$GRDIR/lib -lGR
でコンパイルし、

  ./tree
で実行できるはずである。上手くいけば図 2 のような絵 がでてくるはずである。なお、環境変数 GKS_WSTYPE を x11 にしないと何も でないかもしれない。

Figure 2: tree の出力例

3.3. グラフィックライブラリ

ここでは、 GR framework の基本的な機能を使っ て画面に線を書いている。

とりあえず、ここで使っている関数についてそれらが何をしているかを見ておこう。上で述べたように、

  #include "gr.h"
によって、 GR framework で提供されている関数が使えるようになる。 iostream は前にでてきたが、 cmath は sin, cos 等の数学関数と、 のような数学でよく使われる定数を使えるようにする。その上の

  #define _USE_MATH_DEFINES
がないと定数のほうは使えるようにならない。これで、 M_PI を の値が 必要なところで使うことができる。

さて、その次で

  void draw(double x1, double y1, double x2, double y2);
という関数を定義している。この中身の解説はちょっとあとまわしにして、 まずはこれは点 (x1,y1) から 点 (x2,y2) まで線を引くように、 GR の機能を 使って作った関数である、と思ってほしい。

tree は draw を使って樹形図を書く関数なので後回しにして、 main 関数で 使っている GR の機能をみていく。といっても今回

    gr_setwindow(0,1,0,1);
だけで、これは、画面(ウインドゥ)内での座標系を決めている。 4 つの引数 は x座標の最小値、x座標の最大値、y座標の最小値、y座標の最大値である。

同工異曲だが、こんなものも書ける。

     1:// fract.cpp
     2:#define _USE_MATH_DEFINES
     3:#include <iostream>
     4:#include <cmath>
     5:#include <gr.h>
     6:using namespace std;
     7:
     8:void draw(double x1, double y1, double x2, double y2)
     9:{
    10:    double xa[] = {x1,x2};
    11:    double ya[] = {y1,y2};
    12:    gr_polyline(2,xa,ya);
    13:}
    14:
    15:
    16:void fractal(int n,
    17:       double x0,
    18:       double y0,
    19:       double x1,
    20:       double y1)
    21:{
    22:    double dx, dy, xa, ya; 
    23:    if (n > 0){
    24:  dx = (x1 - x0)/2;
    25:  dy = (y1 - y0)/2;
    26:  xa =  x0 + dx  - dy ;
    27:  ya =  y0  + dx +dy ;
    28:  fractal(n-1,x0, y0, xa, ya);
    29:  fractal(n-1,xa, ya, x1, y1);
    30:    }else{
    31:  draw(x0,y0,x1,y1);
    32:    }
    33:}
    34:  
    35:int main()
    36:{
    37:    int n;
    38:    cerr << "Level of the tree? :";
    39:    cin >> n;
    40:    gr_setwindow(0,1,0,1);
    41:    fractal(n, 0.6, 0.3, 0.6, 0.7);
    42:    cerr <<"Enter some char + retern to finish:";
    43:    char c; cin >>c;
    44:}
なお、画像をファイルに落とすには、環境変数 GKS_WSTYPE を例えば eps に すれば eps ファイルが、 png, jpg 等でそれぞれのタイプのファイルが、 gks.png みたいな名前でできる。

3.4. 練習

  1. この木では枝が2本ずつ出ているが、もっとたくさん出すにはどうすればい いか?
  2. この木は枝分かれが完全に規則的で不自然である。自然にするにはどうすれ ばいいだろうか? (ヒント:drand48() という関数を呼ぶと、0 から x まで の範囲の乱数 --- デタラメな数 --- を返す。これを使って枝分かれの長さ、 角度を変えて見よう)
  3. 他のフラクタル曲線、たとえばコッホ曲線やペアノ曲線を書くプログラ ムを作ってみる。

これでC++ 言語のミニマムな入門は終わり。
Previous ToC Next