mathutil.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. /*
  2. ** Command & Conquer Generals(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. //
  19. // Filename: mathutil.cpp
  20. // Project: wwutil
  21. // Author: Tom Spencer-Smith
  22. // Date: June 1998
  23. // Description:
  24. //
  25. //-----------------------------------------------------------------------------
  26. #include "mathutil.h" // I WANNA BE FIRST!
  27. #include <math.h>
  28. #include <stdlib.h>
  29. #include "wwmath.h"
  30. #include "miscutil.h"
  31. #include "wwdebug.h"
  32. const double cMathUtil::PI = 3.1415927;
  33. const double cMathUtil::PI_2 = 1.5707963;
  34. //-----------------------------------------------------------------------------
  35. //
  36. // Returns a unit vector
  37. //
  38. void cMathUtil::Angle_To_Vector(double angle, double & dx, double & dy)
  39. {
  40. WWASSERT(angle > -WWMATH_EPSILON && angle < 360.0 + WWMATH_EPSILON);
  41. double angleRadians;
  42. if (angle >= 0 && angle < 90) {
  43. angleRadians = angle * PI / 180.0;
  44. dx = WWMath::Sin(angleRadians);
  45. dy = WWMath::Cos(angleRadians);
  46. } else if (angle >= 90 && angle < 180) {
  47. angleRadians = (angle - 90) * PI / 180.0;
  48. dx = WWMath::Cos(angleRadians);
  49. dy = -WWMath::Sin(angleRadians);
  50. } else if (angle >= 180 && angle < 270) {
  51. angleRadians = (angle - 180) * PI / 180.0;
  52. dx = -WWMath::Sin(angleRadians);
  53. dy = -WWMath::Cos(angleRadians);
  54. } else {
  55. angleRadians = (angle - 270) * PI / 180.0;
  56. dx = -WWMath::Cos(angleRadians);
  57. dy = WWMath::Sin(angleRadians);
  58. }
  59. double len;
  60. len = ::sqrt(dx * dx + dy * dy);
  61. WWASSERT(::fabs(len - 1) < 0.0005);
  62. //
  63. // Correction for Irish nature of windows y coords
  64. //
  65. dy *= -1;
  66. }
  67. //-----------------------------------------------------------------------------
  68. void cMathUtil::Vector_To_Angle(double dx, double dy, double & angle)
  69. {
  70. double theta;
  71. if (dx == 0 && dy == 0) {
  72. theta = 0;
  73. }
  74. if (dx == 0) {
  75. if (dy <= 0) {
  76. theta = 0;
  77. } else {
  78. theta = PI;
  79. }
  80. } else {
  81. theta = WWMath::Atan(-dy / dx);
  82. if (dx < 0) {
  83. theta += PI;
  84. }
  85. theta += 3 * PI_2;
  86. if (theta >= 2 * PI) {
  87. theta -= 2 * PI;
  88. }
  89. theta = 2 * PI - theta;
  90. if (theta == 2 * PI) {
  91. theta = 0;
  92. }
  93. }
  94. angle = theta * 180.0 / PI;
  95. }
  96. //-----------------------------------------------------------------------------
  97. double cMathUtil::Simple_Distance(double x1, double y1, double x2, double y2)
  98. {
  99. double dx = x2 - x1;
  100. double dy = y2 - y1;
  101. return(::sqrt(dx * dx + dy * dy));
  102. }
  103. //-----------------------------------------------------------------------------
  104. int cMathUtil::Round(double arg)
  105. {
  106. //return (int)(arg + 0.5);
  107. if (arg > MISCUTIL_EPSILON) {
  108. return (int) (arg + 0.5f);
  109. } else if (arg < -MISCUTIL_EPSILON) {
  110. return (int) (arg - 0.5f);
  111. } else {
  112. return 0;
  113. }
  114. }
  115. //-----------------------------------------------------------------------------
  116. void cMathUtil::Rotate_Vector(double & vx, double & vy, double angle)
  117. {
  118. double angle_radians = angle * PI / 180.0;
  119. double vx1 = vx;
  120. double vy1 = vy;
  121. vx = vx1 * ::WWMath::Cos(angle_radians) - vy1 * ::WWMath::Sin(angle_radians);
  122. vy = vx1 * ::WWMath::Sin(angle_radians) + vy1 * ::WWMath::Cos(angle_radians);
  123. }
  124. //-----------------------------------------------------------------------------
  125. double cMathUtil::Get_Uniform_Pdf_Double(double lower, double upper)
  126. {
  127. WWASSERT(upper - lower > -MISCUTIL_EPSILON);
  128. double x = lower + ::rand() / (double) RAND_MAX * (upper - lower);
  129. WWASSERT(x - lower > -MISCUTIL_EPSILON && upper - x > -MISCUTIL_EPSILON);
  130. return x;
  131. }
  132. //-----------------------------------------------------------------------------
  133. double cMathUtil::Get_Normalized_Uniform_Pdf_Double()
  134. {
  135. return Get_Uniform_Pdf_Double(0, 1);
  136. }
  137. //-----------------------------------------------------------------------------
  138. int cMathUtil::Get_Uniform_Pdf_Int(int lower, int upper)
  139. {
  140. WWASSERT(lower <= upper);
  141. int x = lower + ::rand() % (upper - lower + 1);
  142. WWASSERT(x >= lower && upper >= x);
  143. return x;
  144. }
  145. //-----------------------------------------------------------------------------
  146. double cMathUtil::Get_Hat_Pdf_Double(double lower, double upper)
  147. {
  148. WWASSERT(upper - lower > -MISCUTIL_EPSILON);
  149. double x;
  150. if (::fabs(upper - lower) < MISCUTIL_EPSILON) {
  151. x = lower;
  152. } else {
  153. double dx = (upper - lower) / 2.0f;
  154. double dy = 1 / dx;
  155. double m = dy / dx;
  156. double c = -m * lower;
  157. x = Get_Uniform_Pdf_Double(lower, lower + dx);
  158. double y = Get_Uniform_Pdf_Double(0, dy);
  159. if (y > m * x + c) {
  160. x += dx;
  161. }
  162. }
  163. WWASSERT(x - lower > -MISCUTIL_EPSILON && upper - x > -MISCUTIL_EPSILON);
  164. return x;
  165. }
  166. //-----------------------------------------------------------------------------
  167. double cMathUtil::Get_Normalized_Hat_Pdf_Double()
  168. {
  169. return Get_Hat_Pdf_Double(0, 1);
  170. }
  171. //-----------------------------------------------------------------------------
  172. int cMathUtil::Get_Hat_Pdf_Int(int lower, int upper)
  173. {
  174. return Round(Get_Hat_Pdf_Double(lower, upper));
  175. }