/src/FreeImage/Source/OpenEXR/Imath/ImathLineAlgo.h

https://bitbucket.org/cabalistic/ogredeps/ · C++ Header · 287 lines · 132 code · 43 blank · 112 comment · 12 complexity · db36c0940f750b7946e1e73a1ff93ef5 MD5 · raw file

  1. ///////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2002, 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. namespace Imath {
  73. template <class T>
  74. bool
  75. closestPoints
  76. (const Line3<T>& line1,
  77. const Line3<T>& line2,
  78. Vec3<T>& point1,
  79. Vec3<T>& point2)
  80. {
  81. //
  82. // Compute point1 and point2 such that point1 is on line1, point2
  83. // is on line2 and the distance between point1 and point2 is minimal.
  84. // This function returns true if point1 and point2 can be computed,
  85. // or false if line1 and line2 are parallel or nearly parallel.
  86. // This function assumes that line1.dir and line2.dir are normalized.
  87. //
  88. Vec3<T> w = line1.pos - line2.pos;
  89. T d1w = line1.dir ^ w;
  90. T d2w = line2.dir ^ w;
  91. T d1d2 = line1.dir ^ line2.dir;
  92. T n1 = d1d2 * d2w - d1w;
  93. T n2 = d2w - d1d2 * d1w;
  94. T d = 1 - d1d2 * d1d2;
  95. T absD = abs (d);
  96. if ((absD > 1) ||
  97. (abs (n1) < limits<T>::max() * absD &&
  98. abs (n2) < limits<T>::max() * absD))
  99. {
  100. point1 = line1 (n1 / d);
  101. point2 = line2 (n2 / d);
  102. return true;
  103. }
  104. else
  105. {
  106. return false;
  107. }
  108. }
  109. template <class T>
  110. bool
  111. intersect
  112. (const Line3<T> &line,
  113. const Vec3<T> &v0,
  114. const Vec3<T> &v1,
  115. const Vec3<T> &v2,
  116. Vec3<T> &pt,
  117. Vec3<T> &barycentric,
  118. bool &front)
  119. {
  120. //
  121. // Given a line and a triangle (v0, v1, v2), the intersect() function
  122. // finds the intersection of the line and the plane that contains the
  123. // triangle.
  124. //
  125. // If the intersection point cannot be computed, either because the
  126. // line and the triangle's plane are nearly parallel or because the
  127. // triangle's area is very small, intersect() returns false.
  128. //
  129. // If the intersection point is outside the triangle, intersect
  130. // returns false.
  131. //
  132. // If the intersection point, pt, is inside the triangle, intersect()
  133. // computes a front-facing flag and the barycentric coordinates of
  134. // the intersection point, and returns true.
  135. //
  136. // The front-facing flag is true if the dot product of the triangle's
  137. // normal, (v2-v1)%(v1-v0), and the line's direction is negative.
  138. //
  139. // The barycentric coordinates have the following property:
  140. //
  141. // pt = v0 * barycentric.x + v1 * barycentric.y + v2 * barycentric.z
  142. //
  143. Vec3<T> edge0 = v1 - v0;
  144. Vec3<T> edge1 = v2 - v1;
  145. Vec3<T> normal = edge1 % edge0;
  146. T l = normal.length();
  147. if (l != 0)
  148. normal /= l;
  149. else
  150. return false; // zero-area triangle
  151. //
  152. // d is the distance of line.pos from the plane that contains the triangle.
  153. // The intersection point is at line.pos + (d/nd) * line.dir.
  154. //
  155. T d = normal ^ (v0 - line.pos);
  156. T nd = normal ^ line.dir;
  157. if (abs (nd) > 1 || abs (d) < limits<T>::max() * abs (nd))
  158. pt = line (d / nd);
  159. else
  160. return false; // line and plane are nearly parallel
  161. //
  162. // Compute the barycentric coordinates of the intersection point.
  163. // The intersection is inside the triangle if all three barycentric
  164. // coordinates are between zero and one.
  165. //
  166. {
  167. Vec3<T> en = edge0.normalized();
  168. Vec3<T> a = pt - v0;
  169. Vec3<T> b = v2 - v0;
  170. Vec3<T> c = (a - en * (en ^ a));
  171. Vec3<T> d = (b - en * (en ^ b));
  172. T e = c ^ d;
  173. T f = d ^ d;
  174. if (e >= 0 && e <= f)
  175. barycentric.z = e / f;
  176. else
  177. return false; // outside
  178. }
  179. {
  180. Vec3<T> en = edge1.normalized();
  181. Vec3<T> a = pt - v1;
  182. Vec3<T> b = v0 - v1;
  183. Vec3<T> c = (a - en * (en ^ a));
  184. Vec3<T> d = (b - en * (en ^ b));
  185. T e = c ^ d;
  186. T f = d ^ d;
  187. if (e >= 0 && e <= f)
  188. barycentric.x = e / f;
  189. else
  190. return false; // outside
  191. }
  192. barycentric.y = 1 - barycentric.x - barycentric.z;
  193. if (barycentric.y < 0)
  194. return false; // outside
  195. front = ((line.dir ^ normal) < 0);
  196. return true;
  197. }
  198. template <class T>
  199. Vec3<T>
  200. closestVertex
  201. (const Vec3<T> &v0,
  202. const Vec3<T> &v1,
  203. const Vec3<T> &v2,
  204. const Line3<T> &l)
  205. {
  206. Vec3<T> nearest = v0;
  207. T neardot = (v0 - l.closestPointTo(v0)).length2();
  208. T tmp = (v1 - l.closestPointTo(v1)).length2();
  209. if (tmp < neardot)
  210. {
  211. neardot = tmp;
  212. nearest = v1;
  213. }
  214. tmp = (v2 - l.closestPointTo(v2)).length2();
  215. if (tmp < neardot)
  216. {
  217. neardot = tmp;
  218. nearest = v2;
  219. }
  220. return nearest;
  221. }
  222. template <class T>
  223. Vec3<T>
  224. rotatePoint (const Vec3<T> p, Line3<T> l, T angle)
  225. {
  226. //
  227. // Rotate the point p around the line l by the given angle.
  228. //
  229. //
  230. // Form a coordinate frame with <x,y,a>. The rotation is the in xy
  231. // plane.
  232. //
  233. Vec3<T> q = l.closestPointTo(p);
  234. Vec3<T> x = p - q;
  235. T radius = x.length();
  236. x.normalize();
  237. Vec3<T> y = (x % l.dir).normalize();
  238. T cosangle = Math<T>::cos(angle);
  239. T sinangle = Math<T>::sin(angle);
  240. Vec3<T> r = q + x * radius * cosangle + y * radius * sinangle;
  241. return r;
  242. }
  243. } // namespace Imath
  244. #endif