boundingLine.cxx 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. /**
  2. * PANDA 3D SOFTWARE
  3. * Copyright (c) Carnegie Mellon University. All rights reserved.
  4. *
  5. * All use of this software is subject to the terms of the revised BSD
  6. * license. You should have received a copy of this license along
  7. * with this source code in a file named "LICENSE."
  8. *
  9. * @file boundingLine.cxx
  10. * @author drose
  11. * @date 2000-07-04
  12. */
  13. #include "boundingLine.h"
  14. #include "boundingSphere.h"
  15. #include "boundingBox.h"
  16. #include "config_mathutil.h"
  17. #include <math.h>
  18. TypeHandle BoundingLine::_type_handle;
  19. /**
  20. *
  21. */
  22. BoundingVolume *BoundingLine::
  23. make_copy() const {
  24. return new BoundingLine(*this);
  25. }
  26. /**
  27. *
  28. */
  29. LPoint3 BoundingLine::
  30. get_approx_center() const {
  31. nassertr(!is_empty(), LPoint3(0.0f, 0.0f, 0.0f));
  32. nassertr(!is_infinite(), LPoint3(0.0f, 0.0f, 0.0f));
  33. return (get_point_a() + get_point_b()) / 2.0;
  34. }
  35. /**
  36. *
  37. */
  38. void BoundingLine::
  39. xform(const LMatrix4 &mat) {
  40. nassertv(!mat.is_nan());
  41. if (!is_empty() && !is_infinite()) {
  42. _origin = _origin * mat;
  43. _vector = _vector * mat;
  44. if (!_vector.normalize()) {
  45. // If we just scaled the line down to nothing, it becomes an empty
  46. // volume.
  47. _flags |= F_empty;
  48. }
  49. }
  50. }
  51. /**
  52. *
  53. */
  54. void BoundingLine::
  55. output(std::ostream &out) const {
  56. if (is_empty()) {
  57. out << "bline, empty";
  58. } else if (is_infinite()) {
  59. out << "bline, infinite";
  60. } else {
  61. out << "bline, (" << _origin << ") - (" << _origin + _vector << ")";
  62. }
  63. }
  64. /**
  65. * Virtual downcast method. Returns this object as a pointer of the indicated
  66. * type, if it is in fact that type. Returns NULL if it is not that type.
  67. */
  68. const BoundingLine *BoundingLine::
  69. as_bounding_line() const {
  70. return this;
  71. }
  72. /**
  73. *
  74. */
  75. bool BoundingLine::
  76. extend_other(BoundingVolume *other) const {
  77. return other->extend_by_line(this);
  78. }
  79. /**
  80. *
  81. */
  82. bool BoundingLine::
  83. around_other(BoundingVolume *other,
  84. const BoundingVolume **first,
  85. const BoundingVolume **last) const {
  86. return other->around_lines(first, last);
  87. }
  88. /**
  89. *
  90. */
  91. int BoundingLine::
  92. contains_other(const BoundingVolume *other) const {
  93. return other->contains_line(this);
  94. }
  95. /**
  96. *
  97. */
  98. bool BoundingLine::
  99. extend_by_line(const BoundingLine *line) {
  100. nassertr(!line->is_empty() && !line->is_infinite(), false);
  101. nassertr(!is_infinite(), false);
  102. if (is_empty()) {
  103. _origin = line->_origin;
  104. _vector = line->_vector;
  105. _flags = 0;
  106. } else {
  107. _flags = F_infinite;
  108. }
  109. return true;
  110. }
  111. /**
  112. *
  113. */
  114. int BoundingLine::
  115. contains_sphere(const BoundingSphere *sphere) const {
  116. nassertr(!is_empty() && !is_infinite(), 0);
  117. nassertr(!sphere->is_empty() && !sphere->is_infinite(), 0);
  118. PN_stdfloat r = sphere->get_radius();
  119. if (r * r >= sqr_dist_to_line(sphere->get_center())) {
  120. return IF_possible | IF_some;
  121. } else {
  122. return IF_no_intersection;
  123. }
  124. }
  125. /**
  126. *
  127. */
  128. int BoundingLine::
  129. contains_box(const BoundingBox *box) const {
  130. nassertr(!is_empty() && !is_infinite(), 0);
  131. nassertr(!box->is_empty() && !box->is_infinite(), 0);
  132. LPoint3 center = (box->get_minq() + box->get_maxq()) * 0.5f;
  133. PN_stdfloat r2 = (box->get_maxq() - box->get_minq()).length_squared() * 0.25f;
  134. if (r2 >= sqr_dist_to_line(center)) {
  135. return IF_possible;
  136. } else {
  137. return IF_no_intersection;
  138. }
  139. }
  140. /**
  141. *
  142. */
  143. PN_stdfloat BoundingLine::
  144. sqr_dist_to_line(const LPoint3 &point) const {
  145. nassertr(!point.is_nan(), 0.0f);
  146. nassertr(!is_empty() && !is_infinite(), 0.0f);
  147. nassertr(!_vector.almost_equal(LVector3(0.0f, 0.0f, 0.0f)), 0.0f);
  148. // The formula for the distance from a point to the line based on the
  149. // quadratic equation.
  150. PN_stdfloat A = dot(_vector, _vector);
  151. nassertr(A != 0.0f, 0.0f);
  152. LVector3 fc = _origin - point;
  153. PN_stdfloat B = 2.0 * dot(_vector, fc);
  154. PN_stdfloat fc_d2 = dot(fc, fc);
  155. PN_stdfloat r2 = fc_d2 - B*B / 4.0*A;
  156. nassertr(!cnan(r2), 0.0f);
  157. return r2;
  158. }