• 締切済み

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

こんにちは。 次の問題がわかりません(>_<) 【グラッフィックスのダイヤモンドパターンを回転させる】問題です。  平面図形(正八角形、正十二角形とか)がくるくる回るようにしたいのですが、図形が崩れた感じで奇妙な(?)回転になります。一応、プログラムは書いてみましたが、どこが間違っているのかわかりません。  下に自分で考えたプログラムの流れとソースを記しておきました。わかる方ご回答願います。 ※ 実行結果は無限に設定してあるので、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

  • 三次元を二次元に・・・

    ヘッダーファイルの中にXeasyGraphic.hと言うのがあり、立方体を表示させ回転たいのです。 そして、三次元で回転させ、二次元に落とすという方法をしたかったのですが、どうしても、ゆがんでしまいます。どうしたらいいでしょうか? -------ソース------- #include<stdio.h> #include<XeasyGraphics.h> #include<math.h> int main(){ /*立方体の宣言*/ float box_x[8]={10,10,10,-10,10,-10,-10,-10};/*X軸*/ float box_y[8]={10,10,-10,10,-10,10,-10,-10};/*Y軸*/ float box_z[8]={10,-10,10,-10,-10,10,10,-10};/*Z軸*/ /*立方体のキャッシュ*/ float box_x2[360][8],box_y2[360][8],box_z2[360][8]; /*平面に落とした時のキャッシュ*/ float flat_x[360][8],flat_y[360][8]; /*回転用*/ int j,i; float th,x,y,x2,y2; /*回転プログラム*/ for(j=1;j<=360;j++){ for(i=0;i<8;i++){ x=box_x[i]; y=box_y[i]; th=(PAI/180)*j; box_x2[j-1][i]=x*cos(th)-y*sin(th); box_y2[j-1][i]=x*sin(th)+y*cos(th); box_z2[j-1][i]=box_z[i]; } } /*三次元から二次元へ*//*ここが間違えていると思われる*/ for(j=0;j<360;j++){ for(i=0;i<8;i++){ flat_x[j][i]=box_x2[j][i]-box_z2[j][i]; flat_y[j][i]=box_y2[j][i]-box_z2[j][i]; } } /*この後に表示が入る予定*/ getchar(); exit(0); }

  • 座標系の回転の問題です

    大学物理入門の問題です 【問題】 空間に固定された座標系Sと、回転している別の座標系S'を考える。座標系S'は、Sに対して角速度ω=Ωi+Ωjで回転しているものとする。ただしこれらの座標系の原点は一致するとする。また、時刻t=0においてこれらの2つの座標系は一致するとする。時刻tにおいて、座標系S'のx'軸、y'軸、z'軸方向の単位ベクトルをそれぞれi'(t)、j'(t)、k'(t)とする。 時刻tにおけるベクトルi'(t)、j'(t)、k'(t)を求めよ 問題は以上です 文中のωはベクトル、i、j、kはそれぞれ座標系Sのx軸、y軸、z軸方向の単位ベクトルです できれば、ベクトルi'(t)、j'(t)、k'(t)がどのような回転をするのか、図を用いて説明していただけると嬉しいです どなたか知恵をお貸しください よろしくお願いします

  • 幾何学変換

    Windowsアプリケーションでボタン一つで画像を45度回転させるプログラムを作りたいのですが、プログラムがよく分かりません。どなたか教えていただけないでしょうか。あと、回転変化後の画像には線形補間法(バイリニア法)を使っての補間処理をして表示させたいのですがよろしいでしょうか。言語はC#です。 自分で色々プログラム組んでるのですがなかなか出来ないです。今組んでるプログラムを実行すると変な風に実行されます。 組んでる途中のプログラム↓↓ private Color[,] SpinImage(Color[,] colImage) { int iHeight = colImage.GetLength(0); int iWidth = colImage.GetLength(1); //Console.WriteLine(iHeight + "\t" + iWidth); double X = 45.0 * Math.PI / 180.0; int iHeight2 = (int)(iWidth * Math.Cos(X) + iHeight * Math.Sin(X)); int iWidth2 = (int)(iWidth * Math.Sin(X) + iHeight * Math.Cos(X)); Color[,] colImage2 = new Color[iHeight2, iWidth2]; //Console.WriteLine(iHeight +"\t" +iWidth); for (int j = 0; j < iHeight-1; j++) { for (int i = 0; i < iWidth-1; i++) { int m = (int)(i * Math.Cos(X) + j * Math.Sin(X)); int n = (int)(-1 * i * Math.Sin(X) + j * Math.Cos(X)) + 100; int iRed = 0; int iGreen = 0; int iBlue = 0; // Console.WriteLine("y:"+ j +"\t i:"+i+"\t m:" +m + "\tn:" + n); iRed = colImage[j, i].R; iGreen = colImage[j, i].G; iBlue = colImage[j, i].B; #region a //if ((j >= 0) && (j < iWidth) && (i >= 0) && (i < iHeight)) //{ // iRed = colImage[i, j].R; // iGreen = colImage[i, j].G; // iBlue = colImage[i, j].B; // colImage[m, n] = Color.FromArgb(iRed, iGreen, iBlue); //} //else //{ // colImage[m, n] = Color.FromArgb(0, 0, 0); //} #endregion if (m < iHeight && n >= 0) { colImage2[m, n] = Color.FromArgb(iRed, iGreen, iBlue); } } } return colImage2; }

  • C言語、行列の積を求めるプログラムについて

    「次に示す行列x,yの積を求めるプログラムを作成せよ。   x[2][3]={{1,2,3},{4,5,6}} y=[3][2]={{1,5},{5,3},{81}}」 という問題です。自分ではとりあえず、 #include<stdio.h> int main(void) { int i,j; int x[2][3]={{1,2,3},{4,5,6}}; int y[3][2]={{1,5},{5,3},{8,1}}; int xy[3][3]={0}; for(i=0;i<3;i++) for(j=0;j<3;j++) xy[i][j]=x[i][j]*y[i][j]; for(i=0;i<3;i++){ for(j=0;j<3;j++) printf("%3d",xy[i][j]); putchar('\n'); } return 0; } というプログラムを作ってみましたが、ダメでした。 ちゃんと積の表示が出るようにするにはどこをどう変えるべきでしょうか?

  • fprintfでの文字化け

    Cで作ったプログラムなのですが最後の部分でファイルに出力すると数字が 文字化けして出てきます(‰など)その原因を教えて頂ければ嬉しいです 他にも何かあれば教えてください プログラミングは詳しくないのでゴロゴロ見つかるかもしれません 【プログラム】 #include <stdio.h> #include <math.h> #include <stdlib.h> #include <time.h> int a,i,j,k,t; double p,p1,b; int X[999][1000],Y[999][1000]; int s0,s1,delta; int main(void) { int**X = calloc(sizeof(int),sizeof(int)*1000); int**Y = calloc(sizeof(int),sizeof(int)*1000); FILE *output; output=fopen("monte.dat","w"); b = 0.01; /*逆温度*/ srand((unsigned int)time(0)); /*メモリの確保*/ if( X == NULL ){ exit( EXIT_FAILURE ); } for(i=0; i<=999; ++i){ /* 各列分の領域を割り当てる */ X[i] = (int*)calloc(sizeof(int),sizeof(int)*1000); } if( Y == NULL ){ exit( EXIT_FAILURE ); } for(i=0; i<=999; ++i){ /* 各列分の領域を割り当てる */ Y[i] = (int*)calloc(sizeof(int),sizeof(int)*1000); } /*終わり*/ /*初期配列の設定*/ for(i=0;i<1000;i++){ X[0][i]=a; a = (int)((rand() / ((double)RAND_MAX+1.0)) * 2);//debag } /*終わり*/ for(t=0;t<2;t++){ //debag /*配列中a番目を抽出*/ a = 10; //debag /*終わり*/ /*a番目のスピンを逆にした配列作成*/ for(j=0;j<1000;j++){ Y[t][j] = X[t][j]; } Y[t][a] = (X[t][a]+1)%2; /*終わり*/ /*遷移確率p1計算*/ s0=0; s1=0; for(k=0;k<1000;k++){ s0=s0+pow(-1,X[t][k]+X[t][k+1]);//(11),(00)なら値1 s1=s1+pow(-1,Y[t][k]+Y[t][k+1]);//(10),(01)なら値-1 } delta = -s1 + s0; p1 = 0.5 * (1 - tanh(0.5 * b * delta)); printf("%d %d %d %f ",s0,s1,delta,p1); //←この時点ではX[t][]は正しく出力する /*終わり*/ /*新しい配列(i番目の符号を交換するか)*/ p = (double)((rand() / ((double)RAND_MAX+1.0)) * 1); for(j=0;j<1000;j++){ X[t+1][j] = X[t][j]; } if(p<=p1){ X[t+1][a] = (X[t][a]+1)%2; printf("交換したよ! %d → %d\n",X[t][a],X[t+1][a]); } else{ X[t+1][a] = X[t][a]; printf("交換しないよ!\n"); } /*終わり*/ } /*記入*/ for(i=0;i<1000;i++){ fprintf(output,"%d ",X[0][i]); //←ここが文字化けする } fprintf(output,"\n"); for(i=0;i<1000;i++){ fprintf(output,"%d ",Y[0][i]); //←出力されない } /*終わり*/ fclose(output); return 0; } 【プログラム終】

  • テーパ加工で寸法がでない。

    テーパ加工時の寸法が出なくなりました。 G91GO1G41G52T2Y5;X-10;GO3X-5Y-5J-5;X5Y-5I-5;G01X20; G03X5Y5J5;X-5Y5I-5;G01X-10;G5040Y-5;M30 上記のようなプログラムで円弧時の寸法がでなくなりました。円弧を分けることが問題なのかと思うんですが、わかりません。 誰か教えて下さい。

  • 配列の逆順コピー

    for文を使って、配列xの並びを逆順にしたものを配列yにコピーするプログラムを作りたいのですがうまくいきません。どうすればよいでしょうか? #include<iostream.h> int main(void){ int i,j; int x[5]={1,2,3,4,5}; int y[5]; for(i=4;i>=0;i--){ for(j=0;j<5;j++){ x[i]=y[j]; } } for(j=0;j<5;j++) cout<<y[j]<<endl; return 0; }

  • 次のプログラムは、円周率だの近似値を求めるプログラムである。プログラム

    次のプログラムは、円周率だの近似値を求めるプログラムである。プログラム中の○に適するものを記入しなさい。 これを教えてください! C言語です #include<stdio.h> void main(void) { int sei,en; float pai,x,y,r; r=1.0; sei=0; en=0; for(x=0,1;○;x=x+0,1){ for(y=0.1;y<=1.0;○){ sei=sei+1; if((x*x+y*y)<=r*r)en=○; } } pai=(4.0*○)/(float)sei; printf("円周率=○¥n",pai); }

  • プログラムのスレッド化について。

    以下の処理をスレッド化しようとしています。 public class FCP{ int N=10 long LOOP_MAX=100 double x[][] = new double[N][4] int g[][] = new int[N][4] boolean y[][] = new boolean[N][4]//出力 boolean A[][] = new boolean[N][10] double T=0.5 Set_Adjacent_Matrix() //A配列にtrueとfalseを代入 Set_initial_value() //y配列に初期値を代入(Math.random()>0.5) g1(int i, int j) //k<4 sum=1 if( y[i][k] == true ) --sum return(double)sum g2(int i, int j) //k<N sum=0 if( y[i][j] == true ) if( y[k][j] == true && A[i][k] == true ) --sum return(double)sum Display_output() //結果表示 if( y[i][j] ) System.out.print("0") else System.out.print(".") public static void main(String args[]) { long loop; int i, j, k; Set_Adjacent_Matrix(); Set_initial_value(); for( loop=0; loop<LOOP_MAX; loop++ ){ for( i=0; i<N; i++ ){ for( j=0; j<4; j++ ){ x[i][j] = g1( i, j ) + g2( i, j ); if( y[i][j] ){ x[i][j] += T; }else{ x[i][j] -= T; } if( x[i][j] > 0.0){ y[i][j] = true; }else{ y[i][j] = false; } } } Display_output(); } } 今回Threadクラスの継承を使ってスレッド化しようと考えました。runメソッドには上のプログラムのmain部分の処理をさせようと思っています。そしてstartメソッドで必要な数(Nの値=10コ)のスレッドを生成しrunメソッドを実行する。 と、ここまではわかったのですが、「生成された各スレッドの番号を保持し、そのスレッドに担当させる処理を決める」という部分をどうすればいいのかわかりません。 「i(1~10)番目のスレッドはN(1~10)列目の処理を担当している」という風にするにはどうしたらいいのでしょうか? よろしくお願いします。

    • ベストアンサー
    • Java
  • 「関数ポインタとして評価されない式」?(sin波)

    知っている(ある程度のプログラミング知識がある)方にはばかばかしい内容かもしれませんが・・・。 sin波とcos波を描くものをC++でプログラミングしている途中です。 いざ実行!と思ってコンパイルすると、「関数ポインタとして評価されない式を使って、関数を呼び出そうとしました。」と出たのですが、何が原因かわかりません。 プログラム内容↓ #include <stdio.h> #include <math.h> #define PAI 3.14 (中略・ペン設定など) double j=0.0, sinwave[400]; int x0=50, y0=50, i=0; while(i<400){   for(j=0.0; j<=PAI; j=j+0.1){ sinwave[i]=sin(j); ●ここが原因らしい   }   i++; } (後略・ペンdeleteなど) math.hもあるし、特に変なところはないと思います。 また、そのあとにMoveTo,LineToでsin波を描きたいのですが、 for文で繰り返し MoveTo(x0+sin[i],?) LineTo(x0+sin[i+1],?) の、はてなの部分に何を入れればよいかわかりません。(x0:勝手にきめた原点)x0+sin[i]も、これで良いのか「?」です・・・。 お願いします。

専門家に質問してみよう