The following function is supposed to return the points p1 on line segment a, and p2 line segment b, such that |p1 - p2| is minimized.
point_pair get_closest_points(line_segment const& a, line_segment const& b)
{
auto const intersect = intersection(extension(a), extension(b));
if(line_segment::valid(intersect.a))
{
if(line_segment::valid(intersect.b))
{
auto const loc_a = point_at(a, intersect.a);
auto const loc_b = point_at(b, intersect.b);
return point_pair{loc_a, loc_b};
}
else
{
auto const loc_b = point_at(extension(b), line_segment::clamp(intersect.b));
auto const proj = project(extension(a), loc_b);
auto const loc_a = point_at(extension(a), proj);
return point_pair{loc_a, loc_b};
}
}
else
{
if(line_segment::valid(intersect.b))
{
auto const loc_a = point_at(extension(a), line_segment::clamp(intersect.a));
auto const proj = project(extension(b), loc_a);
auto const loc_b = point_at(extension(b), proj);
return point_pair{loc_a, loc_b};
}
else
{
auto const loc_a = point_at(extension(a), line_segment::clamp(intersect.a));
auto const proj_a_on_b = project(extension(b), loc_a);
if(line_segment::valid(proj_a_on_b))
{
return point_pair{loc_a, point_at(extension(b), proj_a_on_b)};
}
else
{
auto const loc_b = point_at(extension(b), line_segment::clamp(intersect.b));
auto const proj_b_on_a = project(extension(a), loc_b);
if(line_segment::valid(proj_b_on_a))
{
return point_pair{point_at(extension(a), proj_b_on_a), loc_b};
}
else
{
return point_pair{loc_a, loc_b};
}
}
}
}
}
Helper functions used:
line extension(line_segment a)
converts a line segment and extends it to a lineline_intersection intersection(line a, line b)
, computes the parameters of a and b that corresponds to the closest points on the lines.bool line_segment::valid(line_parameter t)
, checks thatt
is a valid parameter for a line_segment (should be between 0 and 1)point point_at(line a, line_parameter t)
returns the point on a that corresponds tot
line_parameter line_segment::clamp(line_parameter t)
clampst
to the valid rangeline_parameter project(line l, point p)
projectsp
onl
From my testing, the function appears to work. Questions:
Is there some case that is not handled properly? As a precondition, a and b are assumed be non-parallel and to have non-zero length.
Can I get rid of some branches?