2001年5月2日 分割して作成
  関谷トップページへ CG2001 トップページへ  

kacp59.c 透視, 河西,C言語によるはじめてのアルゴリズム入門 練習問題59 p.374-377 [viewにより3つの枠に表示]

/*  kacp59.c 透視-練習問題59 
	河西,C言語によるはじめてのアルゴリズム入門p.374-377 1998.3.21,2000.4.22 sekiya
	2000.4.22 新しい線分の番号を始点に表示する */
#include <stdlib.h>   /* EXIT_SUCCESS */
#include <stdarg.h>   /* sprintf */
#include <math.h>
#include <time.h>

#include "gint.f"     /* グラフィックス初期化関数 gint,gend */
#include "basescrn.f" /* 基本画面設定関数  base_screen */
#include "gcls.f"     /* 画面の消去関数 */
#include "symbol.f"   /* 文字関数 */
#include "Glibwv.h"  /*  Glibwv(タートル)関数(河西Glib.hをslsを使って移植) */
#include "rectfxor.f"   /* 長方形塗りつぶし関数 */

void pers(double ay, double vp, double l, double m, double n
		, double x, double y, double z,	double *px, double *py);	/* pers */

main(int argc,char *argv[])
{
	static struct {
		int f;
		double x,y,z;
	} a[]
	={ -1,80,50,100,	1,0,50,100,		1,0,0,100,		1,80,0,100,
		1,80,0,0,		1,80,50,0,		1,80,50,100,	1,80,0,100,
		-1,0,50,100,	1,0,50,0,		1,0,0,0,		1,0,0,100,
		-1,0,50,0,		1,80,50,0,		-1,0,0,0,		1,80,0,0,
		-1,0,50,100,	1,40,80,100,	1,80,50,100,	-1,0,50,0,
		1,40,80,0,		1,80,50,0,		-1,40,80,100,	1,40,80,0,
		-1,50,72,100,	1,50,90,100,	1,65,90,100,	1,65,61,100,
		1,65,61,80, 	1,65,90,80,	 1,50,90,80,	1,50,90,100,
		-1,65,90,100,	1,65,90,80,	-1,50,90,80,	1,50,72,80,
		1,65,61,80,	-1,50,72,100,	1,50,72,80,	-999,0,0,0	};
};
	int		c, k,  vxl=0, vxr=200, line=50, i, ni;
	double  ay, px, py, rd=3.1415926535898/180.0, cay, say;
	double  beta=-35.0, vp=-300.0, l=-25.0, m=-70.0, n=0.0, h;
	char title[100], ni_char[4];
	char    *pa;        /* *pa:日付用文字列(ポインタ変数)*/
	long nowtime;

	time(&nowtime);
	pa = ctime(&nowtime);
	*(pa+24)='\0';
	printf("<%s>\n", pa);	/* 実行年月日などをコマンドプロンプトに表示する。 */

	c=5;

  printf("ka_cp59.h 透視 p.374-377\n");  
  printf("非数字で入力を止めます。Ctrl+Cで終ります。\n");  

	if(argc==1)
  { /* 引数なし(標準) */
    gint(640,400); /* グラフィックス初期化(640x400dot) */
  }
  else
  { /* 引数あり(拡大) */
    gint(1000,625); /* グラフィックス初期化(1000x625dot) */
    base_screen(1000,625); /* 基本画面設定 */
  }

	gcls();
	symbol(20,10,"透視ka_cp59-河西,C言語によるはじめてのアルゴリズム入門 p.374-377",5,1,1);
	symbol(20,25,"練習問題59 by 関谷順太",5,1,1);
	symbol(350,25, pa, 7,1.,1.0);
	
	for(i=0;i<3;i++){							// 3つのview 反復
		printf("beta:%5.0lf vp:%5.0lf l:%5.0lf m:%5.0lf n:%5.0lf\n", beta,vp,l,m,n);// Dos 
		sprintf(title,"β:%3.0lf°vp:%3.0lf l:%3.0lf m:%3.0lf n:%3.0lf",
			  beta, vp, l, m, n);						// 文字列セット
		symbol(vxl+10, line, title,4,1,1);				// 図のパラメータ表示
		line += 20;		

		window(-100,-200,100,200);
		view(vxl,450,vxr,50);					// viewをセット
		vxl += 180; vxr +=180;					// 次のview

		ay = beta*rd;							// 回転量
		ni=1;
		for (k=0; a[k].f!=-999; k++){			// データの終わりはf==-999
			pers(ay, vp, l, m, n, a[k].x, a[k].y, a[k].z, &px, &py);/* 透視 pers */
			if (a[k].f == -1)		/* 始点(f == -1)なら 現在点をセット*/
				setpoint(px,py);
			else {
				moveto(px,py,c);	// 直線を引く(現在点から(px,py)まで)
				if(a[k-1].f == -1){
					sprintf(ni_char,"%2d",ni++);	// 新しい線分の番号
					symbol(PX1,PY1,ni_char,3,1,1);	// Glibwv.hでの変数を使用
			    }
			}
		}
				// y axiss plot
		pers(ay, vp, l, m, n, 0.0, 0.0,0.0, &px, &py);setpoint(px,py);
		pers(ay, vp, l, m, n, 0.0, 120.0,0.0, &px, &py);moveto(px,py, 6);
		symbol(PX2,PY2,"Y軸",6,1,1);				// Glibwv.hでの変数を使用
		pers(ay, vp, l, m, n, 0.0, 0.0,0.0, &px, &py);setpoint(px,py);
		pers(ay, vp, l, m, n, 100.0, 0.0,0.0, &px, &py);moveto(px,py, 7);
		symbol(PX2,PY2,"X軸",7,1,1);		

		if(i==2) continue;
		printf("Key-in beta vp l m n ->\n");
		if(scanf("%lf %lf %lf %lf %lf", &beta,&vp, &l, &m, &n)!=5) continue;
	}
	rectfillXOR(0,0,639,399,7);
	gend(); /* グラフィックス終了 */
	return EXIT_SUCCESS;
} /* main */

void pers(double ay, double vp, double l, double m, double n
		, double x, double y, double z,	double *px, double *py)	/* pers */
{				// 透視変換の関数 (x,y) to (px,py)
	double h, cay, say;
	cay=cos(ay); say= sin(ay);				// ここは 計算回数が多くなっている
	h = -x*say/vp + z*cay/vp + n/vp + 1.0;
	*px = (x*cay + z*say + 1.0) / h;
	*py = (y + m) / h;
}