nna42799

Untitled

Apr 23rd, 2024
25
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 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.  
Add Comment
Please, Sign In to add comment