Advertisement
nna42799

Untitled

Apr 23rd, 2024
8
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.83 KB | None | 0 0
  1. // Yujia Zhou E22214017 AHU Software Engineering
  2.  
  3. // Noitce: This program require compile environment newer than C++20
  4. // (Including C++ 20) as some of it's newly added features used in
  5. // this program
  6.  
  7. #include <iostream>
  8. #include <algorithm>
  9. #include <cmath>
  10.  
  11. using std::cout, std::endl;
  12. using std::max, std::min;
  13. using LL = long long;
  14. using db = double;
  15.  
  16. // const values
  17. const double G = 9.8;
  18. const double PI = 3.1415926535;
  19. const double ANG_RAD_CONV_FACTOR = PI / 180;
  20.  
  21. struct TestCaseData;
  22.  
  23. // function declarations
  24. double angToRad(double ang);
  25. double RadToAng(double rad);
  26. void preprocessData(TestCaseData &data);
  27. double frac(double n, double d);
  28. double pointDistance(double x1, double y1, double x2, double y2);
  29.  
  30. double frac(double n, double d)
  31. {
  32. return n / d;
  33. }
  34.  
  35. double angToRad(double ang)
  36. {
  37. return (ang * ANG_RAD_CONV_FACTOR);
  38. }
  39.  
  40. double RadToAng(double rad)
  41. {
  42. return (rad / ANG_RAD_CONV_FACTOR);
  43. }
  44.  
  45. double pointDistance(double x1, double y1, double x2, double y2)
  46. {
  47. double xd = x1 - x2;
  48. double yd = y1 - y2;
  49. return sqrt(xd * xd + yd * yd);
  50. }
  51.  
  52. double solveQuadratic(double a, double b, double c)
  53. {
  54. double discriminant = b * b - 4 * a * c;
  55. double root;
  56.  
  57. if (discriminant < 0)
  58. {
  59. return -1;
  60. }
  61.  
  62. double root1 = (-b + sqrt(discriminant)) / (2 * a);
  63. double root2 = (-b - sqrt(discriminant)) / (2 * a);
  64.  
  65. if (root1 < 0 && root2 < 0)
  66. {
  67. return -1;
  68. }
  69.  
  70. if (root1 < 0 || root2 < 0)
  71. {
  72. return max(root1, root2);
  73. }
  74.  
  75. if (sqrt(root1) > sqrt(root2))
  76. {
  77. return root2;
  78. }
  79. else
  80. {
  81. return root1;
  82. }
  83. }
  84.  
  85. // Data of a testcase
  86. //
  87. // Notice:
  88. // All degree data inside TestCaseData is about the moving items.
  89. struct TestCaseData
  90. {
  91. // original data
  92. double v;
  93. double w;
  94. double ang;
  95. double x0;
  96. double y0;
  97.  
  98. // pre-processed data
  99. double rad;
  100. double wx;
  101. double wy;
  102. };
  103.  
  104. /// @brief Pre-process the TestCaseData instance
  105. /// @param data The data need to be pre-processed
  106. void preprocessData(TestCaseData &data)
  107. {
  108. data.rad = angToRad(data.ang);
  109. data.wx = data.w * cos(data.rad);
  110. data.wy = data.w * sin(data.rad);
  111. }
  112.  
  113. struct TestCaseRuntime
  114. {
  115. TestCaseData caseData;
  116. double xi;
  117. double yi;
  118. double xip; // stands for xi previous
  119. double yip;
  120. double ti;
  121. double rad;
  122. bool iterated;
  123. bool canSolve;
  124. bool solved;
  125. };
  126.  
  127. TestCaseRuntime createTestCaseRuntime(const TestCaseData &data)
  128. {
  129. TestCaseRuntime rt{
  130. .caseData{data},
  131. .xi{data.x0},
  132. .yi{data.y0},
  133. .xip{data.x0},
  134. .yip{data.y0},
  135. .ti{0},
  136. .rad{0},
  137. .iterated{false},
  138. .canSolve{true},
  139. .solved{false}};
  140.  
  141. return rt;
  142. }
  143.  
  144. // Iterate the runtime data
  145. //
  146. // If return false, means iteration terminated
  147. // (maybe found solution or can NOT be solved)
  148. bool iterateRuntime(TestCaseRuntime &rt)
  149. {
  150. // cout << "[DEBUG] Iterating..." << endl;
  151. // calculate t
  152. const static double a = frac(1, 4) * G * G;
  153. double b = rt.yi * G - rt.caseData.v * rt.caseData.v;
  154. double c = rt.xi * rt.xi + rt.yi * rt.yi;
  155. double t2 = solveQuadratic(a, b, c);
  156. double t = sqrt(t2);
  157. // debug
  158. if (t2 < 0 && t2 != -1)
  159. {
  160. cout << "[DEBUG][ERROR] solveQuadratic return negative value";
  161. exit(0);
  162. }
  163. // no solution
  164. if (t2 == -1 || t2 < 0)
  165. {
  166. rt.canSolve = false;
  167. rt.solved = false;
  168.  
  169. return false;
  170. }
  171.  
  172. // update t
  173. rt.ti = t;
  174.  
  175. // update point
  176. rt.xip = rt.xi;
  177. rt.yip = rt.yi;
  178. // calc new xi, yi
  179. rt.xi = rt.caseData.x0 + rt.caseData.wx * t;
  180. rt.yi = rt.caseData.y0 + rt.caseData.wy * t;
  181.  
  182. // calculate delta
  183. double delta = pointDistance(rt.xi, rt.yi, rt.xip, rt.yip);
  184. // debug
  185. if (delta < 0)
  186. {
  187. cout << "[DEBUG][ERROR] pointDistance return negative value";
  188. exit(0);
  189. }
  190. // cout << "[DEBUG] Distance: " << delta << endl;
  191. // meet terminate condition
  192. if (delta < 1e-4)
  193. {
  194. rt.solved = true;
  195. rt.canSolve = true;
  196. rt.rad = acos(rt.xi / (rt.caseData.v * rt.ti));
  197. return false;
  198. }
  199. if (delta > 9999999)
  200. {
  201. cout << "[DEBUG][NOTICE] Iteration result diverge, force terminated"
  202. << endl;
  203. rt.solved = false;
  204. rt.canSolve = true;
  205. return false;
  206. }
  207.  
  208. return true;
  209. }
  210.  
  211. void solveCase(TestCaseData caseData)
  212. {
  213. preprocessData(caseData);
  214. auto runtime = createTestCaseRuntime(caseData);
  215. LL itCount = 0;
  216. while (iterateRuntime(runtime))
  217. {
  218. }
  219. cout << "-------------------------" << endl;
  220. cout << " Case solved: " << (runtime.solved == 1 ? "Yes" : "No") << endl;
  221. if (runtime.solved)
  222. {
  223. cout << " Result: " << endl
  224. << " ti: " << runtime.ti << endl
  225. << " xi: " << runtime.xi << endl
  226. << " yi: " << runtime.yi << endl;
  227.  
  228. cout << "Luanch angle: " << runtime.rad << " Rad." << endl
  229. << " " << RadToAng(runtime.rad) << " Ang." << endl;
  230. }
  231. else if (runtime.canSolve)
  232. {
  233. cout << " Reason: Result Diverged." << endl;
  234. }
  235. else
  236. {
  237. cout << " Reason: No real root for equation, "
  238. << " which means it's impossible for projectile to hit target. " << endl;
  239. }
  240. cout << "-------------------------" << endl;
  241. }
  242.  
  243. void showCredential()
  244. {
  245. cout << "周裕佳 E22214017" << endl;
  246. }
  247.  
  248. int main()
  249. {
  250. showCredential();
  251.  
  252. TestCaseData case1{
  253. .v{100},
  254. .w{20},
  255. .ang{150},
  256. .x0{600},
  257. .y0{200},
  258. };
  259.  
  260. TestCaseData case2{
  261. .v{100},
  262. .w{120},
  263. .ang{30},
  264. .x0{500},
  265. .y0{100},
  266. };
  267.  
  268. TestCaseData case3{
  269. .v{120},
  270. .w{30},
  271. .ang{-60},
  272. .x0{500},
  273. .y0{-100},
  274. };
  275.  
  276. solveCase(case1);
  277. solveCase(case2);
  278. solveCase(case3);
  279.  
  280. return 0;
  281. }
  282.  
  283. // Output:
  284.  
  285. /**
  286. 周裕佳 E22214017
  287. -------------------------
  288. Case solved: Yes
  289. Result:
  290. ti: 6.99227
  291. xi: 478.89
  292. yi: 269.923
  293. Luanch angle: 0.816351 Rad.
  294. 46.7735 Ang.
  295. -------------------------
  296. -------------------------
  297. Case solved: No
  298. Reason: No real root for equation, which means it's impossible for projectile to hit target.
  299. -------------------------
  300. -------------------------
  301. Case solved: Yes
  302. Result:
  303. ti: 4.86242
  304. xi: 572.936
  305. yi: -226.329
  306. Luanch angle: 0.19049 Rad.
  307. 10.9142 Ang.
  308. -------------------------
  309. */
  310.  
  311. // Answer has been examinated, for more info check out: https://www.geogebra.org/calculator/zvrrge3r
  312.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement