fork download
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <math.h>
  4. #include <float.h>
  5.  
  6. #define FLG_CONTACT_LESS (0)
  7. #define FLG_A_TOUCH_ON_B (1)
  8. #define FLG_A_IS_IN_B (2)
  9.  
  10. #define SIMULATION_SECONDS (20.0)
  11.  
  12. typedef struct {
  13. /* 球の物理的な値 */
  14. double r; /* 球の半径(m) */
  15. double m; /* 球の質量(kg) */
  16.  
  17. /* 球の初期状態を表す変数 */
  18. double x0; /* 球のx軸上の初期位置 (m) */
  19. double y0; /* 球のy軸上の初期位置 (m) */
  20. double vx0; /* 球のx軸上の初期速度 (m/s) */
  21. double vy0; /* 球のy軸上の初期速度 (m/s) */
  22.  
  23. /* 球の現在の状態を表す変数 */
  24. double x; /* 球の中心座標のx軸上の現在地 (m) */
  25. double y; /* 球の中心座標のy軸上の現在地 (m) */
  26. double vx; /* x軸方向の現在の速度 (m/s) */
  27. double vy; /* y軸方向の現在の速度 (m/s) */
  28.  
  29. } sphere_object_t;
  30.  
  31. /* 正負は数学の平面を表すxy軸と一致する。
  32.   実験1:
  33.   物体a: 半径 1cm, 100g, 初期位置右に 10cm , 上に 0cm の状態で、
  34.   左に 1 cm/sec の速度で進む。
  35.   物体b: 半径 1cm, 100g, 初期位置左に 10cm , 上に 0cm の状態で、
  36.   右に 1 cm/sec の速度で進む。
  37.   10 秒後に物体a,b が衝突する。
  38.  
  39.   実験2: 現在は適当。
  40.   物体a 半径 2cm, 100g, 初期位置右に 10cm , 上に 0cm の状態で、
  41.   左に 1 cm/sec の速度で進む。
  42.   物体b: 半径 10cm, 100g, 初期位置左に 10cm , 上に 0cm の状態で、
  43.   右に 1 cm/sec の速度で進む。
  44.  */
  45.  
  46. int so_init(sphere_object_t *so,
  47. double r, double m,
  48. double x0, double y0,
  49. double vx0, double vy0)
  50. {
  51. /* 球の物理的な値 */
  52. so->r = r; /* 球の半径(m) */
  53. so->m = m; /* 球の質量(kg) */
  54.  
  55. /* 球の初期状態を表す変数 */
  56. so->x0 = x0; /* 球のx軸上の初期位置 (m) */
  57. so->y0 = y0; /* 球のy軸上の初期位置 (m) */
  58. so->vx0 = vx0; /* 球のx軸上の初期速度 (m/s) */
  59. so->vy0 = vy0; /* 球のy軸上の初期速度 (m/s) */
  60.  
  61. /* 球の現在の状態を表す変数 */
  62. so->x = x0; /* 球の中心座標のx軸上の現在地 (m) */
  63. so->y = y0; /* 球の中心座標のy軸上の現在地 (m) */
  64. so->vx = vx0; /* x軸方向の現在の速度 (m/s) */
  65. so->vy = vy0; /* y軸方向の現在の速度 (m/s) */
  66.  
  67. return 0;
  68. }
  69.  
  70. int so_view_current(sphere_object_t *so)
  71. {
  72. fprintf(stdout, " so = %p\n", so);
  73.  
  74. /* 球の現在の状態 */
  75. fprintf(stdout, " so->(r, x, y, m, vx, vy) = (%.3f, %.3f, %.3f, %.3f, %.3f, %.3f)\n", so->r, so->x, so->y, so->m, so->vx, so->vy);
  76.  
  77. return 0;
  78. }
  79.  
  80. int so_view(sphere_object_t *so)
  81. {
  82. fprintf(stdout, " so = %p\n", so);
  83. /* 球の物理的な値 */
  84. fprintf(stdout, " so->(r, m) = (%.3f, %.3f)\n", so->r, so->m);
  85.  
  86. /* 球の初期状態を表す変数 */
  87. fprintf(stdout, "so->(x0, y0, vx0, vy0) = (%.3f, %.3f, %.3f, %.3f)\n", so->x0, so->y0, so->vx0, so->vy0);
  88.  
  89. /* 球の現在の状態を表す変数 */
  90. fprintf(stdout, " so->(x, y, vx, vy) = (%.3f, %.3f, %.3f, %.3f)\n", so->x, so->y, so->vx, so->vy);
  91.  
  92.  
  93. return 0;
  94. }
  95.  
  96. int so_copy(sphere_object_t *dst, sphere_object_t *src)
  97. {
  98. memcpy(dst, src, sizeof(sphere_object_t));
  99.  
  100. return 0;
  101. }
  102.  
  103. int so_collision_detect(sphere_object_t *a, sphere_object_t *b)
  104. {
  105. double distance_of_a_and_b, sum_of_a_r_and_b_r;
  106. double dx, dx2, dy, dy2;
  107. int hit_flg = FLG_CONTACT_LESS;
  108.  
  109. sum_of_a_r_and_b_r = a->r + b->r;
  110.  
  111. dx = a->x - b->x;
  112. dx2 = dx * dx;
  113. dy = a->y - b->y;
  114. dy2 = dy * dy;
  115. distance_of_a_and_b = sqrt(dx2 + dy2);
  116.  
  117. fprintf(stdout, " sum_of_a_r_and_b_r = %f\n", sum_of_a_r_and_b_r);
  118. fprintf(stdout, "distance_of_a_and_b = %f\n", distance_of_a_and_b);
  119. if (fabs(distance_of_a_and_b - sum_of_a_r_and_b_r) < DBL_EPSILON){
  120. fprintf(stdout, "/* a touch on b */\n");
  121. hit_flg |= FLG_A_TOUCH_ON_B;
  122. }
  123. if (distance_of_a_and_b < sum_of_a_r_and_b_r) {
  124. fprintf(stdout, "/* a is in b */\n");
  125. hit_flg |= FLG_A_IS_IN_B;
  126. }
  127.  
  128. return hit_flg;
  129. }
  130.  
  131. /* sphere_object の何秒後の状態を知りたいか、sec引数にて指定する。*/
  132. int so_update(sphere_object_t *dst, sphere_object_t *src, double sec)
  133. {
  134. sphere_object_t tmp_, *tmp = &tmp_;
  135.  
  136. so_copy(tmp, src);
  137. tmp->x += tmp->vx * sec;
  138. tmp->y += tmp->vy * sec;
  139. so_copy(dst, tmp);
  140.  
  141. return 0;
  142. }
  143.  
  144. int so_clash(double *v1_, double *v2_,
  145. double m1, double v1,
  146. double m2, double v2,
  147. double e)
  148. {
  149. /*
  150.   1. m1 * v1 + m2 + v2 = m1 * v1' + m2 * v2'
  151.   2. v1' - v2' = -e * (v1 - v2)
  152.   e = - ((v1' - v2') / (v1 - v2))
  153.   2-1. v2' = v1' + e * (v1 - v2)
  154.   2-2. v1' = v2' - e * (v1 - v2)
  155.   1. に 2-1. を代入して、
  156.   m1 * v1 + m2 + v2 = m1 * v1' + m2 * (v1' + e * (v1 - v2))
  157.   = v1' * (m1 + m2) + e * m2 * (v1 - v2)
  158.   v1' * (m1 + m2) = m1 * v1 + m2 * v2 - (e * m2 * (v1 - v2))
  159.  
  160.   m1 * v1 + m2 * v2 - m2 * (e * (v1 - v2))
  161.   v1' = ----------------------------------------
  162.   m1 + m2
  163.  
  164.   1. に 2-2. を代入して、
  165.   m1 * v1 + m2 * v2 + m1 * (e * (v1 - v2))
  166.   v2' = ----------------------------------------
  167.   m1 + m2
  168.  
  169.   */
  170. *v1_ = (m1 * v1 + m2 * v2 - m2 * (e * (v1 - v2))) / (m1 + m2);
  171. *v2_ = (m1 * v1 + m2 * v2 + m1 * (e * (v1 - v2))) / (m1 + m2);
  172.  
  173. return 0;
  174. }
  175.  
  176. int so_change_mv(sphere_object_t *a, sphere_object_t *b, double e)
  177. {
  178. /* v1 as a->vx, v2 as b->vx */
  179. so_clash(&a->vx, &b->vx, a->m, a->vx, b->m, b->vx, e);
  180. so_clash(&a->vy, &b->vy, a->m, a->vy, b->m, b->vy, e);
  181.  
  182. return 0;
  183. }
  184.  
  185. /* 完全弾性衝突の実験 */
  186. void experiment_1(double e)
  187. {
  188. sphere_object_t a_, b_, *a = &a_, *b = &b_;
  189. double sec, delta;
  190. int collision_flg;
  191.  
  192. /* r, m, x0, y0, vx0, vy0 */
  193. so_init(a, 0.010, 0.10, 0.100, 0.000, -0.010, 0.000);
  194. so_init(b, 0.010, 0.10, -0.100, 0.000, 0.010, 0.000);
  195.  
  196. delta = 1.0;
  197. for (sec=0.0;sec<SIMULATION_SECONDS + 1.0;sec+=delta) {
  198. fprintf(stdout, "現在は実験開始から %.1f 秒後の状態です。\n", sec);
  199. so_view_current(a);
  200. so_view_current(b);
  201. collision_flg = so_collision_detect(a, b);
  202. if (collision_flg) {
  203. fprintf(stdout, "a detect collision of b.(collision_flg=%d)\n", collision_flg);
  204. so_change_mv(a, b, e);
  205. }
  206. fprintf(stdout, "\n");
  207.  
  208. so_update(a, a, delta);
  209. so_update(b, b, delta);
  210. }
  211. }
  212.  
  213. int main(void)
  214. {
  215. /* 完全弾性衝突の実験 */
  216. experiment_1(1.0);
  217.  
  218. return 0;
  219. }
Success #stdin #stdout 0s 2252KB
stdin
Standard input is empty
stdout
現在は実験開始から 0.0 秒後の状態です。
                       so = 0xbf8901c0
 so->(r, x, y, m, vx, vy) = (0.010, 0.100, 0.000, 0.100, -0.010, 0.000)
                       so = 0xbf890210
 so->(r, x, y, m, vx, vy) = (0.010, -0.100, 0.000, 0.100, 0.010, 0.000)
 sum_of_a_r_and_b_r = 0.020000
distance_of_a_and_b = 0.200000

現在は実験開始から 1.0 秒後の状態です。
                       so = 0xbf8901c0
 so->(r, x, y, m, vx, vy) = (0.010, 0.090, 0.000, 0.100, -0.010, 0.000)
                       so = 0xbf890210
 so->(r, x, y, m, vx, vy) = (0.010, -0.090, 0.000, 0.100, 0.010, 0.000)
 sum_of_a_r_and_b_r = 0.020000
distance_of_a_and_b = 0.180000

現在は実験開始から 2.0 秒後の状態です。
                       so = 0xbf8901c0
 so->(r, x, y, m, vx, vy) = (0.010, 0.080, 0.000, 0.100, -0.010, 0.000)
                       so = 0xbf890210
 so->(r, x, y, m, vx, vy) = (0.010, -0.080, 0.000, 0.100, 0.010, 0.000)
 sum_of_a_r_and_b_r = 0.020000
distance_of_a_and_b = 0.160000

現在は実験開始から 3.0 秒後の状態です。
                       so = 0xbf8901c0
 so->(r, x, y, m, vx, vy) = (0.010, 0.070, 0.000, 0.100, -0.010, 0.000)
                       so = 0xbf890210
 so->(r, x, y, m, vx, vy) = (0.010, -0.070, 0.000, 0.100, 0.010, 0.000)
 sum_of_a_r_and_b_r = 0.020000
distance_of_a_and_b = 0.140000

現在は実験開始から 4.0 秒後の状態です。
                       so = 0xbf8901c0
 so->(r, x, y, m, vx, vy) = (0.010, 0.060, 0.000, 0.100, -0.010, 0.000)
                       so = 0xbf890210
 so->(r, x, y, m, vx, vy) = (0.010, -0.060, 0.000, 0.100, 0.010, 0.000)
 sum_of_a_r_and_b_r = 0.020000
distance_of_a_and_b = 0.120000

現在は実験開始から 5.0 秒後の状態です。
                       so = 0xbf8901c0
 so->(r, x, y, m, vx, vy) = (0.010, 0.050, 0.000, 0.100, -0.010, 0.000)
                       so = 0xbf890210
 so->(r, x, y, m, vx, vy) = (0.010, -0.050, 0.000, 0.100, 0.010, 0.000)
 sum_of_a_r_and_b_r = 0.020000
distance_of_a_and_b = 0.100000

現在は実験開始から 6.0 秒後の状態です。
                       so = 0xbf8901c0
 so->(r, x, y, m, vx, vy) = (0.010, 0.040, 0.000, 0.100, -0.010, 0.000)
                       so = 0xbf890210
 so->(r, x, y, m, vx, vy) = (0.010, -0.040, 0.000, 0.100, 0.010, 0.000)
 sum_of_a_r_and_b_r = 0.020000
distance_of_a_and_b = 0.080000

現在は実験開始から 7.0 秒後の状態です。
                       so = 0xbf8901c0
 so->(r, x, y, m, vx, vy) = (0.010, 0.030, 0.000, 0.100, -0.010, 0.000)
                       so = 0xbf890210
 so->(r, x, y, m, vx, vy) = (0.010, -0.030, 0.000, 0.100, 0.010, 0.000)
 sum_of_a_r_and_b_r = 0.020000
distance_of_a_and_b = 0.060000

現在は実験開始から 8.0 秒後の状態です。
                       so = 0xbf8901c0
 so->(r, x, y, m, vx, vy) = (0.010, 0.020, 0.000, 0.100, -0.010, 0.000)
                       so = 0xbf890210
 so->(r, x, y, m, vx, vy) = (0.010, -0.020, 0.000, 0.100, 0.010, 0.000)
 sum_of_a_r_and_b_r = 0.020000
distance_of_a_and_b = 0.040000

現在は実験開始から 9.0 秒後の状態です。
                       so = 0xbf8901c0
 so->(r, x, y, m, vx, vy) = (0.010, 0.010, 0.000, 0.100, -0.010, 0.000)
                       so = 0xbf890210
 so->(r, x, y, m, vx, vy) = (0.010, -0.010, 0.000, 0.100, 0.010, 0.000)
 sum_of_a_r_and_b_r = 0.020000
distance_of_a_and_b = 0.020000
/* a touch on b */
a detect collision of b.(collision_flg=1)

現在は実験開始から 10.0 秒後の状態です。
                       so = 0xbf8901c0
 so->(r, x, y, m, vx, vy) = (0.010, 0.020, 0.000, 0.100, 0.010, 0.000)
                       so = 0xbf890210
 so->(r, x, y, m, vx, vy) = (0.010, -0.020, 0.000, 0.100, -0.010, 0.000)
 sum_of_a_r_and_b_r = 0.020000
distance_of_a_and_b = 0.040000

現在は実験開始から 11.0 秒後の状態です。
                       so = 0xbf8901c0
 so->(r, x, y, m, vx, vy) = (0.010, 0.030, 0.000, 0.100, 0.010, 0.000)
                       so = 0xbf890210
 so->(r, x, y, m, vx, vy) = (0.010, -0.030, 0.000, 0.100, -0.010, 0.000)
 sum_of_a_r_and_b_r = 0.020000
distance_of_a_and_b = 0.060000

現在は実験開始から 12.0 秒後の状態です。
                       so = 0xbf8901c0
 so->(r, x, y, m, vx, vy) = (0.010, 0.040, 0.000, 0.100, 0.010, 0.000)
                       so = 0xbf890210
 so->(r, x, y, m, vx, vy) = (0.010, -0.040, 0.000, 0.100, -0.010, 0.000)
 sum_of_a_r_and_b_r = 0.020000
distance_of_a_and_b = 0.080000

現在は実験開始から 13.0 秒後の状態です。
                       so = 0xbf8901c0
 so->(r, x, y, m, vx, vy) = (0.010, 0.050, 0.000, 0.100, 0.010, 0.000)
                       so = 0xbf890210
 so->(r, x, y, m, vx, vy) = (0.010, -0.050, 0.000, 0.100, -0.010, 0.000)
 sum_of_a_r_and_b_r = 0.020000
distance_of_a_and_b = 0.100000

現在は実験開始から 14.0 秒後の状態です。
                       so = 0xbf8901c0
 so->(r, x, y, m, vx, vy) = (0.010, 0.060, 0.000, 0.100, 0.010, 0.000)
                       so = 0xbf890210
 so->(r, x, y, m, vx, vy) = (0.010, -0.060, 0.000, 0.100, -0.010, 0.000)
 sum_of_a_r_and_b_r = 0.020000
distance_of_a_and_b = 0.120000

現在は実験開始から 15.0 秒後の状態です。
                       so = 0xbf8901c0
 so->(r, x, y, m, vx, vy) = (0.010, 0.070, 0.000, 0.100, 0.010, 0.000)
                       so = 0xbf890210
 so->(r, x, y, m, vx, vy) = (0.010, -0.070, 0.000, 0.100, -0.010, 0.000)
 sum_of_a_r_and_b_r = 0.020000
distance_of_a_and_b = 0.140000

現在は実験開始から 16.0 秒後の状態です。
                       so = 0xbf8901c0
 so->(r, x, y, m, vx, vy) = (0.010, 0.080, 0.000, 0.100, 0.010, 0.000)
                       so = 0xbf890210
 so->(r, x, y, m, vx, vy) = (0.010, -0.080, 0.000, 0.100, -0.010, 0.000)
 sum_of_a_r_and_b_r = 0.020000
distance_of_a_and_b = 0.160000

現在は実験開始から 17.0 秒後の状態です。
                       so = 0xbf8901c0
 so->(r, x, y, m, vx, vy) = (0.010, 0.090, 0.000, 0.100, 0.010, 0.000)
                       so = 0xbf890210
 so->(r, x, y, m, vx, vy) = (0.010, -0.090, 0.000, 0.100, -0.010, 0.000)
 sum_of_a_r_and_b_r = 0.020000
distance_of_a_and_b = 0.180000

現在は実験開始から 18.0 秒後の状態です。
                       so = 0xbf8901c0
 so->(r, x, y, m, vx, vy) = (0.010, 0.100, 0.000, 0.100, 0.010, 0.000)
                       so = 0xbf890210
 so->(r, x, y, m, vx, vy) = (0.010, -0.100, 0.000, 0.100, -0.010, 0.000)
 sum_of_a_r_and_b_r = 0.020000
distance_of_a_and_b = 0.200000

現在は実験開始から 19.0 秒後の状態です。
                       so = 0xbf8901c0
 so->(r, x, y, m, vx, vy) = (0.010, 0.110, 0.000, 0.100, 0.010, 0.000)
                       so = 0xbf890210
 so->(r, x, y, m, vx, vy) = (0.010, -0.110, 0.000, 0.100, -0.010, 0.000)
 sum_of_a_r_and_b_r = 0.020000
distance_of_a_and_b = 0.220000

現在は実験開始から 20.0 秒後の状態です。
                       so = 0xbf8901c0
 so->(r, x, y, m, vx, vy) = (0.010, 0.120, 0.000, 0.100, 0.010, 0.000)
                       so = 0xbf890210
 so->(r, x, y, m, vx, vy) = (0.010, -0.120, 0.000, 0.100, -0.010, 0.000)
 sum_of_a_r_and_b_r = 0.020000
distance_of_a_and_b = 0.240000