From: <pat...@us...> - 2011-03-27 18:11:06
|
Revision: 1272 http://ggt.svn.sourceforge.net/ggt/?rev=1272&view=rev Author: patrickh Date: 2011-03-27 18:11:00 +0000 (Sun, 27 Mar 2011) Log Message: ----------- Added an overload of gmtl::findClosestPt() for use with gmtl::Tri<T> and gmtl::Point<T, 3>. Submitted by: Sebastian Messerschmidt Modified Paths: -------------- trunk/ChangeLog trunk/gmtl/TriOps.h Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2011-03-27 17:31:11 UTC (rev 1271) +++ trunk/ChangeLog 2011-03-27 18:11:00 UTC (rev 1272) @@ -1,5 +1,8 @@ DATE AUTHOR CHANGE ---------- ------------ ------------------------------------------------------- +2011-03-27 patrickh Added an overload of gmtl::findClosestPt() for use with + gmtl::Tri<T> and gmtl::Point<T, 3>. + Submitted by Sebastian Messerschmidt 2011-03-27 patrickh Added an overload of gmtl::intersectDoubleSided() for Tri/LineSeg intersection that ignores the triangle winding. Modified: trunk/gmtl/TriOps.h =================================================================== --- trunk/gmtl/TriOps.h 2011-03-27 17:31:11 UTC (rev 1271) +++ trunk/gmtl/TriOps.h 2011-03-27 18:11:00 UTC (rev 1272) @@ -18,6 +18,83 @@ */ /** + * Finds the closest point on the triangle to a given point. + * + * @param tri The triangle to test. + * @param pt The point which to test against triangle. + * + * @return the point on the line segment closest to pt. + * + * @since 0.7.0 + */ +template< class DATA_TYPE > +Point<DATA_TYPE, 3> findNearestPt(const Tri<DATA_TYPE>& tri, + const Point<DATA_TYPE, 3>& pt) +{ + // inspired by Real Time Collision Detection 1st Edition p. 144 ff + Vec<DATA_TYPE, 3> ab = tri.edge(0,1); + Vec<DATA_TYPE, 3> ac = tri.edge(0,2); + Vec<DATA_TYPE, 3> ap = pt - tri.mVerts[0]; // p - a + + // check if P in vertex region outside a + DATA_TYPE d1 = dot(ab, ap); + DATA_TYPE d2 = dot(ac, ap); + if (d1 <= 0.0 && d2 <= 0.0) + { + return tri.mVerts[0]; + } + +// check if P in vertex region outside b + Vec<DATA_TYPE, 3> bp = pt - tri.mVerts[1]; // p -b + DATA_TYPE d3 = dot(ab, bp); + DATA_TYPE d4 = dot(ac, bp); + + if (d3 >= 0 && d4 <= d3) + { + return tri.mVerts[1]; + } + + // check if p in edge region of AB, if true return projection of P onto AB + DATA_TYPE vc = d1*d4 - d3*d2; + if (vc <= 0.0 && d1 >= 0.0 && d3 <= 0.0) + { + DATA_TYPE v = d1 / (d1 - d3); + return tri.mVerts[0] + v * ab; + } + + // check if P in vertex region outside c + Vec<DATA_TYPE, 3> cp = pt - tri.mVerts[2]; // p - c + DATA_TYPE d5 = dot(ab, cp); + DATA_TYPE d6 = dot(ac, cp); + if (d6 >= 0.0 && d5 <= d6) + { + return tri.mVerts[2]; + } + + // check if p in edge region of AC, if true return projection of P onto AC + DATA_TYPE vb = (d5 * d2) - (d1 * d6); + if (vb <= 0.0 && d2 >= 0.0 && d6 <= 0.0) + { + DATA_TYPE w = d2 / (d2 - d6); + return tri.mVerts[0] + w * ac; + } + + // check if p in edge region of BC, if true return projection of P onto BC + DATA_TYPE va = (d3 * d6) - (d5 * d4); + if (va <= 0.0 && (d4 -d3) >= 0.0 && (d5 - d6) >= 0.0) + { + DATA_TYPE w = (d4 -d3) / ((d4 - d3) + (d5 -d6)); + return tri.mVerts[1] + w * (tri.edge(1,2)); + } + + // P inside face region Compute Q trough barycentric coordinates + DATA_TYPE denom = 1.0 / (va + vb + vc); + DATA_TYPE v = vb * denom; + DATA_TYPE w = vc * denom; + return (tri.mVerts[0] + (ab * v) + (ac * w)); +} + +/** * Computes the point at the center of the given triangle. * * @param tri the triangle to find the center of This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |