PageRenderTime 33ms CodeModel.GetById 16ms app.highlight 14ms RepoModel.GetById 1ms app.codeStats 0ms

/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
 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
 78namespace Imath {
 79
 80
 81template <class T>
 82bool
 83closestPoints
 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
121template <class T>
122bool
123intersect
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
226template <class T>
227Vec3<T>
228closestVertex
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
256template <class T>
257Vec3<T>
258rotatePoint (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