| 342 | } |
| 343 | |
| 344 | IntersectionResult< Point3D > line_triangle_intersection( |
| 345 | const InfiniteLine3D& line, const Triangle3D& triangle ) |
| 346 | { |
| 347 | // http://www.geometrictools.com/LibMathematics/Intersection/Intersection.html |
| 348 | // Compute the offset origin, edges, and normal. |
| 349 | const auto& vertices = triangle.vertices(); |
| 350 | const Vector3D edge1{ vertices[0], vertices[1] }; |
| 351 | const Vector3D edge2{ vertices[0], vertices[2] }; |
| 352 | const auto normal = edge1.cross( edge2 ); |
| 353 | |
| 354 | // Solve Q + t*D = b1*E1 + b2*E2 (Q = diff, D = segment direction, |
| 355 | // E1 = edge1, E2 = edge2, N = Cross(E1,E2)) by |
| 356 | // |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2)) |
| 357 | // |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q)) |
| 358 | // |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N) |
| 359 | auto d_dot_n = line.direction().dot( normal ); |
| 360 | signed_index_t sign; |
| 361 | if( d_dot_n > 0. ) |
| 362 | { |
| 363 | sign = 1; |
| 364 | } |
| 365 | else if( d_dot_n < -0. ) |
| 366 | { |
| 367 | sign = -1; |
| 368 | d_dot_n = -d_dot_n; |
| 369 | } |
| 370 | else |
| 371 | { |
| 372 | // Segment and triangle are parallel |
| 373 | return { INTERSECTION_TYPE::parallel }; |
| 374 | } |
| 375 | |
| 376 | const Vector3D diff{ vertices[0], line.origin() }; |
| 377 | const auto d_dot_q_cross_e2 = |
| 378 | sign * line.direction().dot( diff.cross( edge2 ) ); |
| 379 | if( d_dot_q_cross_e2 >= -GLOBAL_EPSILON ) |
| 380 | { |
| 381 | const auto d_dot_e1_cross_q = |
| 382 | sign * line.direction().dot( edge1.cross( diff ) ); |
| 383 | if( d_dot_e1_cross_q >= -GLOBAL_EPSILON |
| 384 | && d_dot_q_cross_e2 + d_dot_e1_cross_q <= d_dot_n ) |
| 385 | { |
| 386 | // InfiniteLine intersects triangle. |
| 387 | const auto q_dot_n = -sign * diff.dot( normal ); |
| 388 | const auto inv = 1. / d_dot_n; |
| 389 | const auto seg_parameter = q_dot_n * inv; |
| 390 | |
| 391 | auto result = line.origin() + line.direction() * seg_parameter; |
| 392 | CorrectnessInfo< Point3D >::Correctness first_correctness{ |
| 393 | point_line_distance( result, line ) <= GLOBAL_EPSILON, |
| 394 | point_line_projection( result, line ) |
| 395 | }; |
| 396 | const auto tri_lambdas = |
| 397 | safe_triangle_barycentric_coordinates( result, triangle ); |
| 398 | const auto correctness_point = |
| 399 | vertices[0].get() * tri_lambdas[0] |
| 400 | + vertices[1].get() * tri_lambdas[1] |
| 401 | + vertices[2].get() * tri_lambdas[2]; |
nothing calls this directly
no test coverage detected