• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
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
closestPoints(const Line3<T> & line1,const Line3<T> & line2,Vec3<T> & point1,Vec3<T> & point2)83 closestPoints
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
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)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>
closestVertex(const Vec3<T> & v0,const Vec3<T> & v1,const Vec3<T> & v2,const Line3<T> & l)228 closestVertex
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>
rotatePoint(const Vec3<T> p,Line3<T> l,T angle)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
288