| 299 | } |
| 300 | |
| 301 | double getDistancePointToTriangle(const Point3d& point, const std::vector<Point3d>& triangle) { |
| 302 | if (triangle.size() != 3) { |
| 303 | return 0; |
| 304 | } |
| 305 | |
| 306 | //Distance Between Point and Triangle in 3D |
| 307 | //David Eberly |
| 308 | //Geometric Tools, LLC |
| 309 | //http://www.geometrictools.com/ |
| 310 | |
| 311 | //T(s; t) = B+sE0+tE1 |
| 312 | |
| 313 | const Point3d& B = triangle[0]; |
| 314 | const Vector3d E0 = triangle[1] - triangle[0]; |
| 315 | const Vector3d E1 = triangle[2] - triangle[0]; |
| 316 | const Vector3d BminusP = B - point; |
| 317 | |
| 318 | const double b = E0.dot(E1); |
| 319 | |
| 320 | if (std::abs(b) > 1.0 - 1.0E-12) { |
| 321 | // triangle is collinear |
| 322 | return 0; |
| 323 | } |
| 324 | |
| 325 | const double a = E0.dot(E0); |
| 326 | const double c = E1.dot(E1); |
| 327 | const double d = E0.dot(BminusP); |
| 328 | const double e = E1.dot(BminusP); |
| 329 | // const double f = BminusP.dot(BminusP); // unused |
| 330 | |
| 331 | const double det = a * c - b * b; |
| 332 | const double s = b * e - c * d; |
| 333 | const double t = b * d - a * e; |
| 334 | |
| 335 | Point3d closestPoint; |
| 336 | |
| 337 | if (s + t <= det) { |
| 338 | if (s < 0) { |
| 339 | if (t < 0) { |
| 340 | //region 4, closest to point triangle[0] |
| 341 | return getDistance(point, triangle[0]); |
| 342 | } else { |
| 343 | //region 3, closest to line triangle[0] to triangle[2] |
| 344 | std::vector<Point3d> line; |
| 345 | line.push_back(triangle[0]); |
| 346 | line.push_back(triangle[2]); |
| 347 | return getDistancePointToLineSegment(point, line); |
| 348 | } |
| 349 | } else if (t < 0) { |
| 350 | //region 5, closest to line triangle[0] to triangle[1] |
| 351 | std::vector<Point3d> line; |
| 352 | line.push_back(triangle[0]); |
| 353 | line.push_back(triangle[1]); |
| 354 | return getDistancePointToLineSegment(point, line); |
| 355 | } else { |
| 356 | //region 0, closest point is inside triangle |
| 357 | const double invDet = 1.0 / det; |
| 358 | closestPoint = B + invDet * s * E0 + invDet * t * E1; |