2000年4月12日更新(実行画面例を追加)
  関谷トップページへ CGトップページへ   作者へのメッセージ

図形処理・計算処理実習No.2 Glibwv.hを使ったグラフィックス(1)    

2000.4.19 KPC 情報技術科  関谷

1.基本グラフィックライブラリGlib.hとその使用例

 MS-DOS版 C言語コンパイラのグラフィックス関数の違いを吸収して、12個の標準ライブラリ関数とその仕様を、河西朝雄が1992年5月に決めた。(河西朝雄、C言語によるはじめてのアルゴリズム入門、技術評論社、1992.5.25初版、第8章-pp.313-408)

 Glib.hの主な特徴は次の3点である。   

  • y軸の向きを、上方を正とする座標系を用いる。   
  • ウィンドウをサポートし、実数型データの描画を行う。   
  • タートルグラフィック型ライブラリのサポート  

     そのGlib.hを使って、河西は以下の機能を実現している。

    1. Move と Turn
    2. 2次元座標変換
    3. ジオメトリック・グラフィックス
    4. 3次元座標変換
    5. 立体モデル
    6. 陰線処理
    7. リカーシブ・グラフィックス

    詳細は、テキストを参照のこと。
     なお、河西は、「Visual Basicによるはじめてのアルゴリズム入門」(1999年6月、技術評論社刊)8章グラフィックスで、VBでのWindowsグラフィックスを示している。

    2.Glibwv.hとSLSによるWindows グラフィックス

    Slsは平林によるWindows グラフィックス用のライブラリである。(No.1の平林雅著,Windows95プログラムを10倍簡単に作るを参照)。
     Slsの上に、上記の河西のGlib.hを移植したものが、Glibwv.hグラフィクス・ライブラリである。MoveとTurn、2D、3Dなどのグラフィックス・プログラミングが、Windows上で実現できる。

    3.Glibwv.hとSlsによるWindowsプログラミング

    3.1 MoveとTurn、2次元座標変換の例題の提示

    図形処理の基本プログラム例として、 1)Move とTurnでは、例題56 正n角形を描く(n=3〜9)
           練習問題56 渦巻き模様
    2)2次元座標変換では、例題57 対称図形
    練習問題57 回転・拡大コピー
    を紹介する。

    <

    対称複写をビューを使って同じ描画を繰り返した例

    3.2 MoveとTurn、2次元座標変換のプログラムの解析と改造など

    例題を参考に、皆さんの描きたい図形データなどを用意して、プログラムを改造し、作品を作りなさい。

    3.3 レポートの提出方法

    Wordに、考察、ソースリスト、実行グラフィックス画面を貼り付けたものを「Word文書」の形式で保存したファイル(ファイル名は、学籍番号2桁_02.doc)を、ファイルサーバ(R:\sekiya\図形処理\No02_Gl1に提出のこと。

     

    注1) 画面のハードコピーとWordへの貼りつけ・保存の手順は以下のとおり。(窓全体なら、3−4は省略できる)
      1 作図したグラフの画面をアクティブにします。(窓の選択です。)
      2 Alt キーを押したまま,PrintScreen キーを押して, クリップボードに取り込みます。
      3 アクセサリのペイントを起動して,カーソルを左上に移します。( 既にある場合は,すべてを選択して, 切り取り( 削除) してから, 上記の 2をすること。カーソルの移動をします)
      4 ペイントで,編集−貼り付けを実行します。
      5 次に, このなかの必要部分の図を,選択・コピーします。
      6 Wordに貼り付ける。大きさや配置などが変更できます。
      7 Wordで, 文書として各自のホームドライブの科目のフォルダに、名前を付けて保存する。

    注2) Webページの作り方については、関谷のWebページの「個人ホームページの作成と更新」のページを参照のこと。(現在、Webサーバのバージョンアップ中で使えない。)
    (ローカルのホームページフォルダは、c:\でなく、各自のサーバのホーム(H:)ドライブに作ること。)
     作業としては、index_htmlフォルダの作成とそこでのindex_htmlファイルの変更−名前を表示したり、今回のページに対するリンクを作る−が必要になる。

    ソースリスト(Glibwv.h, ka_cap57.c)

    Glibwv.h (河西のGlib.hをSLSを使用して、Windows用に移植したもの

    // Glibwv.h  河西朝雄、C言語によるはじめてのアルゴリズム入門、pp.346-356 からSLSを使用して、Windows用に移植。
    //      1998.3.16 北九州職業能力開発短期大学校 情報処理科 関谷順太

    #include <math.h>

    #include "line.f"
    #include "pset.f"
    
    #define pset(x,y,c) \
    				WvLine((double)(x),(double)(y),(double)(x),(double)(y),(int)c)
    #define window(x1,y1,x2,y2) \
    				Window((double)(x1),(double)(y1),(double)(x2),(double)(y2))
    #define view(x1,y1,x2,y2) \
    				View((int)(x1),(int)(y1),(int)(x2),(int)(y2))
    #define setpoint(x,y) \
    				SetPoint((double)(x),(double)(y))
    #define setangle(a) \
    				ANGLE=(double)(a)
    #define turn(a) \
    				ANGLE=fmod(ANGLE+(a), 360.0)
    #define move(l,c) \
    				Move((double)(l), (int)(c))
    #define moveto(x,y,c) \
    				MoveTo((double)(x),(double)(y),(int)(c))
    #define moverel(x,y,c) \
    				MoveTo((double)(LPX+(x)),(double)(LPY+(y)), (int)(c))
    #define wvline(x1,y1,x2,y2,c) \
    				WvLine((double)(x1),(double)(y1),(double)(x2),(double)(y2),(int)(c))
    
    double  ANGLE,				/*  現在角   */
    		LPX, LPY;			/*  現在位置 */
    //int     C=1;				/*  色       */
    double	WX1,WY1,WX2,WY2,	/* ワールド座標 */
    		VX1,VY1,VX2,VY2,	/* ビュー座標 */
            FACTX,FACTY;        /* スケール */
    int PX1,PY1, PX2, PY2;        // 現在スクリーン座標
    
    int Cpy(void){
        return PY2;
    }
    int Cpx(void){
        return PX2;
    }
    void Window(double x1, double y1, double x2, double y2)
    {
    	WX1=x1; WY1=y1; WX2=x2; WY2=y2;
    	FACTX=(VX2-VX1)/(WX2-WX1);
    	FACTY=(VY2-VY1)/(WY2-WY1);
    }
    void View(int x1, int y1, int x2, int y2)
    {
    	VX1=(double)x1; VY1=(double)y1; VX2=(double)x2; VY2=(double)y2;
    	FACTX=(VX2-VX1)/(WX2-WX1);
    	FACTY=(VY2-VY1)/(WY2-WY1);
    }
    
    void WvLine(double x1, double y1, double x2, double y2, int c)
    {
        PX1 = (int)((x1-WX1)*FACTX+VX1);
        PY1 = (int)((y1-WY1)*FACTY+VY1);
        PX2 = (int)((x2-WX1)*FACTX+VX1);
        PY2 = (int)((y2-WY1)*FACTY+VY1);
      line(PX1, PY1, PX2, PY2, c);
    //	LPX=x2; LPY=y2;
    }
    void Move(double l, int c)
    {
    	double x,y,rd=3.14159265359/180.0;
    	x=l*cos(rd*ANGLE); y=-l*sin(rd*ANGLE);
    	WvLine(LPX, LPY, LPX+x, LPY+y, c);
      LPX += x; LPY +=y;
    }
    void MoveTo(double x, double y, int c)
    {
    	WvLine(LPX, LPY, x, y, c);
      LPX = x; LPY =y;
    }
    void SetPoint(double x, double y)
    {
    	LPX=x; LPY=y;
    }
    

    ka_cap57.c 練習問題57 2次元座標変換(拡大、回転)

    /*  ka_cap57.c 2次元座標変換  p.364-5 1998.3.27 sekiya */

    #include <stdlib.h> /* EXIT_SUCCESS */

    #include "gint.f"     /* グラフィックス初期化関数 gint,gend */
    #include "basescrn.f" /* 基本画面設定関数  base_screen */
    #include "line.f"   /* 直線関数 */
    #include "gcls.f"   /* 消去関数 */
    #include "symbol.f"   /* 文字関数 */
    #include "Glibwv.h"  /*  タートル関数Glibwv.h(河西) */
    
    void multi(double fx, double fy, double *x, double *y); // change size
    void rotate(double angle, double *x, double *y);   // 回転移動
    
    main(int argc,char *argv[])
    {
        static double  xo[]={  0., 100.,100.,   0., 0.},
                       yo[]={  0.,   0.,200., 200., 0.};
        double  x[5], y[5], fx=0.6, fy =0.6, angle= 15.0;
        int     i, j, k, imax=3, vxl=0, vxr=200, vxd=200, n=5;
    
        printf("Ctrl+Cで終ります。\n");  
    
        if(argc==1)
        { /* 引数なし(標準) */
        gint(640,400); /* グラフィックス初期化(640x400dot) */
        }
        else
        { /* 引数あり(拡大) */
            gint(1000,625); /* グラフィックス初期化(1000x625dot) */
            base_screen(640,400); /* 基本画面設定 */
        }
    
    	gcls();
        window(- 70, -280, 130, 120);
    
        symbol(20,20,"<河西、回転移動(c言語によるはじめてのアルゴリズム入門、",7,1,1);
        symbol(20,40,"練習問題57、pp.364-365>  by 関谷、1998.3.27, 2000.4.19",7,1,1);
    
    
      for(i=0; i<3; i++){
        view(vxl,370+33*i, vxr,40);               // ビューポートの設定
        printf("angle:%5.0f, fx:%5.1f,  fy:%5.1f\n", angle, fx, fy);
    
        for(j=0; j < n; j++) {
            x[j] = xo[j];  y[j] =yo[j];
            if (j==0)
                setpoint(x[j],-y[j]);
            else
                moveto(x[j],-y[j], 6);
        }
    
        for(j=0; j<12; j++) {
            for(k=0; k < n; k++) {
            }
            for(k=0; k < n; k++) {
                multi(fx, fy, &x[k], &y[k]);       // x,y座標値の拡大・縮小
                rotate(angle, &x[k], &y[k]);       // x,y座標値の回転
    
                if (k==0)
                    setpoint(x[k],-y[k]);
                else
                    moveto(x[k],-y[k], 7);
            }
        }
                  // y axiss plot
        setpoint(0., 0.);
        moveto(0, -220.0, 6);
        symbol(Cpx(), Cpy(), "Y'軸",6,1,1);
                  // x axiss plot
        setpoint(0., 0.);
        moveto(110.0, 0.0 , 6);
        symbol(Cpx(), Cpy(), "X'軸",6,1,1);
    
    	// view を描く
    	wvline(-49,-99,-49,99,1); // blue left line
    	wvline(-49, 99, 49,99,2); // red uper line
    	wvline( 49, 99, 49,-99,3); // purple right line
    	wvline( 49,-99,-49,-99,4); // green lower line
    
        vxl += vxd; vxr += vxd;
        angle += 15.0;
        fx += 0.10; fy += 0.10; 
      }
        gend(); /* グラフィックス終了 */
    
        return EXIT_SUCCESS;
    } /* main */
    
    void multi(double fx, double fy, double *x, double *y) // change size
    {
        *x = fx *(*x);
        *y = fy *(*y);
    }
    void rotate(double deg, double *x, double *y)  // 回転移動
    {
        double dx, dy, rd=3.14159/180;
    
        deg *= rd;
    
        dx = (*x)*cos(deg) - (*y)*sin(deg);
        dy = (*x)*sin(deg) + (*y)*cos(deg);
        *x = dx; *y = dy;
     }