Skip to content

Commit 554195e

Browse files
committed
fix(Geometry): new distance functions between triangles
1 parent 512e371 commit 554195e

File tree

2 files changed

+208
-1
lines changed

2 files changed

+208
-1
lines changed

include/geode/geometry/distance.hpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,33 @@ namespace geode
136136
opengeode_geometry_api segment_triangle_distance(
137137
const Segment3D& segment, const Triangle3D& triangle );
138138

139+
/*!
140+
* Compute the smallest distance between two triangles
141+
* @return a tuple containing:
142+
* - the smallest distance.
143+
* - the closest point on the first triangle.
144+
* - the closest point on the second triangle.
145+
*/
146+
[[nodiscard]] std::tuple< double, Point3D, Point3D >
147+
opengeode_geometry_api triangle_triangle_distance(
148+
const Triangle3D& triangle0, const Triangle3D& triangle1 );
149+
150+
/*!
151+
* Compute the smallest distance between two triangles
152+
* @details if the two triangles are the same, return nullopt. Only non
153+
* conformal part of triangles are considered in computation of distance,
154+
* i.e. if the triangle have a common point, it iterates on opposite
155+
* segment, if the triangle have a common edge, it computes distance with
156+
* the opposite point
157+
* @return a tuple containing:
158+
* - the smallest distance.
159+
* - the closest point on the first triangle.
160+
* - the closest point on the second triangle.
161+
*/
162+
[[nodiscard]] std::optional< std::tuple< double, Point3D, Point3D > >
163+
opengeode_geometry_api triangle_triangle_non_conformal_distance(
164+
const Triangle3D& triangle0, const Triangle3D& triangle1 );
165+
139166
/*!
140167
* Compute the distance between a point and a tetrahedron
141168
* @return a tuple containing:

src/geode/geometry/distance.cpp

Lines changed: 181 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,79 @@ namespace
339339
geode::point_point_distance( point, closest_point );
340340
return std::make_tuple( distance, std::move( closest_point ) );
341341
}
342+
343+
std::pair< std::vector< geode::local_index_t >,
344+
std::vector< geode::local_index_t > >
345+
find_non_colocated_triangles_points( const geode::Triangle3D& triangle0,
346+
const geode::Triangle3D& triangle1 )
347+
{
348+
std::pair< std::array< bool, 3 >, std::array< bool, 3 > > colocated{
349+
{ false, false, false }, { false, false, false }
350+
};
351+
const auto& vertices0 = triangle0.vertices();
352+
const auto& vertices1 = triangle1.vertices();
353+
for( const auto vertex0 : geode::LRange{ 3 } )
354+
{
355+
for( const auto vertex1 : geode::LRange{ 3 } )
356+
{
357+
if( geode::point_point_distance(
358+
vertices0[vertex0].get(), vertices1[vertex1].get() )
359+
<= geode::GLOBAL_EPSILON )
360+
{
361+
colocated.first[vertex0] = true;
362+
colocated.second[vertex1] = true;
363+
}
364+
}
365+
}
366+
367+
std::pair< std::vector< geode::local_index_t >,
368+
std::vector< geode::local_index_t > >
369+
result;
370+
for( const auto v : geode::LRange{ 3 } )
371+
{
372+
if( !colocated.first[v] )
373+
{
374+
result.first.push_back( v );
375+
}
376+
if( !colocated.second[v] )
377+
{
378+
result.second.push_back( v );
379+
}
380+
}
381+
return result;
382+
}
383+
384+
std::tuple< double, geode::Point3D, geode::Point3D > test_close_triangles(
385+
const std::vector< geode::local_index_t >& non_colocated_points,
386+
const geode::Triangle3D& base_triangle,
387+
const geode::Triangle3D& other_triangle )
388+
{
389+
const auto& base_vertices = base_triangle.vertices();
390+
double min_distance{ std::numeric_limits< double >::max() };
391+
geode::Point3D point0;
392+
geode::Point3D point1;
393+
for( const auto vertex0 : non_colocated_points )
394+
{
395+
for( const auto vertex1 : non_colocated_points )
396+
{
397+
if( vertex0 == vertex1 )
398+
{
399+
continue;
400+
}
401+
const geode::Segment3D edge{ base_vertices[vertex0],
402+
base_vertices[vertex1] };
403+
auto [cur_distance, cur_pt0, cur_pt1] =
404+
geode::segment_triangle_distance( edge, other_triangle );
405+
if( cur_distance < min_distance )
406+
{
407+
min_distance = cur_distance;
408+
point0 = cur_pt0;
409+
point1 = cur_pt1;
410+
}
411+
}
412+
}
413+
return std::make_tuple( min_distance, point0, point1 );
414+
}
342415
} // namespace
343416

344417
namespace geode
@@ -923,6 +996,112 @@ namespace geode
923996
closest_on_segment, closest_on_triangle );
924997
}
925998

999+
std::tuple< double, Point3D, Point3D >
1000+
opengeode_geometry_api triangle_triangle_distance(
1001+
const Triangle3D& triangle0, const Triangle3D& triangle1 )
1002+
{
1003+
const auto non_colocated_points =
1004+
find_non_colocated_triangles_points( triangle0, triangle1 );
1005+
if( non_colocated_points.first.size() < 3 )
1006+
{
1007+
for( const auto v : LRange{ 3 } )
1008+
{
1009+
if( !absl::c_contains( non_colocated_points.first, v ) )
1010+
{
1011+
auto& pt0 = triangle0.vertices()[v].get();
1012+
auto [distance, pt1] =
1013+
point_triangle_distance( pt0, triangle1 );
1014+
return std::make_tuple( distance, pt0, pt1 );
1015+
}
1016+
}
1017+
}
1018+
if( non_colocated_points.second.size() < 3 )
1019+
{
1020+
for( const auto v : LRange{ 3 } )
1021+
{
1022+
if( !absl::c_contains( non_colocated_points.second, v ) )
1023+
{
1024+
auto& pt1 = triangle1.vertices()[v].get();
1025+
auto [distance, pt0] =
1026+
point_triangle_distance( pt1, triangle0 );
1027+
return std::make_tuple( distance, pt0, pt1 );
1028+
}
1029+
}
1030+
}
1031+
auto [cur_distance0, cur_pt00, cur_pt01] = test_close_triangles(
1032+
non_colocated_points.first, triangle0, triangle1 );
1033+
auto [cur_distance1, cur_pt11, cur_pt10] = test_close_triangles(
1034+
non_colocated_points.second, triangle1, triangle0 );
1035+
if( cur_distance0 < cur_distance1 )
1036+
{
1037+
return std::make_tuple( cur_distance0, cur_pt00, cur_pt01 );
1038+
}
1039+
return std::make_tuple( cur_distance1, cur_pt10, cur_pt11 );
1040+
}
1041+
1042+
std::optional< std::tuple< double, Point3D, Point3D > >
1043+
triangle_triangle_non_conformal_distance(
1044+
const Triangle3D& triangle0, const Triangle3D& triangle1 )
1045+
{
1046+
const auto non_colocated_points =
1047+
find_non_colocated_triangles_points( triangle0, triangle1 );
1048+
if( non_colocated_points.first.size() == 0
1049+
|| non_colocated_points.second.size() == 0 )
1050+
{
1051+
return std::nullopt;
1052+
}
1053+
const auto& vertices0 = triangle0.vertices();
1054+
const auto& vertices1 = triangle1.vertices();
1055+
double min_distance{ std::numeric_limits< double >::max() };
1056+
Point3D point0;
1057+
Point3D point1;
1058+
if( non_colocated_points.first.size() == 1 )
1059+
{
1060+
auto [cur_distance, cur_pt] = point_triangle_distance(
1061+
vertices0[non_colocated_points.first[0]].get(), triangle1 );
1062+
if( cur_distance < min_distance )
1063+
{
1064+
min_distance = cur_distance;
1065+
point0 = vertices0[non_colocated_points.first[0]].get();
1066+
point1 = cur_pt;
1067+
}
1068+
}
1069+
if( non_colocated_points.second.size() == 1 )
1070+
{
1071+
auto [cur_distance, cur_pt] = point_triangle_distance(
1072+
vertices1[non_colocated_points.second[0]].get(), triangle0 );
1073+
if( cur_distance < min_distance )
1074+
{
1075+
min_distance = cur_distance;
1076+
point0 = cur_pt;
1077+
point1 = vertices1[non_colocated_points.second[0]].get();
1078+
}
1079+
}
1080+
if( non_colocated_points.first.size() > 1 )
1081+
{
1082+
auto [cur_distance, cur_pt0, cur_pt1] = test_close_triangles(
1083+
non_colocated_points.first, triangle0, triangle1 );
1084+
if( cur_distance < min_distance )
1085+
{
1086+
min_distance = cur_distance;
1087+
point0 = cur_pt0;
1088+
point1 = cur_pt1;
1089+
}
1090+
}
1091+
if( non_colocated_points.second.size() > 1 )
1092+
{
1093+
auto [cur_distance, cur_pt1, cur_pt0] = test_close_triangles(
1094+
non_colocated_points.second, triangle1, triangle0 );
1095+
if( cur_distance < min_distance )
1096+
{
1097+
min_distance = cur_distance;
1098+
point0 = cur_pt0;
1099+
point1 = cur_pt1;
1100+
}
1101+
}
1102+
return std::make_tuple( min_distance, point0, point1 );
1103+
}
1104+
9261105
std::tuple< double, Point3D > point_tetrahedron_distance(
9271106
const Point3D& point, const Tetrahedron& tetra )
9281107
{
@@ -1048,7 +1227,8 @@ namespace geode
10481227
}
10491228
OPENGEODE_ASSERT(
10501229
!circle.plane().normal().inexact_equal( other_direction ),
1051-
"[point_circle_distance] Problem while getting circle nearest "
1230+
"[point_circle_distance] Problem while getting circle "
1231+
"nearest "
10521232
"point" );
10531233
const Vector3D other_projected_on_plane =
10541234
other_direction

0 commit comments

Comments
 (0)