line3d.h 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. // Copyright (C) 2002-2012 Nikolaus Gebhardt
  2. // This file is part of the "Irrlicht Engine".
  3. // For conditions of distribution and use, see copyright notice in irrlicht.h
  4. #pragma once
  5. #include "irrTypes.h"
  6. #include "vector3d.h"
  7. namespace irr
  8. {
  9. namespace core
  10. {
  11. //! 3D line between two points with intersection methods.
  12. template <class T>
  13. class line3d
  14. {
  15. public:
  16. //! Default constructor
  17. /** line from (0,0,0) to (1,1,1) */
  18. constexpr line3d() :
  19. start(0, 0, 0), end(1, 1, 1) {}
  20. //! Constructor with two points
  21. constexpr line3d(T xa, T ya, T za, T xb, T yb, T zb) :
  22. start(xa, ya, za), end(xb, yb, zb) {}
  23. //! Constructor with two points as vectors
  24. constexpr line3d(const vector3d<T> &start, const vector3d<T> &end) :
  25. start(start), end(end) {}
  26. // operators
  27. line3d<T> operator+(const vector3d<T> &point) const { return line3d<T>(start + point, end + point); }
  28. line3d<T> &operator+=(const vector3d<T> &point)
  29. {
  30. start += point;
  31. end += point;
  32. return *this;
  33. }
  34. line3d<T> operator-(const vector3d<T> &point) const { return line3d<T>(start - point, end - point); }
  35. line3d<T> &operator-=(const vector3d<T> &point)
  36. {
  37. start -= point;
  38. end -= point;
  39. return *this;
  40. }
  41. constexpr bool operator==(const line3d<T> &other) const
  42. {
  43. return (start == other.start && end == other.end) || (end == other.start && start == other.end);
  44. }
  45. constexpr bool operator!=(const line3d<T> &other) const
  46. {
  47. return !(start == other.start && end == other.end) || (end == other.start && start == other.end);
  48. }
  49. // functions
  50. //! Set this line to a new line going through the two points.
  51. void setLine(const T &xa, const T &ya, const T &za, const T &xb, const T &yb, const T &zb)
  52. {
  53. start.set(xa, ya, za);
  54. end.set(xb, yb, zb);
  55. }
  56. //! Set this line to a new line going through the two points.
  57. void setLine(const vector3d<T> &nstart, const vector3d<T> &nend)
  58. {
  59. start.set(nstart);
  60. end.set(nend);
  61. }
  62. //! Set this line to new line given as parameter.
  63. void setLine(const line3d<T> &line)
  64. {
  65. start.set(line.start);
  66. end.set(line.end);
  67. }
  68. //! Get length of line
  69. /** \return Length of line. */
  70. T getLength() const { return start.getDistanceFrom(end); }
  71. //! Get squared length of line
  72. /** \return Squared length of line. */
  73. T getLengthSQ() const { return start.getDistanceFromSQ(end); }
  74. //! Get middle of line
  75. /** \return Center of line. */
  76. vector3d<T> getMiddle() const
  77. {
  78. return (start + end) / (T)2;
  79. }
  80. //! Get vector of line
  81. /** \return vector of line. */
  82. vector3d<T> getVector() const
  83. {
  84. return end - start;
  85. }
  86. //! Check if the given point is between start and end of the line.
  87. /** Assumes that the point is already somewhere on the line.
  88. \param point The point to test.
  89. \return True if point is on the line between start and end, else false.
  90. */
  91. bool isPointBetweenStartAndEnd(const vector3d<T> &point) const
  92. {
  93. return point.isBetweenPoints(start, end);
  94. }
  95. //! Get the closest point on this line to a point
  96. /** \param point The point to compare to.
  97. \return The nearest point which is part of the line. */
  98. vector3d<T> getClosestPoint(const vector3d<T> &point) const
  99. {
  100. vector3d<T> c = point - start;
  101. vector3d<T> v = end - start;
  102. T d = (T)v.getLength();
  103. v /= d;
  104. T t = v.dotProduct(c);
  105. if (t < (T)0.0)
  106. return start;
  107. if (t > d)
  108. return end;
  109. v *= t;
  110. return start + v;
  111. }
  112. //! Check if the line intersects with a sphere
  113. /** \param sorigin: Origin of the sphere.
  114. \param sradius: Radius of the sphere.
  115. \param outdistance: The distance to the first intersection point.
  116. \return True if there is an intersection.
  117. If there is one, the distance to the first intersection point
  118. is stored in outdistance. */
  119. bool getIntersectionWithSphere(const vector3d<T> &sorigin, T sradius, f64 &outdistance) const
  120. {
  121. const vector3d<T> q = sorigin - start;
  122. T c = q.getLength();
  123. T v = q.dotProduct(getVector().normalize());
  124. T d = sradius * sradius - (c * c - v * v);
  125. if (d < 0.0)
  126. return false;
  127. outdistance = v - core::squareroot(d);
  128. return true;
  129. }
  130. // member variables
  131. //! Start point of line
  132. vector3d<T> start;
  133. //! End point of line
  134. vector3d<T> end;
  135. };
  136. //! Typedef for an f32 line.
  137. typedef line3d<f32> line3df;
  138. //! Typedef for an integer line.
  139. typedef line3d<s32> line3di;
  140. } // end namespace core
  141. } // end namespace irr