HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ImathLineAlgo.h
Go to the documentation of this file.
1 //
2 // SPDX-License-Identifier: BSD-3-Clause
3 // Copyright Contributors to the OpenEXR Project.
4 //
5 
6 //
7 // Algorithms applied to or in conjunction with Imath::Line class
8 //
9 
10 #ifndef INCLUDED_IMATHLINEALGO_H
11 #define INCLUDED_IMATHLINEALGO_H
12 
13 #include "ImathFun.h"
14 #include "ImathLine.h"
15 #include "ImathNamespace.h"
16 #include "ImathVecAlgo.h"
17 
18 IMATH_INTERNAL_NAMESPACE_HEADER_ENTER
19 
20 ///
21 /// Compute point1 and point2 such that point1 is on line1, point2
22 /// is on line2 and the distance between point1 and point2 is minimal.
23 ///
24 /// This function returns true if point1 and point2 can be computed,
25 /// or false if line1 and line2 are parallel or nearly parallel.
26 /// This function assumes that line1.dir and line2.dir are normalized.
27 ///
28 
29 template <class T>
30 IMATH_CONSTEXPR14 bool
32  const Line3<T>& line1,
33  const Line3<T>& line2,
34  Vec3<T>& point1,
35  Vec3<T>& point2) IMATH_NOEXCEPT
36 {
37  Vec3<T> w = line1.pos - line2.pos;
38  T d1w = line1.dir ^ w;
39  T d2w = line2.dir ^ w;
40  T d1d2 = line1.dir ^ line2.dir;
41  T n1 = d1d2 * d2w - d1w;
42  T n2 = d2w - d1d2 * d1w;
43  T d = 1 - d1d2 * d1d2;
44  T absD = abs (d);
45 
46  if ((absD > 1) || (abs (n1) < std::numeric_limits<T>::max () * absD &&
47  abs (n2) < std::numeric_limits<T>::max () * absD))
48  {
49  point1 = line1 (n1 / d);
50  point2 = line2 (n2 / d);
51  return true;
52  }
53  else
54  {
55  return false;
56  }
57 }
58 
59 ///
60 /// Given a line and a triangle (v0, v1, v2), the intersect() function
61 /// finds the intersection of the line and the plane that contains the
62 /// triangle.
63 ///
64 /// If the intersection point cannot be computed, either because the
65 /// line and the triangle's plane are nearly parallel or because the
66 /// triangle's area is very small, intersect() returns false.
67 ///
68 /// If the intersection point is outside the triangle, intersect
69 /// returns false.
70 ///
71 /// If the intersection point, pt, is inside the triangle, intersect()
72 /// computes a front-facing flag and the barycentric coordinates of
73 /// the intersection point, and returns true.
74 ///
75 /// The front-facing flag is true if the dot product of the triangle's
76 /// normal, (v2-v1)%(v1-v0), and the line's direction is negative.
77 ///
78 /// The barycentric coordinates have the following property:
79 ///
80 /// pt = v0 * barycentric.x + v1 * barycentric.y + v2 * barycentric.z
81 ///
82 
83 template <class T>
84 IMATH_CONSTEXPR14 bool
86  const Line3<T>& line,
87  const Vec3<T>& v0,
88  const Vec3<T>& v1,
89  const Vec3<T>& v2,
90  Vec3<T>& pt,
91  Vec3<T>& barycentric,
92  bool& front) IMATH_NOEXCEPT
93 {
94  Vec3<T> edge0 = v1 - v0;
95  Vec3<T> edge1 = v2 - v1;
96  Vec3<T> normal = edge1 % edge0;
97 
98  T l = normal.length ();
99 
100  if (l != 0)
101  normal /= l;
102  else
103  return false; // zero-area triangle
104 
105  //
106  // d is the distance of line.pos from the plane that contains the triangle.
107  // The intersection point is at line.pos + (d/nd) * line.dir.
108  //
109 
110  T d = normal ^ (v0 - line.pos);
111  T nd = normal ^ line.dir;
112 
113  if (abs (nd) > 1 || abs (d) < std::numeric_limits<T>::max () * abs (nd))
114  pt = line (d / nd);
115  else
116  return false; // line and plane are nearly parallel
117 
118  //
119  // Compute the barycentric coordinates of the intersection point.
120  // The intersection is inside the triangle if all three barycentric
121  // coordinates are between zero and one.
122  //
123 
124  {
125  Vec3<T> en = edge0.normalized ();
126  Vec3<T> a = pt - v0;
127  Vec3<T> b = v2 - v0;
128  Vec3<T> c = (a - en * (en ^ a));
129  Vec3<T> d = (b - en * (en ^ b));
130  T e = c ^ d;
131  T f = d ^ d;
132 
133  if (e >= 0 && e <= f)
134  barycentric.z = e / f;
135  else
136  return false; // outside
137  }
138 
139  {
140  Vec3<T> en = edge1.normalized ();
141  Vec3<T> a = pt - v1;
142  Vec3<T> b = v0 - v1;
143  Vec3<T> c = (a - en * (en ^ a));
144  Vec3<T> d = (b - en * (en ^ b));
145  T e = c ^ d;
146  T f = d ^ d;
147 
148  if (e >= 0 && e <= f)
149  barycentric.x = e / f;
150  else
151  return false; // outside
152  }
153 
154  barycentric.y = 1 - barycentric.x - barycentric.z;
155 
156  if (barycentric.y < 0) return false; // outside
157 
158  front = ((line.dir ^ normal) < 0);
159  return true;
160 }
161 
162 ///
163 /// Return the vertex that is closest to the given line. The returned
164 /// point is either v0, v1, or v2.
165 ///
166 
167 template <class T>
168 IMATH_CONSTEXPR14 Vec3<T>
170  const Vec3<T>& v0, const Vec3<T>& v1, const Vec3<T>& v2, const Line3<T>& l)
172 {
173  Vec3<T> nearest = v0;
174  T neardot = (v0 - l.closestPointTo (v0)).length2 ();
175 
176  T tmp = (v1 - l.closestPointTo (v1)).length2 ();
177 
178  if (tmp < neardot)
179  {
180  neardot = tmp;
181  nearest = v1;
182  }
183 
184  tmp = (v2 - l.closestPointTo (v2)).length2 ();
185  if (tmp < neardot)
186  {
187  neardot = tmp;
188  nearest = v2;
189  }
190 
191  return nearest;
192 }
193 
194 ///
195 /// Rotate the point p around the line l by the given angle.
196 ///
197 
198 template <class T>
199 IMATH_CONSTEXPR14 Vec3<T>
201 {
202  //
203  // Form a coordinate frame with <x,y,a>. The rotation is the in xy
204  // plane.
205  //
206 
207  Vec3<T> q = l.closestPointTo (p);
208  Vec3<T> x = p - q;
209  T radius = x.length ();
210 
211  x.normalize ();
212  Vec3<T> y = (x % l.dir).normalize ();
213 
214  T cosangle = std::cos (angle);
215  T sinangle = std::sin (angle);
216 
217  Vec3<T> r = q + x * radius * cosangle + y * radius * sinangle;
218 
219  return r;
220 }
221 
222 IMATH_INTERNAL_NAMESPACE_HEADER_EXIT
223 
224 #endif // INCLUDED_IMATHLINEALGO_H
#define IMATH_NOEXCEPT
Definition: ImathConfig.h:78
Definition: ImathVec.h:40
SIM_API const UT_StringHolder angle
IMATH_HOSTDEVICE T length() const IMATH_NOEXCEPT
Return the Euclidean norm.
Definition: ImathVec.h:2064
IMATH_CONSTEXPR14 Vec3< T > closestVertex(const Vec3< T > &v0, const Vec3< T > &v1, const Vec3< T > &v2, const Line3< T > &l) IMATH_NOEXCEPT
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1222
IMATH_HOSTDEVICE Vec3< T > normalized() const IMATH_NOEXCEPT
Return a normalized vector. Does not modify *this.
Definition: ImathVec.h:2131
GLint y
Definition: glcorearb.h:103
GLfloat GLfloat GLfloat v2
Definition: glcorearb.h:818
GLdouble GLdouble GLdouble q
Definition: glad.h:2445
IMATH_INTERNAL_NAMESPACE_HEADER_ENTER IMATH_CONSTEXPR14 bool closestPoints(const Line3< T > &line1, const Line3< T > &line2, Vec3< T > &point1, Vec3< T > &point2) IMATH_NOEXCEPT
Definition: ImathLineAlgo.h:31
GLfloat f
Definition: glcorearb.h:1926
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1222
GLint GLenum GLint x
Definition: glcorearb.h:409
GLfloat v0
Definition: glcorearb.h:816
IMATH_CONSTEXPR14 Vec3< T > rotatePoint(const Vec3< T > p, Line3< T > l, T angle) IMATH_NOEXCEPT
IMATH_CONSTEXPR14 bool intersect(const Line3< T > &line, const Vec3< T > &v0, const Vec3< T > &v1, const Vec3< T > &v2, Vec3< T > &pt, Vec3< T > &barycentric, bool &front) IMATH_NOEXCEPT
Definition: ImathLineAlgo.h:85
GLfloat GLfloat v1
Definition: glcorearb.h:817
ImageBuf OIIO_API max(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
FMT_CONSTEXPR basic_fp< F > normalize(basic_fp< F > value)
Definition: format.h:1701
GLubyte GLubyte GLubyte GLubyte w
Definition: glcorearb.h:857
IMATH_INTERNAL_NAMESPACE_HEADER_ENTER IMATH_HOSTDEVICE constexpr T abs(T a) IMATH_NOEXCEPT
Definition: ImathFun.h:26
GLboolean r
Definition: glcorearb.h:1222
IMATH_HOSTDEVICE const Vec3 & normalize() IMATH_NOEXCEPT
Normalize in place. If length()==0, return a null vector.
Definition: ImathVec.h:2083