ImathLineAlgo.h 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. ///////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas
  4. // Digital Ltd. LLC
  5. //
  6. // All rights reserved.
  7. //
  8. // Redistribution and use in source and binary forms, with or without
  9. // modification, are permitted provided that the following conditions are
  10. // met:
  11. // * Redistributions of source code must retain the above copyright
  12. // notice, this list of conditions and the following disclaimer.
  13. // * Redistributions in binary form must reproduce the above
  14. // copyright notice, this list of conditions and the following disclaimer
  15. // in the documentation and/or other materials provided with the
  16. // distribution.
  17. // * Neither the name of Industrial Light & Magic nor the names of
  18. // its contributors may be used to endorse or promote products derived
  19. // from this software without specific prior written permission.
  20. //
  21. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  24. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  25. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  26. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  27. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  28. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  29. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  30. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  31. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32. //
  33. ///////////////////////////////////////////////////////////////////////////
  34. #ifndef INCLUDED_IMATHLINEALGO_H
  35. #define INCLUDED_IMATHLINEALGO_H
  36. //------------------------------------------------------------------
  37. //
  38. // This file contains algorithms applied to or in conjunction
  39. // with lines (Imath::Line). These algorithms may require
  40. // more headers to compile. The assumption made is that these
  41. // functions are called much less often than the basic line
  42. // functions or these functions require more support classes
  43. //
  44. // Contains:
  45. //
  46. // bool closestPoints(const Line<T>& line1,
  47. // const Line<T>& line2,
  48. // Vec3<T>& point1,
  49. // Vec3<T>& point2)
  50. //
  51. // bool intersect( const Line3<T> &line,
  52. // const Vec3<T> &v0,
  53. // const Vec3<T> &v1,
  54. // const Vec3<T> &v2,
  55. // Vec3<T> &pt,
  56. // Vec3<T> &barycentric,
  57. // bool &front)
  58. //
  59. // V3f
  60. // closestVertex(const Vec3<T> &v0,
  61. // const Vec3<T> &v1,
  62. // const Vec3<T> &v2,
  63. // const Line3<T> &l)
  64. //
  65. // V3f
  66. // rotatePoint(const Vec3<T> p, Line3<T> l, float angle)
  67. //
  68. //------------------------------------------------------------------
  69. #include "ImathLine.h"
  70. #include "ImathVecAlgo.h"
  71. #include "ImathFun.h"
  72. #include "ImathNamespace.h"
  73. IMATH_INTERNAL_NAMESPACE_HEADER_ENTER
  74. template <class T>
  75. bool
  76. closestPoints
  77. (const Line3<T>& line1,
  78. const Line3<T>& line2,
  79. Vec3<T>& point1,
  80. Vec3<T>& point2)
  81. {
  82. //
  83. // Compute point1 and point2 such that point1 is on line1, point2
  84. // is on line2 and the distance between point1 and point2 is minimal.
  85. // This function returns true if point1 and point2 can be computed,
  86. // or false if line1 and line2 are parallel or nearly parallel.
  87. // This function assumes that line1.dir and line2.dir are normalized.
  88. //
  89. Vec3<T> w = line1.pos - line2.pos;
  90. T d1w = line1.dir ^ w;
  91. T d2w = line2.dir ^ w;
  92. T d1d2 = line1.dir ^ line2.dir;
  93. T n1 = d1d2 * d2w - d1w;
  94. T n2 = d2w - d1d2 * d1w;
  95. T d = 1 - d1d2 * d1d2;
  96. T absD = abs (d);
  97. if ((absD > 1) ||
  98. (abs (n1) < limits<T>::max() * absD &&
  99. abs (n2) < limits<T>::max() * absD))
  100. {
  101. point1 = line1 (n1 / d);
  102. point2 = line2 (n2 / d);
  103. return true;
  104. }
  105. else
  106. {
  107. return false;
  108. }
  109. }
  110. template <class T>
  111. bool
  112. intersect
  113. (const Line3<T> &line,
  114. const Vec3<T> &v0,
  115. const Vec3<T> &v1,
  116. const Vec3<T> &v2,
  117. Vec3<T> &pt,
  118. Vec3<T> &barycentric,
  119. bool &front)
  120. {
  121. //
  122. // Given a line and a triangle (v0, v1, v2), the intersect() function
  123. // finds the intersection of the line and the plane that contains the
  124. // triangle.
  125. //
  126. // If the intersection point cannot be computed, either because the
  127. // line and the triangle's plane are nearly parallel or because the
  128. // triangle's area is very small, intersect() returns false.
  129. //
  130. // If the intersection point is outside the triangle, intersect
  131. // returns false.
  132. //
  133. // If the intersection point, pt, is inside the triangle, intersect()
  134. // computes a front-facing flag and the barycentric coordinates of
  135. // the intersection point, and returns true.
  136. //
  137. // The front-facing flag is true if the dot product of the triangle's
  138. // normal, (v2-v1)%(v1-v0), and the line's direction is negative.
  139. //
  140. // The barycentric coordinates have the following property:
  141. //
  142. // pt = v0 * barycentric.x + v1 * barycentric.y + v2 * barycentric.z
  143. //
  144. Vec3<T> edge0 = v1 - v0;
  145. Vec3<T> edge1 = v2 - v1;
  146. Vec3<T> normal = edge1 % edge0;
  147. T l = normal.length();
  148. if (l != 0)
  149. normal /= l;
  150. else
  151. return false; // zero-area triangle
  152. //
  153. // d is the distance of line.pos from the plane that contains the triangle.
  154. // The intersection point is at line.pos + (d/nd) * line.dir.
  155. //
  156. T d = normal ^ (v0 - line.pos);
  157. T nd = normal ^ line.dir;
  158. if (abs (nd) > 1 || abs (d) < limits<T>::max() * abs (nd))
  159. pt = line (d / nd);
  160. else
  161. return false; // line and plane are nearly parallel
  162. //
  163. // Compute the barycentric coordinates of the intersection point.
  164. // The intersection is inside the triangle if all three barycentric
  165. // coordinates are between zero and one.
  166. //
  167. {
  168. Vec3<T> en = edge0.normalized();
  169. Vec3<T> a = pt - v0;
  170. Vec3<T> b = v2 - v0;
  171. Vec3<T> c = (a - en * (en ^ a));
  172. Vec3<T> d = (b - en * (en ^ b));
  173. T e = c ^ d;
  174. T f = d ^ d;
  175. if (e >= 0 && e <= f)
  176. barycentric.z = e / f;
  177. else
  178. return false; // outside
  179. }
  180. {
  181. Vec3<T> en = edge1.normalized();
  182. Vec3<T> a = pt - v1;
  183. Vec3<T> b = v0 - v1;
  184. Vec3<T> c = (a - en * (en ^ a));
  185. Vec3<T> d = (b - en * (en ^ b));
  186. T e = c ^ d;
  187. T f = d ^ d;
  188. if (e >= 0 && e <= f)
  189. barycentric.x = e / f;
  190. else
  191. return false; // outside
  192. }
  193. barycentric.y = 1 - barycentric.x - barycentric.z;
  194. if (barycentric.y < 0)
  195. return false; // outside
  196. front = ((line.dir ^ normal) < 0);
  197. return true;
  198. }
  199. template <class T>
  200. Vec3<T>
  201. closestVertex
  202. (const Vec3<T> &v0,
  203. const Vec3<T> &v1,
  204. const Vec3<T> &v2,
  205. const Line3<T> &l)
  206. {
  207. Vec3<T> nearest = v0;
  208. T neardot = (v0 - l.closestPointTo(v0)).length2();
  209. T tmp = (v1 - l.closestPointTo(v1)).length2();
  210. if (tmp < neardot)
  211. {
  212. neardot = tmp;
  213. nearest = v1;
  214. }
  215. tmp = (v2 - l.closestPointTo(v2)).length2();
  216. if (tmp < neardot)
  217. {
  218. neardot = tmp;
  219. nearest = v2;
  220. }
  221. return nearest;
  222. }
  223. template <class T>
  224. Vec3<T>
  225. rotatePoint (const Vec3<T> p, Line3<T> l, T angle)
  226. {
  227. //
  228. // Rotate the point p around the line l by the given angle.
  229. //
  230. //
  231. // Form a coordinate frame with <x,y,a>. The rotation is the in xy
  232. // plane.
  233. //
  234. Vec3<T> q = l.closestPointTo(p);
  235. Vec3<T> x = p - q;
  236. T radius = x.length();
  237. x.normalize();
  238. Vec3<T> y = (x % l.dir).normalize();
  239. T cosangle = Math<T>::cos(angle);
  240. T sinangle = Math<T>::sin(angle);
  241. Vec3<T> r = q + x * radius * cosangle + y * radius * sinangle;
  242. return r;
  243. }
  244. IMATH_INTERNAL_NAMESPACE_HEADER_EXIT
  245. #endif // INCLUDED_IMATHLINEALGO_H