ENH: Making nearestPointClassify query for triangle.

This is to access the face/edge/point status of the nearest at the
same time to ensure a consistent result.

Using getVolumeType query in distanceSurface, not simple normal
dot-product comparison, fails on edges.
This commit is contained in:
graham
2010-10-06 10:25:26 +01:00
parent 0a26787282
commit 6cdbd0ada7
11 changed files with 439 additions and 581 deletions

View File

@ -35,145 +35,145 @@ defineTypeNameAndDebug(Foam::treeDataTriSurface, 0);
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
// Fast distance to triangle calculation. From
// "Distance Between Point and Trangle in 3D"
// David Eberly, Magic Software Inc. Aug. 2003.
// Works on function Q giving distance to point and tries to minimize this.
Foam::scalar Foam::treeDataTriSurface::nearestCoords
(
const point& base,
const point& E0,
const point& E1,
const scalar a,
const scalar b,
const scalar c,
const point& P,
scalar& s,
scalar& t
)
{
// distance vector
const vector D(base - P);
// // Fast distance to triangle calculation. From
// // "Distance Between Point and Triangle in 3D"
// // David Eberly, Magic Software Inc. Aug. 2003.
// // Works on function Q giving distance to point and tries to minimize this.
// Foam::scalar Foam::treeDataTriSurface::nearestCoords
// (
// const point& base,
// const point& E0,
// const point& E1,
// const scalar a,
// const scalar b,
// const scalar c,
// const point& P,
// scalar& s,
// scalar& t
// )
// {
// // distance vector
// const vector D(base - P);
// Precalculate distance factors.
const scalar d = E0 & D;
const scalar e = E1 & D;
// // Precalculate distance factors.
// const scalar d = E0 & D;
// const scalar e = E1 & D;
// Do classification
const scalar det = a*c - b*b;
// // Do classification
// const scalar det = a*c - b*b;
s = b*e - c*d;
t = b*d - a*e;
// s = b*e - c*d;
// t = b*d - a*e;
if (s+t < det)
{
if (s < 0)
{
if (t < 0)
{
//region 4
if (e > 0)
{
//min on edge t = 0
t = 0;
s = (d >= 0 ? 0 : (-d >= a ? 1 : -d/a));
}
else
{
//min on edge s=0
s = 0;
t = (e >= 0 ? 0 : (-e >= c ? 1 : -e/c));
}
}
else
{
//region 3. Min on edge s = 0
s = 0;
t = (e >= 0 ? 0 : (-e >= c ? 1 : -e/c));
}
}
else if (t < 0)
{
//region 5
t = 0;
s = (d >= 0 ? 0 : (-d >= a ? 1 : -d/a));
}
else
{
//region 0
const scalar invDet = 1/det;
s *= invDet;
t *= invDet;
}
}
else
{
if (s < 0)
{
//region 2
const scalar tmp0 = b + d;
const scalar tmp1 = c + e;
if (tmp1 > tmp0)
{
//min on edge s+t=1
const scalar numer = tmp1 - tmp0;
const scalar denom = a-2*b+c;
s = (numer >= denom ? 1 : numer/denom);
t = 1 - s;
}
else
{
//min on edge s=0
s = 0;
t = (tmp1 <= 0 ? 1 : (e >= 0 ? 0 : - e/c));
}
}
else if (t < 0)
{
//region 6
const scalar tmp0 = b + d;
const scalar tmp1 = c + e;
if (tmp1 > tmp0)
{
//min on edge s+t=1
const scalar numer = tmp1 - tmp0;
const scalar denom = a-2*b+c;
s = (numer >= denom ? 1 : numer/denom);
t = 1 - s;
}
else
{
//min on edge t=0
t = 0;
s = (tmp1 <= 0 ? 1 : (d >= 0 ? 0 : - d/a));
}
}
else
{
//region 1
const scalar numer = c+e-(b+d);
if (numer <= 0)
{
s = 0;
}
else
{
const scalar denom = a-2*b+c;
s = (numer >= denom ? 1 : numer/denom);
}
}
t = 1 - s;
}
// if (s+t < det)
// {
// if (s < 0)
// {
// if (t < 0)
// {
// //region 4
// if (e > 0)
// {
// //min on edge t = 0
// t = 0;
// s = (d >= 0 ? 0 : (-d >= a ? 1 : -d/a));
// }
// else
// {
// //min on edge s=0
// s = 0;
// t = (e >= 0 ? 0 : (-e >= c ? 1 : -e/c));
// }
// }
// else
// {
// //region 3. Min on edge s = 0
// s = 0;
// t = (e >= 0 ? 0 : (-e >= c ? 1 : -e/c));
// }
// }
// else if (t < 0)
// {
// //region 5
// t = 0;
// s = (d >= 0 ? 0 : (-d >= a ? 1 : -d/a));
// }
// else
// {
// //region 0
// const scalar invDet = 1/det;
// s *= invDet;
// t *= invDet;
// }
// }
// else
// {
// if (s < 0)
// {
// //region 2
// const scalar tmp0 = b + d;
// const scalar tmp1 = c + e;
// if (tmp1 > tmp0)
// {
// //min on edge s+t=1
// const scalar numer = tmp1 - tmp0;
// const scalar denom = a-2*b+c;
// s = (numer >= denom ? 1 : numer/denom);
// t = 1 - s;
// }
// else
// {
// //min on edge s=0
// s = 0;
// t = (tmp1 <= 0 ? 1 : (e >= 0 ? 0 : - e/c));
// }
// }
// else if (t < 0)
// {
// //region 6
// const scalar tmp0 = b + d;
// const scalar tmp1 = c + e;
// if (tmp1 > tmp0)
// {
// //min on edge s+t=1
// const scalar numer = tmp1 - tmp0;
// const scalar denom = a-2*b+c;
// s = (numer >= denom ? 1 : numer/denom);
// t = 1 - s;
// }
// else
// {
// //min on edge t=0
// t = 0;
// s = (tmp1 <= 0 ? 1 : (d >= 0 ? 0 : - d/a));
// }
// }
// else
// {
// //region 1
// const scalar numer = c+e-(b+d);
// if (numer <= 0)
// {
// s = 0;
// }
// else
// {
// const scalar denom = a-2*b+c;
// s = (numer >= denom ? 1 : numer/denom);
// }
// }
// t = 1 - s;
// }
// Calculate distance.
// Note: abs should not be needed but truncation error causes problems
// with points very close to one of the triangle vertices.
// (seen up to -9e-15). Alternatively add some small value.
// // Calculate distance.
// // Note: abs should not be needed but truncation error causes problems
// // with points very close to one of the triangle vertices.
// // (seen up to -9e-15). Alternatively add some small value.
const scalar f = D & D;
return Foam::mag(a*s*s + 2*b*s*t + c*t*t + 2*d*s + 2*e*t + f);
}
// const scalar f = D & D;
// return Foam::mag(a*s*s + 2*b*s*t + c*t*t + 2*d*s + 2*e*t + f);
// }
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
@ -234,9 +234,7 @@ Foam::label Foam::treeDataTriSurface::getVolumeType
(
surface_,
sample,
pHit.index(),
pHit.hitPoint(),
indexedOctree<treeDataTriSurface>::perturbTol()
pHit.index()
);
if (t == triSurfaceTools::UNKNOWN)
@ -353,39 +351,43 @@ void Foam::treeDataTriSurface::findNearest
// )
//)
{
// Get spanning vectors of triangle
vector base(p1);
vector E0(p0 - p1);
vector E1(p2 - p1);
// // Get spanning vectors of triangle
// vector base(p1);
// vector E0(p0 - p1);
// vector E1(p2 - p1);
scalar a(E0& E0);
scalar b(E0& E1);
scalar c(E1& E1);
// scalar a(E0& E0);
// scalar b(E0& E1);
// scalar c(E1& E1);
// Get nearest point in s,t coordinates (s is along E0, t is along
// E1)
scalar s;
scalar t;
// // Get nearest point in s,t coordinates (s is along E0, t is along
// // E1)
// scalar s;
// scalar t;
scalar distSqr = nearestCoords
(
base,
E0,
E1,
a,
b,
c,
sample,
// scalar distSqr = nearestCoords
// (
// base,
// E0,
// E1,
// a,
// b,
// c,
// sample,
s,
t
);
// s,
// t
// );
pointHit pHit = triPointRef(p0, p1, p2).nearestPoint(sample);
scalar distSqr = sqr(pHit.distance());
if (distSqr < nearestDistSqr)
{
nearestDistSqr = distSqr;
minIndex = index;
nearestPoint = base + s*E0 + t*E1;
nearestPoint = pHit.rawPoint();
}
}
}