Path: blob/master/3rdparty/openexr/Imath/ImathLineAlgo.h
16337 views
///////////////////////////////////////////////////////////////////////////1//2// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas3// Digital Ltd. LLC4//5// All rights reserved.6//7// Redistribution and use in source and binary forms, with or without8// modification, are permitted provided that the following conditions are9// met:10// * Redistributions of source code must retain the above copyright11// notice, this list of conditions and the following disclaimer.12// * Redistributions in binary form must reproduce the above13// copyright notice, this list of conditions and the following disclaimer14// in the documentation and/or other materials provided with the15// distribution.16// * Neither the name of Industrial Light & Magic nor the names of17// its contributors may be used to endorse or promote products derived18// from this software without specific prior written permission.19//20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS21// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT22// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR23// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT24// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,25// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT26// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,27// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY28// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT29// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE30// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.31//32///////////////////////////////////////////////////////////////////////////33343536#ifndef INCLUDED_IMATHLINEALGO_H37#define INCLUDED_IMATHLINEALGO_H3839//------------------------------------------------------------------40//41// This file contains algorithms applied to or in conjunction42// with lines (Imath::Line). These algorithms may require43// more headers to compile. The assumption made is that these44// functions are called much less often than the basic line45// functions or these functions require more support classes46//47// Contains:48//49// bool closestPoints(const Line<T>& line1,50// const Line<T>& line2,51// Vec3<T>& point1,52// Vec3<T>& point2)53//54// bool intersect( const Line3<T> &line,55// const Vec3<T> &v0,56// const Vec3<T> &v1,57// const Vec3<T> &v2,58// Vec3<T> &pt,59// Vec3<T> &barycentric,60// bool &front)61//62// V3f63// closestVertex(const Vec3<T> &v0,64// const Vec3<T> &v1,65// const Vec3<T> &v2,66// const Line3<T> &l)67//68// V3f69// rotatePoint(const Vec3<T> p, Line3<T> l, float angle)70//71//------------------------------------------------------------------7273#include "ImathLine.h"74#include "ImathVecAlgo.h"75#include "ImathFun.h"7677namespace Imath {787980template <class T>81bool82closestPoints83(const Line3<T>& line1,84const Line3<T>& line2,85Vec3<T>& point1,86Vec3<T>& point2)87{88//89// Compute point1 and point2 such that point1 is on line1, point290// is on line2 and the distance between point1 and point2 is minimal.91// This function returns true if point1 and point2 can be computed,92// or false if line1 and line2 are parallel or nearly parallel.93// This function assumes that line1.dir and line2.dir are normalized.94//9596Vec3<T> w = line1.pos - line2.pos;97T d1w = line1.dir ^ w;98T d2w = line2.dir ^ w;99T d1d2 = line1.dir ^ line2.dir;100T n1 = d1d2 * d2w - d1w;101T n2 = d2w - d1d2 * d1w;102T d = 1 - d1d2 * d1d2;103T absD = abs (d);104105if ((absD > 1) ||106(abs (n1) < limits<T>::max() * absD &&107abs (n2) < limits<T>::max() * absD))108{109point1 = line1 (n1 / d);110point2 = line2 (n2 / d);111return true;112}113else114{115return false;116}117}118119120template <class T>121bool122intersect123(const Line3<T> &line,124const Vec3<T> &v0,125const Vec3<T> &v1,126const Vec3<T> &v2,127Vec3<T> &pt,128Vec3<T> &barycentric,129bool &front)130{131//132// Given a line and a triangle (v0, v1, v2), the intersect() function133// finds the intersection of the line and the plane that contains the134// triangle.135//136// If the intersection point cannot be computed, either because the137// line and the triangle's plane are nearly parallel or because the138// triangle's area is very small, intersect() returns false.139//140// If the intersection point is outside the triangle, intersect141// returns false.142//143// If the intersection point, pt, is inside the triangle, intersect()144// computes a front-facing flag and the barycentric coordinates of145// the intersection point, and returns true.146//147// The front-facing flag is true if the dot product of the triangle's148// normal, (v2-v1)%(v1-v0), and the line's direction is negative.149//150// The barycentric coordinates have the following property:151//152// pt = v0 * barycentric.x + v1 * barycentric.y + v2 * barycentric.z153//154155Vec3<T> edge0 = v1 - v0;156Vec3<T> edge1 = v2 - v1;157Vec3<T> normal = edge1 % edge0;158159T l = normal.length();160161if (l != 0)162normal /= l;163else164return false; // zero-area triangle165166//167// d is the distance of line.pos from the plane that contains the triangle.168// The intersection point is at line.pos + (d/nd) * line.dir.169//170171T d = normal ^ (v0 - line.pos);172T nd = normal ^ line.dir;173174if (abs (nd) > 1 || abs (d) < limits<T>::max() * abs (nd))175pt = line (d / nd);176else177return false; // line and plane are nearly parallel178179//180// Compute the barycentric coordinates of the intersection point.181// The intersection is inside the triangle if all three barycentric182// coordinates are between zero and one.183//184185{186Vec3<T> en = edge0.normalized();187Vec3<T> a = pt - v0;188Vec3<T> b = v2 - v0;189Vec3<T> c = (a - en * (en ^ a));190Vec3<T> d = (b - en * (en ^ b));191T e = c ^ d;192T f = d ^ d;193194if (e >= 0 && e <= f)195barycentric.z = e / f;196else197return false; // outside198}199200{201Vec3<T> en = edge1.normalized();202Vec3<T> a = pt - v1;203Vec3<T> b = v0 - v1;204Vec3<T> c = (a - en * (en ^ a));205Vec3<T> d = (b - en * (en ^ b));206T e = c ^ d;207T f = d ^ d;208209if (e >= 0 && e <= f)210barycentric.x = e / f;211else212return false; // outside213}214215barycentric.y = 1 - barycentric.x - barycentric.z;216217if (barycentric.y < 0)218return false; // outside219220front = ((line.dir ^ normal) < 0);221return true;222}223224225template <class T>226Vec3<T>227closestVertex228(const Vec3<T> &v0,229const Vec3<T> &v1,230const Vec3<T> &v2,231const Line3<T> &l)232{233Vec3<T> nearest = v0;234T neardot = (v0 - l.closestPointTo(v0)).length2();235236T tmp = (v1 - l.closestPointTo(v1)).length2();237238if (tmp < neardot)239{240neardot = tmp;241nearest = v1;242}243244tmp = (v2 - l.closestPointTo(v2)).length2();245if (tmp < neardot)246{247neardot = tmp;248nearest = v2;249}250251return nearest;252}253254255template <class T>256Vec3<T>257rotatePoint (const Vec3<T> p, Line3<T> l, T angle)258{259//260// Rotate the point p around the line l by the given angle.261//262263//264// Form a coordinate frame with <x,y,a>. The rotation is the in xy265// plane.266//267268Vec3<T> q = l.closestPointTo(p);269Vec3<T> x = p - q;270T radius = x.length();271272x.normalize();273Vec3<T> y = (x % l.dir).normalize();274275T cosangle = Math<T>::cos(angle);276T sinangle = Math<T>::sin(angle);277278Vec3<T> r = q + x * radius * cosangle + y * radius * sinangle;279280return r;281}282283284} // namespace Imath285286#endif287288289