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;
}