|
23 | 23 |
|
24 | 24 | #include <optional> |
25 | 25 |
|
| 26 | +#include <geode/basic/logger.hpp> |
26 | 27 | #include <geode/geometry/distance.hpp> |
27 | 28 |
|
28 | 29 | #include <absl/algorithm/container.h> |
@@ -339,6 +340,92 @@ namespace |
339 | 340 | geode::point_point_distance( point, closest_point ); |
340 | 341 | return std::make_tuple( distance, std::move( closest_point ) ); |
341 | 342 | } |
| 343 | + |
| 344 | + std::pair< std::vector< geode::local_index_t >, |
| 345 | + std::vector< geode::local_index_t > > |
| 346 | + find_non_colocated_triangles_points( const geode::Triangle3D& triangle0, |
| 347 | + const geode::Triangle3D& triangle1 ) |
| 348 | + { |
| 349 | + std::pair< std::array< bool, 3 >, std::array< bool, 3 > > colocated{ |
| 350 | + { false, false, false }, { false, false, false } |
| 351 | + }; |
| 352 | + const auto& vertices0 = triangle0.vertices(); |
| 353 | + const auto& vertices1 = triangle1.vertices(); |
| 354 | + for( const auto vertex0 : geode::LRange{ 3 } ) |
| 355 | + { |
| 356 | + for( const auto vertex1 : geode::LRange{ 3 } ) |
| 357 | + { |
| 358 | + if( geode::point_point_distance( |
| 359 | + vertices0[vertex0].get(), vertices1[vertex1].get() ) |
| 360 | + <= geode::GLOBAL_EPSILON ) |
| 361 | + { |
| 362 | + colocated.first[vertex0] = true; |
| 363 | + colocated.second[vertex1] = true; |
| 364 | + } |
| 365 | + } |
| 366 | + } |
| 367 | + |
| 368 | + std::pair< std::vector< geode::local_index_t >, |
| 369 | + std::vector< geode::local_index_t > > |
| 370 | + result; |
| 371 | + for( const auto v : geode::LRange{ 3 } ) |
| 372 | + { |
| 373 | + if( !colocated.first[v] ) |
| 374 | + { |
| 375 | + result.first.push_back( v ); |
| 376 | + } |
| 377 | + if( !colocated.second[v] ) |
| 378 | + { |
| 379 | + result.second.push_back( v ); |
| 380 | + } |
| 381 | + } |
| 382 | + return result; |
| 383 | + } |
| 384 | + |
| 385 | + std::tuple< double, geode::Point3D, geode::Point3D > test_close_triangles( |
| 386 | + const std::vector< geode::local_index_t >& non_colocated_points, |
| 387 | + const geode::Triangle3D& base_triangle, |
| 388 | + const geode::Triangle3D& other_triangle ) |
| 389 | + { |
| 390 | + const auto& base_vertices = base_triangle.vertices(); |
| 391 | + double min_distance{ std::numeric_limits< double >::max() }; |
| 392 | + geode::Point3D point0; |
| 393 | + geode::Point3D point1; |
| 394 | + for( const auto vertex0 : non_colocated_points ) |
| 395 | + { |
| 396 | + for( const auto vertex1 : non_colocated_points ) |
| 397 | + { |
| 398 | + if( vertex0 == vertex1 ) |
| 399 | + { |
| 400 | + continue; |
| 401 | + } |
| 402 | + if( geode::point_point_distance( base_vertices[vertex0].get(), |
| 403 | + base_vertices[vertex1].get() ) |
| 404 | + <= geode::GLOBAL_EPSILON ) |
| 405 | + { |
| 406 | + DEBUG( vertex0 ); |
| 407 | + DEBUG( vertex1 ); |
| 408 | + SDEBUG( base_vertices[0].get() ); |
| 409 | + SDEBUG( base_vertices[1].get() ); |
| 410 | + SDEBUG( base_vertices[2].get() ); |
| 411 | + SDEBUG( other_triangle.vertices()[0].get() ); |
| 412 | + SDEBUG( other_triangle.vertices()[1].get() ); |
| 413 | + SDEBUG( other_triangle.vertices()[2].get() ); |
| 414 | + } |
| 415 | + const geode::Segment3D edge{ base_vertices[vertex0], |
| 416 | + base_vertices[vertex1] }; |
| 417 | + auto [cur_distance, cur_pt0, cur_pt1] = |
| 418 | + geode::segment_triangle_distance( edge, other_triangle ); |
| 419 | + if( cur_distance < min_distance ) |
| 420 | + { |
| 421 | + min_distance = cur_distance; |
| 422 | + point0 = cur_pt0; |
| 423 | + point1 = cur_pt1; |
| 424 | + } |
| 425 | + } |
| 426 | + } |
| 427 | + return std::make_tuple( min_distance, point0, point1 ); |
| 428 | + } |
342 | 429 | } // namespace |
343 | 430 |
|
344 | 431 | namespace geode |
@@ -923,6 +1010,112 @@ namespace geode |
923 | 1010 | closest_on_segment, closest_on_triangle ); |
924 | 1011 | } |
925 | 1012 |
|
| 1013 | + std::tuple< double, Point3D, Point3D > |
| 1014 | + opengeode_geometry_api triangle_triangle_distance( |
| 1015 | + const Triangle3D& triangle0, const Triangle3D& triangle1 ) |
| 1016 | + { |
| 1017 | + const auto non_colocated_points = |
| 1018 | + find_non_colocated_triangles_points( triangle0, triangle1 ); |
| 1019 | + if( non_colocated_points.first.size() < 3 ) |
| 1020 | + { |
| 1021 | + for( const auto v : LRange{ 3 } ) |
| 1022 | + { |
| 1023 | + if( !absl::c_contains( non_colocated_points.first, v ) ) |
| 1024 | + { |
| 1025 | + auto& pt0 = triangle0.vertices()[v].get(); |
| 1026 | + auto [distance, pt1] = |
| 1027 | + point_triangle_distance( pt0, triangle1 ); |
| 1028 | + return std::tuple{ distance, pt0, pt1 }; |
| 1029 | + } |
| 1030 | + } |
| 1031 | + } |
| 1032 | + if( non_colocated_points.second.size() < 3 ) |
| 1033 | + { |
| 1034 | + for( const auto v : LRange{ 3 } ) |
| 1035 | + { |
| 1036 | + if( !absl::c_contains( non_colocated_points.second, v ) ) |
| 1037 | + { |
| 1038 | + auto& pt1 = triangle1.vertices()[v].get(); |
| 1039 | + auto [distance, pt0] = |
| 1040 | + point_triangle_distance( pt1, triangle0 ); |
| 1041 | + return std::tuple{ distance, pt0, pt1 }; |
| 1042 | + } |
| 1043 | + } |
| 1044 | + } |
| 1045 | + auto [cur_distance0, cur_pt00, cur_pt01] = test_close_triangles( |
| 1046 | + non_colocated_points.first, triangle0, triangle1 ); |
| 1047 | + auto [cur_distance1, cur_pt11, cur_pt10] = test_close_triangles( |
| 1048 | + non_colocated_points.second, triangle1, triangle0 ); |
| 1049 | + if( cur_distance0 < cur_distance1 ) |
| 1050 | + { |
| 1051 | + return std::tuple{ cur_distance0, cur_pt00, cur_pt01 }; |
| 1052 | + } |
| 1053 | + return std::tuple{ cur_distance1, cur_pt10, cur_pt11 }; |
| 1054 | + } |
| 1055 | + |
| 1056 | + std::optional< std::tuple< double, Point3D, Point3D > > |
| 1057 | + triangle_triangle_distance_between_non_conformal_parts( |
| 1058 | + const Triangle3D& triangle0, const Triangle3D& triangle1 ) |
| 1059 | + { |
| 1060 | + const auto [non_colocated_points0, non_colocated_points1] = |
| 1061 | + find_non_colocated_triangles_points( triangle0, triangle1 ); |
| 1062 | + if( non_colocated_points0.size() == 0 |
| 1063 | + || non_colocated_points1.size() == 0 ) |
| 1064 | + { |
| 1065 | + return std::nullopt; |
| 1066 | + } |
| 1067 | + const auto& vertices0 = triangle0.vertices(); |
| 1068 | + const auto& vertices1 = triangle1.vertices(); |
| 1069 | + double min_distance{ std::numeric_limits< double >::max() }; |
| 1070 | + Point3D point0; |
| 1071 | + Point3D point1; |
| 1072 | + if( non_colocated_points0.size() == 1 ) |
| 1073 | + { |
| 1074 | + auto [cur_distance, cur_pt] = point_triangle_distance( |
| 1075 | + vertices0[non_colocated_points0[0]].get(), triangle1 ); |
| 1076 | + if( cur_distance < min_distance ) |
| 1077 | + { |
| 1078 | + min_distance = cur_distance; |
| 1079 | + point0 = vertices0[non_colocated_points0[0]].get(); |
| 1080 | + point1 = cur_pt; |
| 1081 | + } |
| 1082 | + } |
| 1083 | + if( non_colocated_points1.size() == 1 ) |
| 1084 | + { |
| 1085 | + auto [cur_distance, cur_pt] = point_triangle_distance( |
| 1086 | + vertices1[non_colocated_points1[0]].get(), triangle0 ); |
| 1087 | + if( cur_distance < min_distance ) |
| 1088 | + { |
| 1089 | + min_distance = cur_distance; |
| 1090 | + point0 = cur_pt; |
| 1091 | + point1 = vertices1[non_colocated_points1[0]].get(); |
| 1092 | + } |
| 1093 | + } |
| 1094 | + if( non_colocated_points0.size() > 1 ) |
| 1095 | + { |
| 1096 | + auto [cur_distance, cur_pt0, cur_pt1] = test_close_triangles( |
| 1097 | + non_colocated_points0, triangle0, triangle1 ); |
| 1098 | + if( cur_distance < min_distance ) |
| 1099 | + { |
| 1100 | + min_distance = cur_distance; |
| 1101 | + point0 = cur_pt0; |
| 1102 | + point1 = cur_pt1; |
| 1103 | + } |
| 1104 | + } |
| 1105 | + if( non_colocated_points1.size() > 1 ) |
| 1106 | + { |
| 1107 | + auto [cur_distance, cur_pt1, cur_pt0] = test_close_triangles( |
| 1108 | + non_colocated_points1, triangle1, triangle0 ); |
| 1109 | + if( cur_distance < min_distance ) |
| 1110 | + { |
| 1111 | + min_distance = cur_distance; |
| 1112 | + point0 = cur_pt0; |
| 1113 | + point1 = cur_pt1; |
| 1114 | + } |
| 1115 | + } |
| 1116 | + return std::tuple{ min_distance, point0, point1 }; |
| 1117 | + } |
| 1118 | + |
926 | 1119 | std::tuple< double, Point3D > point_tetrahedron_distance( |
927 | 1120 | const Point3D& point, const Tetrahedron& tetra ) |
928 | 1121 | { |
@@ -1048,7 +1241,8 @@ namespace geode |
1048 | 1241 | } |
1049 | 1242 | OPENGEODE_ASSERT( |
1050 | 1243 | !circle.plane().normal().inexact_equal( other_direction ), |
1051 | | - "[point_circle_distance] Problem while getting circle nearest " |
| 1244 | + "[point_circle_distance] Problem while getting circle " |
| 1245 | + "nearest " |
1052 | 1246 | "point" ); |
1053 | 1247 | const Vector3D other_projected_on_plane = |
1054 | 1248 | other_direction |
|
0 commit comments