Let's suppose the are three line segments in a plane, each line segment has coordinates (x1, y1) and (x2, y2). What is the best approach to find out the nearest line segment from a point (x, y)?
Hint: use vectors dot product.
Let's suppose the are three line segments in a plane, each line segment has coordinates (x1, y1) and (x2, y2). What is the best approach to find out the nearest line segment from a point (x, y)?
Hint: use vectors dot product.
On
Let's think about the problem in geometric terms. The given point and the two points defining any one of the lines form a triangle. One of the altitudes of that triangle is the distance from the given point to the chosen line. So the problem reduces to finding the relevant altitudes of three triangles and selecting the shortest one.
In V12, Wolfram introduced the function TriangleConstruct into Mathematica which, when given a list of tree points (coordinate pairs) representing a triangle, can compute many properties of that triangle. One of those properties is its altitude.
Once we have the altitudes for thee triangles, we can order the altitudes by length and use the ordering to identify the line we are looking for.
Here is some code that does what I have described.
SeedRandom[6]
pt = {0, 0}; (* the given point *)
lines = Partition[RandomReal[{-1, 1}, {6, 2}], 2];
triangles = {pt, #[[1]], #[[2]]} & /@ lines;
altitudes = TriangleConstruct[#, {"Altitude", pt}] & /@ triangles;
ordering = OrderingBy[altitudes, Apply[EuclideanDistance, First[#]] &];
lines[[ordering[[1]]]] (* the line closest to the given point *)
{{0.446885, 0.440912}, {0.612913, -0.86427}}
Here is a visualization of the geometry created by the above code.
Graphics[
{InfiniteLine /@ lines,
{Dashed, altitudes},
{AbsolutePointSize[8],
{Red,
Point[pt],
TriangleConstruct[triangles[[ordering[[1]]]], {"Foot", pt}]},
{Black, Point /@ lines}},
Block[{x1, x2},
{x1, x2} = (lines[[ordering[[1]]]][[#]] & /@ {1, 2});
{Text[Style[#, 8], # + {.28, .05}] & /@ {x1, x2}}]},
PlotRange -> {{-1, 1}, Automatic},
PlotRangePadding -> {{Automatic, .2}, Automatic},
Frame -> True]
Notes
On
For three line segment instead of infinite line. Here we use Line instead of InfiniteLine.
pairs = RandomReal[{-4, 4}, {3, 2, 2}];
pt = RandomReal[{-3, 3}, 2];
result = {Line[#], RegionNearest[Line[#], pt],
RegionDistance[Line[#], pt]} & /@ pairs
point = TakeSmallestBy[result, Last, 1][[1, 2]];
Graphics[{Line /@ pairs, {PointSize[Large], Red, Point[pt]},
Line[{pt, point}], {PointSize[Large], Blue, Point[point]}}]
The distance from a point to a line is given by the projection of a line from the point to some point on the line onto a unit vector orthogonal to the line.
First we need same data.
Then we need unit vectors orthogonal to our lines:
The distance from the point to the lines is now given by the absolute value of the projection of the line from
pointto the start of the lines onto the orthogonal unit vector:It is obvious, for our example, that the first line is closest to the point.