• 締切済み

ダイヤモンドパターンを回転させる

こんにちは。 次の問題がわかりません(>_<) 【グラッフィックスのダイヤモンドパターンを回転させる】問題です。  平面図形(正八角形、正十二角形とか)がくるくる回るようにしたいのですが、図形が崩れた感じで奇妙な(?)回転になります。一応、プログラムは書いてみましたが、どこが間違っているのかわかりません。  下に自分で考えたプログラムの流れとソースを記しておきました。わかる方ご回答願います。 ※ 実行結果は無限に設定してあるので、Ctrl+C でプログラムを強制的に終わらせることとします。 【プログラムの流れ】 (1) 座標を計算(半径1のもの) (2) ダイヤモンドパターンを書く (3) 座標を回転 (4) ちょっと待つ (5) 画面を消去する→(2)に戻る 【プログラム】 ----------------------------------------------------------- /* ダイヤモンドパターンを回転させる */ #include <stdio.h> #include <math.h> #include <gucc/gucc.h> #define PAI 3.141593 void main( void ) { int i, j, np, k, t1,c,t2,rad,u,v; double x[100], y[100], z[100]; int R[5]={0,64,128,192,255}; int G[5]={0,64,128,192,255}; int B[5]={0,64,128,192,255}; double rs, ang; rs = 150.0;/*円の半径*/ printf("頂点数? "); scanf( "%d",&np );/*npは頂点数*/ for( i=0; i<np; i++ ){ ang = 2.0 * PAI * (i-1) /np ;/*PAIはπ*/ /*半径1の円周上の点*/ x[i] = cos(ang); y[i] = sin(ang); } G_INIT();/*グラフィックモードの切り替えと初期化*/ G_CLS(); do{ /*図形を描く*/ for( i=0; i<np-1; i++ ){ for( j=i+1; j<np; j++ ){ G_LINE( rs*x[i]+ 300.0, rs*y[i]+ 240.0, rs*x[j]+ 300.0 , rs*y[j]+ 240.0 ); } } /*座標を回転 */ for( i=0; i<np-1; i++ ){ rad=rad+0.05; z[i] = x[i] * cos(0.05) + y[i] * sin(0.05); y[i] = -x[i] * sin(0.05) + y[i] * cos(0.05); x[i]=z[i]; } /*ちょっと待つ*/ t1=time(&t2); while(t1==time(&t2)); /*画面を消去*/ G_CLS(); }while(1); } ----------------------------------------------------------------

みんなの回答

  • chie65536
  • ベストアンサー率41% (2512/6032)
回答No.3

もう1つ。 for( i=0; i<np-1; i++ ){ G_LINE( rs*(y[i] * cos(rad) - x[i] * sin(rad))+ 300.0, rs*(x[i] * cos(rad) + y[i] * sin(rad))+ 240.0, rs*(y[i+1] * cos(rad) - x[i+1] * sin(rad))+ 300.0 , rs*(x[i+1] * cos(rad) + y[i+1] * sin(rad))+ 240.0 ); } の後に G_LINE( rs*(y[0] * cos(rad) - x[0] * sin(rad))+ 300.0, rs*(x[0] * cos(rad) + y[0] * sin(rad))+ 240.0, rs*(y[np-1] * cos(rad) - x[np-1] * sin(rad))+ 300.0 , rs*(x[np-1] * cos(rad) + y[np-1] * sin(rad))+ 240.0 ); を追加。 ループで [0]から[1]に線を引く [1]から[2]に線を引く [2]から[3]に線を引く [3]から[4]に線を引く (中略) [np-2]から[np-1]に線を引く までを繰り返した後で、最後に [0]から[np-1]に線を引く としないと、多角形が閉じません。

pierrot5
質問者

お礼

お礼が遅くなってすみません。アドバイスありがとうございました!!とても参考になりました。 プログラムは無事に完成し、多角形がきれいにくるくる回っています(^^)

  • chie65536
  • ベストアンサー率41% (2512/6032)
回答No.2

追記。 {と}の対応を修正し忘れたので、余計な}、足りない}は、質問者さんが適切に修正して下さい。

  • chie65536
  • ベストアンサー率41% (2512/6032)
回答No.1

回転させる度に、x[]とy[]の中身を書き替えると、誤差が蓄積され、すぐに図形が歪んでしまう。 多角形の座標をx[]とy[]に作成したら、それ以降、x[]とy[]の中身は変更しないようにした方が良い。 #include <stdio.h> #include <math.h> #include <time.h> /* time関数を使用するにはtime.hが必要 */ #include <gucc/gucc.h> /* doubleを使用するなら、最低、15桁は書くこと */ #define PAI 3.141592653589793 void main( void ) { int i, j, np, k, c, kakudo,u,v; double x[100], y[100], z[100]; int R[5]={0,64,128,192,255}; int G[5]={0,64,128,192,255}; int B[5]={0,64,128,192,255}; double rs, ang, rad; time_t t1; /* time()の引数はtime_t *である。int *である保証はない 通常、 typedef unsigned long time_t; と定義されている sizeof(int)とsizeof(unsigned long)が異なる場合 time(&int_val)の呼び出しはメモリを破壊する */ rs = 150.0;/*円の半径*/ printf("頂点数? "); scanf( "%d",&np );/*npは頂点数*/ for( i=0; i<np; i++ ){ ang = 2.0 * PAI * i /np ;/*PAIはπ*/ /*半径1の円周上の点*/ x[i] = cos(ang); y[i] = sin(ang); } G_INIT();/*グラフィックモードの切り替えと初期化*/ G_CLS(); kakudo = 0; for (;;) { /* 無限ループは「do ~ while(1);」よりも「for (;;) {~}」の方が好ましい */ rad = (double)kakudo * PAI / 180.0; /* 角度からラジアン値を求める */ /*図形を描く*/ for( i=0; i<np-1; i++ ){ G_LINE( rs*(y[i] * cos(rad) - x[i] * sin(rad))+ 300.0, rs*(x[i] * cos(rad) + y[i] * sin(rad))+ 240.0, rs*(y[i+1] * cos(rad) - x[i+1] * sin(rad))+ 300.0 , rs*(x[i+1] * cos(rad) + y[i+1] * sin(rad))+ 240.0 ); } } /* 角度を変更 */ kakudo += 5; kakudo %= 360; /* kakudoが大きくなるとsin、cosの誤差が大きくなるので、kakudoは常に0~359度の間に収める */ /* ラジアン値のradを操作して「1周したら0度に戻す」のは、誤差の問題があるので、好ましくない */ /*ちょっと待つ*/ /* 戻り値をt1に代入するなら、引数はNULLで良い 引数を指定するならtime(&t1);で良く、戻り値は不要 */ t1=time(NULL); /* 戻り値をt1と比較するなら、引数はNULLで良い */ while(t1==time(NULL)) {;} /* 「ループ内で何もしない場合」は「;」のみで済まさず「{;}」の ように「何もしないのを明示的に記述する」こと。 「;」のみでは「do {~} while(条件);」の場合の 「while(条件);」と紛らわしい。 ここは for (t1=time(NULL);t1==time(NULL);) {;} とも書けるが、代入と比較で似た式が並び、紛らわしいので好ましくない */ /*画面を消去*/ G_CLS(); }

関連するQ&A