C言語によるプログラミングで四角形を描く方法と重なった辺のデータ取得について

このQ&Aのポイント
  • C言語によるプログラミングで四角形を描くアルゴリズムについて考えています。四角形をX,Y方向に分割し、辺に番号をつけ、その辺のデータを取得する方法を知りたいです。
  • 四角形を1つ描く場合はうまくデータが取れるようになりましたが、四角形がX,Y方向に重なった場合、重なった辺のデータを正しく取得することができません。
  • 具体的には、最初の四角形をx,y共に2分割すると辺の数は全部で8個になり、上辺の番号は5,6になります。次にy方向に同じ形状の四角形を増やした際に、1,2(7,8)が6,5と重なるため、若い番号に書き換えたいですが、どのようなif構文を使用すれば良いかが分かりません。
回答を見る
  • ベストアンサー

C言語によるプログラミング

四角形を描き、X,Y方向にそれぞれ分割し、分割した辺に左下から反時計回りに番号をつけ、その辺の両端のx,yデータを書き出すというアルゴリズムを考えています。 1つの四角形ならうまくデータが取れるようになったのですが、四角形がX,Y方向に重なった時に、重なった辺のデータがうまく取れません。例えば、最初の四角形をx,y共に2分割すると辺の数は全部で8個になり上辺の番号は5,6ということになります。次にy方向に同じ形状の四角形を増やした時に、1,2(7,8)は6,5と重なるので、若い番号に書き換えたい(6=7,7=5)ですが、どこに、どんなif構文なりをいれればいいのかが分かりません。コードを載せると800字を超えてしまうので、流れだけ書きます。 o=0; so4=so4+so2; p=adn; for(v=1;v<ups1+1;v++) { for(u=1;u<ups2+1;u++) { for(r=0;r<su4;r++){ for(r=0;r<su4;r++){ p=0; s=0; data[o][p]=o+1; data[o][p+1]=ups3; data[o][p+2]=bu4*r+bu1*(v-1); data[o][p+4]=bu5*s+bu2*(u-1); data[o][p+5]=bu4*(r+1)+bu1*(v-1); data[o][p+7]=bu5*s+bu2*(u-1); o=o+1; } この後は4辺のデータを同じ風に書くです。

質問者が選んだベストアンサー

  • ベストアンサー
  • kacchann
  • ベストアンサー率58% (347/594)
回答No.3

>データが真逆になるので、同じと認識してくれない 認識して「くれない」!? 認識して「くれない」のではなく、 認識「させる」のだ。 --- 「線分が同一かどうかの判定処理」についてのみ書く。 とにかく、「理屈」を理解し、 その理屈にのっとってソースコードを書こう。 --- 四角形の"一周"を適当な数の"小片"に分割する。 小片とは、すなわち「線分」である。 線分とは、「始点と終点を持ったもの」にほかならない。 すなわち、小片を表現する(一意に決定する)には、 始点と終点のデータさえあればよい。 (ここ最重要ポイント) したがって、 すべての四角形の、すべての小片のデータは、 次のような「4つの配列」で表せる。 int start_x[kSize];//始点のx座標 int start_y[kSize];//始点のy座標 int end_x[kSize];//終点のx座標 int end_y[kSize];//終点のy座標 (※kSize は存在するすべての小片の数) --- じゃあ例えば、現在、xy平面上に、たった2つの線分があるとする。 1つは、始点(0, 0), 終点(1, 0) もう1つは、始点(1, 0), 終点(0, 0)。 つまり2つの線分は始点と終点が逆になっている。 (本来、この2つの線分は等しい「はず」である) では、この2つの線分を、 上記のデータ構造(「4つの配列」)に当てはめてみよう。 start_x = {0, 1} start_y = {0, 0} end_x = {1, 0} end_y = {0, 0} (kSize = 2) これで、「xy平面上に存在する線分のすべて」が表された。 ---- 次に、この2つの線分が「等しいかどうか」を調べたい。 どのような処理を書けばよいだろうか? パッと思いつくかな? 「線分として等しい」とは、どういうことだろう? --- 「線分として等しい」とは、すなわち、 「『始点同士が一致』し、かつ『終点同士が一致する』」 または 「『一方の始点と他方の終点が一致』し、    かつ『一方の終点と他方の始点が一致する』」 ことにほかならない。 (ここ重要ポイント) 具体的に書けば、 int i, sx1, sy1, ex1, ey1, sx2, sy2, ex2, ey2; //線分1のデータ sx1 = start_x[0]; sy1 = start_y[0]; ex1 = end_x[0]; ey1 = end_y[0]; //線分2のデータ sx2 = start_x[1]; sy2 = start_y[1]; ex2 = end_x[1]; ey2 = end_y[1]; if ( (sx1 == sx2) && (sy1 == sy2) && (ex1 == ex2) && (ey1 == ey2) ){ printf("等しいです"); } else if ((sx1 == ex2) && (sy1 == ey2) && (ex1 == sx2) && (ey1 == sy2)) { printf("等しいです");//向きは逆だが } else { printf("等しくありません"); }

その他の回答 (2)

  • kacchann
  • ベストアンサー率58% (347/594)
回答No.2

#1です >この文をもう少し詳しく書いていただけると 『重複を許さない配列(またはリスト)を作る』というのは、 たとえば、 次のような要素からなる配列(またはリスト)があるとする。 arr = {"りんご", "みかん", "なし", "りんご", "バナナ", "なし"} この配列は、要素が重複している。 この配列を元にして、 新たに、以下のような「重複を許さない配列」を作るということ。 newArr = {"りんご", "みかん", "なし", "バナナ"} または newArr = {"りんご", "みかん", "なし", "バナナ", "", ""} または newArr = {"りんご", "みかん", "なし", "バナナ", -1, -1}

hiro0163
質問者

補足

今回の重複は、データが真逆になるので、同じと認識してくれないのです・・・。なるべく多くのソースコードを書いてみました。 float souyouso2; float su4,su5; //x,yの分割数 float bu1,bu2,bu4,bu5; //距離 su4=ups4; su5=ups5; //ups1,2は四角の数。両方1の時はうまくいくが2になると辺のデータが重なる。 bu1=wide/ups1; bu2=hight/ups2; bu4=bu1/ups4; bu5=bu2/ups5; souyouso2=ups4*2+ups5*2; //各寸法決定/////// int o,p,q,r,s,t,u,v; ss3=0; ss4=0; BeginWaitCursor(); for(q=0;q<1;q++){ r=0; domno[q][r]=ups1*ups2; domno[q][r+1]=souyouso2*ups1*ups2; so=domno[0][0]; } for(s=0;s<so;s++){ t=0; domdata[s][t]=souyouso2; domdata[s][t+1]=0; domdata[s][t+2]=0; so2=domdata[s][0]; } o=0; so4=so4+so2; p=adn; for(v=1;v<ups1+1;v++) { for(u=1;u<ups2+1;u++) { for(r=0;r<su4;r++){ p=0; s=0; data[o][p]=o+1; data[o][p+1]=ups3; data[o][p+2]=bu4*r+bu1*(v-1); data[o][p+4]=bu5*s+bu2*(u-1); data[o][p+5]=bu4*(r+1)+bu1*(v-1); data[o][p+7]=bu5*s+bu2*(u-1); o=o+1; } for(s=0;s<su5;s++){ p=0; r=su4; data[o][p]=o+1; data[o][p+1]=ups3; data[o][p+2]=bu4*r+bu1*(v-1); data[o][p+4]=bu5*s+bu2*(u-1); data[o][p+5]=bu4*r+bu1*(v-1); data[o][p+7]=bu5*(s+1)+bu2*(u-1); o=o+1; } for(r=su4-1;r>-1;r--){ p=0; s=su5; data[o][p]=o+1; data[o][p+1]=ups3; data[o][p+2]=bu4*(r+1)+bu1*(v-1); data[o][p+4]=bu5*s+bu2*(u-1); data[o][p+5]=bu4*r+bu1*(v-1); data[o][p+7]=bu5*s+bu2*(u-1); o=o+1; } for(s=su5-1;s>-1;s--){ p=0; r=0; data[o][p]=o+1; data[o][p+1]=ups3; data[o][p+2]=bu4*r+bu1*(v-1); data[o][p+4]=bu5*(s+1)+bu2*(u-1); data[o][p+5]=bu4*r+bu1*(v-1); data[o][p+7]=bu5*s+bu2*(u-1); o=o+1; } } } こんな感じです四角形を2回分けるのがダメなのかなぁ。迷惑なのは分かってますが、本当に行き詰まってしまって困ってます。どうかよろしくお願いいたします。

  • kacchann
  • ベストアンサー率58% (347/594)
回答No.1

考え方だけ書く。 <<まず前置き>> 四角形の「一周」を細かな小片に分ける。 たとえば、x軸方向の辺は各々 2分割、y軸方向の辺は各々 3分割するとすれば、 「一周」は (2+3)×2=10 の小片に分けられる。 同様に一周を分割された四角形が N個 あるとすると、 小片の総数 allFrags は allFrags = 10*N となる。 <<前置きおわり>> まず、すべての小片のデータ(※リストや配列)を作成する。 しかし、ここで作成されたデータの各要素は、互いに重複するものがあるかもしれない。 (※たとえば異なる2つの四角形の辺が重なっていた場合) よって、このデータをもとにして、 今度は「要素の重複を許さない」小片データを新規に作る。 もし小片の番号を取得したい場合は、 その番号として、 新しいデータのインデクス値を採用すればよい。

hiro0163
質問者

補足

まず、すべての小片のデータ(※リストや配列)を作成する。-> ここまではdata[o][p]を書き出す事によって可能なんですが、 このデータをもとにして、 今度は「要素の重複を許さない」小片データを新規に作る。-> この文をもう少し詳しく書いていただけるとありがたいのですが・・・。

関連するQ&A

  • 2次元配列のソートについて。

     四角形を描き、X,Y方向にそれぞれ分割し、分割した辺に左下から反時計回りに番号をつけ、その辺の両端のx,yデータを書き出すというアルゴリズムを考えています。  1つの四角形ならうまくデータが取れるようになったのですが、四角形がX,Y方向に重なった時に、問題が発生してしまいます。  例えば、最初の四角形をx,y共に2分割すると辺の数は全部で8個になり上辺の番号は5,6ということになります。次にy方向に同じ形状の四角形を増やした時に、1,2(7,8)は6,5と重なるので、若い番号に書き換えます(6=7,8=5)。その次は9から始まるのではなく、書き換えた事により使っていない番号、7から書き出したいのですが、どなたか詳しい方、回答の方よろしくお願いします。 _______________________ | 5 | 11 | | | | |6 4|12 10| | | | |____3_____|____ 9____| | 3 | 9 | | | | |4 2|2 8| | | | |____1_____|____7_____| for(p=0;p<souyouso1-1;p++){ for(n=p+1;n<souyouso1;n++){ if((data[n][x1]==data[p][x2])&&(data[n][y1]==data[p][y2]) &&(data[n][x2]==data[p][x1])&&(data[n][y2]==data[p][y1])){ data[n][0]=data[p][0]; break; } } }

  • c言語 プログラミング

    以下のプログラムで分からないところがあります。 数式をxpyの形式で入力して、(x,y:整数、p:x,-,*,/のいずれかの演算記号) 答えを表示するというプログラムなのですが、 5行目と9行目にある”-'0'”の意味が分からないので教えてください。 01: int x=0,y=0,z,i;char a[30],p; 02: printf("式を入力してください。:);gets(a); 03: for(i=0;a[i];i++) 04:  if('0'<=a[i] && a[i]<='9') 05:   x=10*x+a[i]-'0'; 06:  else{p=a[i]-'0';break;} 07: for(i++;a[i];i++) 08:  if('0'<=a[i] && a[i]<='9') 09:   y=10*y+a[i]-'0'; 010: switch(p){ 11:  case '+':z=x+y;break; 12:  case '-':z=x+y;break; 13:  case '*':z=x*y;break; 14:  case '/':z=x/y;break; 15:  default:puts("入力エラーです。");return 0; 16: } 17: printf("%d%c%d=%d\n",x,p,y,z); よろしくお願いします。(読みにくかったらメモ帳などにコピペしてください)

  • プログラミング(c言語)

    以下のプログラムでオイラー法を用いた2階微分方程式を解きたいのですが、xとvyの値が変化しません。どこが間違っているのか教えて欲しいです 写真は問題文です #define _USE_MATH_DEFINES #include<stdio.h> #include<math.h> int main(){ int i; double x,x0,y,y0,vx,vx0,vy,vy0,r,dt,t=0.0; double G=6.674/pow(10.0,11.0),M=1.988*pow(10.0,30.0); x0=1.496*pow(10.0,11.0),y0=0.0,vx0=0.0,vy0=2.978*pow(10.0,4.0); dt=M_PI/100; for(i=1;i<=2000;i++){ x=x0+dt*vx0; y=y0+dt*vy0; r=sqrt(x0*x0+y0*y0); vx=vx0-dt*(G*M*x0/(r*r*r));vy=vy0-dt*(G*M*y0/(r*r*r)); t=dt*i; printf("x(%f)=%e y(%f)=%e vx(%f)=%e vy(%f)=%e\n",t,x,t,y,t,vx,t,vy); x0=x; y0=y; vx0=vx; vy0=vy; } return(0); }

  • 初級プログラミングCです

    -11x+97y=1 という関数を満たす整数(x、y)を求めるプログラムなんですが 自力で考えると #include<studio.h> void main() { int x,y,a; for(x=1;;x++){ for(y=1;;y++){ a=-11*x+97*y+1 if (a==o) printf("(%d,%d)\n",x,y); if (a=!0) break } for(y=0;;y--){ a=-11*x+97*y+1 if (a==o) printf("(%d,%d)\n",x,y); if (a=!0) break } } for(x=1;;x--){ for(y=1;;y++){ a=-11*x+97*y+1 if (a==o) printf("(%d,%d)\n",x,y); if (a=!0) break } for(y=0;;y--){ a=-11*x+97*y+1 if (a==o) printf("(%d,%d)\n",x,y); if (a=!0) break } } } こうなりました xもyも上限がないのでこれでは無限ループであたいがでないとおもいます 実行するにもソフトがないのでわかりませんが たぶん間違えています どこが違いますかね? 根本的に違ったりしますか? 回答お待ちしています

  • c言語

    #include<stdio.h> main(void) { int x; double y,sum; void p(double *); for(sum=0.0,x=1;x<10;x++){ sum+=1.0/p(&x); ここでエラーがでます。 } printf("%d\n",sum); } void p(double *y) { *y*=*y; } どうしてエラーがでるかわかりません。教えてください!

  • C言語のプログラミングについて教えてください

    課題で下記に示すのようなデータをファイル名を入力してのそのデータを読み込みyの最大値とそのときのxの値を表示するプログラムを作成しろと言われたのですが、僕はプログラミングが初心者でむしろ苦手でホント困ってます。だれか助けてください、お願いします! データ    x  y 0.12132 3.45355 0.12353  3.415451 . . . . . . のようにxとyの行列となっていて、その数は2000個を超えています。 自分なりにやってみたのですがデータをすべて読み込まないし、まずどのようにして、yの最大値をだし、なおかつそのxの値を表示させるのもわかんなくてホント困っています。 本末転倒になりますが、プログラムを書いていただけるとほんと助かります。よろしくお願いいたします。 ちなみにこれが自分で考えたプログラムです。とりあえず、yの値がでかいのでyの最大値だけだすつもりでやってみたけど駄目でした。 #include <stdio.h> #include <stdlib.h> int main(void) { FILE *fin; char *list[256]; char buf[1024]; char filename1[80]; printf("入力ファイル名"); gets(filename1); fin=fopen(filename1,"r"); if (fin ==NULL) { printf("%sをオープンできません\n",filename1); exit(1); } while (fgets(buf, 1024, fin) !=NULL) { printf("%s",buf); } static float max; int x; fscanf(fin,"%f",&x); if(x>max){ max=x; printf("yの最大値=%f\n",max); } fclose(fin); }

  • C言語の課題

    何度も申し訳ありません http://okwave.jp/qa/q7877142.html より、回答を受けてプログラムを作成したのですが、 衝突時の時間と座標をどのように作成すれば良いか分からなく、 一秒後の点Pの位置を算出したのですが、合っているかどうかが分かりません。 非常に難しくで困っています。お助け下さい。 ソースコード #include <stdio.h> #include<math.h> int main(void) { float p,v,vx,vy,x,y,x1,y1,katamuki,gyaku,seiki_x,seiki_y,n,touei_x,touei_y,idoux,idouy,px,py; /* p=(x,y); v=(vx,vy); */ x=1.0; y=1.0; vx=1.0; //x方向の速さ vy=-2.0; //y方向の速さ y1=-x; //逆数 x1=-y; //逆数 printf("逆数は(x1,y1)=(%f,%f)\n",x1,y1); seiki_x=x1/(sqrt(x1*x1+y1*y1)); seiki_y=y1/(sqrt(x1*x1+y1*y1)); printf("正規化、(x方向,y方向)=(%f,%f)\n",seiki_x,seiki_y); n=-(vx*seiki_x)+(vy*seiki_y); //nは内積 touei_x=n*seiki_x; //touei_xは投影x軸 touei_y=n*seiki_y; //touei_yは投影y軸 printf("投影ベクトル(x,y)=(%f,%f)\n",touei_x,touei_y); idoux=vx+2*touei_x; //衝突後、点Pのxの移動方向 idouy=vy+2*touei_y; //衝突後、点Pのyの移動方向 px=-idoux; //点Pのx座標 py=-idouy; //点Pのy座標 printf("1秒後の位置は点P(x,y)=(%f,%f)",px,py); return 0; } /* 逆数は(x1,y1)=(-1.000000,-1.000000) 正規化、(x方向,y方向)=(-0.707107,-0.707107) 投影ベクトル(x,y)=(-1.500000,-1.500000) 1秒後の位置は点P(x,y)=(2.000000,5.000000) */

  • C言語のプログラミングについて

    C言語のプログラミングについて プログラミング初心者です。下のプログラムに詰まりました。 下のプログラムをfgets()、atoi()の組とgetchar()を用いて表示するにはどのようなプログラムを書けばよろしいのでしょうか? % ./descending 正の整数: 10 英文字: z 1: z 2: y 3: x 4: w 5: v 6: u 7: t 8: s 9: r 10: q %

  • 重積分の変数変換問題

    重積分について勉強していたら ∬x^2dxdy D:{(x,y)|x^2/a^2+y^2/b^2≦1}を 適当な変数変換を用いて解け …という問題でつまってしまいました。 僕はx/a=u,y/b=vと変数変換して 与式=∬a^3bu^2dudv E:{(u,v)|u^2+v^2≦1} として重積分して   =∫[v:-1→1]dv∫[u:-√1-v^2→:√1-v^2]a^3bu^2du =a^3b∫[v:-1→1][u^3/3][u:-√1-v^2→:√1-v^2]dv =2a^3b/3∫[v:-1→1](1-v^2)^3/2dv と求めましたが、これ以降が行き詰ってしましました。 これ以降の計算方法がわかる方、またはまったく異なる計算方法をご存知の方は教えてください!

  • Cプログラミングで困っています><

    添付した画像のように配列がx>y>zの順に並べ替えられました。実際はもっとデータありますが、省略します。 よくご覧いただけるとうれしいですが、二つのx座標の絶対値差が2以内かつ二つのy座標の絶対値差が2以内かつstate==1かつstate Flag==3であれば、(x,y固定)z方向に伸びる一つのグループ(何個かの球体が構成する直線)と見なします。(それぞれ行のx,y,z座標値は球体それぞれの中心座標である) さらに直線のグループ数とグループを構成する球体数を数えて、出力します。 以上のことですが質問の内容です。 まず配列を作り、例えばx[N]配列を作ったとします,座標の絶対値の差をdiff1,y[N]配列を作り、座標の絶対値差をdiff2と定義し, さらにz[N]配列を作ります。 for(i=0;i<N;i++){ diff1=x[i+1]-x[i]; diff2=y[i+1]-y[i]; } if(diff1<2&&diff2<2&&state==1&&stateFlag==3){ for(i=0;i<N;i++){ printf(“%lf”,x[i]); printf(“%lf”,y[i]); } } でもこの考えだとindexの番号がもともとバラバラなので、配列の番号として理解できないし、表示もちょく座標だけをx,y座標の表示だけして終わり、z方向に伸びるグループ数もわからないし、それぞれのグループを構成する球体数もわかりません。 よろしければ、ご教授いただければ幸いです。

専門家に質問してみよう