fork download
  1. /*
  2.   ttps://ideone.com/trIqHxの修正版
  3.   2019/03/03 関数hogehogeの条件分岐を修正。
  4.   2019/03/04 関数fugaの計算方法が間違っていたので修正。
  5.  
  6.   プログラミングのお題スレ Part13
  7.   ttps://mevius.5ch.net/test/read.cgi/tech/1549160513/
  8.  
  9.   473デフォルトの名無しさん2019/03/03(日) 08:56:00.68ID:NMVimqZR
  10.   お題:2つの円が重なった時、重なった部分の面積を求めなさい。
  11.   このプログラムでは以下のURLの画像の場合を計算します。
  12.   ttps://imgur.com/i2G9Ahd
  13.  
  14.  
  15.   注: マジで実装する場合は1つ1つのコードが本当に正しいか確認してください。
  16. */
  17. #include <stdio.h>
  18. #include <math.h>
  19.  
  20. #ifndef M_PI
  21. #define M_PI 3.14159265358979323846
  22. #endif /* M_PI */
  23.  
  24. /* 円の構造体定義 */
  25. typedef struct{
  26. double x; //座標x
  27. double y; //座標y
  28. double r; //半径r
  29. }cir_t;
  30.  
  31. double hoge(cir_t a, cir_t b){
  32. double l = sqrt( (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y) );
  33. double theta_a = 2.0 * acos( (l * l + a.r * a.r - b.r * b.r) / (2.0 * l * a.r) );
  34. double theta_b = 2.0 * acos( (l * l + b.r * b.r - a.r * a.r) / (2.0 * l * b.r) );
  35. double area_a = 0.5 * a.r * a.r * (theta_a - sin(theta_a));
  36. double area_b = 0.5 * b.r * b.r * (theta_b - sin(theta_b));
  37. return (area_a + area_b);
  38. }
  39.  
  40. double fuga(cir_t a, cir_t b){
  41. double l = sqrt( (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y) );
  42. double theta_a = 2.0 * acos( (l * l + a.r * a.r - b.r * b.r) / (2.0 * l * a.r) );
  43. double theta_b = 2.0 * acos( (l * l + b.r * b.r - a.r * a.r) / (2.0 * l * b.r) );
  44. double area_a = 0.5 * a.r * a.r * (theta_a - sin(theta_a));
  45. double area_b = 0.5 * b.r * b.r * theta_b;
  46. double area_c = 0.5 * b.r * b.r * sin(2.0 * M_PI - theta_b);
  47. return (area_a + area_b + area_c);
  48. }
  49.  
  50. double piyo(cir_t a){
  51. return (a.r * a.r * M_PI);
  52. }
  53.  
  54. double hogehoge(cir_t a, cir_t b){
  55. if(a.r < 0.0 || b.r < 0.0){
  56. return (NAN);
  57. }
  58.  
  59. if(a.r < b.r){
  60. cir_t tmp = a;
  61. a = b;
  62. b = tmp;
  63. }
  64. double l = sqrt( (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y) );
  65.  
  66. if(a.r + b.r <= l){
  67. return (0.0);
  68. }
  69. else if(b.r + l < a.r){
  70. return (piyo(b));
  71. }
  72. else{
  73. double l_a = (l * l + a.r * a.r - b.r * b.r) / (2.0 * l * a.r) * a.r;
  74. if(l_a < l){
  75. return(hoge(a,b));
  76. }
  77. else{
  78. return(fuga(a,b));
  79. }
  80. }
  81. }
  82.  
  83. void calc(cir_t a, cir_t b){
  84. printf("座標x1 = %f\n"
  85. "座標y1 = %f\n"
  86. "半径r1 = %f\n",
  87. a.x,a.y,a.r);
  88. printf("座標x2 = %f\n"
  89. "座標y2 = %f\n"
  90. "半径r2 = %f\n",
  91. b.x,b.y,b.r);
  92.  
  93. double val = hogehoge(a,b);
  94. if(isnan(val)){
  95. puts("N/A");
  96. }
  97. else{
  98. printf("重複面積 = %f\n\n",hogehoge(a,b));
  99. }
  100. }
  101.  
  102. int main(void){
  103. cir_t no_0 = { -1200.0, 600.0, 400.0 };
  104. cir_t no_1 = { -500.0, 600.0, 200.0 };
  105. cir_t no_2 = { -1200.0, -600.0, 400.0 };
  106. cir_t no_3 = { -700.0, -600.0, 200.0 };
  107. cir_t no_4 = { 400.0, 600.0, 400.0 };
  108. cir_t no_5 = { 700.0, 600.0, 200.0 };
  109. cir_t no_6 = { 400.0, -600.0, 400.0 };
  110. cir_t no_7 = { 500.0, -600.0, 200.0 };
  111.  
  112. puts("No.0とNo.1"); calc(no_0, no_1);
  113. puts("No.2とNo.3"); calc(no_2, no_3);
  114. puts("No.4とNo.5"); calc(no_4, no_5);
  115. puts("No.6とNo.7"); calc(no_6, no_7);
  116.  
  117. return (0);
  118. }
  119.  
  120.  
Success #stdin #stdout 0s 9432KB
stdin
Standard input is empty
stdout
No.0とNo.1
座標x1 = -1200.000000
座標y1 = 600.000000
半径r1 = 400.000000
座標x2 = -500.000000
座標y2 = 600.000000
半径r2 = 200.000000
重複面積 = 0.000000

No.2とNo.3
座標x1 = -1200.000000
座標y1 = -600.000000
半径r1 = 400.000000
座標x2 = -700.000000
座標y2 = -600.000000
半径r2 = 200.000000
重複面積 = 20896.772083

No.4とNo.5
座標x1 = 400.000000
座標y1 = 600.000000
半径r1 = 400.000000
座標x2 = 700.000000
座標y2 = 600.000000
半径r2 = 200.000000
重複面積 = 95701.994730

No.6とNo.7
座標x1 = 400.000000
座標y1 = -600.000000
半径r1 = 400.000000
座標x2 = 500.000000
座標y2 = -600.000000
半径r2 = 200.000000
重複面積 = 125663.706144