Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

円の中を反射する点をgnuplotで描画したい!

Q&A

Closed

前回間違えて記事に質問を投稿してしまったので、質問欄にリベンジ投稿します!ぜひ知識を貸してください!!

解決したいこと

大学の授業でC言語を勉強しています。
授業で正方形の中を反射して動く点のコードを作りました。そこで、追加の課題として円の中を反射する点を描画するというものが出題されました。
自分で作っては見たのですが、うまくいかなかったので教えていただきたいです。

参考に、正方形の中を反射するコードは、以下に貼っておきます。(20回反射したら終了するようになっています。)

//ball.c
#include <stdio.h>
#include <unistd.h>
#include <math.h>

int main(void){
  FILE *gp,*fp;

  int counter = 0;
  int counter_max = 20;
  double x,y, vx,vy;
  
  // set boundary condition//
  double xmin = 0.0;
  double ymin = 0.0;    
  double xmax = 2.0;
  double ymax = 2.0;

  fp = fopen("trajectory.dat","w"); // 軌跡を保存
  gp = popen("gnuplot", "w"); // 
  fprintf(gp,"set terminal gif animate delay 2 loop 0; set output 'ball.gif'\n"); // 描画した結果をgifに保存     
  fprintf(gp, "set border 0\n");  // 枠線を消す
  fprintf(gp, "set object 1 rect from first %f, first %f to first %f, first %f back fc rgb 'white' fs solid\n", xmin,ymin,xmax,ymax);
  // boxの背景を白抜きにする
  fprintf(gp, "set xrange [%f:%f]\n",xmin-0.5,xmax+0.5);
  fprintf(gp, "set yrange [%f:%f]\n",ymin-0.5,ymax+0.5);
  fprintf(gp, "set size square\n");
  fprintf(gp, "unset tics\n");  
  
  // set initial condition //
  x = 0.2;
  y = 0.2;
  vx = 0.02;
  vy = sqrt(2.0)*0.01;

  while (counter < counter_max){
    x = x + vx;
    y = y + vy;        
    if(x>=xmax) {
      x=2.0*xmax-x;
      vx=-vx;
      counter += 1;
    }
    if(x<=xmin) {
      x=-x;
      vx=-vx;
      counter += 1;
    }
    if(y>=ymax) {
      y=2.0*ymax-y;
      vy=-vy;
      counter += 1;
    }
    if(y<=ymin) {
      y=-y;
      vy=-vy;
      counter += 1;
    }
    
    fprintf(fp,"%f %f\n", x,y);
    
    fprintf(gp,"set title '%d-th bounces'\n", counter);        
    fprintf(gp,"plot '-'w p pt 7 ps 7 lc 3 tit ''\n");
    fprintf(gp,"%f %f\n",x,y);
    fprintf(gp,"e\n");
    fflush(gp);
    usleep(5000);
  }
  return 0;
}
0

2Answer

もともとのソースコードっぽくしているので直したい部分もありますが・・

こんな感じですかねえ…… なお、衝突周りの実装が雑なので、若干誤差がのります。

image.png

//ball2.c
// gcc ball2.c -o a.out -lm
#include <stdio.h>
#include <unistd.h>
#include <math.h>

int main( void )
{
  FILE *gp,*fp;

  int counter = 0;
  int counter_max = 6;

  // circle area
  double cx   = 1.0;
  double cy   = 1.0;
  double cr   = 1.0;

  // set boundary condition//
  double xmin = cx - cr;
  double ymin = cy - cr;
  double xmax = cx + cr;
  double ymax = cy + cr;

  //
  fp = fopen("trajectory.dat","w"); // 軌跡を保存
  gp = popen("gnuplot", "w"); //
  fprintf(gp,"set terminal gif animate delay 2 loop 0; set output 'ball.gif'\n"); // 描画した結果をgifに保存
  fprintf(gp, "set border 0\n");  // 枠線を消す
  // fprintf(gp, "set object 1 rect from first %f, first %f to first %f, first %f back fc rgb 'white' fs solid\n", xmin,ymin,xmax,ymax);
  // boxの背景を白抜きにする
  fprintf(gp, "set xrange [%f:%f]\n",xmin-0.5,xmax+0.5);
  fprintf(gp, "set yrange [%f:%f]\n",ymin-0.5,ymax+0.5);
  fprintf(gp, "set size square\n");
  fprintf(gp, "unset tics\n");

  // set initial condition //
  double x = 0.4;
  double y = 0.8;
  double v = 0.02;
  double rad = ( (double)36.0 / 180.0 ) * M_PI;

  while (counter < counter_max)
  {
    // Update Position
    x = x + v * cos ( rad );
    y = y + v * sin ( rad );

    // Detect collesion
    if ( ( cx - x ) * ( cx - x) + ( cy - y ) * (cy - y ) > cr * cr )
    {
      double radB = atan2(y - cy, x - cx);
      double radX = radB - rad;
      rad =  M_PI + rad + radX * 2.0;

      // Normalize radian.
      while ( rad > 2.0 * M_PI ) { rad -= 2.0 * M_PI; }
      while ( rad < 0          ) { rad += 2.0 * M_PI; }

      // count up.
      counter += 1;
    }
    fprintf(gp, "set title '%d-th bounces'\n", counter);
    fprintf(gp, "set parametric \n");
    fprintf(gp, "set nokey \n");
    fprintf(gp, "plot cos(t)+1.0,sin(t)+1.0, " );
    fprintf(gp, "'-'w p pt 7 ps 2 lc 3 tit ''\n");
    fprintf(gp, "%f %f \n",x, y);
    fprintf(gp, "e\n ");
    fflush(gp);
  }
  return 0;
}
1Like

markdownで円は描け無いの?svgもダメみたい。

□ ○

さて、
多角形の場合、辺に対する入射角?と反射角?は辺と直角方向に対照になると思います。
 一方、円の場合は中心点から入射点?に対照になると思います。(定義は曖昧)
 加えて、発射点、入射点、中心点の三角形と入射点、到達点、中心点の三角形は反転させると合同ですね!
 
 この考えは正しいでしょうか?

ここで、円の常套手段のラジアン角が登場!

そうすると、ラジアン角と円の半径で入射点?が求まり、発射点からの軌道線が描けます。
 更に、中心点から対照になる到達点が特定できるのでは?角度計算不要??ではなく、ラジアン角で計算している?

暇人x in 電車

0Like

Your answer might help someone💌