You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
229 lines
7.4 KiB
229 lines
7.4 KiB
// David Eberly, Geometric Tools, Redmond WA 98052
|
|
// Copyright (c) 1998-2021
|
|
// 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 gte
|
|
{
|
|
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;
|
|
}
|
|
};
|
|
}
|
|
|