lineseg.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  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. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : WWMath *
  23. * *
  24. * $Archive:: /Commando/Code/wwmath/lineseg.cpp $*
  25. * *
  26. * Author:: Greg_h *
  27. * *
  28. * $Modtime:: 3/16/00 3:16p $*
  29. * *
  30. * $Revision:: 25 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * LineSegClass::Set -- Initialize this 'lineseg' by transforming another 'lineseg' *
  35. * LineSegClass::Set_Random -- create a random linesegment within the given space *
  36. * LineSegClass::Find_Point_Closest_To -- Finds point on line closest to point supplied. *
  37. * LineSegClass::Find_Intersection -- Finds the closest points on the two lines *
  38. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  39. #include "lineseg.h"
  40. //#include <stdlib.h>
  41. #include "matrix3d.h"
  42. /***********************************************************************************************
  43. * LineSegClass::Set -- Initialize this 'lineseg' by transforming another 'lineseg' *
  44. * *
  45. * INPUT: *
  46. * *
  47. * OUTPUT: *
  48. * *
  49. * WARNINGS: *
  50. * *
  51. * HISTORY: *
  52. * 6/17/98 GTH : Created. *
  53. *=============================================================================================*/
  54. void LineSegClass::Set(const LineSegClass & that,const Matrix3D & tm)
  55. {
  56. /*
  57. ** Transform P0 and P1
  58. */
  59. Matrix3D::Transform_Vector(tm,that.P0,&P0);
  60. Matrix3D::Transform_Vector(tm,that.P1,&P1);
  61. /*
  62. ** Just calculate DP
  63. */
  64. DP = P1 - P0;
  65. /*
  66. ** Rotate the direction vector
  67. */
  68. Matrix3D::Rotate_Vector(tm,that.Dir,&Dir);
  69. /*
  70. ** Length should be un-changed
  71. */
  72. Length = that.Length;
  73. }
  74. /***********************************************************************************************
  75. * LineSegClass::Set_Random -- create a random linesegment within the given space *
  76. * *
  77. * INPUT: *
  78. * *
  79. * OUTPUT: *
  80. * *
  81. * WARNINGS: *
  82. * *
  83. * HISTORY: *
  84. * 4/21/98 GTH : Created. *
  85. *=============================================================================================*/
  86. void LineSegClass::Set_Random(const Vector3 & min,const Vector3 & max)
  87. {
  88. float frac;
  89. frac = WWMath::Random_Float();
  90. P0.X = min.X + frac * (max.X - min.X);
  91. frac = WWMath::Random_Float();
  92. P0.Y = min.Y + frac * (max.Y - min.Y);
  93. frac = WWMath::Random_Float();
  94. P0.Z = min.Z + frac * (max.Z - min.Z);
  95. frac = WWMath::Random_Float();
  96. P1.X = min.X + frac * (max.X - min.X);
  97. frac = WWMath::Random_Float();
  98. P1.Y = min.Y + frac * (max.Y - min.Y);
  99. frac = WWMath::Random_Float();
  100. P1.Z = min.Z + frac * (max.Z - min.Z);
  101. DP = P1 - P0;
  102. Dir = DP;
  103. Dir.Normalize();
  104. Length = DP.Length();
  105. }
  106. /***********************************************************************************************
  107. * LineSegClass::Find_Point_Closest_To -- Finds point on line closest to point supplied. *
  108. * *
  109. * INPUT: *
  110. * *
  111. * OUTPUT: *
  112. * *
  113. * WARNINGS: *
  114. * *
  115. * HISTORY: *
  116. * 07/26/1999 SKB : Created. *
  117. *=============================================================================================*/
  118. Vector3 LineSegClass::Find_Point_Closest_To(const Vector3 &pos) const
  119. {
  120. // Get a vector from one line endpoint to point in question.
  121. Vector3 v_0_pos = (pos - P0);
  122. float dotprod = Vector3::Dot_Product(Dir, v_0_pos);
  123. // Check to see if point is past either of the endpoints.
  124. // (Unable to draw a perpendicular line from the point to the line segment.)
  125. if (dotprod <= 0.0) {
  126. return(P0);
  127. } else if (dotprod >= Length) {
  128. return(P1);
  129. }
  130. // Find point on line seg that is closest to pos passed in.
  131. Vector3 point = P0 + (dotprod * Dir);
  132. return(point);
  133. }
  134. /***********************************************************************************************
  135. * LineSegClass::Find_Intersection -- Finds the closest points on the two lines.. *
  136. * *
  137. * INPUT: *
  138. * *
  139. * OUTPUT: *
  140. * *
  141. * WARNINGS: *
  142. * *
  143. * HISTORY: *
  144. * 03/03/2000 PDS : Created. *
  145. *=============================================================================================*/
  146. bool
  147. LineSegClass::Find_Intersection
  148. (
  149. const LineSegClass & other_line,
  150. Vector3 * p1,
  151. float * fraction1,
  152. Vector3 * p2,
  153. float * fraction2
  154. ) const
  155. {
  156. bool retval = false;
  157. #ifdef ALLOW_TEMPORARIES
  158. Vector3 cross1 = Vector3::Cross_Product (Dir, other_line.Dir);
  159. Vector3 cross2 = Vector3::Cross_Product (other_line.P0 - P0, other_line.Dir);
  160. float top1 = cross2 * cross1;
  161. float bottom1 = cross1 * cross1;
  162. Vector3 cross3 = Vector3::Cross_Product (other_line.Dir, Dir);
  163. Vector3 cross4 = Vector3::Cross_Product (P0 - other_line.P0, Dir);
  164. float top2 = cross4 * cross3;
  165. float bottom2 = cross3 * cross3;
  166. #else
  167. Vector3 cross1, cross2, cross3, cross4;
  168. Vector3::Cross_Product(Dir, other_line.Dir, &cross1);
  169. Vector3::Cross_Product(other_line.P0 - P0, other_line.Dir, &cross2);
  170. float top1 = Vector3::Dot_Product(cross2, cross1);
  171. float bottom1 = Vector3::Dot_Product(cross1, cross1);
  172. Vector3::Cross_Product(other_line.Dir, Dir, &cross3);
  173. Vector3::Cross_Product(P0 - other_line.P0, Dir, &cross4);
  174. float top2 = Vector3::Dot_Product(cross4, cross3);
  175. float bottom2 = Vector3::Dot_Product(cross3, cross3);
  176. #endif
  177. //
  178. // If either of the divisors are 0, then the lines are parallel
  179. //
  180. if (bottom1 != 0 && bottom2 != 0) {
  181. float length1 = top1 / bottom1;
  182. float length2 = top2 / bottom2;
  183. //
  184. // Calculate the closest points on both lines.
  185. // Note: If the points are the same, then the lines intersect.
  186. //
  187. (*p1) = P0 + (Dir * length1);
  188. (*p2) = other_line.P0 + (other_line.Dir * length2);
  189. //
  190. // Return the fractions if they caller wants them
  191. //
  192. if (fraction1 != NULL) {
  193. (*fraction1) = length1 / Length;
  194. }
  195. if (fraction2 != NULL) {
  196. (*fraction2) = length2 / Length;
  197. }
  198. retval = true;
  199. }
  200. return retval;
  201. }