123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229 |
- // David Eberly, Geometric Tools, Redmond WA 98052
- // Copyright (c) 1998-2020
- // Distributed under the Boost Software License, Version 1.0.
- // https://www.boost.org/LICENSE_1_0.txt
- // https://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
- // Version: 4.0.2019.08.13
- #pragma once
- #include <Mathematics/DCPQuery.h>
- #include <Mathematics/Triangle.h>
- namespace WwiseGTE
- {
- template <int N, typename Rational>
- class DistancePointTriangleExact
- {
- public:
- struct Result
- {
- Rational sqrDistance;
- // barycentric coordinates for triangle.v[3]
- Rational parameter[3];
- Vector<N, Rational> closest;
- };
- Result operator()(Vector<N, Rational> const& point, Triangle<N, Rational> const& triangle)
- {
- Vector<N, Rational> diff = point - triangle.v[0];
- Vector<N, Rational> edge0 = triangle.v[1] - triangle.v[0];
- Vector<N, Rational> edge1 = triangle.v[2] - triangle.v[0];
- Rational a00 = Dot(edge0, edge0);
- Rational a01 = Dot(edge0, edge1);
- Rational a11 = Dot(edge1, edge1);
- Rational b0 = -Dot(diff, edge0);
- Rational b1 = -Dot(diff, edge1);
- Rational const zero = (Rational)0;
- Rational const one = (Rational)1;
- Rational det = a00 * a11 - a01 * a01;
- Rational t0 = a01 * b1 - a11 * b0;
- Rational t1 = a01 * b0 - a00 * b1;
- if (t0 + t1 <= det)
- {
- if (t0 < zero)
- {
- if (t1 < zero) // region 4
- {
- if (b0 < zero)
- {
- t1 = zero;
- if (-b0 >= a00) // V1
- {
- t0 = one;
- }
- else // E01
- {
- t0 = -b0 / a00;
- }
- }
- else
- {
- t0 = zero;
- if (b1 >= zero) // V0
- {
- t1 = zero;
- }
- else if (-b1 >= a11) // V2
- {
- t1 = one;
- }
- else // E20
- {
- t1 = -b1 / a11;
- }
- }
- }
- else // region 3
- {
- t0 = zero;
- if (b1 >= zero) // V0
- {
- t1 = zero;
- }
- else if (-b1 >= a11) // V2
- {
- t1 = one;
- }
- else // E20
- {
- t1 = -b1 / a11;
- }
- }
- }
- else if (t1 < zero) // region 5
- {
- t1 = zero;
- if (b0 >= zero) // V0
- {
- t0 = zero;
- }
- else if (-b0 >= a00) // V1
- {
- t0 = one;
- }
- else // E01
- {
- t0 = -b0 / a00;
- }
- }
- else // region 0, interior
- {
- Rational invDet = one / det;
- t0 *= invDet;
- t1 *= invDet;
- }
- }
- else
- {
- Rational tmp0, tmp1, numer, denom;
- if (t0 < zero) // region 2
- {
- tmp0 = a01 + b0;
- tmp1 = a11 + b1;
- if (tmp1 > tmp0)
- {
- numer = tmp1 - tmp0;
- denom = a00 - (Rational)2 * a01 + a11;
- if (numer >= denom) // V1
- {
- t0 = one;
- t1 = zero;
- }
- else // E12
- {
- t0 = numer / denom;
- t1 = one - t0;
- }
- }
- else
- {
- t0 = zero;
- if (tmp1 <= zero) // V2
- {
- t1 = one;
- }
- else if (b1 >= zero) // V0
- {
- t1 = zero;
- }
- else // E20
- {
- t1 = -b1 / a11;
- }
- }
- }
- else if (t1 < zero) // region 6
- {
- tmp0 = a01 + b1;
- tmp1 = a00 + b0;
- if (tmp1 > tmp0)
- {
- numer = tmp1 - tmp0;
- denom = a00 - (Rational)2 * a01 + a11;
- if (numer >= denom) // V2
- {
- t1 = one;
- t0 = zero;
- }
- else // E12
- {
- t1 = numer / denom;
- t0 = one - t1;
- }
- }
- else
- {
- t1 = zero;
- if (tmp1 <= zero) // V1
- {
- t0 = one;
- }
- else if (b0 >= zero) // V0
- {
- t0 = zero;
- }
- else // E01
- {
- t0 = -b0 / a00;
- }
- }
- }
- else // region 1
- {
- numer = a11 + b1 - a01 - b0;
- if (numer <= zero) // V2
- {
- t0 = zero;
- t1 = one;
- }
- else
- {
- denom = a00 - (Rational)2 * a01 + a11;
- if (numer >= denom) // V1
- {
- t0 = one;
- t1 = zero;
- }
- else // 12
- {
- t0 = numer / denom;
- t1 = one - t0;
- }
- }
- }
- }
- Result result;
- result.parameter[0] = one - t0 - t1;
- result.parameter[1] = t0;
- result.parameter[2] = t1;
- result.closest = triangle.v[0] + t0 * edge0 + t1 * edge1;
- diff = point - result.closest;
- result.sqrDistance = Dot(diff, diff);
- return result;
- }
- };
- }
|