Rumba C++ SDK
ImathLineAlgo.h
Go to the documentation of this file.
1 //
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 //
34 
35 
36 
37 #ifndef INCLUDED_IMATHLINEALGO_H
38 #define INCLUDED_IMATHLINEALGO_H
39 
40 //------------------------------------------------------------------
41 //
42 // This file contains algorithms applied to or in conjunction
43 // with lines (Imath::Line). These algorithms may require
44 // more headers to compile. The assumption made is that these
45 // functions are called much less often than the basic line
46 // functions or these functions require more support classes
47 //
48 // Contains:
49 //
50 // bool closestPoints(const Line<T>& line1,
51 // const Line<T>& line2,
52 // Vec3<T>& point1,
53 // Vec3<T>& point2)
54 //
55 // bool intersect( const Line3<T> &line,
56 // const Vec3<T> &v0,
57 // const Vec3<T> &v1,
58 // const Vec3<T> &v2,
59 // Vec3<T> &pt,
60 // Vec3<T> &barycentric,
61 // bool &front)
62 //
63 // V3f
64 // closestVertex(const Vec3<T> &v0,
65 // const Vec3<T> &v1,
66 // const Vec3<T> &v2,
67 // const Line3<T> &l)
68 //
69 // V3f
70 // rotatePoint(const Vec3<T> p, Line3<T> l, float angle)
71 //
72 //------------------------------------------------------------------
73 
74 #include "ImathLine.h"
75 #include "ImathVecAlgo.h"
76 #include "ImathFun.h"
77 
78 namespace Imath {
79 
80 
81 template <class T>
82 bool
84  (const Line3<T>& line1,
85  const Line3<T>& line2,
86  Vec3<T>& point1,
87  Vec3<T>& point2)
88 {
89  //
90  // Compute point1 and point2 such that point1 is on line1, point2
91  // is on line2 and the distance between point1 and point2 is minimal.
92  // This function returns true if point1 and point2 can be computed,
93  // or false if line1 and line2 are parallel or nearly parallel.
94  // This function assumes that line1.dir and line2.dir are normalized.
95  //
96 
97  Vec3<T> w = line1.pos - line2.pos;
98  T d1w = line1.dir ^ w;
99  T d2w = line2.dir ^ w;
100  T d1d2 = line1.dir ^ line2.dir;
101  T n1 = d1d2 * d2w - d1w;
102  T n2 = d2w - d1d2 * d1w;
103  T d = 1 - d1d2 * d1d2;
104  T absD = abs (d);
105 
106  if ((absD > 1) ||
107  (abs (n1) < limits<T>::max() * absD &&
108  abs (n2) < limits<T>::max() * absD))
109  {
110  point1 = line1 (n1 / d);
111  point2 = line2 (n2 / d);
112  return true;
113  }
114  else
115  {
116  return false;
117  }
118 }
119 
120 
121 template <class T>
122 bool
123 intersect
124  (const Line3<T> &line,
125  const Vec3<T> &v0,
126  const Vec3<T> &v1,
127  const Vec3<T> &v2,
128  Vec3<T> &pt,
129  Vec3<T> &barycentric,
130  bool &front)
131 {
132  //
133  // Given a line and a triangle (v0, v1, v2), the intersect() function
134  // finds the intersection of the line and the plane that contains the
135  // triangle.
136  //
137  // If the intersection point cannot be computed, either because the
138  // line and the triangle's plane are nearly parallel or because the
139  // triangle's area is very small, intersect() returns false.
140  //
141  // If the intersection point is outside the triangle, intersect
142  // returns false.
143  //
144  // If the intersection point, pt, is inside the triangle, intersect()
145  // computes a front-facing flag and the barycentric coordinates of
146  // the intersection point, and returns true.
147  //
148  // The front-facing flag is true if the dot product of the triangle's
149  // normal, (v2-v1)%(v1-v0), and the line's direction is negative.
150  //
151  // The barycentric coordinates have the following property:
152  //
153  // pt = v0 * barycentric.x + v1 * barycentric.y + v2 * barycentric.z
154  //
155 
156  Vec3<T> edge0 = v1 - v0;
157  Vec3<T> edge1 = v2 - v1;
158  Vec3<T> normal = edge1 % edge0;
159 
160  T l = normal.length();
161 
162  if (l != 0)
163  normal /= l;
164  else
165  return false; // zero-area triangle
166 
167  //
168  // d is the distance of line.pos from the plane that contains the triangle.
169  // The intersection point is at line.pos + (d/nd) * line.dir.
170  //
171 
172  T d = normal ^ (v0 - line.pos);
173  T nd = normal ^ line.dir;
174 
175  if (abs (nd) > 1 || abs (d) < limits<T>::max() * abs (nd))
176  pt = line (d / nd);
177  else
178  return false; // line and plane are nearly parallel
179 
180  //
181  // Compute the barycentric coordinates of the intersection point.
182  // The intersection is inside the triangle if all three barycentric
183  // coordinates are between zero and one.
184  //
185 
186  {
187  Vec3<T> en = edge0.normalized();
188  Vec3<T> a = pt - v0;
189  Vec3<T> b = v2 - v0;
190  Vec3<T> c = (a - en * (en ^ a));
191  Vec3<T> d = (b - en * (en ^ b));
192  T e = c ^ d;
193  T f = d ^ d;
194 
195  if (e >= 0 && e <= f)
196  barycentric.z = e / f;
197  else
198  return false; // outside
199  }
200 
201  {
202  Vec3<T> en = edge1.normalized();
203  Vec3<T> a = pt - v1;
204  Vec3<T> b = v0 - v1;
205  Vec3<T> c = (a - en * (en ^ a));
206  Vec3<T> d = (b - en * (en ^ b));
207  T e = c ^ d;
208  T f = d ^ d;
209 
210  if (e >= 0 && e <= f)
211  barycentric.x = e / f;
212  else
213  return false; // outside
214  }
215 
216  barycentric.y = 1 - barycentric.x - barycentric.z;
217 
218  if (barycentric.y < 0)
219  return false; // outside
220 
221  front = ((line.dir ^ normal) < 0);
222  return true;
223 }
224 
225 
226 template <class T>
227 Vec3<T>
229  (const Vec3<T> &v0,
230  const Vec3<T> &v1,
231  const Vec3<T> &v2,
232  const Line3<T> &l)
233 {
234  Vec3<T> nearest = v0;
235  T neardot = (v0 - l.closestPointTo(v0)).length2();
236 
237  T tmp = (v1 - l.closestPointTo(v1)).length2();
238 
239  if (tmp < neardot)
240  {
241  neardot = tmp;
242  nearest = v1;
243  }
244 
245  tmp = (v2 - l.closestPointTo(v2)).length2();
246  if (tmp < neardot)
247  {
248  neardot = tmp;
249  nearest = v2;
250  }
251 
252  return nearest;
253 }
254 
255 
256 template <class T>
257 Vec3<T>
258 rotatePoint (const Vec3<T> p, Line3<T> l, T angle)
259 {
260  //
261  // Rotate the point p around the line l by the given angle.
262  //
263 
264  //
265  // Form a coordinate frame with <x,y,a>. The rotation is the in xy
266  // plane.
267  //
268 
269  Vec3<T> q = l.closestPointTo(p);
270  Vec3<T> x = p - q;
271  T radius = x.length();
272 
273  x.normalize();
274  Vec3<T> y = (x % l.dir).normalize();
275 
276  T cosangle = Math<T>::cos(angle);
277  T sinangle = Math<T>::sin(angle);
278 
279  Vec3<T> r = q + x * radius * cosangle + y * radius * sinangle;
280 
281  return r;
282 }
283 
284 
285 } // namespace Imath
286 
287 #endif
Vec3< T > closestVertex(const Vec3< T > &v0, const Vec3< T > &v1, const Vec3< T > &v2, const Line3< T > &l)
Definition: ImathLineAlgo.h:229
Definition: ImathFrame.h:42
T length() const
Definition: ImathVec.h:1662
T abs(T a)
Definition: ImathFun.h:53
bool closestPoints(const Line3< T > &line1, const Line3< T > &line2, Vec3< T > &point1, Vec3< T > &point2)
Definition: ImathLineAlgo.h:84
Definition: ImathLimits.h:117
T x
Definition: ImathVec.h:274
Vec3< T > rotatePoint(const Vec3< T > p, Line3< T > l, T angle)
Definition: ImathLineAlgo.h:258
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)
Definition: ImathLineAlgo.h:124
T y
Definition: ImathVec.h:274
static T cos(T x)
Definition: ImathMath.h:97
Vec3< T > dir
Definition: ImathLine.h:59
Vec3< T > closestPointTo(const Vec3< T > &point) const
Definition: ImathLine.h:130
Vec3< T > pos
Definition: ImathLine.h:58
T z
Definition: ImathVec.h:274
Vec3< T > normalized() const
Definition: ImathVec.h:1730
Definition: ImathLine.h:54
static T max()
Definition: ImathBox.h:67
static T sin(T x)
Definition: ImathMath.h:98